blob: ec39b9ab6569fcbed3ba4cd1e4ebfc53b192bf62 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * NSA Security-Enhanced Linux (SELinux) security module
3 *
4 * This file contains the SELinux hook function implementations.
5 *
6 * Authors: Stephen Smalley, <sds@epoch.ncsc.mil>
Eric Paris828dfe12008-04-17 13:17:49 -04007 * Chris Vance, <cvance@nai.com>
8 * Wayne Salamon, <wsalamon@nai.com>
9 * James Morris <jmorris@redhat.com>
Linus Torvalds1da177e2005-04-16 15:20:36 -070010 *
11 * Copyright (C) 2001,2002 Networks Associates Technology, Inc.
Eric Paris2069f452008-07-04 09:47:13 +100012 * Copyright (C) 2003-2008 Red Hat, Inc., James Morris <jmorris@redhat.com>
13 * Eric Paris <eparis@redhat.com>
Linus Torvalds1da177e2005-04-16 15:20:36 -070014 * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
Eric Paris828dfe12008-04-17 13:17:49 -040015 * <dgoeddel@trustedcs.com>
Paul Mooreed6d76e2009-08-28 18:12:49 -040016 * Copyright (C) 2006, 2007, 2009 Hewlett-Packard Development Company, L.P.
Paul Moore82c21bf2011-08-01 11:10:33 +000017 * Paul Moore <paul@paul-moore.com>
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +090018 * Copyright (C) 2007 Hitachi Software Engineering Co., Ltd.
Eric Paris828dfe12008-04-17 13:17:49 -040019 * Yuichi Nakamura <ynakam@hitachisoft.jp>
Linus Torvalds1da177e2005-04-16 15:20:36 -070020 *
21 * This program is free software; you can redistribute it and/or modify
22 * it under the terms of the GNU General Public License version 2,
Eric Paris828dfe12008-04-17 13:17:49 -040023 * as published by the Free Software Foundation.
Linus Torvalds1da177e2005-04-16 15:20:36 -070024 */
25
Linus Torvalds1da177e2005-04-16 15:20:36 -070026#include <linux/init.h>
Eric Paris0b24dcb2011-02-25 15:39:20 -050027#include <linux/kd.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070028#include <linux/kernel.h>
Roland McGrath0d094ef2008-07-25 19:45:49 -070029#include <linux/tracehook.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070030#include <linux/errno.h>
31#include <linux/sched.h>
Casey Schaufler3c4ed7b2015-05-02 15:10:46 -070032#include <linux/lsm_hooks.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070033#include <linux/xattr.h>
34#include <linux/capability.h>
35#include <linux/unistd.h>
36#include <linux/mm.h>
37#include <linux/mman.h>
38#include <linux/slab.h>
39#include <linux/pagemap.h>
Eric Paris0b24dcb2011-02-25 15:39:20 -050040#include <linux/proc_fs.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070041#include <linux/swap.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070042#include <linux/spinlock.h>
43#include <linux/syscalls.h>
Eric Paris2a7dba32011-02-01 11:05:39 -050044#include <linux/dcache.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070045#include <linux/file.h>
Al Viro9f3acc32008-04-24 07:44:08 -040046#include <linux/fdtable.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070047#include <linux/namei.h>
48#include <linux/mount.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070049#include <linux/netfilter_ipv4.h>
50#include <linux/netfilter_ipv6.h>
51#include <linux/tty.h>
52#include <net/icmp.h>
Stephen Hemminger227b60f2007-10-10 17:30:46 -070053#include <net/ip.h> /* for local_port_range[] */
Linus Torvalds1da177e2005-04-16 15:20:36 -070054#include <net/tcp.h> /* struct or_callable used in sock_rcv_skb */
Paul Moore47180062013-12-04 16:10:45 -050055#include <net/inet_connection_sock.h>
Paul Moore220deb92008-01-29 08:38:23 -050056#include <net/net_namespace.h>
Paul Moored621d352008-01-29 08:43:36 -050057#include <net/netlabel.h>
Eric Parisf5269712008-05-14 11:27:45 -040058#include <linux/uaccess.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070059#include <asm/ioctls.h>
Arun Sharma600634972011-07-26 16:09:06 -070060#include <linux/atomic.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070061#include <linux/bitops.h>
62#include <linux/interrupt.h>
63#include <linux/netdevice.h> /* for network interface checks */
Hong zhi guo77954982013-03-27 06:49:35 +000064#include <net/netlink.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070065#include <linux/tcp.h>
66#include <linux/udp.h>
James Morris2ee92d42006-11-13 16:09:01 -080067#include <linux/dccp.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070068#include <linux/quota.h>
69#include <linux/un.h> /* for Unix socket types */
70#include <net/af_unix.h> /* for Unix socket types */
71#include <linux/parser.h>
72#include <linux/nfs_mount.h>
73#include <net/ipv6.h>
74#include <linux/hugetlb.h>
75#include <linux/personality.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070076#include <linux/audit.h>
Eric Paris6931dfc2005-06-30 02:58:51 -070077#include <linux/string.h>
Catherine Zhang877ce7c2006-06-29 12:27:47 -070078#include <linux/selinux.h>
Eric Paris23970742006-09-25 23:32:01 -070079#include <linux/mutex.h>
Frank Mayharf06febc2008-09-12 09:54:39 -070080#include <linux/posix-timers.h>
Kees Cook00234592010-02-03 15:36:43 -080081#include <linux/syslog.h>
Serge E. Hallyn34867402011-03-23 16:43:17 -070082#include <linux/user_namespace.h>
Paul Gortmaker44fc7ea2011-05-26 20:52:10 -040083#include <linux/export.h>
Al Viro40401532012-02-13 03:58:52 +000084#include <linux/msg.h>
85#include <linux/shm.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070086
87#include "avc.h"
88#include "objsec.h"
89#include "netif.h"
Paul Moore224dfbd2008-01-29 08:38:13 -050090#include "netnode.h"
Paul Moore3e1121722008-04-10 10:48:14 -040091#include "netport.h"
Trent Jaegerd28d1e02005-12-13 23:12:40 -080092#include "xfrm.h"
Paul Moorec60475b2007-02-28 15:14:23 -050093#include "netlabel.h"
Ahmed S. Darwish9d57a7f2008-03-01 22:03:14 +020094#include "audit.h"
James Morris7b98a582011-08-30 12:52:32 +100095#include "avc_ss.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070096
Paul Moored621d352008-01-29 08:43:36 -050097/* SECMARK reference count */
James Morris56a4ca92011-08-17 11:08:43 +100098static atomic_t selinux_secmark_refcount = ATOMIC_INIT(0);
Paul Moored621d352008-01-29 08:43:36 -050099
Linus Torvalds1da177e2005-04-16 15:20:36 -0700100#ifdef CONFIG_SECURITY_SELINUX_DEVELOP
Eric Paris828dfe12008-04-17 13:17:49 -0400101int selinux_enforcing;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700102
103static int __init enforcing_setup(char *str)
104{
Eric Parisf5269712008-05-14 11:27:45 -0400105 unsigned long enforcing;
Jingoo Han29707b22014-02-05 15:13:14 +0900106 if (!kstrtoul(str, 0, &enforcing))
Eric Parisf5269712008-05-14 11:27:45 -0400107 selinux_enforcing = enforcing ? 1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108 return 1;
109}
110__setup("enforcing=", enforcing_setup);
111#endif
112
113#ifdef CONFIG_SECURITY_SELINUX_BOOTPARAM
114int selinux_enabled = CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE;
115
116static int __init selinux_enabled_setup(char *str)
117{
Eric Parisf5269712008-05-14 11:27:45 -0400118 unsigned long enabled;
Jingoo Han29707b22014-02-05 15:13:14 +0900119 if (!kstrtoul(str, 0, &enabled))
Eric Parisf5269712008-05-14 11:27:45 -0400120 selinux_enabled = enabled ? 1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700121 return 1;
122}
123__setup("selinux=", selinux_enabled_setup);
Stephen Smalley30d55282006-05-03 10:52:36 -0400124#else
125int selinux_enabled = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126#endif
127
Christoph Lametere18b8902006-12-06 20:33:20 -0800128static struct kmem_cache *sel_inode_cache;
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)
Stephen Smalley134509d2015-06-04 16:22:17 -0400727 sbsec->flags |= SE_SBPROC | SE_SBGENFS;
728
729 if (strcmp(sb->s_type->name, "debugfs") == 0)
730 sbsec->flags |= SE_SBGENFS;
Eric Parisc9180a52007-11-30 13:00:35 -0500731
David Quigleyeb9ae682013-05-22 12:50:37 -0400732 if (!sbsec->behavior) {
733 /*
734 * Determine the labeling behavior to use for this
735 * filesystem type.
736 */
Paul Moore98f700f2013-09-18 13:52:20 -0400737 rc = security_fs_use(sb);
David Quigleyeb9ae682013-05-22 12:50:37 -0400738 if (rc) {
739 printk(KERN_WARNING
740 "%s: security_fs_use(%s) returned %d\n",
741 __func__, sb->s_type->name, rc);
742 goto out;
743 }
Eric Parisc9180a52007-11-30 13:00:35 -0500744 }
Eric Parisc9180a52007-11-30 13:00:35 -0500745 /* sets the context of the superblock for the fs being mounted. */
746 if (fscontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100747 rc = may_context_mount_sb_relabel(fscontext_sid, sbsec, cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500748 if (rc)
749 goto out;
750
751 sbsec->sid = fscontext_sid;
752 }
753
754 /*
755 * Switch to using mount point labeling behavior.
756 * sets the label used on all file below the mountpoint, and will set
757 * the superblock context if not already set.
758 */
David Quigleyeb9ae682013-05-22 12:50:37 -0400759 if (kern_flags & SECURITY_LSM_NATIVE_LABELS && !context_sid) {
760 sbsec->behavior = SECURITY_FS_USE_NATIVE;
761 *set_kern_flags |= SECURITY_LSM_NATIVE_LABELS;
762 }
763
Eric Parisc9180a52007-11-30 13:00:35 -0500764 if (context_sid) {
765 if (!fscontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100766 rc = may_context_mount_sb_relabel(context_sid, sbsec,
767 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500768 if (rc)
769 goto out;
770 sbsec->sid = context_sid;
771 } else {
David Howells275bb412008-11-14 10:39:19 +1100772 rc = may_context_mount_inode_relabel(context_sid, sbsec,
773 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500774 if (rc)
775 goto out;
776 }
777 if (!rootcontext_sid)
778 rootcontext_sid = context_sid;
779
780 sbsec->mntpoint_sid = context_sid;
781 sbsec->behavior = SECURITY_FS_USE_MNTPOINT;
782 }
783
784 if (rootcontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100785 rc = may_context_mount_inode_relabel(rootcontext_sid, sbsec,
786 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500787 if (rc)
788 goto out;
789
790 root_isec->sid = rootcontext_sid;
791 root_isec->initialized = 1;
792 }
793
794 if (defcontext_sid) {
David Quigleyeb9ae682013-05-22 12:50:37 -0400795 if (sbsec->behavior != SECURITY_FS_USE_XATTR &&
796 sbsec->behavior != SECURITY_FS_USE_NATIVE) {
Eric Parisc9180a52007-11-30 13:00:35 -0500797 rc = -EINVAL;
798 printk(KERN_WARNING "SELinux: defcontext option is "
799 "invalid for this filesystem type\n");
800 goto out;
801 }
802
803 if (defcontext_sid != sbsec->def_sid) {
804 rc = may_context_mount_inode_relabel(defcontext_sid,
David Howells275bb412008-11-14 10:39:19 +1100805 sbsec, cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500806 if (rc)
807 goto out;
808 }
809
810 sbsec->def_sid = defcontext_sid;
811 }
812
813 rc = sb_finish_set_opts(sb);
814out:
Eric Parisbc7e9822006-09-25 23:32:02 -0700815 mutex_unlock(&sbsec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700816 return rc;
Eric Parisc9180a52007-11-30 13:00:35 -0500817out_double_mount:
818 rc = -EINVAL;
819 printk(KERN_WARNING "SELinux: mount invalid. Same superblock, different "
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800820 "security settings for (dev %s, type %s)\n", sb->s_id, name);
Eric Parisc9180a52007-11-30 13:00:35 -0500821 goto out;
822}
823
Jeff Layton094f7b62013-04-01 08:14:24 -0400824static int selinux_cmp_sb_context(const struct super_block *oldsb,
825 const struct super_block *newsb)
826{
827 struct superblock_security_struct *old = oldsb->s_security;
828 struct superblock_security_struct *new = newsb->s_security;
829 char oldflags = old->flags & SE_MNTMASK;
830 char newflags = new->flags & SE_MNTMASK;
831
832 if (oldflags != newflags)
833 goto mismatch;
834 if ((oldflags & FSCONTEXT_MNT) && old->sid != new->sid)
835 goto mismatch;
836 if ((oldflags & CONTEXT_MNT) && old->mntpoint_sid != new->mntpoint_sid)
837 goto mismatch;
838 if ((oldflags & DEFCONTEXT_MNT) && old->def_sid != new->def_sid)
839 goto mismatch;
840 if (oldflags & ROOTCONTEXT_MNT) {
David Howellsc6f493d2015-03-17 22:26:22 +0000841 struct inode_security_struct *oldroot = d_backing_inode(oldsb->s_root)->i_security;
842 struct inode_security_struct *newroot = d_backing_inode(newsb->s_root)->i_security;
Jeff Layton094f7b62013-04-01 08:14:24 -0400843 if (oldroot->sid != newroot->sid)
844 goto mismatch;
845 }
846 return 0;
847mismatch:
848 printk(KERN_WARNING "SELinux: mount invalid. Same superblock, "
849 "different security settings for (dev %s, "
850 "type %s)\n", newsb->s_id, newsb->s_type->name);
851 return -EBUSY;
852}
853
854static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
Eric Parisc9180a52007-11-30 13:00:35 -0500855 struct super_block *newsb)
856{
857 const struct superblock_security_struct *oldsbsec = oldsb->s_security;
858 struct superblock_security_struct *newsbsec = newsb->s_security;
859
860 int set_fscontext = (oldsbsec->flags & FSCONTEXT_MNT);
861 int set_context = (oldsbsec->flags & CONTEXT_MNT);
862 int set_rootcontext = (oldsbsec->flags & ROOTCONTEXT_MNT);
863
Eric Paris0f5e6422008-04-21 16:24:11 -0400864 /*
865 * if the parent was able to be mounted it clearly had no special lsm
Al Viroe8c26252010-03-23 06:36:54 -0400866 * mount options. thus we can safely deal with this superblock later
Eric Paris0f5e6422008-04-21 16:24:11 -0400867 */
Al Viroe8c26252010-03-23 06:36:54 -0400868 if (!ss_initialized)
Jeff Layton094f7b62013-04-01 08:14:24 -0400869 return 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500870
Eric Parisc9180a52007-11-30 13:00:35 -0500871 /* how can we clone if the old one wasn't set up?? */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500872 BUG_ON(!(oldsbsec->flags & SE_SBINITIALIZED));
Eric Parisc9180a52007-11-30 13:00:35 -0500873
Jeff Layton094f7b62013-04-01 08:14:24 -0400874 /* if fs is reusing a sb, make sure that the contexts match */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500875 if (newsbsec->flags & SE_SBINITIALIZED)
Jeff Layton094f7b62013-04-01 08:14:24 -0400876 return selinux_cmp_sb_context(oldsb, newsb);
Eric Paris5a552612008-04-09 14:08:35 -0400877
Eric Parisc9180a52007-11-30 13:00:35 -0500878 mutex_lock(&newsbsec->lock);
879
880 newsbsec->flags = oldsbsec->flags;
881
882 newsbsec->sid = oldsbsec->sid;
883 newsbsec->def_sid = oldsbsec->def_sid;
884 newsbsec->behavior = oldsbsec->behavior;
885
886 if (set_context) {
887 u32 sid = oldsbsec->mntpoint_sid;
888
889 if (!set_fscontext)
890 newsbsec->sid = sid;
891 if (!set_rootcontext) {
David Howellsc6f493d2015-03-17 22:26:22 +0000892 struct inode *newinode = d_backing_inode(newsb->s_root);
Eric Parisc9180a52007-11-30 13:00:35 -0500893 struct inode_security_struct *newisec = newinode->i_security;
894 newisec->sid = sid;
895 }
896 newsbsec->mntpoint_sid = sid;
897 }
898 if (set_rootcontext) {
David Howellsc6f493d2015-03-17 22:26:22 +0000899 const struct inode *oldinode = d_backing_inode(oldsb->s_root);
Eric Parisc9180a52007-11-30 13:00:35 -0500900 const struct inode_security_struct *oldisec = oldinode->i_security;
David Howellsc6f493d2015-03-17 22:26:22 +0000901 struct inode *newinode = d_backing_inode(newsb->s_root);
Eric Parisc9180a52007-11-30 13:00:35 -0500902 struct inode_security_struct *newisec = newinode->i_security;
903
904 newisec->sid = oldisec->sid;
905 }
906
907 sb_finish_set_opts(newsb);
908 mutex_unlock(&newsbsec->lock);
Jeff Layton094f7b62013-04-01 08:14:24 -0400909 return 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500910}
911
Adrian Bunk2e1479d2008-03-17 22:29:23 +0200912static int selinux_parse_opts_str(char *options,
913 struct security_mnt_opts *opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500914{
Eric Parise0007522008-03-05 10:31:54 -0500915 char *p;
Eric Parisc9180a52007-11-30 13:00:35 -0500916 char *context = NULL, *defcontext = NULL;
917 char *fscontext = NULL, *rootcontext = NULL;
Eric Parise0007522008-03-05 10:31:54 -0500918 int rc, num_mnt_opts = 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500919
Eric Parise0007522008-03-05 10:31:54 -0500920 opts->num_mnt_opts = 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500921
922 /* Standard string-based options. */
923 while ((p = strsep(&options, "|")) != NULL) {
924 int token;
925 substring_t args[MAX_OPT_ARGS];
926
927 if (!*p)
928 continue;
929
930 token = match_token(p, tokens, args);
931
932 switch (token) {
933 case Opt_context:
934 if (context || defcontext) {
935 rc = -EINVAL;
936 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
937 goto out_err;
938 }
939 context = match_strdup(&args[0]);
940 if (!context) {
941 rc = -ENOMEM;
942 goto out_err;
943 }
944 break;
945
946 case Opt_fscontext:
947 if (fscontext) {
948 rc = -EINVAL;
949 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
950 goto out_err;
951 }
952 fscontext = match_strdup(&args[0]);
953 if (!fscontext) {
954 rc = -ENOMEM;
955 goto out_err;
956 }
957 break;
958
959 case Opt_rootcontext:
960 if (rootcontext) {
961 rc = -EINVAL;
962 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
963 goto out_err;
964 }
965 rootcontext = match_strdup(&args[0]);
966 if (!rootcontext) {
967 rc = -ENOMEM;
968 goto out_err;
969 }
970 break;
971
972 case Opt_defcontext:
973 if (context || defcontext) {
974 rc = -EINVAL;
975 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
976 goto out_err;
977 }
978 defcontext = match_strdup(&args[0]);
979 if (!defcontext) {
980 rc = -ENOMEM;
981 goto out_err;
982 }
983 break;
David P. Quigley11689d42009-01-16 09:22:03 -0500984 case Opt_labelsupport:
985 break;
Eric Parisc9180a52007-11-30 13:00:35 -0500986 default:
987 rc = -EINVAL;
988 printk(KERN_WARNING "SELinux: unknown mount option\n");
989 goto out_err;
990
991 }
992 }
993
Eric Parise0007522008-03-05 10:31:54 -0500994 rc = -ENOMEM;
995 opts->mnt_opts = kcalloc(NUM_SEL_MNT_OPTS, sizeof(char *), GFP_ATOMIC);
996 if (!opts->mnt_opts)
997 goto out_err;
998
999 opts->mnt_opts_flags = kcalloc(NUM_SEL_MNT_OPTS, sizeof(int), GFP_ATOMIC);
1000 if (!opts->mnt_opts_flags) {
1001 kfree(opts->mnt_opts);
1002 goto out_err;
Eric Parisc9180a52007-11-30 13:00:35 -05001003 }
1004
Eric Parise0007522008-03-05 10:31:54 -05001005 if (fscontext) {
1006 opts->mnt_opts[num_mnt_opts] = fscontext;
1007 opts->mnt_opts_flags[num_mnt_opts++] = FSCONTEXT_MNT;
1008 }
1009 if (context) {
1010 opts->mnt_opts[num_mnt_opts] = context;
1011 opts->mnt_opts_flags[num_mnt_opts++] = CONTEXT_MNT;
1012 }
1013 if (rootcontext) {
1014 opts->mnt_opts[num_mnt_opts] = rootcontext;
1015 opts->mnt_opts_flags[num_mnt_opts++] = ROOTCONTEXT_MNT;
1016 }
1017 if (defcontext) {
1018 opts->mnt_opts[num_mnt_opts] = defcontext;
1019 opts->mnt_opts_flags[num_mnt_opts++] = DEFCONTEXT_MNT;
1020 }
1021
1022 opts->num_mnt_opts = num_mnt_opts;
1023 return 0;
1024
Eric Parisc9180a52007-11-30 13:00:35 -05001025out_err:
1026 kfree(context);
1027 kfree(defcontext);
1028 kfree(fscontext);
1029 kfree(rootcontext);
1030 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001031}
Eric Parise0007522008-03-05 10:31:54 -05001032/*
1033 * string mount options parsing and call set the sbsec
1034 */
1035static int superblock_doinit(struct super_block *sb, void *data)
1036{
1037 int rc = 0;
1038 char *options = data;
1039 struct security_mnt_opts opts;
1040
1041 security_init_mnt_opts(&opts);
1042
1043 if (!data)
1044 goto out;
1045
1046 BUG_ON(sb->s_type->fs_flags & FS_BINARY_MOUNTDATA);
1047
1048 rc = selinux_parse_opts_str(options, &opts);
1049 if (rc)
1050 goto out_err;
1051
1052out:
David Quigley649f6e72013-05-22 12:50:36 -04001053 rc = selinux_set_mnt_opts(sb, &opts, 0, NULL);
Eric Parise0007522008-03-05 10:31:54 -05001054
1055out_err:
1056 security_free_mnt_opts(&opts);
1057 return rc;
1058}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001059
Adrian Bunk3583a712008-07-22 20:21:23 +03001060static void selinux_write_opts(struct seq_file *m,
1061 struct security_mnt_opts *opts)
Eric Paris2069f452008-07-04 09:47:13 +10001062{
1063 int i;
1064 char *prefix;
1065
1066 for (i = 0; i < opts->num_mnt_opts; i++) {
David P. Quigley11689d42009-01-16 09:22:03 -05001067 char *has_comma;
1068
1069 if (opts->mnt_opts[i])
1070 has_comma = strchr(opts->mnt_opts[i], ',');
1071 else
1072 has_comma = NULL;
Eric Paris2069f452008-07-04 09:47:13 +10001073
1074 switch (opts->mnt_opts_flags[i]) {
1075 case CONTEXT_MNT:
1076 prefix = CONTEXT_STR;
1077 break;
1078 case FSCONTEXT_MNT:
1079 prefix = FSCONTEXT_STR;
1080 break;
1081 case ROOTCONTEXT_MNT:
1082 prefix = ROOTCONTEXT_STR;
1083 break;
1084 case DEFCONTEXT_MNT:
1085 prefix = DEFCONTEXT_STR;
1086 break;
Eric Paris12f348b2012-10-09 10:56:25 -04001087 case SBLABEL_MNT:
David P. Quigley11689d42009-01-16 09:22:03 -05001088 seq_putc(m, ',');
1089 seq_puts(m, LABELSUPP_STR);
1090 continue;
Eric Paris2069f452008-07-04 09:47:13 +10001091 default:
1092 BUG();
Eric Parisa35c6c832011-04-20 10:21:28 -04001093 return;
Eric Paris2069f452008-07-04 09:47:13 +10001094 };
1095 /* we need a comma before each option */
1096 seq_putc(m, ',');
1097 seq_puts(m, prefix);
1098 if (has_comma)
1099 seq_putc(m, '\"');
1100 seq_puts(m, opts->mnt_opts[i]);
1101 if (has_comma)
1102 seq_putc(m, '\"');
1103 }
1104}
1105
1106static int selinux_sb_show_options(struct seq_file *m, struct super_block *sb)
1107{
1108 struct security_mnt_opts opts;
1109 int rc;
1110
1111 rc = selinux_get_mnt_opts(sb, &opts);
Eric Paris383795c2008-07-29 17:07:26 -04001112 if (rc) {
1113 /* before policy load we may get EINVAL, don't show anything */
1114 if (rc == -EINVAL)
1115 rc = 0;
Eric Paris2069f452008-07-04 09:47:13 +10001116 return rc;
Eric Paris383795c2008-07-29 17:07:26 -04001117 }
Eric Paris2069f452008-07-04 09:47:13 +10001118
1119 selinux_write_opts(m, &opts);
1120
1121 security_free_mnt_opts(&opts);
1122
1123 return rc;
1124}
1125
Linus Torvalds1da177e2005-04-16 15:20:36 -07001126static inline u16 inode_mode_to_security_class(umode_t mode)
1127{
1128 switch (mode & S_IFMT) {
1129 case S_IFSOCK:
1130 return SECCLASS_SOCK_FILE;
1131 case S_IFLNK:
1132 return SECCLASS_LNK_FILE;
1133 case S_IFREG:
1134 return SECCLASS_FILE;
1135 case S_IFBLK:
1136 return SECCLASS_BLK_FILE;
1137 case S_IFDIR:
1138 return SECCLASS_DIR;
1139 case S_IFCHR:
1140 return SECCLASS_CHR_FILE;
1141 case S_IFIFO:
1142 return SECCLASS_FIFO_FILE;
1143
1144 }
1145
1146 return SECCLASS_FILE;
1147}
1148
James Morris13402582005-09-30 14:24:34 -04001149static inline int default_protocol_stream(int protocol)
1150{
1151 return (protocol == IPPROTO_IP || protocol == IPPROTO_TCP);
1152}
1153
1154static inline int default_protocol_dgram(int protocol)
1155{
1156 return (protocol == IPPROTO_IP || protocol == IPPROTO_UDP);
1157}
1158
Linus Torvalds1da177e2005-04-16 15:20:36 -07001159static inline u16 socket_type_to_security_class(int family, int type, int protocol)
1160{
1161 switch (family) {
1162 case PF_UNIX:
1163 switch (type) {
1164 case SOCK_STREAM:
1165 case SOCK_SEQPACKET:
1166 return SECCLASS_UNIX_STREAM_SOCKET;
1167 case SOCK_DGRAM:
1168 return SECCLASS_UNIX_DGRAM_SOCKET;
1169 }
1170 break;
1171 case PF_INET:
1172 case PF_INET6:
1173 switch (type) {
1174 case SOCK_STREAM:
James Morris13402582005-09-30 14:24:34 -04001175 if (default_protocol_stream(protocol))
1176 return SECCLASS_TCP_SOCKET;
1177 else
1178 return SECCLASS_RAWIP_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001179 case SOCK_DGRAM:
James Morris13402582005-09-30 14:24:34 -04001180 if (default_protocol_dgram(protocol))
1181 return SECCLASS_UDP_SOCKET;
1182 else
1183 return SECCLASS_RAWIP_SOCKET;
James Morris2ee92d42006-11-13 16:09:01 -08001184 case SOCK_DCCP:
1185 return SECCLASS_DCCP_SOCKET;
James Morris13402582005-09-30 14:24:34 -04001186 default:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001187 return SECCLASS_RAWIP_SOCKET;
1188 }
1189 break;
1190 case PF_NETLINK:
1191 switch (protocol) {
1192 case NETLINK_ROUTE:
1193 return SECCLASS_NETLINK_ROUTE_SOCKET;
Pavel Emelyanov7f1fb602011-12-06 07:56:43 +00001194 case NETLINK_SOCK_DIAG:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001195 return SECCLASS_NETLINK_TCPDIAG_SOCKET;
1196 case NETLINK_NFLOG:
1197 return SECCLASS_NETLINK_NFLOG_SOCKET;
1198 case NETLINK_XFRM:
1199 return SECCLASS_NETLINK_XFRM_SOCKET;
1200 case NETLINK_SELINUX:
1201 return SECCLASS_NETLINK_SELINUX_SOCKET;
Stephen Smalley6c6d2e92015-06-04 16:22:16 -04001202 case NETLINK_ISCSI:
1203 return SECCLASS_NETLINK_ISCSI_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001204 case NETLINK_AUDIT:
1205 return SECCLASS_NETLINK_AUDIT_SOCKET;
Stephen Smalley6c6d2e92015-06-04 16:22:16 -04001206 case NETLINK_FIB_LOOKUP:
1207 return SECCLASS_NETLINK_FIB_LOOKUP_SOCKET;
1208 case NETLINK_CONNECTOR:
1209 return SECCLASS_NETLINK_CONNECTOR_SOCKET;
1210 case NETLINK_NETFILTER:
1211 return SECCLASS_NETLINK_NETFILTER_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001212 case NETLINK_DNRTMSG:
1213 return SECCLASS_NETLINK_DNRT_SOCKET;
James Morris0c9b7942005-04-16 15:24:13 -07001214 case NETLINK_KOBJECT_UEVENT:
1215 return SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET;
Stephen Smalley6c6d2e92015-06-04 16:22:16 -04001216 case NETLINK_GENERIC:
1217 return SECCLASS_NETLINK_GENERIC_SOCKET;
1218 case NETLINK_SCSITRANSPORT:
1219 return SECCLASS_NETLINK_SCSITRANSPORT_SOCKET;
1220 case NETLINK_RDMA:
1221 return SECCLASS_NETLINK_RDMA_SOCKET;
1222 case NETLINK_CRYPTO:
1223 return SECCLASS_NETLINK_CRYPTO_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001224 default:
1225 return SECCLASS_NETLINK_SOCKET;
1226 }
1227 case PF_PACKET:
1228 return SECCLASS_PACKET_SOCKET;
1229 case PF_KEY:
1230 return SECCLASS_KEY_SOCKET;
Christopher J. PeBenito3e3ff152006-06-09 00:25:03 -07001231 case PF_APPLETALK:
1232 return SECCLASS_APPLETALK_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001233 }
1234
1235 return SECCLASS_SOCKET;
1236}
1237
Stephen Smalley134509d2015-06-04 16:22:17 -04001238static int selinux_genfs_get_sid(struct dentry *dentry,
1239 u16 tclass,
1240 u16 flags,
1241 u32 *sid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001242{
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001243 int rc;
Stephen Smalley134509d2015-06-04 16:22:17 -04001244 struct super_block *sb = dentry->d_inode->i_sb;
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001245 char *buffer, *path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001246
Eric Paris828dfe12008-04-17 13:17:49 -04001247 buffer = (char *)__get_free_page(GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001248 if (!buffer)
1249 return -ENOMEM;
1250
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001251 path = dentry_path_raw(dentry, buffer, PAGE_SIZE);
1252 if (IS_ERR(path))
1253 rc = PTR_ERR(path);
1254 else {
Stephen Smalley134509d2015-06-04 16:22:17 -04001255 if (flags & SE_SBPROC) {
1256 /* each process gets a /proc/PID/ entry. Strip off the
1257 * PID part to get a valid selinux labeling.
1258 * e.g. /proc/1/net/rpc/nfs -> /net/rpc/nfs */
1259 while (path[1] >= '0' && path[1] <= '9') {
1260 path[1] = '/';
1261 path++;
1262 }
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001263 }
Stephen Smalley134509d2015-06-04 16:22:17 -04001264 rc = security_genfs_sid(sb->s_type->name, path, tclass, sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001265 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001266 free_page((unsigned long)buffer);
1267 return rc;
1268}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001269
1270/* The inode's security attributes must be initialized before first use. */
1271static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry)
1272{
1273 struct superblock_security_struct *sbsec = NULL;
1274 struct inode_security_struct *isec = inode->i_security;
1275 u32 sid;
1276 struct dentry *dentry;
1277#define INITCONTEXTLEN 255
1278 char *context = NULL;
1279 unsigned len = 0;
1280 int rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001281
1282 if (isec->initialized)
1283 goto out;
1284
Eric Paris23970742006-09-25 23:32:01 -07001285 mutex_lock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001286 if (isec->initialized)
Eric Paris23970742006-09-25 23:32:01 -07001287 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001288
1289 sbsec = inode->i_sb->s_security;
David P. Quigley0d90a7e2009-01-16 09:22:02 -05001290 if (!(sbsec->flags & SE_SBINITIALIZED)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001291 /* Defer initialization until selinux_complete_init,
1292 after the initial policy is loaded and the security
1293 server is ready to handle calls. */
1294 spin_lock(&sbsec->isec_lock);
1295 if (list_empty(&isec->list))
1296 list_add(&isec->list, &sbsec->isec_head);
1297 spin_unlock(&sbsec->isec_lock);
Eric Paris23970742006-09-25 23:32:01 -07001298 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001299 }
1300
1301 switch (sbsec->behavior) {
David Quigleyeb9ae682013-05-22 12:50:37 -04001302 case SECURITY_FS_USE_NATIVE:
1303 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001304 case SECURITY_FS_USE_XATTR:
1305 if (!inode->i_op->getxattr) {
1306 isec->sid = sbsec->def_sid;
1307 break;
1308 }
1309
1310 /* Need a dentry, since the xattr API requires one.
1311 Life would be simpler if we could just pass the inode. */
1312 if (opt_dentry) {
1313 /* Called from d_instantiate or d_splice_alias. */
1314 dentry = dget(opt_dentry);
1315 } else {
1316 /* Called from selinux_complete_init, try to find a dentry. */
1317 dentry = d_find_alias(inode);
1318 }
1319 if (!dentry) {
Eric Parisdf7f54c2009-03-09 14:35:58 -04001320 /*
1321 * this is can be hit on boot when a file is accessed
1322 * before the policy is loaded. When we load policy we
1323 * may find inodes that have no dentry on the
1324 * sbsec->isec_head list. No reason to complain as these
1325 * will get fixed up the next time we go through
1326 * inode_doinit with a dentry, before these inodes could
1327 * be used again by userspace.
1328 */
Eric Paris23970742006-09-25 23:32:01 -07001329 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001330 }
1331
1332 len = INITCONTEXTLEN;
Eric Paris4cb912f2009-02-12 14:50:05 -05001333 context = kmalloc(len+1, GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001334 if (!context) {
1335 rc = -ENOMEM;
1336 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001337 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001338 }
Eric Paris4cb912f2009-02-12 14:50:05 -05001339 context[len] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001340 rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX,
1341 context, len);
1342 if (rc == -ERANGE) {
James Morris314dabb2009-08-10 22:00:13 +10001343 kfree(context);
1344
Linus Torvalds1da177e2005-04-16 15:20:36 -07001345 /* Need a larger buffer. Query for the right size. */
1346 rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX,
1347 NULL, 0);
1348 if (rc < 0) {
1349 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001350 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001351 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001352 len = rc;
Eric Paris4cb912f2009-02-12 14:50:05 -05001353 context = kmalloc(len+1, GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001354 if (!context) {
1355 rc = -ENOMEM;
1356 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001357 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001358 }
Eric Paris4cb912f2009-02-12 14:50:05 -05001359 context[len] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001360 rc = inode->i_op->getxattr(dentry,
1361 XATTR_NAME_SELINUX,
1362 context, len);
1363 }
1364 dput(dentry);
1365 if (rc < 0) {
1366 if (rc != -ENODATA) {
Eric Paris744ba352008-04-17 11:52:44 -04001367 printk(KERN_WARNING "SELinux: %s: getxattr returned "
Harvey Harrisondd6f9532008-03-06 10:03:59 +11001368 "%d for dev=%s ino=%ld\n", __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001369 -rc, inode->i_sb->s_id, inode->i_ino);
1370 kfree(context);
Eric Paris23970742006-09-25 23:32:01 -07001371 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001372 }
1373 /* Map ENODATA to the default file SID */
1374 sid = sbsec->def_sid;
1375 rc = 0;
1376 } else {
James Morrisf5c1d5b2005-07-28 01:07:37 -07001377 rc = security_context_to_sid_default(context, rc, &sid,
Stephen Smalley869ab512008-04-04 08:46:05 -04001378 sbsec->def_sid,
1379 GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001380 if (rc) {
Eric Paris4ba0a8a2009-02-12 15:01:10 -05001381 char *dev = inode->i_sb->s_id;
1382 unsigned long ino = inode->i_ino;
1383
1384 if (rc == -EINVAL) {
1385 if (printk_ratelimit())
1386 printk(KERN_NOTICE "SELinux: inode=%lu on dev=%s was found to have an invalid "
1387 "context=%s. This indicates you may need to relabel the inode or the "
1388 "filesystem in question.\n", ino, dev, context);
1389 } else {
1390 printk(KERN_WARNING "SELinux: %s: context_to_sid(%s) "
1391 "returned %d for dev=%s ino=%ld\n",
1392 __func__, context, -rc, dev, ino);
1393 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001394 kfree(context);
1395 /* Leave with the unlabeled SID */
1396 rc = 0;
1397 break;
1398 }
1399 }
1400 kfree(context);
1401 isec->sid = sid;
1402 break;
1403 case SECURITY_FS_USE_TASK:
1404 isec->sid = isec->task_sid;
1405 break;
1406 case SECURITY_FS_USE_TRANS:
1407 /* Default to the fs SID. */
1408 isec->sid = sbsec->sid;
1409
1410 /* Try to obtain a transition SID. */
1411 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Eric Paris652bb9b2011-02-01 11:05:40 -05001412 rc = security_transition_sid(isec->task_sid, sbsec->sid,
1413 isec->sclass, NULL, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001414 if (rc)
Eric Paris23970742006-09-25 23:32:01 -07001415 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001416 isec->sid = sid;
1417 break;
Eric Parisc312feb2006-07-10 04:43:53 -07001418 case SECURITY_FS_USE_MNTPOINT:
1419 isec->sid = sbsec->mntpoint_sid;
1420 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001421 default:
Eric Parisc312feb2006-07-10 04:43:53 -07001422 /* Default to the fs superblock SID. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001423 isec->sid = sbsec->sid;
1424
Stephen Smalley134509d2015-06-04 16:22:17 -04001425 if ((sbsec->flags & SE_SBGENFS) && !S_ISLNK(inode->i_mode)) {
Paul Mooref64410e2014-03-19 16:46:18 -04001426 /* We must have a dentry to determine the label on
1427 * procfs inodes */
1428 if (opt_dentry)
1429 /* Called from d_instantiate or
1430 * d_splice_alias. */
1431 dentry = dget(opt_dentry);
1432 else
1433 /* Called from selinux_complete_init, try to
1434 * find a dentry. */
1435 dentry = d_find_alias(inode);
1436 /*
1437 * This can be hit on boot when a file is accessed
1438 * before the policy is loaded. When we load policy we
1439 * may find inodes that have no dentry on the
1440 * sbsec->isec_head list. No reason to complain as
1441 * these will get fixed up the next time we go through
1442 * inode_doinit() with a dentry, before these inodes
1443 * could be used again by userspace.
1444 */
1445 if (!dentry)
1446 goto out_unlock;
1447 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Stephen Smalley134509d2015-06-04 16:22:17 -04001448 rc = selinux_genfs_get_sid(dentry, isec->sclass,
1449 sbsec->flags, &sid);
Paul Mooref64410e2014-03-19 16:46:18 -04001450 dput(dentry);
1451 if (rc)
1452 goto out_unlock;
1453 isec->sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001454 }
1455 break;
1456 }
1457
1458 isec->initialized = 1;
1459
Eric Paris23970742006-09-25 23:32:01 -07001460out_unlock:
1461 mutex_unlock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001462out:
1463 if (isec->sclass == SECCLASS_FILE)
1464 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001465 return rc;
1466}
1467
1468/* Convert a Linux signal to an access vector. */
1469static inline u32 signal_to_av(int sig)
1470{
1471 u32 perm = 0;
1472
1473 switch (sig) {
1474 case SIGCHLD:
1475 /* Commonly granted from child to parent. */
1476 perm = PROCESS__SIGCHLD;
1477 break;
1478 case SIGKILL:
1479 /* Cannot be caught or ignored */
1480 perm = PROCESS__SIGKILL;
1481 break;
1482 case SIGSTOP:
1483 /* Cannot be caught or ignored */
1484 perm = PROCESS__SIGSTOP;
1485 break;
1486 default:
1487 /* All other signals. */
1488 perm = PROCESS__SIGNAL;
1489 break;
1490 }
1491
1492 return perm;
1493}
1494
David Howells275bb412008-11-14 10:39:19 +11001495/*
David Howellsd84f4f92008-11-14 10:39:23 +11001496 * Check permission between a pair of credentials
1497 * fork check, ptrace check, etc.
1498 */
1499static int cred_has_perm(const struct cred *actor,
1500 const struct cred *target,
1501 u32 perms)
1502{
1503 u32 asid = cred_sid(actor), tsid = cred_sid(target);
1504
1505 return avc_has_perm(asid, tsid, SECCLASS_PROCESS, perms, NULL);
1506}
1507
1508/*
David Howells88e67f32008-11-14 10:39:21 +11001509 * Check permission between a pair of tasks, e.g. signal checks,
David Howells275bb412008-11-14 10:39:19 +11001510 * fork check, ptrace check, etc.
1511 * tsk1 is the actor and tsk2 is the target
David Howells3b11a1d2008-11-14 10:39:26 +11001512 * - this uses the default subjective creds of tsk1
David Howells275bb412008-11-14 10:39:19 +11001513 */
1514static int task_has_perm(const struct task_struct *tsk1,
1515 const struct task_struct *tsk2,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001516 u32 perms)
1517{
David Howells275bb412008-11-14 10:39:19 +11001518 const struct task_security_struct *__tsec1, *__tsec2;
1519 u32 sid1, sid2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001520
David Howells275bb412008-11-14 10:39:19 +11001521 rcu_read_lock();
1522 __tsec1 = __task_cred(tsk1)->security; sid1 = __tsec1->sid;
1523 __tsec2 = __task_cred(tsk2)->security; sid2 = __tsec2->sid;
1524 rcu_read_unlock();
1525 return avc_has_perm(sid1, sid2, SECCLASS_PROCESS, perms, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001526}
1527
David Howells3b11a1d2008-11-14 10:39:26 +11001528/*
1529 * Check permission between current and another task, e.g. signal checks,
1530 * fork check, ptrace check, etc.
1531 * current is the actor and tsk2 is the target
1532 * - this uses current's subjective creds
1533 */
1534static int current_has_perm(const struct task_struct *tsk,
1535 u32 perms)
1536{
1537 u32 sid, tsid;
1538
1539 sid = current_sid();
1540 tsid = task_sid(tsk);
1541 return avc_has_perm(sid, tsid, SECCLASS_PROCESS, perms, NULL);
1542}
1543
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001544#if CAP_LAST_CAP > 63
1545#error Fix SELinux to handle capabilities > 63.
1546#endif
1547
Linus Torvalds1da177e2005-04-16 15:20:36 -07001548/* Check whether a task is allowed to use a capability. */
Eric Paris6a9de492012-01-03 12:25:14 -05001549static int cred_has_capability(const struct cred *cred,
Eric Paris06112162008-11-11 22:02:50 +11001550 int cap, int audit)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001551{
Thomas Liu2bf49692009-07-14 12:14:09 -04001552 struct common_audit_data ad;
Eric Paris06112162008-11-11 22:02:50 +11001553 struct av_decision avd;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001554 u16 sclass;
David Howells3699c532009-01-06 22:27:01 +00001555 u32 sid = cred_sid(cred);
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001556 u32 av = CAP_TO_MASK(cap);
Eric Paris06112162008-11-11 22:02:50 +11001557 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001558
Eric Paris50c205f2012-04-04 15:01:43 -04001559 ad.type = LSM_AUDIT_DATA_CAP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001560 ad.u.cap = cap;
1561
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001562 switch (CAP_TO_INDEX(cap)) {
1563 case 0:
1564 sclass = SECCLASS_CAPABILITY;
1565 break;
1566 case 1:
1567 sclass = SECCLASS_CAPABILITY2;
1568 break;
1569 default:
1570 printk(KERN_ERR
1571 "SELinux: out of range capability %d\n", cap);
1572 BUG();
Eric Parisa35c6c832011-04-20 10:21:28 -04001573 return -EINVAL;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001574 }
Eric Paris06112162008-11-11 22:02:50 +11001575
David Howells275bb412008-11-14 10:39:19 +11001576 rc = avc_has_perm_noaudit(sid, sid, sclass, av, 0, &avd);
Eric Paris9ade0cf2011-04-25 16:26:29 -04001577 if (audit == SECURITY_CAP_AUDIT) {
Linus Torvaldsab354062013-10-04 14:05:38 -07001578 int rc2 = avc_audit(sid, sid, sclass, av, &avd, rc, &ad);
Eric Paris9ade0cf2011-04-25 16:26:29 -04001579 if (rc2)
1580 return rc2;
1581 }
Eric Paris06112162008-11-11 22:02:50 +11001582 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001583}
1584
1585/* Check whether a task is allowed to use a system operation. */
1586static int task_has_system(struct task_struct *tsk,
1587 u32 perms)
1588{
David Howells275bb412008-11-14 10:39:19 +11001589 u32 sid = task_sid(tsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001590
David Howells275bb412008-11-14 10:39:19 +11001591 return avc_has_perm(sid, SECINITSID_KERNEL,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001592 SECCLASS_SYSTEM, perms, NULL);
1593}
1594
1595/* Check whether a task has a particular permission to an inode.
1596 The 'adp' parameter is optional and allows other audit
1597 data to be passed (e.g. the dentry). */
David Howells88e67f32008-11-14 10:39:21 +11001598static int inode_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001599 struct inode *inode,
1600 u32 perms,
Linus Torvalds19e49832013-10-04 12:54:11 -07001601 struct common_audit_data *adp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001602{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001603 struct inode_security_struct *isec;
David Howells275bb412008-11-14 10:39:19 +11001604 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001605
David Howellse0e81732009-09-02 09:13:40 +01001606 validate_creds(cred);
1607
Eric Paris828dfe12008-04-17 13:17:49 -04001608 if (unlikely(IS_PRIVATE(inode)))
Stephen Smalleybbaca6c2007-02-14 00:34:16 -08001609 return 0;
1610
David Howells88e67f32008-11-14 10:39:21 +11001611 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001612 isec = inode->i_security;
1613
Linus Torvalds19e49832013-10-04 12:54:11 -07001614 return avc_has_perm(sid, isec->sid, isec->sclass, perms, adp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001615}
1616
1617/* Same as inode_has_perm, but pass explicit audit data containing
1618 the dentry to help the auditing code to more easily generate the
1619 pathname if needed. */
David Howells88e67f32008-11-14 10:39:21 +11001620static inline int dentry_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001621 struct dentry *dentry,
1622 u32 av)
1623{
David Howellsc6f493d2015-03-17 22:26:22 +00001624 struct inode *inode = d_backing_inode(dentry);
Thomas Liu2bf49692009-07-14 12:14:09 -04001625 struct common_audit_data ad;
David Howells88e67f32008-11-14 10:39:21 +11001626
Eric Paris50c205f2012-04-04 15:01:43 -04001627 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Paris2875fa02011-04-28 16:04:24 -04001628 ad.u.dentry = dentry;
Linus Torvalds19e49832013-10-04 12:54:11 -07001629 return inode_has_perm(cred, inode, av, &ad);
Eric Paris2875fa02011-04-28 16:04:24 -04001630}
1631
1632/* Same as inode_has_perm, but pass explicit audit data containing
1633 the path to help the auditing code to more easily generate the
1634 pathname if needed. */
1635static inline int path_has_perm(const struct cred *cred,
Al Viro3f7036a2015-03-08 19:28:30 -04001636 const struct path *path,
Eric Paris2875fa02011-04-28 16:04:24 -04001637 u32 av)
1638{
David Howellsc6f493d2015-03-17 22:26:22 +00001639 struct inode *inode = d_backing_inode(path->dentry);
Eric Paris2875fa02011-04-28 16:04:24 -04001640 struct common_audit_data ad;
1641
Eric Paris50c205f2012-04-04 15:01:43 -04001642 ad.type = LSM_AUDIT_DATA_PATH;
Eric Paris2875fa02011-04-28 16:04:24 -04001643 ad.u.path = *path;
Linus Torvalds19e49832013-10-04 12:54:11 -07001644 return inode_has_perm(cred, inode, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001645}
1646
David Howells13f8e982013-06-13 23:37:55 +01001647/* Same as path_has_perm, but uses the inode from the file struct. */
1648static inline int file_path_has_perm(const struct cred *cred,
1649 struct file *file,
1650 u32 av)
1651{
1652 struct common_audit_data ad;
1653
1654 ad.type = LSM_AUDIT_DATA_PATH;
1655 ad.u.path = file->f_path;
Linus Torvalds19e49832013-10-04 12:54:11 -07001656 return inode_has_perm(cred, file_inode(file), av, &ad);
David Howells13f8e982013-06-13 23:37:55 +01001657}
1658
Linus Torvalds1da177e2005-04-16 15:20:36 -07001659/* Check whether a task can use an open file descriptor to
1660 access an inode in a given way. Check access to the
1661 descriptor itself, and then use dentry_has_perm to
1662 check a particular permission to the file.
1663 Access to the descriptor is implicitly granted if it
1664 has the same SID as the process. If av is zero, then
1665 access to the file is not checked, e.g. for cases
1666 where only the descriptor is affected like seek. */
David Howells88e67f32008-11-14 10:39:21 +11001667static int file_has_perm(const struct cred *cred,
1668 struct file *file,
1669 u32 av)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001670{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001671 struct file_security_struct *fsec = file->f_security;
Al Viro496ad9a2013-01-23 17:07:38 -05001672 struct inode *inode = file_inode(file);
Thomas Liu2bf49692009-07-14 12:14:09 -04001673 struct common_audit_data ad;
David Howells88e67f32008-11-14 10:39:21 +11001674 u32 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001675 int rc;
1676
Eric Paris50c205f2012-04-04 15:01:43 -04001677 ad.type = LSM_AUDIT_DATA_PATH;
Eric Parisf48b7392011-04-25 12:54:27 -04001678 ad.u.path = file->f_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001679
David Howells275bb412008-11-14 10:39:19 +11001680 if (sid != fsec->sid) {
1681 rc = avc_has_perm(sid, fsec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001682 SECCLASS_FD,
1683 FD__USE,
1684 &ad);
1685 if (rc)
David Howells88e67f32008-11-14 10:39:21 +11001686 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001687 }
1688
1689 /* av is zero if only checking access to the descriptor. */
David Howells88e67f32008-11-14 10:39:21 +11001690 rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001691 if (av)
Linus Torvalds19e49832013-10-04 12:54:11 -07001692 rc = inode_has_perm(cred, inode, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001693
David Howells88e67f32008-11-14 10:39:21 +11001694out:
1695 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001696}
1697
1698/* Check whether a task can create a file. */
1699static int may_create(struct inode *dir,
1700 struct dentry *dentry,
1701 u16 tclass)
1702{
Paul Moore5fb49872010-04-22 14:46:19 -04001703 const struct task_security_struct *tsec = current_security();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001704 struct inode_security_struct *dsec;
1705 struct superblock_security_struct *sbsec;
David Howells275bb412008-11-14 10:39:19 +11001706 u32 sid, newsid;
Thomas Liu2bf49692009-07-14 12:14:09 -04001707 struct common_audit_data ad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001708 int rc;
1709
Linus Torvalds1da177e2005-04-16 15:20:36 -07001710 dsec = dir->i_security;
1711 sbsec = dir->i_sb->s_security;
1712
David Howells275bb412008-11-14 10:39:19 +11001713 sid = tsec->sid;
1714 newsid = tsec->create_sid;
1715
Eric Paris50c205f2012-04-04 15:01:43 -04001716 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04001717 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001718
David Howells275bb412008-11-14 10:39:19 +11001719 rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001720 DIR__ADD_NAME | DIR__SEARCH,
1721 &ad);
1722 if (rc)
1723 return rc;
1724
Eric Paris12f348b2012-10-09 10:56:25 -04001725 if (!newsid || !(sbsec->flags & SBLABEL_MNT)) {
Eric Pariscb1e9222011-04-28 15:11:21 -04001726 rc = security_transition_sid(sid, dsec->sid, tclass,
1727 &dentry->d_name, &newsid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001728 if (rc)
1729 return rc;
1730 }
1731
David Howells275bb412008-11-14 10:39:19 +11001732 rc = avc_has_perm(sid, newsid, tclass, FILE__CREATE, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001733 if (rc)
1734 return rc;
1735
1736 return avc_has_perm(newsid, sbsec->sid,
1737 SECCLASS_FILESYSTEM,
1738 FILESYSTEM__ASSOCIATE, &ad);
1739}
1740
Michael LeMay4eb582c2006-06-26 00:24:57 -07001741/* Check whether a task can create a key. */
1742static int may_create_key(u32 ksid,
1743 struct task_struct *ctx)
1744{
David Howells275bb412008-11-14 10:39:19 +11001745 u32 sid = task_sid(ctx);
Michael LeMay4eb582c2006-06-26 00:24:57 -07001746
David Howells275bb412008-11-14 10:39:19 +11001747 return avc_has_perm(sid, ksid, SECCLASS_KEY, KEY__CREATE, NULL);
Michael LeMay4eb582c2006-06-26 00:24:57 -07001748}
1749
Eric Paris828dfe12008-04-17 13:17:49 -04001750#define MAY_LINK 0
1751#define MAY_UNLINK 1
1752#define MAY_RMDIR 2
Linus Torvalds1da177e2005-04-16 15:20:36 -07001753
1754/* Check whether a task can link, unlink, or rmdir a file/directory. */
1755static int may_link(struct inode *dir,
1756 struct dentry *dentry,
1757 int kind)
1758
1759{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001760 struct inode_security_struct *dsec, *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04001761 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11001762 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001763 u32 av;
1764 int rc;
1765
Linus Torvalds1da177e2005-04-16 15:20:36 -07001766 dsec = dir->i_security;
David Howellsc6f493d2015-03-17 22:26:22 +00001767 isec = d_backing_inode(dentry)->i_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001768
Eric Paris50c205f2012-04-04 15:01:43 -04001769 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04001770 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001771
1772 av = DIR__SEARCH;
1773 av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME);
David Howells275bb412008-11-14 10:39:19 +11001774 rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001775 if (rc)
1776 return rc;
1777
1778 switch (kind) {
1779 case MAY_LINK:
1780 av = FILE__LINK;
1781 break;
1782 case MAY_UNLINK:
1783 av = FILE__UNLINK;
1784 break;
1785 case MAY_RMDIR:
1786 av = DIR__RMDIR;
1787 break;
1788 default:
Eric Paris744ba352008-04-17 11:52:44 -04001789 printk(KERN_WARNING "SELinux: %s: unrecognized kind %d\n",
1790 __func__, kind);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001791 return 0;
1792 }
1793
David Howells275bb412008-11-14 10:39:19 +11001794 rc = avc_has_perm(sid, isec->sid, isec->sclass, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001795 return rc;
1796}
1797
1798static inline int may_rename(struct inode *old_dir,
1799 struct dentry *old_dentry,
1800 struct inode *new_dir,
1801 struct dentry *new_dentry)
1802{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001803 struct inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04001804 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11001805 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001806 u32 av;
1807 int old_is_dir, new_is_dir;
1808 int rc;
1809
Linus Torvalds1da177e2005-04-16 15:20:36 -07001810 old_dsec = old_dir->i_security;
David Howellsc6f493d2015-03-17 22:26:22 +00001811 old_isec = d_backing_inode(old_dentry)->i_security;
David Howellse36cb0b2015-01-29 12:02:35 +00001812 old_is_dir = d_is_dir(old_dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001813 new_dsec = new_dir->i_security;
1814
Eric Paris50c205f2012-04-04 15:01:43 -04001815 ad.type = LSM_AUDIT_DATA_DENTRY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001816
Eric Parisa2694342011-04-25 13:10:27 -04001817 ad.u.dentry = old_dentry;
David Howells275bb412008-11-14 10:39:19 +11001818 rc = avc_has_perm(sid, old_dsec->sid, SECCLASS_DIR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001819 DIR__REMOVE_NAME | DIR__SEARCH, &ad);
1820 if (rc)
1821 return rc;
David Howells275bb412008-11-14 10:39:19 +11001822 rc = avc_has_perm(sid, old_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001823 old_isec->sclass, FILE__RENAME, &ad);
1824 if (rc)
1825 return rc;
1826 if (old_is_dir && new_dir != old_dir) {
David Howells275bb412008-11-14 10:39:19 +11001827 rc = avc_has_perm(sid, old_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001828 old_isec->sclass, DIR__REPARENT, &ad);
1829 if (rc)
1830 return rc;
1831 }
1832
Eric Parisa2694342011-04-25 13:10:27 -04001833 ad.u.dentry = new_dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001834 av = DIR__ADD_NAME | DIR__SEARCH;
David Howells2c616d42015-01-29 12:02:33 +00001835 if (d_is_positive(new_dentry))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001836 av |= DIR__REMOVE_NAME;
David Howells275bb412008-11-14 10:39:19 +11001837 rc = avc_has_perm(sid, new_dsec->sid, SECCLASS_DIR, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001838 if (rc)
1839 return rc;
David Howells2c616d42015-01-29 12:02:33 +00001840 if (d_is_positive(new_dentry)) {
David Howellsc6f493d2015-03-17 22:26:22 +00001841 new_isec = d_backing_inode(new_dentry)->i_security;
David Howellse36cb0b2015-01-29 12:02:35 +00001842 new_is_dir = d_is_dir(new_dentry);
David Howells275bb412008-11-14 10:39:19 +11001843 rc = avc_has_perm(sid, new_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001844 new_isec->sclass,
1845 (new_is_dir ? DIR__RMDIR : FILE__UNLINK), &ad);
1846 if (rc)
1847 return rc;
1848 }
1849
1850 return 0;
1851}
1852
1853/* Check whether a task can perform a filesystem operation. */
David Howells88e67f32008-11-14 10:39:21 +11001854static int superblock_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001855 struct super_block *sb,
1856 u32 perms,
Thomas Liu2bf49692009-07-14 12:14:09 -04001857 struct common_audit_data *ad)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001858{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001859 struct superblock_security_struct *sbsec;
David Howells88e67f32008-11-14 10:39:21 +11001860 u32 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001861
Linus Torvalds1da177e2005-04-16 15:20:36 -07001862 sbsec = sb->s_security;
David Howells275bb412008-11-14 10:39:19 +11001863 return avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM, perms, ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001864}
1865
1866/* Convert a Linux mode and permission mask to an access vector. */
1867static inline u32 file_mask_to_av(int mode, int mask)
1868{
1869 u32 av = 0;
1870
Al Virodba19c62011-07-25 20:49:29 -04001871 if (!S_ISDIR(mode)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001872 if (mask & MAY_EXEC)
1873 av |= FILE__EXECUTE;
1874 if (mask & MAY_READ)
1875 av |= FILE__READ;
1876
1877 if (mask & MAY_APPEND)
1878 av |= FILE__APPEND;
1879 else if (mask & MAY_WRITE)
1880 av |= FILE__WRITE;
1881
1882 } else {
1883 if (mask & MAY_EXEC)
1884 av |= DIR__SEARCH;
1885 if (mask & MAY_WRITE)
1886 av |= DIR__WRITE;
1887 if (mask & MAY_READ)
1888 av |= DIR__READ;
1889 }
1890
1891 return av;
1892}
1893
1894/* Convert a Linux file to an access vector. */
1895static inline u32 file_to_av(struct file *file)
1896{
1897 u32 av = 0;
1898
1899 if (file->f_mode & FMODE_READ)
1900 av |= FILE__READ;
1901 if (file->f_mode & FMODE_WRITE) {
1902 if (file->f_flags & O_APPEND)
1903 av |= FILE__APPEND;
1904 else
1905 av |= FILE__WRITE;
1906 }
Stephen Smalley0794c662008-03-17 08:55:18 -04001907 if (!av) {
1908 /*
1909 * Special file opened with flags 3 for ioctl-only use.
1910 */
1911 av = FILE__IOCTL;
1912 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001913
1914 return av;
1915}
1916
Eric Paris8b6a5a32008-10-29 17:06:46 -04001917/*
1918 * Convert a file to an access vector and include the correct open
1919 * open permission.
1920 */
1921static inline u32 open_file_to_av(struct file *file)
1922{
1923 u32 av = file_to_av(file);
1924
Eric Paris49b7b8d2010-07-23 11:44:09 -04001925 if (selinux_policycap_openperm)
1926 av |= FILE__OPEN;
1927
Eric Paris8b6a5a32008-10-29 17:06:46 -04001928 return av;
1929}
1930
Linus Torvalds1da177e2005-04-16 15:20:36 -07001931/* Hook functions begin here. */
1932
Stephen Smalley79af7302015-01-21 10:54:10 -05001933static int selinux_binder_set_context_mgr(struct task_struct *mgr)
1934{
1935 u32 mysid = current_sid();
1936 u32 mgrsid = task_sid(mgr);
1937
1938 return avc_has_perm(mysid, mgrsid, SECCLASS_BINDER,
1939 BINDER__SET_CONTEXT_MGR, NULL);
1940}
1941
1942static int selinux_binder_transaction(struct task_struct *from,
1943 struct task_struct *to)
1944{
1945 u32 mysid = current_sid();
1946 u32 fromsid = task_sid(from);
1947 u32 tosid = task_sid(to);
1948 int rc;
1949
1950 if (mysid != fromsid) {
1951 rc = avc_has_perm(mysid, fromsid, SECCLASS_BINDER,
1952 BINDER__IMPERSONATE, NULL);
1953 if (rc)
1954 return rc;
1955 }
1956
1957 return avc_has_perm(fromsid, tosid, SECCLASS_BINDER, BINDER__CALL,
1958 NULL);
1959}
1960
1961static int selinux_binder_transfer_binder(struct task_struct *from,
1962 struct task_struct *to)
1963{
1964 u32 fromsid = task_sid(from);
1965 u32 tosid = task_sid(to);
1966
1967 return avc_has_perm(fromsid, tosid, SECCLASS_BINDER, BINDER__TRANSFER,
1968 NULL);
1969}
1970
1971static int selinux_binder_transfer_file(struct task_struct *from,
1972 struct task_struct *to,
1973 struct file *file)
1974{
1975 u32 sid = task_sid(to);
1976 struct file_security_struct *fsec = file->f_security;
David Howellsc6f493d2015-03-17 22:26:22 +00001977 struct inode *inode = d_backing_inode(file->f_path.dentry);
Stephen Smalley79af7302015-01-21 10:54:10 -05001978 struct inode_security_struct *isec = inode->i_security;
1979 struct common_audit_data ad;
1980 int rc;
1981
1982 ad.type = LSM_AUDIT_DATA_PATH;
1983 ad.u.path = file->f_path;
1984
1985 if (sid != fsec->sid) {
1986 rc = avc_has_perm(sid, fsec->sid,
1987 SECCLASS_FD,
1988 FD__USE,
1989 &ad);
1990 if (rc)
1991 return rc;
1992 }
1993
1994 if (unlikely(IS_PRIVATE(inode)))
1995 return 0;
1996
1997 return avc_has_perm(sid, isec->sid, isec->sclass, file_to_av(file),
1998 &ad);
1999}
2000
Ingo Molnar9e488582009-05-07 19:26:19 +10002001static int selinux_ptrace_access_check(struct task_struct *child,
David Howells5cd9c582008-08-14 11:37:28 +01002002 unsigned int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002003{
Eric Paris69f594a2012-01-03 12:25:15 -05002004 if (mode & PTRACE_MODE_READ) {
David Howells275bb412008-11-14 10:39:19 +11002005 u32 sid = current_sid();
2006 u32 csid = task_sid(child);
2007 return avc_has_perm(sid, csid, SECCLASS_FILE, FILE__READ, NULL);
Stephen Smalley006ebb42008-05-19 08:32:49 -04002008 }
2009
David Howells3b11a1d2008-11-14 10:39:26 +11002010 return current_has_perm(child, PROCESS__PTRACE);
David Howells5cd9c582008-08-14 11:37:28 +01002011}
2012
2013static int selinux_ptrace_traceme(struct task_struct *parent)
2014{
David Howells5cd9c582008-08-14 11:37:28 +01002015 return task_has_perm(parent, current, PROCESS__PTRACE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002016}
2017
2018static int selinux_capget(struct task_struct *target, kernel_cap_t *effective,
Eric Paris828dfe12008-04-17 13:17:49 -04002019 kernel_cap_t *inheritable, kernel_cap_t *permitted)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002020{
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07002021 return current_has_perm(target, PROCESS__GETCAP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002022}
2023
David Howellsd84f4f92008-11-14 10:39:23 +11002024static int selinux_capset(struct cred *new, const struct cred *old,
2025 const kernel_cap_t *effective,
2026 const kernel_cap_t *inheritable,
2027 const kernel_cap_t *permitted)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002028{
David Howellsd84f4f92008-11-14 10:39:23 +11002029 return cred_has_perm(old, new, PROCESS__SETCAP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002030}
2031
James Morris5626d3e2009-01-30 10:05:06 +11002032/*
2033 * (This comment used to live with the selinux_task_setuid hook,
2034 * which was removed).
2035 *
2036 * Since setuid only affects the current process, and since the SELinux
2037 * controls are not based on the Linux identity attributes, SELinux does not
2038 * need to control this operation. However, SELinux does control the use of
2039 * the CAP_SETUID and CAP_SETGID capabilities using the capable hook.
2040 */
2041
Eric Paris6a9de492012-01-03 12:25:14 -05002042static int selinux_capable(const struct cred *cred, struct user_namespace *ns,
2043 int cap, int audit)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002044{
Eric Paris6a9de492012-01-03 12:25:14 -05002045 return cred_has_capability(cred, cap, audit);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002046}
2047
Linus Torvalds1da177e2005-04-16 15:20:36 -07002048static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb)
2049{
David Howells88e67f32008-11-14 10:39:21 +11002050 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002051 int rc = 0;
2052
2053 if (!sb)
2054 return 0;
2055
2056 switch (cmds) {
Eric Paris828dfe12008-04-17 13:17:49 -04002057 case Q_SYNC:
2058 case Q_QUOTAON:
2059 case Q_QUOTAOFF:
2060 case Q_SETINFO:
2061 case Q_SETQUOTA:
David Howells88e67f32008-11-14 10:39:21 +11002062 rc = superblock_has_perm(cred, sb, FILESYSTEM__QUOTAMOD, NULL);
Eric Paris828dfe12008-04-17 13:17:49 -04002063 break;
2064 case Q_GETFMT:
2065 case Q_GETINFO:
2066 case Q_GETQUOTA:
David Howells88e67f32008-11-14 10:39:21 +11002067 rc = superblock_has_perm(cred, sb, FILESYSTEM__QUOTAGET, NULL);
Eric Paris828dfe12008-04-17 13:17:49 -04002068 break;
2069 default:
2070 rc = 0; /* let the kernel handle invalid cmds */
2071 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002072 }
2073 return rc;
2074}
2075
2076static int selinux_quota_on(struct dentry *dentry)
2077{
David Howells88e67f32008-11-14 10:39:21 +11002078 const struct cred *cred = current_cred();
2079
Eric Paris2875fa02011-04-28 16:04:24 -04002080 return dentry_has_perm(cred, dentry, FILE__QUOTAON);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002081}
2082
Eric Paris12b30522010-11-15 18:36:29 -05002083static int selinux_syslog(int type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002084{
2085 int rc;
2086
Linus Torvalds1da177e2005-04-16 15:20:36 -07002087 switch (type) {
Kees Cookd78ca3c2010-02-03 15:37:13 -08002088 case SYSLOG_ACTION_READ_ALL: /* Read last kernel messages */
2089 case SYSLOG_ACTION_SIZE_BUFFER: /* Return size of the log buffer */
Eric Paris828dfe12008-04-17 13:17:49 -04002090 rc = task_has_system(current, SYSTEM__SYSLOG_READ);
2091 break;
Kees Cookd78ca3c2010-02-03 15:37:13 -08002092 case SYSLOG_ACTION_CONSOLE_OFF: /* Disable logging to console */
2093 case SYSLOG_ACTION_CONSOLE_ON: /* Enable logging to console */
2094 /* Set level of messages printed to console */
2095 case SYSLOG_ACTION_CONSOLE_LEVEL:
Eric Paris828dfe12008-04-17 13:17:49 -04002096 rc = task_has_system(current, SYSTEM__SYSLOG_CONSOLE);
2097 break;
Kees Cookd78ca3c2010-02-03 15:37:13 -08002098 case SYSLOG_ACTION_CLOSE: /* Close log */
2099 case SYSLOG_ACTION_OPEN: /* Open log */
2100 case SYSLOG_ACTION_READ: /* Read from log */
2101 case SYSLOG_ACTION_READ_CLEAR: /* Read/clear last kernel messages */
2102 case SYSLOG_ACTION_CLEAR: /* Clear ring buffer */
Eric Paris828dfe12008-04-17 13:17:49 -04002103 default:
2104 rc = task_has_system(current, SYSTEM__SYSLOG_MOD);
2105 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002106 }
2107 return rc;
2108}
2109
2110/*
2111 * Check that a process has enough memory to allocate a new virtual
2112 * mapping. 0 means there is enough memory for the allocation to
2113 * succeed and -ENOMEM implies there is not.
2114 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07002115 * Do not audit the selinux permission check, as this is applied to all
2116 * processes that allocate mappings.
2117 */
Alan Cox34b4e4a2007-08-22 14:01:28 -07002118static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002119{
2120 int rc, cap_sys_admin = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002121
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07002122 rc = cred_has_capability(current_cred(), CAP_SYS_ADMIN,
2123 SECURITY_CAP_NOAUDIT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002124 if (rc == 0)
2125 cap_sys_admin = 1;
2126
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07002127 return cap_sys_admin;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002128}
2129
2130/* binprm security operations */
2131
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002132static int check_nnp_nosuid(const struct linux_binprm *bprm,
2133 const struct task_security_struct *old_tsec,
2134 const struct task_security_struct *new_tsec)
2135{
2136 int nnp = (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS);
2137 int nosuid = (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID);
2138 int rc;
2139
2140 if (!nnp && !nosuid)
2141 return 0; /* neither NNP nor nosuid */
2142
2143 if (new_tsec->sid == old_tsec->sid)
2144 return 0; /* No change in credentials */
2145
2146 /*
2147 * The only transitions we permit under NNP or nosuid
2148 * are transitions to bounded SIDs, i.e. SIDs that are
2149 * guaranteed to only be allowed a subset of the permissions
2150 * of the current SID.
2151 */
2152 rc = security_bounded_transition(old_tsec->sid, new_tsec->sid);
2153 if (rc) {
2154 /*
2155 * On failure, preserve the errno values for NNP vs nosuid.
2156 * NNP: Operation not permitted for caller.
2157 * nosuid: Permission denied to file.
2158 */
2159 if (nnp)
2160 return -EPERM;
2161 else
2162 return -EACCES;
2163 }
2164 return 0;
2165}
2166
David Howellsa6f76f22008-11-14 10:39:24 +11002167static int selinux_bprm_set_creds(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002168{
David Howellsa6f76f22008-11-14 10:39:24 +11002169 const struct task_security_struct *old_tsec;
2170 struct task_security_struct *new_tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002171 struct inode_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04002172 struct common_audit_data ad;
Al Viro496ad9a2013-01-23 17:07:38 -05002173 struct inode *inode = file_inode(bprm->file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002174 int rc;
2175
David Howellsa6f76f22008-11-14 10:39:24 +11002176 /* SELinux context only depends on initial program or script and not
2177 * the script interpreter */
2178 if (bprm->cred_prepared)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002179 return 0;
2180
David Howellsa6f76f22008-11-14 10:39:24 +11002181 old_tsec = current_security();
2182 new_tsec = bprm->cred->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002183 isec = inode->i_security;
2184
2185 /* Default to the current task SID. */
David Howellsa6f76f22008-11-14 10:39:24 +11002186 new_tsec->sid = old_tsec->sid;
2187 new_tsec->osid = old_tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002188
Michael LeMay28eba5b2006-06-27 02:53:42 -07002189 /* Reset fs, key, and sock SIDs on execve. */
David Howellsa6f76f22008-11-14 10:39:24 +11002190 new_tsec->create_sid = 0;
2191 new_tsec->keycreate_sid = 0;
2192 new_tsec->sockcreate_sid = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002193
David Howellsa6f76f22008-11-14 10:39:24 +11002194 if (old_tsec->exec_sid) {
2195 new_tsec->sid = old_tsec->exec_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002196 /* Reset exec SID on execve. */
David Howellsa6f76f22008-11-14 10:39:24 +11002197 new_tsec->exec_sid = 0;
Andy Lutomirski259e5e62012-04-12 16:47:50 -05002198
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002199 /* Fail on NNP or nosuid if not an allowed transition. */
2200 rc = check_nnp_nosuid(bprm, old_tsec, new_tsec);
2201 if (rc)
2202 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002203 } else {
2204 /* Check for a default transition on this program. */
David Howellsa6f76f22008-11-14 10:39:24 +11002205 rc = security_transition_sid(old_tsec->sid, isec->sid,
Eric Paris652bb9b2011-02-01 11:05:40 -05002206 SECCLASS_PROCESS, NULL,
2207 &new_tsec->sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002208 if (rc)
2209 return rc;
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002210
2211 /*
2212 * Fallback to old SID on NNP or nosuid if not an allowed
2213 * transition.
2214 */
2215 rc = check_nnp_nosuid(bprm, old_tsec, new_tsec);
2216 if (rc)
2217 new_tsec->sid = old_tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002218 }
2219
Eric Paris50c205f2012-04-04 15:01:43 -04002220 ad.type = LSM_AUDIT_DATA_PATH;
Eric Parisf48b7392011-04-25 12:54:27 -04002221 ad.u.path = bprm->file->f_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002222
David Howellsa6f76f22008-11-14 10:39:24 +11002223 if (new_tsec->sid == old_tsec->sid) {
2224 rc = avc_has_perm(old_tsec->sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002225 SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, &ad);
2226 if (rc)
2227 return rc;
2228 } else {
2229 /* Check permissions for the transition. */
David Howellsa6f76f22008-11-14 10:39:24 +11002230 rc = avc_has_perm(old_tsec->sid, new_tsec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002231 SECCLASS_PROCESS, PROCESS__TRANSITION, &ad);
2232 if (rc)
2233 return rc;
2234
David Howellsa6f76f22008-11-14 10:39:24 +11002235 rc = avc_has_perm(new_tsec->sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002236 SECCLASS_FILE, FILE__ENTRYPOINT, &ad);
2237 if (rc)
2238 return rc;
2239
David Howellsa6f76f22008-11-14 10:39:24 +11002240 /* Check for shared state */
2241 if (bprm->unsafe & LSM_UNSAFE_SHARE) {
2242 rc = avc_has_perm(old_tsec->sid, new_tsec->sid,
2243 SECCLASS_PROCESS, PROCESS__SHARE,
2244 NULL);
2245 if (rc)
2246 return -EPERM;
2247 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002248
David Howellsa6f76f22008-11-14 10:39:24 +11002249 /* Make sure that anyone attempting to ptrace over a task that
2250 * changes its SID has the appropriate permit */
2251 if (bprm->unsafe &
2252 (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) {
2253 struct task_struct *tracer;
2254 struct task_security_struct *sec;
2255 u32 ptsid = 0;
2256
2257 rcu_read_lock();
Tejun Heo06d98472011-06-17 16:50:40 +02002258 tracer = ptrace_parent(current);
David Howellsa6f76f22008-11-14 10:39:24 +11002259 if (likely(tracer != NULL)) {
2260 sec = __task_cred(tracer)->security;
2261 ptsid = sec->sid;
2262 }
2263 rcu_read_unlock();
2264
2265 if (ptsid != 0) {
2266 rc = avc_has_perm(ptsid, new_tsec->sid,
2267 SECCLASS_PROCESS,
2268 PROCESS__PTRACE, NULL);
2269 if (rc)
2270 return -EPERM;
2271 }
2272 }
2273
2274 /* Clear any possibly unsafe personality bits on exec: */
2275 bprm->per_clear |= PER_CLEAR_ON_SETID;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002276 }
2277
Linus Torvalds1da177e2005-04-16 15:20:36 -07002278 return 0;
2279}
2280
Eric Paris828dfe12008-04-17 13:17:49 -04002281static int selinux_bprm_secureexec(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002282{
Paul Moore5fb49872010-04-22 14:46:19 -04002283 const struct task_security_struct *tsec = current_security();
David Howells275bb412008-11-14 10:39:19 +11002284 u32 sid, osid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002285 int atsecure = 0;
2286
David Howells275bb412008-11-14 10:39:19 +11002287 sid = tsec->sid;
2288 osid = tsec->osid;
2289
2290 if (osid != sid) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002291 /* Enable secure mode for SIDs transitions unless
2292 the noatsecure permission is granted between
2293 the two SIDs, i.e. ahp returns 0. */
David Howells275bb412008-11-14 10:39:19 +11002294 atsecure = avc_has_perm(osid, sid,
David Howellsa6f76f22008-11-14 10:39:24 +11002295 SECCLASS_PROCESS,
2296 PROCESS__NOATSECURE, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002297 }
2298
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07002299 return !!atsecure;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002300}
2301
Al Viroc3c073f2012-08-21 22:32:06 -04002302static int match_file(const void *p, struct file *file, unsigned fd)
2303{
2304 return file_has_perm(p, file, file_to_av(file)) ? fd + 1 : 0;
2305}
2306
Linus Torvalds1da177e2005-04-16 15:20:36 -07002307/* Derived from fs/exec.c:flush_old_files. */
David Howells745ca242008-11-14 10:39:22 +11002308static inline void flush_unauthorized_files(const struct cred *cred,
2309 struct files_struct *files)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002310{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002311 struct file *file, *devnull = NULL;
Stephen Smalleyb20c8122006-09-25 23:32:03 -07002312 struct tty_struct *tty;
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002313 int drop_tty = 0;
Al Viroc3c073f2012-08-21 22:32:06 -04002314 unsigned n;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002315
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002316 tty = get_current_tty();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002317 if (tty) {
Nick Pigginee2ffa02010-08-18 04:37:35 +10002318 spin_lock(&tty_files_lock);
Eric Paris37dd0bd2008-10-31 17:40:00 -04002319 if (!list_empty(&tty->tty_files)) {
Nick Piggind996b622010-08-18 04:37:36 +10002320 struct tty_file_private *file_priv;
Eric Paris37dd0bd2008-10-31 17:40:00 -04002321
Linus Torvalds1da177e2005-04-16 15:20:36 -07002322 /* Revalidate access to controlling tty.
David Howells13f8e982013-06-13 23:37:55 +01002323 Use file_path_has_perm on the tty path directly
2324 rather than using file_has_perm, as this particular
2325 open file may belong to another process and we are
2326 only interested in the inode-based check here. */
Nick Piggind996b622010-08-18 04:37:36 +10002327 file_priv = list_first_entry(&tty->tty_files,
2328 struct tty_file_private, list);
2329 file = file_priv->file;
David Howells13f8e982013-06-13 23:37:55 +01002330 if (file_path_has_perm(cred, file, FILE__READ | FILE__WRITE))
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002331 drop_tty = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002332 }
Nick Pigginee2ffa02010-08-18 04:37:35 +10002333 spin_unlock(&tty_files_lock);
Alan Cox452a00d2008-10-13 10:39:13 +01002334 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002335 }
Eric W. Biederman98a27ba2007-05-08 00:26:56 -07002336 /* Reset controlling tty. */
2337 if (drop_tty)
2338 no_tty();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002339
2340 /* Revalidate access to inherited open files. */
Al Viroc3c073f2012-08-21 22:32:06 -04002341 n = iterate_fd(files, 0, match_file, cred);
2342 if (!n) /* none found? */
2343 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002344
Al Viroc3c073f2012-08-21 22:32:06 -04002345 devnull = dentry_open(&selinux_null, O_RDWR, cred);
Al Viro45525b22012-10-16 13:30:07 -04002346 if (IS_ERR(devnull))
2347 devnull = NULL;
2348 /* replace all the matching ones with this */
2349 do {
2350 replace_fd(n - 1, devnull, 0);
2351 } while ((n = iterate_fd(files, n, match_file, cred)) != 0);
2352 if (devnull)
Al Viroc3c073f2012-08-21 22:32:06 -04002353 fput(devnull);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002354}
2355
Linus Torvalds1da177e2005-04-16 15:20:36 -07002356/*
David Howellsa6f76f22008-11-14 10:39:24 +11002357 * Prepare a process for imminent new credential changes due to exec
Linus Torvalds1da177e2005-04-16 15:20:36 -07002358 */
David Howellsa6f76f22008-11-14 10:39:24 +11002359static void selinux_bprm_committing_creds(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002360{
David Howellsa6f76f22008-11-14 10:39:24 +11002361 struct task_security_struct *new_tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002362 struct rlimit *rlim, *initrlim;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002363 int rc, i;
2364
David Howellsa6f76f22008-11-14 10:39:24 +11002365 new_tsec = bprm->cred->security;
2366 if (new_tsec->sid == new_tsec->osid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002367 return;
2368
2369 /* Close files for which the new task SID is not authorized. */
David Howellsa6f76f22008-11-14 10:39:24 +11002370 flush_unauthorized_files(bprm->cred, current->files);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002371
David Howellsa6f76f22008-11-14 10:39:24 +11002372 /* Always clear parent death signal on SID transitions. */
2373 current->pdeath_signal = 0;
2374
2375 /* Check whether the new SID can inherit resource limits from the old
2376 * SID. If not, reset all soft limits to the lower of the current
2377 * task's hard limit and the init task's soft limit.
2378 *
2379 * Note that the setting of hard limits (even to lower them) can be
2380 * controlled by the setrlimit check. The inclusion of the init task's
2381 * soft limit into the computation is to avoid resetting soft limits
2382 * higher than the default soft limit for cases where the default is
2383 * lower than the hard limit, e.g. RLIMIT_CORE or RLIMIT_STACK.
2384 */
2385 rc = avc_has_perm(new_tsec->osid, new_tsec->sid, SECCLASS_PROCESS,
2386 PROCESS__RLIMITINH, NULL);
2387 if (rc) {
Oleg Nesteroveb2d55a2010-06-23 22:43:32 +02002388 /* protect against do_prlimit() */
2389 task_lock(current);
David Howellsa6f76f22008-11-14 10:39:24 +11002390 for (i = 0; i < RLIM_NLIMITS; i++) {
2391 rlim = current->signal->rlim + i;
2392 initrlim = init_task.signal->rlim + i;
2393 rlim->rlim_cur = min(rlim->rlim_max, initrlim->rlim_cur);
2394 }
Oleg Nesteroveb2d55a2010-06-23 22:43:32 +02002395 task_unlock(current);
2396 update_rlimit_cpu(current, rlimit(RLIMIT_CPU));
David Howellsa6f76f22008-11-14 10:39:24 +11002397 }
2398}
2399
2400/*
2401 * Clean up the process immediately after the installation of new credentials
2402 * due to exec
2403 */
2404static void selinux_bprm_committed_creds(struct linux_binprm *bprm)
2405{
2406 const struct task_security_struct *tsec = current_security();
2407 struct itimerval itimer;
David Howellsa6f76f22008-11-14 10:39:24 +11002408 u32 osid, sid;
2409 int rc, i;
David Howellsa6f76f22008-11-14 10:39:24 +11002410
David Howellsa6f76f22008-11-14 10:39:24 +11002411 osid = tsec->osid;
2412 sid = tsec->sid;
2413
2414 if (sid == osid)
2415 return;
2416
2417 /* Check whether the new SID can inherit signal state from the old SID.
2418 * If not, clear itimers to avoid subsequent signal generation and
2419 * flush and unblock signals.
2420 *
2421 * This must occur _after_ the task SID has been updated so that any
2422 * kill done after the flush will be checked against the new SID.
2423 */
2424 rc = avc_has_perm(osid, sid, SECCLASS_PROCESS, PROCESS__SIGINH, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002425 if (rc) {
2426 memset(&itimer, 0, sizeof itimer);
2427 for (i = 0; i < 3; i++)
2428 do_setitimer(i, &itimer, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002429 spin_lock_irq(&current->sighand->siglock);
Oleg Nesterov9e7c8f82015-06-04 16:22:16 -04002430 if (!fatal_signal_pending(current)) {
2431 flush_sigqueue(&current->pending);
2432 flush_sigqueue(&current->signal->shared_pending);
David Howells3bcac022009-04-29 13:45:05 +01002433 flush_signal_handlers(current, 1);
2434 sigemptyset(&current->blocked);
Oleg Nesterov9e7c8f82015-06-04 16:22:16 -04002435 recalc_sigpending();
David Howells3bcac022009-04-29 13:45:05 +01002436 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002437 spin_unlock_irq(&current->sighand->siglock);
2438 }
2439
David Howellsa6f76f22008-11-14 10:39:24 +11002440 /* Wake up the parent if it is waiting so that it can recheck
2441 * wait permission to the new task SID. */
Oleg Nesterovecd6de32009-04-29 16:02:24 +02002442 read_lock(&tasklist_lock);
Oleg Nesterov0b7570e2009-09-23 15:56:46 -07002443 __wake_up_parent(current, current->real_parent);
Oleg Nesterovecd6de32009-04-29 16:02:24 +02002444 read_unlock(&tasklist_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002445}
2446
2447/* superblock security operations */
2448
2449static int selinux_sb_alloc_security(struct super_block *sb)
2450{
2451 return superblock_alloc_security(sb);
2452}
2453
2454static void selinux_sb_free_security(struct super_block *sb)
2455{
2456 superblock_free_security(sb);
2457}
2458
2459static inline int match_prefix(char *prefix, int plen, char *option, int olen)
2460{
2461 if (plen > olen)
2462 return 0;
2463
2464 return !memcmp(prefix, option, plen);
2465}
2466
2467static inline int selinux_option(char *option, int len)
2468{
Eric Paris832cbd92008-04-01 13:24:09 -04002469 return (match_prefix(CONTEXT_STR, sizeof(CONTEXT_STR)-1, option, len) ||
2470 match_prefix(FSCONTEXT_STR, sizeof(FSCONTEXT_STR)-1, option, len) ||
2471 match_prefix(DEFCONTEXT_STR, sizeof(DEFCONTEXT_STR)-1, option, len) ||
David P. Quigley11689d42009-01-16 09:22:03 -05002472 match_prefix(ROOTCONTEXT_STR, sizeof(ROOTCONTEXT_STR)-1, option, len) ||
2473 match_prefix(LABELSUPP_STR, sizeof(LABELSUPP_STR)-1, option, len));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002474}
2475
2476static inline void take_option(char **to, char *from, int *first, int len)
2477{
2478 if (!*first) {
2479 **to = ',';
2480 *to += 1;
Cory Olmo3528a952006-09-29 01:58:44 -07002481 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002482 *first = 0;
2483 memcpy(*to, from, len);
2484 *to += len;
2485}
2486
Eric Paris828dfe12008-04-17 13:17:49 -04002487static inline void take_selinux_option(char **to, char *from, int *first,
2488 int len)
Cory Olmo3528a952006-09-29 01:58:44 -07002489{
2490 int current_size = 0;
2491
2492 if (!*first) {
2493 **to = '|';
2494 *to += 1;
Eric Paris828dfe12008-04-17 13:17:49 -04002495 } else
Cory Olmo3528a952006-09-29 01:58:44 -07002496 *first = 0;
2497
2498 while (current_size < len) {
2499 if (*from != '"') {
2500 **to = *from;
2501 *to += 1;
2502 }
2503 from += 1;
2504 current_size += 1;
2505 }
2506}
2507
Eric Parise0007522008-03-05 10:31:54 -05002508static int selinux_sb_copy_data(char *orig, char *copy)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002509{
2510 int fnosec, fsec, rc = 0;
2511 char *in_save, *in_curr, *in_end;
2512 char *sec_curr, *nosec_save, *nosec;
Cory Olmo3528a952006-09-29 01:58:44 -07002513 int open_quote = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002514
2515 in_curr = orig;
2516 sec_curr = copy;
2517
Linus Torvalds1da177e2005-04-16 15:20:36 -07002518 nosec = (char *)get_zeroed_page(GFP_KERNEL);
2519 if (!nosec) {
2520 rc = -ENOMEM;
2521 goto out;
2522 }
2523
2524 nosec_save = nosec;
2525 fnosec = fsec = 1;
2526 in_save = in_end = orig;
2527
2528 do {
Cory Olmo3528a952006-09-29 01:58:44 -07002529 if (*in_end == '"')
2530 open_quote = !open_quote;
2531 if ((*in_end == ',' && open_quote == 0) ||
2532 *in_end == '\0') {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002533 int len = in_end - in_curr;
2534
2535 if (selinux_option(in_curr, len))
Cory Olmo3528a952006-09-29 01:58:44 -07002536 take_selinux_option(&sec_curr, in_curr, &fsec, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002537 else
2538 take_option(&nosec, in_curr, &fnosec, len);
2539
2540 in_curr = in_end + 1;
2541 }
2542 } while (*in_end++);
2543
Eric Paris6931dfc2005-06-30 02:58:51 -07002544 strcpy(in_save, nosec_save);
Gerald Schaeferda3caa22005-06-21 17:15:18 -07002545 free_page((unsigned long)nosec_save);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002546out:
2547 return rc;
2548}
2549
Eric Paris026eb162011-03-03 16:09:14 -05002550static int selinux_sb_remount(struct super_block *sb, void *data)
2551{
2552 int rc, i, *flags;
2553 struct security_mnt_opts opts;
2554 char *secdata, **mount_options;
2555 struct superblock_security_struct *sbsec = sb->s_security;
2556
2557 if (!(sbsec->flags & SE_SBINITIALIZED))
2558 return 0;
2559
2560 if (!data)
2561 return 0;
2562
2563 if (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)
2564 return 0;
2565
2566 security_init_mnt_opts(&opts);
2567 secdata = alloc_secdata();
2568 if (!secdata)
2569 return -ENOMEM;
2570 rc = selinux_sb_copy_data(data, secdata);
2571 if (rc)
2572 goto out_free_secdata;
2573
2574 rc = selinux_parse_opts_str(secdata, &opts);
2575 if (rc)
2576 goto out_free_secdata;
2577
2578 mount_options = opts.mnt_opts;
2579 flags = opts.mnt_opts_flags;
2580
2581 for (i = 0; i < opts.num_mnt_opts; i++) {
2582 u32 sid;
2583 size_t len;
2584
Eric Paris12f348b2012-10-09 10:56:25 -04002585 if (flags[i] == SBLABEL_MNT)
Eric Paris026eb162011-03-03 16:09:14 -05002586 continue;
2587 len = strlen(mount_options[i]);
Nikolay Aleksandrov52a4c642014-03-07 12:44:19 +01002588 rc = security_context_to_sid(mount_options[i], len, &sid,
2589 GFP_KERNEL);
Eric Paris026eb162011-03-03 16:09:14 -05002590 if (rc) {
2591 printk(KERN_WARNING "SELinux: security_context_to_sid"
Linus Torvalds29b1deb2013-12-15 11:17:45 -08002592 "(%s) failed for (dev %s, type %s) errno=%d\n",
2593 mount_options[i], sb->s_id, sb->s_type->name, rc);
Eric Paris026eb162011-03-03 16:09:14 -05002594 goto out_free_opts;
2595 }
2596 rc = -EINVAL;
2597 switch (flags[i]) {
2598 case FSCONTEXT_MNT:
2599 if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid, sid))
2600 goto out_bad_option;
2601 break;
2602 case CONTEXT_MNT:
2603 if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid, sid))
2604 goto out_bad_option;
2605 break;
2606 case ROOTCONTEXT_MNT: {
2607 struct inode_security_struct *root_isec;
David Howellsc6f493d2015-03-17 22:26:22 +00002608 root_isec = d_backing_inode(sb->s_root)->i_security;
Eric Paris026eb162011-03-03 16:09:14 -05002609
2610 if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid, sid))
2611 goto out_bad_option;
2612 break;
2613 }
2614 case DEFCONTEXT_MNT:
2615 if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid, sid))
2616 goto out_bad_option;
2617 break;
2618 default:
2619 goto out_free_opts;
2620 }
2621 }
2622
2623 rc = 0;
2624out_free_opts:
2625 security_free_mnt_opts(&opts);
2626out_free_secdata:
2627 free_secdata(secdata);
2628 return rc;
2629out_bad_option:
2630 printk(KERN_WARNING "SELinux: unable to change security options "
Linus Torvalds29b1deb2013-12-15 11:17:45 -08002631 "during remount (dev %s, type=%s)\n", sb->s_id,
2632 sb->s_type->name);
Eric Paris026eb162011-03-03 16:09:14 -05002633 goto out_free_opts;
2634}
2635
James Morris12204e22008-12-19 10:44:42 +11002636static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002637{
David Howells88e67f32008-11-14 10:39:21 +11002638 const struct cred *cred = current_cred();
Thomas Liu2bf49692009-07-14 12:14:09 -04002639 struct common_audit_data ad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002640 int rc;
2641
2642 rc = superblock_doinit(sb, data);
2643 if (rc)
2644 return rc;
2645
James Morris74192242008-12-19 11:41:10 +11002646 /* Allow all mounts performed by the kernel */
2647 if (flags & MS_KERNMOUNT)
2648 return 0;
2649
Eric Paris50c205f2012-04-04 15:01:43 -04002650 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04002651 ad.u.dentry = sb->s_root;
David Howells88e67f32008-11-14 10:39:21 +11002652 return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002653}
2654
David Howells726c3342006-06-23 02:02:58 -07002655static int selinux_sb_statfs(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002656{
David Howells88e67f32008-11-14 10:39:21 +11002657 const struct cred *cred = current_cred();
Thomas Liu2bf49692009-07-14 12:14:09 -04002658 struct common_audit_data ad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002659
Eric Paris50c205f2012-04-04 15:01:43 -04002660 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04002661 ad.u.dentry = dentry->d_sb->s_root;
David Howells88e67f32008-11-14 10:39:21 +11002662 return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002663}
2664
Al Viro808d4e32012-10-11 11:42:01 -04002665static int selinux_mount(const char *dev_name,
Al Virob5266eb2008-03-22 17:48:24 -04002666 struct path *path,
Al Viro808d4e32012-10-11 11:42:01 -04002667 const char *type,
Eric Paris828dfe12008-04-17 13:17:49 -04002668 unsigned long flags,
2669 void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002670{
David Howells88e67f32008-11-14 10:39:21 +11002671 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002672
2673 if (flags & MS_REMOUNT)
Al Virod8c95842011-12-07 18:16:57 -05002674 return superblock_has_perm(cred, path->dentry->d_sb,
Eric Paris828dfe12008-04-17 13:17:49 -04002675 FILESYSTEM__REMOUNT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002676 else
Eric Paris2875fa02011-04-28 16:04:24 -04002677 return path_has_perm(cred, path, FILE__MOUNTON);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002678}
2679
2680static int selinux_umount(struct vfsmount *mnt, int flags)
2681{
David Howells88e67f32008-11-14 10:39:21 +11002682 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002683
David Howells88e67f32008-11-14 10:39:21 +11002684 return superblock_has_perm(cred, mnt->mnt_sb,
Eric Paris828dfe12008-04-17 13:17:49 -04002685 FILESYSTEM__UNMOUNT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002686}
2687
2688/* inode security operations */
2689
2690static int selinux_inode_alloc_security(struct inode *inode)
2691{
2692 return inode_alloc_security(inode);
2693}
2694
2695static void selinux_inode_free_security(struct inode *inode)
2696{
2697 inode_free_security(inode);
2698}
2699
David Quigleyd47be3d2013-05-22 12:50:34 -04002700static int selinux_dentry_init_security(struct dentry *dentry, int mode,
2701 struct qstr *name, void **ctx,
2702 u32 *ctxlen)
2703{
2704 const struct cred *cred = current_cred();
2705 struct task_security_struct *tsec;
2706 struct inode_security_struct *dsec;
2707 struct superblock_security_struct *sbsec;
David Howellsc6f493d2015-03-17 22:26:22 +00002708 struct inode *dir = d_backing_inode(dentry->d_parent);
David Quigleyd47be3d2013-05-22 12:50:34 -04002709 u32 newsid;
2710 int rc;
2711
2712 tsec = cred->security;
2713 dsec = dir->i_security;
2714 sbsec = dir->i_sb->s_security;
2715
2716 if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) {
2717 newsid = tsec->create_sid;
2718 } else {
2719 rc = security_transition_sid(tsec->sid, dsec->sid,
2720 inode_mode_to_security_class(mode),
2721 name,
2722 &newsid);
2723 if (rc) {
2724 printk(KERN_WARNING
2725 "%s: security_transition_sid failed, rc=%d\n",
2726 __func__, -rc);
2727 return rc;
2728 }
2729 }
2730
2731 return security_sid_to_context(newsid, (char **)ctx, ctxlen);
2732}
2733
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002734static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
Tetsuo Handa95489062013-07-25 05:44:02 +09002735 const struct qstr *qstr,
2736 const char **name,
Eric Paris2a7dba32011-02-01 11:05:39 -05002737 void **value, size_t *len)
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002738{
Paul Moore5fb49872010-04-22 14:46:19 -04002739 const struct task_security_struct *tsec = current_security();
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002740 struct inode_security_struct *dsec;
2741 struct superblock_security_struct *sbsec;
David Howells275bb412008-11-14 10:39:19 +11002742 u32 sid, newsid, clen;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002743 int rc;
Tetsuo Handa95489062013-07-25 05:44:02 +09002744 char *context;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002745
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002746 dsec = dir->i_security;
2747 sbsec = dir->i_sb->s_security;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002748
David Howells275bb412008-11-14 10:39:19 +11002749 sid = tsec->sid;
2750 newsid = tsec->create_sid;
2751
Eric Paris415103f2010-12-02 16:13:40 -05002752 if ((sbsec->flags & SE_SBINITIALIZED) &&
2753 (sbsec->behavior == SECURITY_FS_USE_MNTPOINT))
2754 newsid = sbsec->mntpoint_sid;
Eric Paris12f348b2012-10-09 10:56:25 -04002755 else if (!newsid || !(sbsec->flags & SBLABEL_MNT)) {
David Howells275bb412008-11-14 10:39:19 +11002756 rc = security_transition_sid(sid, dsec->sid,
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002757 inode_mode_to_security_class(inode->i_mode),
Eric Paris652bb9b2011-02-01 11:05:40 -05002758 qstr, &newsid);
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002759 if (rc) {
2760 printk(KERN_WARNING "%s: "
2761 "security_transition_sid failed, rc=%d (dev=%s "
2762 "ino=%ld)\n",
Harvey Harrisondd6f9532008-03-06 10:03:59 +11002763 __func__,
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002764 -rc, inode->i_sb->s_id, inode->i_ino);
2765 return rc;
2766 }
2767 }
2768
Eric Paris296fddf2006-09-25 23:32:00 -07002769 /* Possibly defer initialization to selinux_complete_init. */
David P. Quigley0d90a7e2009-01-16 09:22:02 -05002770 if (sbsec->flags & SE_SBINITIALIZED) {
Eric Paris296fddf2006-09-25 23:32:00 -07002771 struct inode_security_struct *isec = inode->i_security;
2772 isec->sclass = inode_mode_to_security_class(inode->i_mode);
2773 isec->sid = newsid;
2774 isec->initialized = 1;
2775 }
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002776
Eric Paris12f348b2012-10-09 10:56:25 -04002777 if (!ss_initialized || !(sbsec->flags & SBLABEL_MNT))
Stephen Smalley25a74f32005-11-08 21:34:33 -08002778 return -EOPNOTSUPP;
2779
Tetsuo Handa95489062013-07-25 05:44:02 +09002780 if (name)
2781 *name = XATTR_SELINUX_SUFFIX;
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002782
2783 if (value && len) {
Stephen Smalley12b29f32008-05-07 13:03:20 -04002784 rc = security_sid_to_context_force(newsid, &context, &clen);
Tetsuo Handa95489062013-07-25 05:44:02 +09002785 if (rc)
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002786 return rc;
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002787 *value = context;
2788 *len = clen;
2789 }
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002790
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002791 return 0;
2792}
2793
Al Viro4acdaf22011-07-26 01:42:34 -04002794static int selinux_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002795{
2796 return may_create(dir, dentry, SECCLASS_FILE);
2797}
2798
Linus Torvalds1da177e2005-04-16 15:20:36 -07002799static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
2800{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002801 return may_link(dir, old_dentry, MAY_LINK);
2802}
2803
Linus Torvalds1da177e2005-04-16 15:20:36 -07002804static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry)
2805{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002806 return may_link(dir, dentry, MAY_UNLINK);
2807}
2808
2809static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry, const char *name)
2810{
2811 return may_create(dir, dentry, SECCLASS_LNK_FILE);
2812}
2813
Al Viro18bb1db2011-07-26 01:41:39 -04002814static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry, umode_t mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002815{
2816 return may_create(dir, dentry, SECCLASS_DIR);
2817}
2818
Linus Torvalds1da177e2005-04-16 15:20:36 -07002819static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry)
2820{
2821 return may_link(dir, dentry, MAY_RMDIR);
2822}
2823
Al Viro1a67aaf2011-07-26 01:52:52 -04002824static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002825{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002826 return may_create(dir, dentry, inode_mode_to_security_class(mode));
2827}
2828
Linus Torvalds1da177e2005-04-16 15:20:36 -07002829static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
Eric Paris828dfe12008-04-17 13:17:49 -04002830 struct inode *new_inode, struct dentry *new_dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002831{
2832 return may_rename(old_inode, old_dentry, new_inode, new_dentry);
2833}
2834
Linus Torvalds1da177e2005-04-16 15:20:36 -07002835static int selinux_inode_readlink(struct dentry *dentry)
2836{
David Howells88e67f32008-11-14 10:39:21 +11002837 const struct cred *cred = current_cred();
2838
Eric Paris2875fa02011-04-28 16:04:24 -04002839 return dentry_has_perm(cred, dentry, FILE__READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002840}
2841
2842static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *nameidata)
2843{
David Howells88e67f32008-11-14 10:39:21 +11002844 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002845
Eric Paris2875fa02011-04-28 16:04:24 -04002846 return dentry_has_perm(cred, dentry, FILE__READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002847}
2848
Eric Parisd4cf970d2012-04-04 15:01:42 -04002849static noinline int audit_inode_permission(struct inode *inode,
2850 u32 perms, u32 audited, u32 denied,
Stephen Smalley626b9742014-04-29 11:29:04 -07002851 int result,
Eric Parisd4cf970d2012-04-04 15:01:42 -04002852 unsigned flags)
2853{
2854 struct common_audit_data ad;
Eric Parisd4cf970d2012-04-04 15:01:42 -04002855 struct inode_security_struct *isec = inode->i_security;
2856 int rc;
2857
Eric Paris50c205f2012-04-04 15:01:43 -04002858 ad.type = LSM_AUDIT_DATA_INODE;
Eric Parisd4cf970d2012-04-04 15:01:42 -04002859 ad.u.inode = inode;
2860
2861 rc = slow_avc_audit(current_sid(), isec->sid, isec->sclass, perms,
Stephen Smalley626b9742014-04-29 11:29:04 -07002862 audited, denied, result, &ad, flags);
Eric Parisd4cf970d2012-04-04 15:01:42 -04002863 if (rc)
2864 return rc;
2865 return 0;
2866}
2867
Al Viroe74f71e2011-06-20 19:38:15 -04002868static int selinux_inode_permission(struct inode *inode, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002869{
David Howells88e67f32008-11-14 10:39:21 +11002870 const struct cred *cred = current_cred();
Eric Parisb782e0a2010-07-23 11:44:03 -04002871 u32 perms;
2872 bool from_access;
Al Virocf1dd1d2011-06-20 19:44:08 -04002873 unsigned flags = mask & MAY_NOT_BLOCK;
Eric Paris2e334052012-04-04 15:01:42 -04002874 struct inode_security_struct *isec;
2875 u32 sid;
2876 struct av_decision avd;
2877 int rc, rc2;
2878 u32 audited, denied;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002879
Eric Parisb782e0a2010-07-23 11:44:03 -04002880 from_access = mask & MAY_ACCESS;
Eric Parisd09ca732010-07-23 11:43:57 -04002881 mask &= (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND);
2882
Eric Parisb782e0a2010-07-23 11:44:03 -04002883 /* No permission to check. Existence test. */
2884 if (!mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002885 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002886
Eric Paris2e334052012-04-04 15:01:42 -04002887 validate_creds(cred);
Eric Parisb782e0a2010-07-23 11:44:03 -04002888
Eric Paris2e334052012-04-04 15:01:42 -04002889 if (unlikely(IS_PRIVATE(inode)))
2890 return 0;
Eric Parisb782e0a2010-07-23 11:44:03 -04002891
2892 perms = file_mask_to_av(inode->i_mode, mask);
2893
Eric Paris2e334052012-04-04 15:01:42 -04002894 sid = cred_sid(cred);
2895 isec = inode->i_security;
2896
2897 rc = avc_has_perm_noaudit(sid, isec->sid, isec->sclass, perms, 0, &avd);
2898 audited = avc_audit_required(perms, &avd, rc,
2899 from_access ? FILE__AUDIT_ACCESS : 0,
2900 &denied);
2901 if (likely(!audited))
2902 return rc;
2903
Stephen Smalley626b9742014-04-29 11:29:04 -07002904 rc2 = audit_inode_permission(inode, perms, audited, denied, rc, flags);
Eric Paris2e334052012-04-04 15:01:42 -04002905 if (rc2)
2906 return rc2;
2907 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002908}
2909
2910static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
2911{
David Howells88e67f32008-11-14 10:39:21 +11002912 const struct cred *cred = current_cred();
Amerigo Wangbc6a6002009-08-20 19:29:02 -07002913 unsigned int ia_valid = iattr->ia_valid;
Eric Paris95dbf732012-04-04 13:45:34 -04002914 __u32 av = FILE__WRITE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002915
Amerigo Wangbc6a6002009-08-20 19:29:02 -07002916 /* ATTR_FORCE is just used for ATTR_KILL_S[UG]ID. */
2917 if (ia_valid & ATTR_FORCE) {
2918 ia_valid &= ~(ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_MODE |
2919 ATTR_FORCE);
2920 if (!ia_valid)
2921 return 0;
2922 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002923
Amerigo Wangbc6a6002009-08-20 19:29:02 -07002924 if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID |
2925 ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_TIMES_SET))
Eric Paris2875fa02011-04-28 16:04:24 -04002926 return dentry_has_perm(cred, dentry, FILE__SETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002927
Eric Paris3d2195c2012-07-06 14:13:30 -04002928 if (selinux_policycap_openperm && (ia_valid & ATTR_SIZE))
Eric Paris95dbf732012-04-04 13:45:34 -04002929 av |= FILE__OPEN;
2930
2931 return dentry_has_perm(cred, dentry, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002932}
2933
Al Viro3f7036a2015-03-08 19:28:30 -04002934static int selinux_inode_getattr(const struct path *path)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002935{
Al Viro3f7036a2015-03-08 19:28:30 -04002936 return path_has_perm(current_cred(), path, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002937}
2938
David Howells8f0cfa52008-04-29 00:59:41 -07002939static int selinux_inode_setotherxattr(struct dentry *dentry, const char *name)
Serge E. Hallynb5376772007-10-16 23:31:36 -07002940{
David Howells88e67f32008-11-14 10:39:21 +11002941 const struct cred *cred = current_cred();
2942
Serge E. Hallynb5376772007-10-16 23:31:36 -07002943 if (!strncmp(name, XATTR_SECURITY_PREFIX,
2944 sizeof XATTR_SECURITY_PREFIX - 1)) {
2945 if (!strcmp(name, XATTR_NAME_CAPS)) {
2946 if (!capable(CAP_SETFCAP))
2947 return -EPERM;
2948 } else if (!capable(CAP_SYS_ADMIN)) {
2949 /* A different attribute in the security namespace.
2950 Restrict to administrator. */
2951 return -EPERM;
2952 }
2953 }
2954
2955 /* Not an attribute we recognize, so just check the
2956 ordinary setattr permission. */
Eric Paris2875fa02011-04-28 16:04:24 -04002957 return dentry_has_perm(cred, dentry, FILE__SETATTR);
Serge E. Hallynb5376772007-10-16 23:31:36 -07002958}
2959
David Howells8f0cfa52008-04-29 00:59:41 -07002960static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
2961 const void *value, size_t size, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002962{
David Howellsc6f493d2015-03-17 22:26:22 +00002963 struct inode *inode = d_backing_inode(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002964 struct inode_security_struct *isec = inode->i_security;
2965 struct superblock_security_struct *sbsec;
Thomas Liu2bf49692009-07-14 12:14:09 -04002966 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11002967 u32 newsid, sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002968 int rc = 0;
2969
Serge E. Hallynb5376772007-10-16 23:31:36 -07002970 if (strcmp(name, XATTR_NAME_SELINUX))
2971 return selinux_inode_setotherxattr(dentry, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002972
2973 sbsec = inode->i_sb->s_security;
Eric Paris12f348b2012-10-09 10:56:25 -04002974 if (!(sbsec->flags & SBLABEL_MNT))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002975 return -EOPNOTSUPP;
2976
Serge E. Hallyn2e149672011-03-23 16:43:26 -07002977 if (!inode_owner_or_capable(inode))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002978 return -EPERM;
2979
Eric Paris50c205f2012-04-04 15:01:43 -04002980 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04002981 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002982
David Howells275bb412008-11-14 10:39:19 +11002983 rc = avc_has_perm(sid, isec->sid, isec->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002984 FILE__RELABELFROM, &ad);
2985 if (rc)
2986 return rc;
2987
Nikolay Aleksandrov52a4c642014-03-07 12:44:19 +01002988 rc = security_context_to_sid(value, size, &newsid, GFP_KERNEL);
Stephen Smalley12b29f32008-05-07 13:03:20 -04002989 if (rc == -EINVAL) {
Eric Parisd6ea83e2012-04-04 13:45:49 -04002990 if (!capable(CAP_MAC_ADMIN)) {
2991 struct audit_buffer *ab;
2992 size_t audit_size;
2993 const char *str;
2994
2995 /* We strip a nul only if it is at the end, otherwise the
2996 * context contains a nul and we should audit that */
Al Viroe3fea3f2012-06-09 08:15:16 +01002997 if (value) {
2998 str = value;
2999 if (str[size - 1] == '\0')
3000 audit_size = size - 1;
3001 else
3002 audit_size = size;
3003 } else {
3004 str = "";
3005 audit_size = 0;
3006 }
Eric Parisd6ea83e2012-04-04 13:45:49 -04003007 ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR);
3008 audit_log_format(ab, "op=setxattr invalid_context=");
3009 audit_log_n_untrustedstring(ab, value, audit_size);
3010 audit_log_end(ab);
3011
Stephen Smalley12b29f32008-05-07 13:03:20 -04003012 return rc;
Eric Parisd6ea83e2012-04-04 13:45:49 -04003013 }
Stephen Smalley12b29f32008-05-07 13:03:20 -04003014 rc = security_context_to_sid_force(value, size, &newsid);
3015 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003016 if (rc)
3017 return rc;
3018
David Howells275bb412008-11-14 10:39:19 +11003019 rc = avc_has_perm(sid, newsid, isec->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003020 FILE__RELABELTO, &ad);
3021 if (rc)
3022 return rc;
3023
David Howells275bb412008-11-14 10:39:19 +11003024 rc = security_validate_transition(isec->sid, newsid, sid,
Eric Paris828dfe12008-04-17 13:17:49 -04003025 isec->sclass);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003026 if (rc)
3027 return rc;
3028
3029 return avc_has_perm(newsid,
3030 sbsec->sid,
3031 SECCLASS_FILESYSTEM,
3032 FILESYSTEM__ASSOCIATE,
3033 &ad);
3034}
3035
David Howells8f0cfa52008-04-29 00:59:41 -07003036static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
Eric Parisf5269712008-05-14 11:27:45 -04003037 const void *value, size_t size,
David Howells8f0cfa52008-04-29 00:59:41 -07003038 int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003039{
David Howellsc6f493d2015-03-17 22:26:22 +00003040 struct inode *inode = d_backing_inode(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003041 struct inode_security_struct *isec = inode->i_security;
3042 u32 newsid;
3043 int rc;
3044
3045 if (strcmp(name, XATTR_NAME_SELINUX)) {
3046 /* Not an attribute we recognize, so nothing to do. */
3047 return;
3048 }
3049
Stephen Smalley12b29f32008-05-07 13:03:20 -04003050 rc = security_context_to_sid_force(value, size, &newsid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003051 if (rc) {
Stephen Smalley12b29f32008-05-07 13:03:20 -04003052 printk(KERN_ERR "SELinux: unable to map context to SID"
3053 "for (%s, %lu), rc=%d\n",
3054 inode->i_sb->s_id, inode->i_ino, -rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003055 return;
3056 }
3057
David Quigleyaa9c2662013-05-22 12:50:44 -04003058 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003059 isec->sid = newsid;
David Quigleyaa9c2662013-05-22 12:50:44 -04003060 isec->initialized = 1;
3061
Linus Torvalds1da177e2005-04-16 15:20:36 -07003062 return;
3063}
3064
David Howells8f0cfa52008-04-29 00:59:41 -07003065static int selinux_inode_getxattr(struct dentry *dentry, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003066{
David Howells88e67f32008-11-14 10:39:21 +11003067 const struct cred *cred = current_cred();
3068
Eric Paris2875fa02011-04-28 16:04:24 -04003069 return dentry_has_perm(cred, dentry, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003070}
3071
Eric Paris828dfe12008-04-17 13:17:49 -04003072static int selinux_inode_listxattr(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003073{
David Howells88e67f32008-11-14 10:39:21 +11003074 const struct cred *cred = current_cred();
3075
Eric Paris2875fa02011-04-28 16:04:24 -04003076 return dentry_has_perm(cred, dentry, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003077}
3078
David Howells8f0cfa52008-04-29 00:59:41 -07003079static int selinux_inode_removexattr(struct dentry *dentry, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003080{
Serge E. Hallynb5376772007-10-16 23:31:36 -07003081 if (strcmp(name, XATTR_NAME_SELINUX))
3082 return selinux_inode_setotherxattr(dentry, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003083
3084 /* No one is allowed to remove a SELinux security label.
3085 You can change the label, but all data must be labeled. */
3086 return -EACCES;
3087}
3088
James Morrisd381d8a2005-10-30 14:59:22 -08003089/*
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04003090 * Copy the inode security context value to the user.
James Morrisd381d8a2005-10-30 14:59:22 -08003091 *
3092 * Permission check is handled by selinux_inode_getxattr hook.
3093 */
David P. Quigley42492592008-02-04 22:29:39 -08003094static int selinux_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003095{
David P. Quigley42492592008-02-04 22:29:39 -08003096 u32 size;
3097 int error;
3098 char *context = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003099 struct inode_security_struct *isec = inode->i_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003100
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00003101 if (strcmp(name, XATTR_SELINUX_SUFFIX))
3102 return -EOPNOTSUPP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003103
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04003104 /*
3105 * If the caller has CAP_MAC_ADMIN, then get the raw context
3106 * value even if it is not defined by current policy; otherwise,
3107 * use the in-core value under current policy.
3108 * Use the non-auditing forms of the permission checks since
3109 * getxattr may be called by unprivileged processes commonly
3110 * and lack of permission just means that we fall back to the
3111 * in-core context value, not a denial.
3112 */
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07003113 error = cap_capable(current_cred(), &init_user_ns, CAP_MAC_ADMIN,
3114 SECURITY_CAP_NOAUDIT);
3115 if (!error)
3116 error = cred_has_capability(current_cred(), CAP_MAC_ADMIN,
3117 SECURITY_CAP_NOAUDIT);
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04003118 if (!error)
3119 error = security_sid_to_context_force(isec->sid, &context,
3120 &size);
3121 else
3122 error = security_sid_to_context(isec->sid, &context, &size);
David P. Quigley42492592008-02-04 22:29:39 -08003123 if (error)
3124 return error;
3125 error = size;
3126 if (alloc) {
3127 *buffer = context;
3128 goto out_nofree;
3129 }
3130 kfree(context);
3131out_nofree:
3132 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003133}
3134
3135static int selinux_inode_setsecurity(struct inode *inode, const char *name,
Eric Paris828dfe12008-04-17 13:17:49 -04003136 const void *value, size_t size, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003137{
3138 struct inode_security_struct *isec = inode->i_security;
3139 u32 newsid;
3140 int rc;
3141
3142 if (strcmp(name, XATTR_SELINUX_SUFFIX))
3143 return -EOPNOTSUPP;
3144
3145 if (!value || !size)
3146 return -EACCES;
3147
Nikolay Aleksandrov52a4c642014-03-07 12:44:19 +01003148 rc = security_context_to_sid((void *)value, size, &newsid, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003149 if (rc)
3150 return rc;
3151
David Quigleyaa9c2662013-05-22 12:50:44 -04003152 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003153 isec->sid = newsid;
David P. Quigleyddd29ec2009-09-09 14:25:37 -04003154 isec->initialized = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003155 return 0;
3156}
3157
3158static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size)
3159{
3160 const int len = sizeof(XATTR_NAME_SELINUX);
3161 if (buffer && len <= buffer_size)
3162 memcpy(buffer, XATTR_NAME_SELINUX, len);
3163 return len;
3164}
3165
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02003166static void selinux_inode_getsecid(const struct inode *inode, u32 *secid)
3167{
3168 struct inode_security_struct *isec = inode->i_security;
3169 *secid = isec->sid;
3170}
3171
Linus Torvalds1da177e2005-04-16 15:20:36 -07003172/* file security operations */
3173
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003174static int selinux_revalidate_file_permission(struct file *file, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003175{
David Howells88e67f32008-11-14 10:39:21 +11003176 const struct cred *cred = current_cred();
Al Viro496ad9a2013-01-23 17:07:38 -05003177 struct inode *inode = file_inode(file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003178
Linus Torvalds1da177e2005-04-16 15:20:36 -07003179 /* file_mask_to_av won't add FILE__WRITE if MAY_APPEND is set */
3180 if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE))
3181 mask |= MAY_APPEND;
3182
Paul Moore389fb8002009-03-27 17:10:34 -04003183 return file_has_perm(cred, file,
3184 file_mask_to_av(inode->i_mode, mask));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003185}
3186
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003187static int selinux_file_permission(struct file *file, int mask)
3188{
Al Viro496ad9a2013-01-23 17:07:38 -05003189 struct inode *inode = file_inode(file);
Stephen Smalley20dda182009-06-22 14:54:53 -04003190 struct file_security_struct *fsec = file->f_security;
3191 struct inode_security_struct *isec = inode->i_security;
3192 u32 sid = current_sid();
3193
Paul Moore389fb8002009-03-27 17:10:34 -04003194 if (!mask)
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003195 /* No permission to check. Existence test. */
3196 return 0;
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003197
Stephen Smalley20dda182009-06-22 14:54:53 -04003198 if (sid == fsec->sid && fsec->isid == isec->sid &&
3199 fsec->pseqno == avc_policy_seqno())
Eric Paris83d49852012-04-04 13:45:40 -04003200 /* No change since file_open check. */
Stephen Smalley20dda182009-06-22 14:54:53 -04003201 return 0;
3202
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003203 return selinux_revalidate_file_permission(file, mask);
3204}
3205
Linus Torvalds1da177e2005-04-16 15:20:36 -07003206static int selinux_file_alloc_security(struct file *file)
3207{
3208 return file_alloc_security(file);
3209}
3210
3211static void selinux_file_free_security(struct file *file)
3212{
3213 file_free_security(file);
3214}
3215
3216static int selinux_file_ioctl(struct file *file, unsigned int cmd,
3217 unsigned long arg)
3218{
David Howells88e67f32008-11-14 10:39:21 +11003219 const struct cred *cred = current_cred();
Eric Paris0b24dcb2011-02-25 15:39:20 -05003220 int error = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003221
Eric Paris0b24dcb2011-02-25 15:39:20 -05003222 switch (cmd) {
3223 case FIONREAD:
3224 /* fall through */
3225 case FIBMAP:
3226 /* fall through */
3227 case FIGETBSZ:
3228 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003229 case FS_IOC_GETFLAGS:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003230 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003231 case FS_IOC_GETVERSION:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003232 error = file_has_perm(cred, file, FILE__GETATTR);
3233 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003234
Al Viro2f99c362012-03-23 16:04:05 -04003235 case FS_IOC_SETFLAGS:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003236 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003237 case FS_IOC_SETVERSION:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003238 error = file_has_perm(cred, file, FILE__SETATTR);
3239 break;
3240
3241 /* sys_ioctl() checks */
3242 case FIONBIO:
3243 /* fall through */
3244 case FIOASYNC:
3245 error = file_has_perm(cred, file, 0);
3246 break;
3247
3248 case KDSKBENT:
3249 case KDSKBSENT:
Eric Paris6a9de492012-01-03 12:25:14 -05003250 error = cred_has_capability(cred, CAP_SYS_TTY_CONFIG,
3251 SECURITY_CAP_AUDIT);
Eric Paris0b24dcb2011-02-25 15:39:20 -05003252 break;
3253
3254 /* default case assumes that the command will go
3255 * to the file's ioctl() function.
3256 */
3257 default:
3258 error = file_has_perm(cred, file, FILE__IOCTL);
3259 }
3260 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003261}
3262
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003263static int default_noexec;
3264
Linus Torvalds1da177e2005-04-16 15:20:36 -07003265static int file_map_prot_check(struct file *file, unsigned long prot, int shared)
3266{
David Howells88e67f32008-11-14 10:39:21 +11003267 const struct cred *cred = current_cred();
David Howellsd84f4f92008-11-14 10:39:23 +11003268 int rc = 0;
David Howells88e67f32008-11-14 10:39:21 +11003269
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003270 if (default_noexec &&
3271 (prot & PROT_EXEC) && (!file || (!shared && (prot & PROT_WRITE)))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003272 /*
3273 * We are making executable an anonymous mapping or a
3274 * private file mapping that will also be writable.
3275 * This has an additional check.
3276 */
David Howellsd84f4f92008-11-14 10:39:23 +11003277 rc = cred_has_perm(cred, cred, PROCESS__EXECMEM);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003278 if (rc)
David Howellsd84f4f92008-11-14 10:39:23 +11003279 goto error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003280 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003281
3282 if (file) {
3283 /* read access is always possible with a mapping */
3284 u32 av = FILE__READ;
3285
3286 /* write access only matters if the mapping is shared */
3287 if (shared && (prot & PROT_WRITE))
3288 av |= FILE__WRITE;
3289
3290 if (prot & PROT_EXEC)
3291 av |= FILE__EXECUTE;
3292
David Howells88e67f32008-11-14 10:39:21 +11003293 return file_has_perm(cred, file, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003294 }
David Howellsd84f4f92008-11-14 10:39:23 +11003295
3296error:
3297 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003298}
3299
Al Viroe5467852012-05-30 13:30:51 -04003300static int selinux_mmap_addr(unsigned long addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003301{
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07003302 int rc = 0;
Paul Moore98883bf2014-03-19 16:46:11 -04003303
3304 if (addr < CONFIG_LSM_MMAP_MIN_ADDR) {
3305 u32 sid = current_sid();
3306 rc = avc_has_perm(sid, sid, SECCLASS_MEMPROTECT,
3307 MEMPROTECT__MMAP_ZERO, NULL);
3308 }
3309
3310 return rc;
Al Viroe5467852012-05-30 13:30:51 -04003311}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003312
Al Viroe5467852012-05-30 13:30:51 -04003313static int selinux_mmap_file(struct file *file, unsigned long reqprot,
3314 unsigned long prot, unsigned long flags)
3315{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003316 if (selinux_checkreqprot)
3317 prot = reqprot;
3318
3319 return file_map_prot_check(file, prot,
3320 (flags & MAP_TYPE) == MAP_SHARED);
3321}
3322
3323static int selinux_file_mprotect(struct vm_area_struct *vma,
3324 unsigned long reqprot,
3325 unsigned long prot)
3326{
David Howells88e67f32008-11-14 10:39:21 +11003327 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003328
3329 if (selinux_checkreqprot)
3330 prot = reqprot;
3331
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003332 if (default_noexec &&
3333 (prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) {
James Morrisd541bbe2009-01-29 12:19:51 +11003334 int rc = 0;
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003335 if (vma->vm_start >= vma->vm_mm->start_brk &&
3336 vma->vm_end <= vma->vm_mm->brk) {
David Howellsd84f4f92008-11-14 10:39:23 +11003337 rc = cred_has_perm(cred, cred, PROCESS__EXECHEAP);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003338 } else if (!vma->vm_file &&
3339 vma->vm_start <= vma->vm_mm->start_stack &&
3340 vma->vm_end >= vma->vm_mm->start_stack) {
David Howells3b11a1d2008-11-14 10:39:26 +11003341 rc = current_has_perm(current, PROCESS__EXECSTACK);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003342 } else if (vma->vm_file && vma->anon_vma) {
3343 /*
3344 * We are making executable a file mapping that has
3345 * had some COW done. Since pages might have been
3346 * written, check ability to execute the possibly
3347 * modified content. This typically should only
3348 * occur for text relocations.
3349 */
David Howellsd84f4f92008-11-14 10:39:23 +11003350 rc = file_has_perm(cred, vma->vm_file, FILE__EXECMOD);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003351 }
Lorenzo Hernandez García-Hierro6b992192005-06-25 14:54:34 -07003352 if (rc)
3353 return rc;
3354 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003355
3356 return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED);
3357}
3358
3359static int selinux_file_lock(struct file *file, unsigned int cmd)
3360{
David Howells88e67f32008-11-14 10:39:21 +11003361 const struct cred *cred = current_cred();
3362
3363 return file_has_perm(cred, file, FILE__LOCK);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003364}
3365
3366static int selinux_file_fcntl(struct file *file, unsigned int cmd,
3367 unsigned long arg)
3368{
David Howells88e67f32008-11-14 10:39:21 +11003369 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003370 int err = 0;
3371
3372 switch (cmd) {
Eric Paris828dfe12008-04-17 13:17:49 -04003373 case F_SETFL:
Eric Paris828dfe12008-04-17 13:17:49 -04003374 if ((file->f_flags & O_APPEND) && !(arg & O_APPEND)) {
David Howells88e67f32008-11-14 10:39:21 +11003375 err = file_has_perm(cred, file, FILE__WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003376 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003377 }
3378 /* fall through */
3379 case F_SETOWN:
3380 case F_SETSIG:
3381 case F_GETFL:
3382 case F_GETOWN:
3383 case F_GETSIG:
Cyrill Gorcunov1d151c32012-07-30 14:43:00 -07003384 case F_GETOWNER_UIDS:
Eric Paris828dfe12008-04-17 13:17:49 -04003385 /* Just check FD__USE permission */
David Howells88e67f32008-11-14 10:39:21 +11003386 err = file_has_perm(cred, file, 0);
Eric Paris828dfe12008-04-17 13:17:49 -04003387 break;
3388 case F_GETLK:
3389 case F_SETLK:
3390 case F_SETLKW:
Jeff Layton0d3f7a22014-04-22 08:23:58 -04003391 case F_OFD_GETLK:
3392 case F_OFD_SETLK:
3393 case F_OFD_SETLKW:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003394#if BITS_PER_LONG == 32
Eric Paris828dfe12008-04-17 13:17:49 -04003395 case F_GETLK64:
3396 case F_SETLK64:
3397 case F_SETLKW64:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003398#endif
David Howells88e67f32008-11-14 10:39:21 +11003399 err = file_has_perm(cred, file, FILE__LOCK);
Eric Paris828dfe12008-04-17 13:17:49 -04003400 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003401 }
3402
3403 return err;
3404}
3405
Jeff Laytone0b93ed2014-08-22 11:27:32 -04003406static void selinux_file_set_fowner(struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003407{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003408 struct file_security_struct *fsec;
3409
Linus Torvalds1da177e2005-04-16 15:20:36 -07003410 fsec = file->f_security;
David Howells275bb412008-11-14 10:39:19 +11003411 fsec->fown_sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003412}
3413
3414static int selinux_file_send_sigiotask(struct task_struct *tsk,
3415 struct fown_struct *fown, int signum)
3416{
Eric Paris828dfe12008-04-17 13:17:49 -04003417 struct file *file;
Stephen Smalley65c90bc2009-05-04 15:43:18 -04003418 u32 sid = task_sid(tsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003419 u32 perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003420 struct file_security_struct *fsec;
3421
3422 /* struct fown_struct is never outside the context of a struct file */
Eric Paris828dfe12008-04-17 13:17:49 -04003423 file = container_of(fown, struct file, f_owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003424
Linus Torvalds1da177e2005-04-16 15:20:36 -07003425 fsec = file->f_security;
3426
3427 if (!signum)
3428 perm = signal_to_av(SIGIO); /* as per send_sigio_to_task */
3429 else
3430 perm = signal_to_av(signum);
3431
David Howells275bb412008-11-14 10:39:19 +11003432 return avc_has_perm(fsec->fown_sid, sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003433 SECCLASS_PROCESS, perm, NULL);
3434}
3435
3436static int selinux_file_receive(struct file *file)
3437{
David Howells88e67f32008-11-14 10:39:21 +11003438 const struct cred *cred = current_cred();
3439
3440 return file_has_perm(cred, file, file_to_av(file));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003441}
3442
Eric Paris83d49852012-04-04 13:45:40 -04003443static int selinux_file_open(struct file *file, const struct cred *cred)
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003444{
3445 struct file_security_struct *fsec;
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003446 struct inode_security_struct *isec;
David Howellsd84f4f92008-11-14 10:39:23 +11003447
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003448 fsec = file->f_security;
Al Viro496ad9a2013-01-23 17:07:38 -05003449 isec = file_inode(file)->i_security;
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003450 /*
3451 * Save inode label and policy sequence number
3452 * at open-time so that selinux_file_permission
3453 * can determine whether revalidation is necessary.
3454 * Task label is already saved in the file security
3455 * struct as its SID.
3456 */
3457 fsec->isid = isec->sid;
3458 fsec->pseqno = avc_policy_seqno();
3459 /*
3460 * Since the inode label or policy seqno may have changed
3461 * between the selinux_inode_permission check and the saving
3462 * of state above, recheck that access is still permitted.
3463 * Otherwise, access might never be revalidated against the
3464 * new inode label or new policy.
3465 * This check is not redundant - do not remove.
3466 */
David Howells13f8e982013-06-13 23:37:55 +01003467 return file_path_has_perm(cred, file, open_file_to_av(file));
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003468}
3469
Linus Torvalds1da177e2005-04-16 15:20:36 -07003470/* task security operations */
3471
3472static int selinux_task_create(unsigned long clone_flags)
3473{
David Howells3b11a1d2008-11-14 10:39:26 +11003474 return current_has_perm(current, PROCESS__FORK);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003475}
3476
David Howellsf1752ee2008-11-14 10:39:17 +11003477/*
David Howellsee18d642009-09-02 09:14:21 +01003478 * allocate the SELinux part of blank credentials
3479 */
3480static int selinux_cred_alloc_blank(struct cred *cred, gfp_t gfp)
3481{
3482 struct task_security_struct *tsec;
3483
3484 tsec = kzalloc(sizeof(struct task_security_struct), gfp);
3485 if (!tsec)
3486 return -ENOMEM;
3487
3488 cred->security = tsec;
3489 return 0;
3490}
3491
3492/*
David Howellsf1752ee2008-11-14 10:39:17 +11003493 * detach and free the LSM part of a set of credentials
3494 */
3495static void selinux_cred_free(struct cred *cred)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003496{
David Howellsf1752ee2008-11-14 10:39:17 +11003497 struct task_security_struct *tsec = cred->security;
David Howellse0e81732009-09-02 09:13:40 +01003498
Tetsuo Handa2edeaa32011-02-07 13:36:10 +00003499 /*
3500 * cred->security == NULL if security_cred_alloc_blank() or
3501 * security_prepare_creds() returned an error.
3502 */
3503 BUG_ON(cred->security && (unsigned long) cred->security < PAGE_SIZE);
David Howellse0e81732009-09-02 09:13:40 +01003504 cred->security = (void *) 0x7UL;
David Howellsf1752ee2008-11-14 10:39:17 +11003505 kfree(tsec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003506}
3507
David Howellsd84f4f92008-11-14 10:39:23 +11003508/*
3509 * prepare a new set of credentials for modification
3510 */
3511static int selinux_cred_prepare(struct cred *new, const struct cred *old,
3512 gfp_t gfp)
3513{
3514 const struct task_security_struct *old_tsec;
3515 struct task_security_struct *tsec;
3516
3517 old_tsec = old->security;
3518
3519 tsec = kmemdup(old_tsec, sizeof(struct task_security_struct), gfp);
3520 if (!tsec)
3521 return -ENOMEM;
3522
3523 new->security = tsec;
3524 return 0;
3525}
3526
3527/*
David Howellsee18d642009-09-02 09:14:21 +01003528 * transfer the SELinux data to a blank set of creds
3529 */
3530static void selinux_cred_transfer(struct cred *new, const struct cred *old)
3531{
3532 const struct task_security_struct *old_tsec = old->security;
3533 struct task_security_struct *tsec = new->security;
3534
3535 *tsec = *old_tsec;
3536}
3537
3538/*
David Howells3a3b7ce2008-11-14 10:39:28 +11003539 * set the security data for a kernel service
3540 * - all the creation contexts are set to unlabelled
3541 */
3542static int selinux_kernel_act_as(struct cred *new, u32 secid)
3543{
3544 struct task_security_struct *tsec = new->security;
3545 u32 sid = current_sid();
3546 int ret;
3547
3548 ret = avc_has_perm(sid, secid,
3549 SECCLASS_KERNEL_SERVICE,
3550 KERNEL_SERVICE__USE_AS_OVERRIDE,
3551 NULL);
3552 if (ret == 0) {
3553 tsec->sid = secid;
3554 tsec->create_sid = 0;
3555 tsec->keycreate_sid = 0;
3556 tsec->sockcreate_sid = 0;
3557 }
3558 return ret;
3559}
3560
3561/*
3562 * set the file creation context in a security record to the same as the
3563 * objective context of the specified inode
3564 */
3565static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode)
3566{
3567 struct inode_security_struct *isec = inode->i_security;
3568 struct task_security_struct *tsec = new->security;
3569 u32 sid = current_sid();
3570 int ret;
3571
3572 ret = avc_has_perm(sid, isec->sid,
3573 SECCLASS_KERNEL_SERVICE,
3574 KERNEL_SERVICE__CREATE_FILES_AS,
3575 NULL);
3576
3577 if (ret == 0)
3578 tsec->create_sid = isec->sid;
David Howellsef574712010-02-26 01:56:16 +00003579 return ret;
David Howells3a3b7ce2008-11-14 10:39:28 +11003580}
3581
Eric Parisdd8dbf22009-11-03 16:35:32 +11003582static int selinux_kernel_module_request(char *kmod_name)
Eric Paris25354c42009-08-13 09:45:03 -04003583{
Eric Parisdd8dbf22009-11-03 16:35:32 +11003584 u32 sid;
3585 struct common_audit_data ad;
3586
3587 sid = task_sid(current);
3588
Eric Paris50c205f2012-04-04 15:01:43 -04003589 ad.type = LSM_AUDIT_DATA_KMOD;
Eric Parisdd8dbf22009-11-03 16:35:32 +11003590 ad.u.kmod_name = kmod_name;
3591
3592 return avc_has_perm(sid, SECINITSID_KERNEL, SECCLASS_SYSTEM,
3593 SYSTEM__MODULE_REQUEST, &ad);
Eric Paris25354c42009-08-13 09:45:03 -04003594}
3595
Linus Torvalds1da177e2005-04-16 15:20:36 -07003596static int selinux_task_setpgid(struct task_struct *p, pid_t pgid)
3597{
David Howells3b11a1d2008-11-14 10:39:26 +11003598 return current_has_perm(p, PROCESS__SETPGID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003599}
3600
3601static int selinux_task_getpgid(struct task_struct *p)
3602{
David Howells3b11a1d2008-11-14 10:39:26 +11003603 return current_has_perm(p, PROCESS__GETPGID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003604}
3605
3606static int selinux_task_getsid(struct task_struct *p)
3607{
David Howells3b11a1d2008-11-14 10:39:26 +11003608 return current_has_perm(p, PROCESS__GETSESSION);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003609}
3610
David Quigleyf9008e4c2006-06-30 01:55:46 -07003611static void selinux_task_getsecid(struct task_struct *p, u32 *secid)
3612{
David Howells275bb412008-11-14 10:39:19 +11003613 *secid = task_sid(p);
David Quigleyf9008e4c2006-06-30 01:55:46 -07003614}
3615
Linus Torvalds1da177e2005-04-16 15:20:36 -07003616static int selinux_task_setnice(struct task_struct *p, int nice)
3617{
David Howells3b11a1d2008-11-14 10:39:26 +11003618 return current_has_perm(p, PROCESS__SETSCHED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003619}
3620
James Morris03e68062006-06-23 02:03:58 -07003621static int selinux_task_setioprio(struct task_struct *p, int ioprio)
3622{
David Howells3b11a1d2008-11-14 10:39:26 +11003623 return current_has_perm(p, PROCESS__SETSCHED);
James Morris03e68062006-06-23 02:03:58 -07003624}
3625
David Quigleya1836a42006-06-30 01:55:49 -07003626static int selinux_task_getioprio(struct task_struct *p)
3627{
David Howells3b11a1d2008-11-14 10:39:26 +11003628 return current_has_perm(p, PROCESS__GETSCHED);
David Quigleya1836a42006-06-30 01:55:49 -07003629}
3630
Jiri Slaby8fd00b42009-08-26 18:41:16 +02003631static int selinux_task_setrlimit(struct task_struct *p, unsigned int resource,
3632 struct rlimit *new_rlim)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003633{
Jiri Slaby8fd00b42009-08-26 18:41:16 +02003634 struct rlimit *old_rlim = p->signal->rlim + resource;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003635
3636 /* Control the ability to change the hard limit (whether
3637 lowering or raising it), so that the hard limit can
3638 later be used as a safe reset point for the soft limit
David Howellsd84f4f92008-11-14 10:39:23 +11003639 upon context transitions. See selinux_bprm_committing_creds. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003640 if (old_rlim->rlim_max != new_rlim->rlim_max)
Jiri Slaby8fd00b42009-08-26 18:41:16 +02003641 return current_has_perm(p, PROCESS__SETRLIMIT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003642
3643 return 0;
3644}
3645
KOSAKI Motohirob0ae1982010-10-15 04:21:18 +09003646static int selinux_task_setscheduler(struct task_struct *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003647{
David Howells3b11a1d2008-11-14 10:39:26 +11003648 return current_has_perm(p, PROCESS__SETSCHED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003649}
3650
3651static int selinux_task_getscheduler(struct task_struct *p)
3652{
David Howells3b11a1d2008-11-14 10:39:26 +11003653 return current_has_perm(p, PROCESS__GETSCHED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003654}
3655
David Quigley35601542006-06-23 02:04:01 -07003656static int selinux_task_movememory(struct task_struct *p)
3657{
David Howells3b11a1d2008-11-14 10:39:26 +11003658 return current_has_perm(p, PROCESS__SETSCHED);
David Quigley35601542006-06-23 02:04:01 -07003659}
3660
David Quigleyf9008e4c2006-06-30 01:55:46 -07003661static int selinux_task_kill(struct task_struct *p, struct siginfo *info,
3662 int sig, u32 secid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003663{
3664 u32 perm;
3665 int rc;
3666
Linus Torvalds1da177e2005-04-16 15:20:36 -07003667 if (!sig)
3668 perm = PROCESS__SIGNULL; /* null signal; existence test */
3669 else
3670 perm = signal_to_av(sig);
David Quigleyf9008e4c2006-06-30 01:55:46 -07003671 if (secid)
David Howells275bb412008-11-14 10:39:19 +11003672 rc = avc_has_perm(secid, task_sid(p),
3673 SECCLASS_PROCESS, perm, NULL);
David Quigleyf9008e4c2006-06-30 01:55:46 -07003674 else
David Howells3b11a1d2008-11-14 10:39:26 +11003675 rc = current_has_perm(p, perm);
David Quigleyf9008e4c2006-06-30 01:55:46 -07003676 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003677}
3678
Linus Torvalds1da177e2005-04-16 15:20:36 -07003679static int selinux_task_wait(struct task_struct *p)
3680{
Eric Paris8a535142007-10-22 16:10:31 -04003681 return task_has_perm(p, current, PROCESS__SIGCHLD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003682}
3683
Linus Torvalds1da177e2005-04-16 15:20:36 -07003684static void selinux_task_to_inode(struct task_struct *p,
3685 struct inode *inode)
3686{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003687 struct inode_security_struct *isec = inode->i_security;
David Howells275bb412008-11-14 10:39:19 +11003688 u32 sid = task_sid(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003689
David Howells275bb412008-11-14 10:39:19 +11003690 isec->sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003691 isec->initialized = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003692}
3693
Linus Torvalds1da177e2005-04-16 15:20:36 -07003694/* Returns error only if unable to parse addresses */
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003695static int selinux_parse_skb_ipv4(struct sk_buff *skb,
Thomas Liu2bf49692009-07-14 12:14:09 -04003696 struct common_audit_data *ad, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003697{
3698 int offset, ihlen, ret = -EINVAL;
3699 struct iphdr _iph, *ih;
3700
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03003701 offset = skb_network_offset(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003702 ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph);
3703 if (ih == NULL)
3704 goto out;
3705
3706 ihlen = ih->ihl * 4;
3707 if (ihlen < sizeof(_iph))
3708 goto out;
3709
Eric Paris48c62af2012-04-02 13:15:44 -04003710 ad->u.net->v4info.saddr = ih->saddr;
3711 ad->u.net->v4info.daddr = ih->daddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003712 ret = 0;
3713
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003714 if (proto)
3715 *proto = ih->protocol;
3716
Linus Torvalds1da177e2005-04-16 15:20:36 -07003717 switch (ih->protocol) {
Eric Paris828dfe12008-04-17 13:17:49 -04003718 case IPPROTO_TCP: {
3719 struct tcphdr _tcph, *th;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003720
Eric Paris828dfe12008-04-17 13:17:49 -04003721 if (ntohs(ih->frag_off) & IP_OFFSET)
3722 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003723
3724 offset += ihlen;
3725 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
3726 if (th == NULL)
3727 break;
3728
Eric Paris48c62af2012-04-02 13:15:44 -04003729 ad->u.net->sport = th->source;
3730 ad->u.net->dport = th->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003731 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003732 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003733
Eric Paris828dfe12008-04-17 13:17:49 -04003734 case IPPROTO_UDP: {
3735 struct udphdr _udph, *uh;
3736
3737 if (ntohs(ih->frag_off) & IP_OFFSET)
3738 break;
3739
3740 offset += ihlen;
3741 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
3742 if (uh == NULL)
3743 break;
3744
Eric Paris48c62af2012-04-02 13:15:44 -04003745 ad->u.net->sport = uh->source;
3746 ad->u.net->dport = uh->dest;
Eric Paris828dfe12008-04-17 13:17:49 -04003747 break;
3748 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003749
James Morris2ee92d42006-11-13 16:09:01 -08003750 case IPPROTO_DCCP: {
3751 struct dccp_hdr _dccph, *dh;
3752
3753 if (ntohs(ih->frag_off) & IP_OFFSET)
3754 break;
3755
3756 offset += ihlen;
3757 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
3758 if (dh == NULL)
3759 break;
3760
Eric Paris48c62af2012-04-02 13:15:44 -04003761 ad->u.net->sport = dh->dccph_sport;
3762 ad->u.net->dport = dh->dccph_dport;
James Morris2ee92d42006-11-13 16:09:01 -08003763 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003764 }
James Morris2ee92d42006-11-13 16:09:01 -08003765
Eric Paris828dfe12008-04-17 13:17:49 -04003766 default:
3767 break;
3768 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003769out:
3770 return ret;
3771}
3772
3773#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
3774
3775/* Returns error only if unable to parse addresses */
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003776static int selinux_parse_skb_ipv6(struct sk_buff *skb,
Thomas Liu2bf49692009-07-14 12:14:09 -04003777 struct common_audit_data *ad, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003778{
3779 u8 nexthdr;
3780 int ret = -EINVAL, offset;
3781 struct ipv6hdr _ipv6h, *ip6;
Jesse Gross75f28112011-11-30 17:05:51 -08003782 __be16 frag_off;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003783
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03003784 offset = skb_network_offset(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003785 ip6 = skb_header_pointer(skb, offset, sizeof(_ipv6h), &_ipv6h);
3786 if (ip6 == NULL)
3787 goto out;
3788
Eric Paris48c62af2012-04-02 13:15:44 -04003789 ad->u.net->v6info.saddr = ip6->saddr;
3790 ad->u.net->v6info.daddr = ip6->daddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003791 ret = 0;
3792
3793 nexthdr = ip6->nexthdr;
3794 offset += sizeof(_ipv6h);
Jesse Gross75f28112011-11-30 17:05:51 -08003795 offset = ipv6_skip_exthdr(skb, offset, &nexthdr, &frag_off);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003796 if (offset < 0)
3797 goto out;
3798
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003799 if (proto)
3800 *proto = nexthdr;
3801
Linus Torvalds1da177e2005-04-16 15:20:36 -07003802 switch (nexthdr) {
3803 case IPPROTO_TCP: {
Eric Paris828dfe12008-04-17 13:17:49 -04003804 struct tcphdr _tcph, *th;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003805
3806 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
3807 if (th == NULL)
3808 break;
3809
Eric Paris48c62af2012-04-02 13:15:44 -04003810 ad->u.net->sport = th->source;
3811 ad->u.net->dport = th->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003812 break;
3813 }
3814
3815 case IPPROTO_UDP: {
3816 struct udphdr _udph, *uh;
3817
3818 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
3819 if (uh == NULL)
3820 break;
3821
Eric Paris48c62af2012-04-02 13:15:44 -04003822 ad->u.net->sport = uh->source;
3823 ad->u.net->dport = uh->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003824 break;
3825 }
3826
James Morris2ee92d42006-11-13 16:09:01 -08003827 case IPPROTO_DCCP: {
3828 struct dccp_hdr _dccph, *dh;
3829
3830 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
3831 if (dh == NULL)
3832 break;
3833
Eric Paris48c62af2012-04-02 13:15:44 -04003834 ad->u.net->sport = dh->dccph_sport;
3835 ad->u.net->dport = dh->dccph_dport;
James Morris2ee92d42006-11-13 16:09:01 -08003836 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003837 }
James Morris2ee92d42006-11-13 16:09:01 -08003838
Linus Torvalds1da177e2005-04-16 15:20:36 -07003839 /* includes fragments */
3840 default:
3841 break;
3842 }
3843out:
3844 return ret;
3845}
3846
3847#endif /* IPV6 */
3848
Thomas Liu2bf49692009-07-14 12:14:09 -04003849static int selinux_parse_skb(struct sk_buff *skb, struct common_audit_data *ad,
David Howellscf9481e2008-07-27 21:31:07 +10003850 char **_addrp, int src, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003851{
David Howellscf9481e2008-07-27 21:31:07 +10003852 char *addrp;
3853 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003854
Eric Paris48c62af2012-04-02 13:15:44 -04003855 switch (ad->u.net->family) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003856 case PF_INET:
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003857 ret = selinux_parse_skb_ipv4(skb, ad, proto);
David Howellscf9481e2008-07-27 21:31:07 +10003858 if (ret)
3859 goto parse_error;
Eric Paris48c62af2012-04-02 13:15:44 -04003860 addrp = (char *)(src ? &ad->u.net->v4info.saddr :
3861 &ad->u.net->v4info.daddr);
David Howellscf9481e2008-07-27 21:31:07 +10003862 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003863
3864#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
3865 case PF_INET6:
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003866 ret = selinux_parse_skb_ipv6(skb, ad, proto);
David Howellscf9481e2008-07-27 21:31:07 +10003867 if (ret)
3868 goto parse_error;
Eric Paris48c62af2012-04-02 13:15:44 -04003869 addrp = (char *)(src ? &ad->u.net->v6info.saddr :
3870 &ad->u.net->v6info.daddr);
David Howellscf9481e2008-07-27 21:31:07 +10003871 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003872#endif /* IPV6 */
3873 default:
David Howellscf9481e2008-07-27 21:31:07 +10003874 addrp = NULL;
3875 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003876 }
3877
David Howellscf9481e2008-07-27 21:31:07 +10003878parse_error:
3879 printk(KERN_WARNING
3880 "SELinux: failure in selinux_parse_skb(),"
3881 " unable to parse packet\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003882 return ret;
David Howellscf9481e2008-07-27 21:31:07 +10003883
3884okay:
3885 if (_addrp)
3886 *_addrp = addrp;
3887 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003888}
3889
Paul Moore4f6a9932007-03-01 14:35:22 -05003890/**
Paul Moore220deb92008-01-29 08:38:23 -05003891 * selinux_skb_peerlbl_sid - Determine the peer label of a packet
Paul Moore4f6a9932007-03-01 14:35:22 -05003892 * @skb: the packet
Paul Moore75e22912008-01-29 08:38:04 -05003893 * @family: protocol family
Paul Moore220deb92008-01-29 08:38:23 -05003894 * @sid: the packet's peer label SID
Paul Moore4f6a9932007-03-01 14:35:22 -05003895 *
3896 * Description:
Paul Moore220deb92008-01-29 08:38:23 -05003897 * Check the various different forms of network peer labeling and determine
3898 * the peer label/SID for the packet; most of the magic actually occurs in
3899 * the security server function security_net_peersid_cmp(). The function
3900 * returns zero if the value in @sid is valid (although it may be SECSID_NULL)
3901 * or -EACCES if @sid is invalid due to inconsistencies with the different
3902 * peer labels.
Paul Moore4f6a9932007-03-01 14:35:22 -05003903 *
3904 */
Paul Moore220deb92008-01-29 08:38:23 -05003905static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)
Paul Moore4f6a9932007-03-01 14:35:22 -05003906{
Paul Moore71f1cb02008-01-29 08:51:16 -05003907 int err;
Paul Moore4f6a9932007-03-01 14:35:22 -05003908 u32 xfrm_sid;
3909 u32 nlbl_sid;
Paul Moore220deb92008-01-29 08:38:23 -05003910 u32 nlbl_type;
Paul Moore4f6a9932007-03-01 14:35:22 -05003911
Paul Moore817eff72013-12-10 14:57:54 -05003912 err = selinux_xfrm_skb_sid(skb, &xfrm_sid);
Paul Moorebed4d7e2013-07-23 17:38:40 -04003913 if (unlikely(err))
3914 return -EACCES;
3915 err = selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid);
3916 if (unlikely(err))
3917 return -EACCES;
Paul Moore220deb92008-01-29 08:38:23 -05003918
Paul Moore71f1cb02008-01-29 08:51:16 -05003919 err = security_net_peersid_resolve(nlbl_sid, nlbl_type, xfrm_sid, sid);
3920 if (unlikely(err)) {
3921 printk(KERN_WARNING
3922 "SELinux: failure in selinux_skb_peerlbl_sid(),"
3923 " unable to determine packet's peer label\n");
Paul Moore220deb92008-01-29 08:38:23 -05003924 return -EACCES;
Paul Moore71f1cb02008-01-29 08:51:16 -05003925 }
Paul Moore220deb92008-01-29 08:38:23 -05003926
3927 return 0;
Paul Moore4f6a9932007-03-01 14:35:22 -05003928}
3929
Paul Moore446b8022013-12-04 16:10:51 -05003930/**
3931 * selinux_conn_sid - Determine the child socket label for a connection
3932 * @sk_sid: the parent socket's SID
3933 * @skb_sid: the packet's SID
3934 * @conn_sid: the resulting connection SID
3935 *
3936 * If @skb_sid is valid then the user:role:type information from @sk_sid is
3937 * combined with the MLS information from @skb_sid in order to create
3938 * @conn_sid. If @skb_sid is not valid then then @conn_sid is simply a copy
3939 * of @sk_sid. Returns zero on success, negative values on failure.
3940 *
3941 */
3942static int selinux_conn_sid(u32 sk_sid, u32 skb_sid, u32 *conn_sid)
3943{
3944 int err = 0;
3945
3946 if (skb_sid != SECSID_NULL)
3947 err = security_sid_mls_copy(sk_sid, skb_sid, conn_sid);
3948 else
3949 *conn_sid = sk_sid;
3950
3951 return err;
3952}
3953
Linus Torvalds1da177e2005-04-16 15:20:36 -07003954/* socket security operations */
Paul Moored4f2d972010-04-22 14:46:18 -04003955
Harry Ciao2ad18bd2011-03-02 13:32:34 +08003956static int socket_sockcreate_sid(const struct task_security_struct *tsec,
3957 u16 secclass, u32 *socksid)
Paul Moored4f2d972010-04-22 14:46:18 -04003958{
Harry Ciao2ad18bd2011-03-02 13:32:34 +08003959 if (tsec->sockcreate_sid > SECSID_NULL) {
3960 *socksid = tsec->sockcreate_sid;
3961 return 0;
3962 }
3963
3964 return security_transition_sid(tsec->sid, tsec->sid, secclass, NULL,
3965 socksid);
Paul Moored4f2d972010-04-22 14:46:18 -04003966}
3967
Paul Moore253bfae2010-04-22 14:46:19 -04003968static int sock_has_perm(struct task_struct *task, struct sock *sk, u32 perms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003969{
Paul Moore253bfae2010-04-22 14:46:19 -04003970 struct sk_security_struct *sksec = sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04003971 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04003972 struct lsm_network_audit net = {0,};
Paul Moore253bfae2010-04-22 14:46:19 -04003973 u32 tsid = task_sid(task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003974
Paul Moore253bfae2010-04-22 14:46:19 -04003975 if (sksec->sid == SECINITSID_KERNEL)
3976 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003977
Eric Paris50c205f2012-04-04 15:01:43 -04003978 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04003979 ad.u.net = &net;
3980 ad.u.net->sk = sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003981
Paul Moore253bfae2010-04-22 14:46:19 -04003982 return avc_has_perm(tsid, sksec->sid, sksec->sclass, perms, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003983}
3984
3985static int selinux_socket_create(int family, int type,
3986 int protocol, int kern)
3987{
Paul Moore5fb49872010-04-22 14:46:19 -04003988 const struct task_security_struct *tsec = current_security();
Paul Moored4f2d972010-04-22 14:46:18 -04003989 u32 newsid;
David Howells275bb412008-11-14 10:39:19 +11003990 u16 secclass;
Harry Ciao2ad18bd2011-03-02 13:32:34 +08003991 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003992
3993 if (kern)
Paul Moored4f2d972010-04-22 14:46:18 -04003994 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003995
David Howells275bb412008-11-14 10:39:19 +11003996 secclass = socket_type_to_security_class(family, type, protocol);
Harry Ciao2ad18bd2011-03-02 13:32:34 +08003997 rc = socket_sockcreate_sid(tsec, secclass, &newsid);
3998 if (rc)
3999 return rc;
4000
Paul Moored4f2d972010-04-22 14:46:18 -04004001 return avc_has_perm(tsec->sid, newsid, secclass, SOCKET__CREATE, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004002}
4003
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07004004static int selinux_socket_post_create(struct socket *sock, int family,
4005 int type, int protocol, int kern)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004006{
Paul Moore5fb49872010-04-22 14:46:19 -04004007 const struct task_security_struct *tsec = current_security();
Paul Moored4f2d972010-04-22 14:46:18 -04004008 struct inode_security_struct *isec = SOCK_INODE(sock)->i_security;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004009 struct sk_security_struct *sksec;
David Howells275bb412008-11-14 10:39:19 +11004010 int err = 0;
4011
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004012 isec->sclass = socket_type_to_security_class(family, type, protocol);
4013
David Howells275bb412008-11-14 10:39:19 +11004014 if (kern)
4015 isec->sid = SECINITSID_KERNEL;
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004016 else {
4017 err = socket_sockcreate_sid(tsec, isec->sclass, &(isec->sid));
4018 if (err)
4019 return err;
4020 }
David Howells275bb412008-11-14 10:39:19 +11004021
Linus Torvalds1da177e2005-04-16 15:20:36 -07004022 isec->initialized = 1;
4023
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004024 if (sock->sk) {
4025 sksec = sock->sk->sk_security;
4026 sksec->sid = isec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05004027 sksec->sclass = isec->sclass;
Paul Moore389fb8002009-03-27 17:10:34 -04004028 err = selinux_netlbl_socket_post_create(sock->sk, family);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004029 }
4030
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07004031 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004032}
4033
4034/* Range of port numbers used to automatically bind.
4035 Need to determine whether we should perform a name_bind
4036 permission check between the socket and the port number. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004037
4038static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen)
4039{
Paul Moore253bfae2010-04-22 14:46:19 -04004040 struct sock *sk = sock->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004041 u16 family;
4042 int err;
4043
Paul Moore253bfae2010-04-22 14:46:19 -04004044 err = sock_has_perm(current, sk, SOCKET__BIND);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004045 if (err)
4046 goto out;
4047
4048 /*
4049 * If PF_INET or PF_INET6, check name_bind permission for the port.
James Morris13402582005-09-30 14:24:34 -04004050 * Multiple address binding for SCTP is not supported yet: we just
4051 * check the first address now.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004052 */
Paul Moore253bfae2010-04-22 14:46:19 -04004053 family = sk->sk_family;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004054 if (family == PF_INET || family == PF_INET6) {
4055 char *addrp;
Paul Moore253bfae2010-04-22 14:46:19 -04004056 struct sk_security_struct *sksec = sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004057 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004058 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004059 struct sockaddr_in *addr4 = NULL;
4060 struct sockaddr_in6 *addr6 = NULL;
4061 unsigned short snum;
James Morrise399f982008-06-12 01:39:58 +10004062 u32 sid, node_perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004063
Linus Torvalds1da177e2005-04-16 15:20:36 -07004064 if (family == PF_INET) {
4065 addr4 = (struct sockaddr_in *)address;
4066 snum = ntohs(addr4->sin_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004067 addrp = (char *)&addr4->sin_addr.s_addr;
4068 } else {
4069 addr6 = (struct sockaddr_in6 *)address;
4070 snum = ntohs(addr6->sin6_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004071 addrp = (char *)&addr6->sin6_addr.s6_addr;
4072 }
4073
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004074 if (snum) {
4075 int low, high;
4076
Eric W. Biederman0bbf87d2013-09-28 14:10:59 -07004077 inet_get_local_port_range(sock_net(sk), &low, &high);
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004078
4079 if (snum < max(PROT_SOCK, low) || snum > high) {
Paul Moore3e1121722008-04-10 10:48:14 -04004080 err = sel_netport_sid(sk->sk_protocol,
4081 snum, &sid);
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004082 if (err)
4083 goto out;
Eric Paris50c205f2012-04-04 15:01:43 -04004084 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004085 ad.u.net = &net;
4086 ad.u.net->sport = htons(snum);
4087 ad.u.net->family = family;
Paul Moore253bfae2010-04-22 14:46:19 -04004088 err = avc_has_perm(sksec->sid, sid,
4089 sksec->sclass,
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004090 SOCKET__NAME_BIND, &ad);
4091 if (err)
4092 goto out;
4093 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004094 }
Eric Paris828dfe12008-04-17 13:17:49 -04004095
Paul Moore253bfae2010-04-22 14:46:19 -04004096 switch (sksec->sclass) {
James Morris13402582005-09-30 14:24:34 -04004097 case SECCLASS_TCP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004098 node_perm = TCP_SOCKET__NODE_BIND;
4099 break;
Eric Paris828dfe12008-04-17 13:17:49 -04004100
James Morris13402582005-09-30 14:24:34 -04004101 case SECCLASS_UDP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004102 node_perm = UDP_SOCKET__NODE_BIND;
4103 break;
James Morris2ee92d42006-11-13 16:09:01 -08004104
4105 case SECCLASS_DCCP_SOCKET:
4106 node_perm = DCCP_SOCKET__NODE_BIND;
4107 break;
4108
Linus Torvalds1da177e2005-04-16 15:20:36 -07004109 default:
4110 node_perm = RAWIP_SOCKET__NODE_BIND;
4111 break;
4112 }
Eric Paris828dfe12008-04-17 13:17:49 -04004113
Paul Moore224dfbd2008-01-29 08:38:13 -05004114 err = sel_netnode_sid(addrp, family, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004115 if (err)
4116 goto out;
Eric Paris828dfe12008-04-17 13:17:49 -04004117
Eric Paris50c205f2012-04-04 15:01:43 -04004118 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004119 ad.u.net = &net;
4120 ad.u.net->sport = htons(snum);
4121 ad.u.net->family = family;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004122
4123 if (family == PF_INET)
Eric Paris48c62af2012-04-02 13:15:44 -04004124 ad.u.net->v4info.saddr = addr4->sin_addr.s_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004125 else
Eric Paris48c62af2012-04-02 13:15:44 -04004126 ad.u.net->v6info.saddr = addr6->sin6_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004127
Paul Moore253bfae2010-04-22 14:46:19 -04004128 err = avc_has_perm(sksec->sid, sid,
4129 sksec->sclass, node_perm, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004130 if (err)
4131 goto out;
4132 }
4133out:
4134 return err;
4135}
4136
4137static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen)
4138{
Paul Moore014ab192008-10-10 10:16:33 -04004139 struct sock *sk = sock->sk;
Paul Moore253bfae2010-04-22 14:46:19 -04004140 struct sk_security_struct *sksec = sk->sk_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004141 int err;
4142
Paul Moore253bfae2010-04-22 14:46:19 -04004143 err = sock_has_perm(current, sk, SOCKET__CONNECT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004144 if (err)
4145 return err;
4146
4147 /*
James Morris2ee92d42006-11-13 16:09:01 -08004148 * If a TCP or DCCP socket, check name_connect permission for the port.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004149 */
Paul Moore253bfae2010-04-22 14:46:19 -04004150 if (sksec->sclass == SECCLASS_TCP_SOCKET ||
4151 sksec->sclass == SECCLASS_DCCP_SOCKET) {
Thomas Liu2bf49692009-07-14 12:14:09 -04004152 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004153 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004154 struct sockaddr_in *addr4 = NULL;
4155 struct sockaddr_in6 *addr6 = NULL;
4156 unsigned short snum;
James Morris2ee92d42006-11-13 16:09:01 -08004157 u32 sid, perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004158
4159 if (sk->sk_family == PF_INET) {
4160 addr4 = (struct sockaddr_in *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07004161 if (addrlen < sizeof(struct sockaddr_in))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004162 return -EINVAL;
4163 snum = ntohs(addr4->sin_port);
4164 } else {
4165 addr6 = (struct sockaddr_in6 *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07004166 if (addrlen < SIN6_LEN_RFC2133)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004167 return -EINVAL;
4168 snum = ntohs(addr6->sin6_port);
4169 }
4170
Paul Moore3e1121722008-04-10 10:48:14 -04004171 err = sel_netport_sid(sk->sk_protocol, snum, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004172 if (err)
4173 goto out;
4174
Paul Moore253bfae2010-04-22 14:46:19 -04004175 perm = (sksec->sclass == SECCLASS_TCP_SOCKET) ?
James Morris2ee92d42006-11-13 16:09:01 -08004176 TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT;
4177
Eric Paris50c205f2012-04-04 15:01:43 -04004178 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004179 ad.u.net = &net;
4180 ad.u.net->dport = htons(snum);
4181 ad.u.net->family = sk->sk_family;
Paul Moore253bfae2010-04-22 14:46:19 -04004182 err = avc_has_perm(sksec->sid, sid, sksec->sclass, perm, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004183 if (err)
4184 goto out;
4185 }
4186
Paul Moore014ab192008-10-10 10:16:33 -04004187 err = selinux_netlbl_socket_connect(sk, address);
4188
Linus Torvalds1da177e2005-04-16 15:20:36 -07004189out:
4190 return err;
4191}
4192
4193static int selinux_socket_listen(struct socket *sock, int backlog)
4194{
Paul Moore253bfae2010-04-22 14:46:19 -04004195 return sock_has_perm(current, sock->sk, SOCKET__LISTEN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004196}
4197
4198static int selinux_socket_accept(struct socket *sock, struct socket *newsock)
4199{
4200 int err;
4201 struct inode_security_struct *isec;
4202 struct inode_security_struct *newisec;
4203
Paul Moore253bfae2010-04-22 14:46:19 -04004204 err = sock_has_perm(current, sock->sk, SOCKET__ACCEPT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004205 if (err)
4206 return err;
4207
4208 newisec = SOCK_INODE(newsock)->i_security;
4209
4210 isec = SOCK_INODE(sock)->i_security;
4211 newisec->sclass = isec->sclass;
4212 newisec->sid = isec->sid;
4213 newisec->initialized = 1;
4214
4215 return 0;
4216}
4217
4218static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg,
Eric Paris828dfe12008-04-17 13:17:49 -04004219 int size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004220{
Paul Moore253bfae2010-04-22 14:46:19 -04004221 return sock_has_perm(current, sock->sk, SOCKET__WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004222}
4223
4224static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg,
4225 int size, int flags)
4226{
Paul Moore253bfae2010-04-22 14:46:19 -04004227 return sock_has_perm(current, sock->sk, SOCKET__READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004228}
4229
4230static int selinux_socket_getsockname(struct socket *sock)
4231{
Paul Moore253bfae2010-04-22 14:46:19 -04004232 return sock_has_perm(current, sock->sk, SOCKET__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004233}
4234
4235static int selinux_socket_getpeername(struct socket *sock)
4236{
Paul Moore253bfae2010-04-22 14:46:19 -04004237 return sock_has_perm(current, sock->sk, SOCKET__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004238}
4239
Eric Paris828dfe12008-04-17 13:17:49 -04004240static int selinux_socket_setsockopt(struct socket *sock, int level, int optname)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004241{
Paul Mooref8687af2006-10-30 15:22:15 -08004242 int err;
4243
Paul Moore253bfae2010-04-22 14:46:19 -04004244 err = sock_has_perm(current, sock->sk, SOCKET__SETOPT);
Paul Mooref8687af2006-10-30 15:22:15 -08004245 if (err)
4246 return err;
4247
4248 return selinux_netlbl_socket_setsockopt(sock, level, optname);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004249}
4250
4251static int selinux_socket_getsockopt(struct socket *sock, int level,
4252 int optname)
4253{
Paul Moore253bfae2010-04-22 14:46:19 -04004254 return sock_has_perm(current, sock->sk, SOCKET__GETOPT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004255}
4256
4257static int selinux_socket_shutdown(struct socket *sock, int how)
4258{
Paul Moore253bfae2010-04-22 14:46:19 -04004259 return sock_has_perm(current, sock->sk, SOCKET__SHUTDOWN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004260}
4261
David S. Miller3610cda2011-01-05 15:38:53 -08004262static int selinux_socket_unix_stream_connect(struct sock *sock,
4263 struct sock *other,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004264 struct sock *newsk)
4265{
David S. Miller3610cda2011-01-05 15:38:53 -08004266 struct sk_security_struct *sksec_sock = sock->sk_security;
4267 struct sk_security_struct *sksec_other = other->sk_security;
Paul Moore4d1e2452010-04-22 14:46:18 -04004268 struct sk_security_struct *sksec_new = newsk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004269 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004270 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004271 int err;
4272
Eric Paris50c205f2012-04-04 15:01:43 -04004273 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004274 ad.u.net = &net;
4275 ad.u.net->sk = other;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004276
Paul Moore4d1e2452010-04-22 14:46:18 -04004277 err = avc_has_perm(sksec_sock->sid, sksec_other->sid,
4278 sksec_other->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004279 UNIX_STREAM_SOCKET__CONNECTTO, &ad);
4280 if (err)
4281 return err;
4282
Linus Torvalds1da177e2005-04-16 15:20:36 -07004283 /* server child socket */
Paul Moore4d1e2452010-04-22 14:46:18 -04004284 sksec_new->peer_sid = sksec_sock->sid;
4285 err = security_sid_mls_copy(sksec_other->sid, sksec_sock->sid,
4286 &sksec_new->sid);
4287 if (err)
4288 return err;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004289
Paul Moore4d1e2452010-04-22 14:46:18 -04004290 /* connecting socket */
4291 sksec_sock->peer_sid = sksec_new->sid;
4292
4293 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004294}
4295
4296static int selinux_socket_unix_may_send(struct socket *sock,
4297 struct socket *other)
4298{
Paul Moore253bfae2010-04-22 14:46:19 -04004299 struct sk_security_struct *ssec = sock->sk->sk_security;
4300 struct sk_security_struct *osec = other->sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004301 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004302 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004303
Eric Paris50c205f2012-04-04 15:01:43 -04004304 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004305 ad.u.net = &net;
4306 ad.u.net->sk = other->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004307
Paul Moore253bfae2010-04-22 14:46:19 -04004308 return avc_has_perm(ssec->sid, osec->sid, osec->sclass, SOCKET__SENDTO,
4309 &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004310}
4311
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004312static int selinux_inet_sys_rcv_skb(struct net *ns, int ifindex,
4313 char *addrp, u16 family, u32 peer_sid,
Thomas Liu2bf49692009-07-14 12:14:09 -04004314 struct common_audit_data *ad)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004315{
4316 int err;
4317 u32 if_sid;
4318 u32 node_sid;
4319
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004320 err = sel_netif_sid(ns, ifindex, &if_sid);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004321 if (err)
4322 return err;
4323 err = avc_has_perm(peer_sid, if_sid,
4324 SECCLASS_NETIF, NETIF__INGRESS, ad);
4325 if (err)
4326 return err;
4327
4328 err = sel_netnode_sid(addrp, family, &node_sid);
4329 if (err)
4330 return err;
4331 return avc_has_perm(peer_sid, node_sid,
4332 SECCLASS_NODE, NODE__RECVFROM, ad);
4333}
4334
Paul Moore220deb92008-01-29 08:38:23 -05004335static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
Paul Moored8395c82008-10-10 10:16:30 -04004336 u16 family)
Paul Moore220deb92008-01-29 08:38:23 -05004337{
Paul Moore277d3422008-12-31 12:54:11 -05004338 int err = 0;
Paul Moore220deb92008-01-29 08:38:23 -05004339 struct sk_security_struct *sksec = sk->sk_security;
Paul Moore220deb92008-01-29 08:38:23 -05004340 u32 sk_sid = sksec->sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04004341 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004342 struct lsm_network_audit net = {0,};
Paul Moored8395c82008-10-10 10:16:30 -04004343 char *addrp;
4344
Eric Paris50c205f2012-04-04 15:01:43 -04004345 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004346 ad.u.net = &net;
4347 ad.u.net->netif = skb->skb_iif;
4348 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04004349 err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
4350 if (err)
4351 return err;
Paul Moore220deb92008-01-29 08:38:23 -05004352
Paul Moore58bfbb52009-03-27 17:10:41 -04004353 if (selinux_secmark_enabled()) {
Paul Moore220deb92008-01-29 08:38:23 -05004354 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
Paul Moored8395c82008-10-10 10:16:30 -04004355 PACKET__RECV, &ad);
Paul Moore58bfbb52009-03-27 17:10:41 -04004356 if (err)
4357 return err;
4358 }
Paul Moore220deb92008-01-29 08:38:23 -05004359
Steffen Klassertb9679a72011-02-23 12:55:21 +01004360 err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, &ad);
4361 if (err)
4362 return err;
4363 err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, &ad);
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004364
James Morris4e5ab4c2006-06-09 00:33:33 -07004365 return err;
4366}
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004367
James Morris4e5ab4c2006-06-09 00:33:33 -07004368static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
4369{
Paul Moore220deb92008-01-29 08:38:23 -05004370 int err;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004371 struct sk_security_struct *sksec = sk->sk_security;
Paul Moore220deb92008-01-29 08:38:23 -05004372 u16 family = sk->sk_family;
4373 u32 sk_sid = sksec->sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04004374 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004375 struct lsm_network_audit net = {0,};
Paul Moore220deb92008-01-29 08:38:23 -05004376 char *addrp;
Paul Moored8395c82008-10-10 10:16:30 -04004377 u8 secmark_active;
4378 u8 peerlbl_active;
James Morris4e5ab4c2006-06-09 00:33:33 -07004379
James Morris4e5ab4c2006-06-09 00:33:33 -07004380 if (family != PF_INET && family != PF_INET6)
Paul Moore220deb92008-01-29 08:38:23 -05004381 return 0;
James Morris4e5ab4c2006-06-09 00:33:33 -07004382
4383 /* Handle mapped IPv4 packets arriving via IPv6 sockets */
Al Viro87fcd702006-12-04 22:00:55 +00004384 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
James Morris4e5ab4c2006-06-09 00:33:33 -07004385 family = PF_INET;
4386
Paul Moored8395c82008-10-10 10:16:30 -04004387 /* If any sort of compatibility mode is enabled then handoff processing
4388 * to the selinux_sock_rcv_skb_compat() function to deal with the
4389 * special handling. We do this in an attempt to keep this function
4390 * as fast and as clean as possible. */
Paul Moore58bfbb52009-03-27 17:10:41 -04004391 if (!selinux_policycap_netpeer)
Paul Moored8395c82008-10-10 10:16:30 -04004392 return selinux_sock_rcv_skb_compat(sk, skb, family);
4393
4394 secmark_active = selinux_secmark_enabled();
Chris PeBenito2be4d742013-05-03 09:05:39 -04004395 peerlbl_active = selinux_peerlbl_enabled();
Paul Moored8395c82008-10-10 10:16:30 -04004396 if (!secmark_active && !peerlbl_active)
4397 return 0;
4398
Eric Paris50c205f2012-04-04 15:01:43 -04004399 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004400 ad.u.net = &net;
4401 ad.u.net->netif = skb->skb_iif;
4402 ad.u.net->family = family;
Paul Moore224dfbd2008-01-29 08:38:13 -05004403 err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
James Morris4e5ab4c2006-06-09 00:33:33 -07004404 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05004405 return err;
James Morris4e5ab4c2006-06-09 00:33:33 -07004406
Paul Moored8395c82008-10-10 10:16:30 -04004407 if (peerlbl_active) {
Paul Moored621d352008-01-29 08:43:36 -05004408 u32 peer_sid;
4409
4410 err = selinux_skb_peerlbl_sid(skb, family, &peer_sid);
4411 if (err)
4412 return err;
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004413 err = selinux_inet_sys_rcv_skb(sock_net(sk), skb->skb_iif,
4414 addrp, family, peer_sid, &ad);
Paul Mooredfaebe92008-10-10 10:16:31 -04004415 if (err) {
4416 selinux_netlbl_err(skb, err, 0);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004417 return err;
Paul Mooredfaebe92008-10-10 10:16:31 -04004418 }
Paul Moored621d352008-01-29 08:43:36 -05004419 err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER,
4420 PEER__RECV, &ad);
Chad Hanson46d01d62013-12-23 17:45:01 -05004421 if (err) {
Paul Mooredfaebe92008-10-10 10:16:31 -04004422 selinux_netlbl_err(skb, err, 0);
Chad Hanson46d01d62013-12-23 17:45:01 -05004423 return err;
4424 }
Paul Moored621d352008-01-29 08:43:36 -05004425 }
4426
Paul Moored8395c82008-10-10 10:16:30 -04004427 if (secmark_active) {
Paul Mooreeffad8d2008-01-29 08:49:27 -05004428 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
4429 PACKET__RECV, &ad);
4430 if (err)
4431 return err;
4432 }
4433
Paul Moored621d352008-01-29 08:43:36 -05004434 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004435}
4436
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004437static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *optval,
4438 int __user *optlen, unsigned len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004439{
4440 int err = 0;
4441 char *scontext;
4442 u32 scontext_len;
Paul Moore253bfae2010-04-22 14:46:19 -04004443 struct sk_security_struct *sksec = sock->sk->sk_security;
Paul Moore3de4bab2006-11-17 17:38:54 -05004444 u32 peer_sid = SECSID_NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004445
Paul Moore253bfae2010-04-22 14:46:19 -04004446 if (sksec->sclass == SECCLASS_UNIX_STREAM_SOCKET ||
4447 sksec->sclass == SECCLASS_TCP_SOCKET)
Eric Parisdd3e7832010-04-07 15:08:46 -04004448 peer_sid = sksec->peer_sid;
Paul Moore253bfae2010-04-22 14:46:19 -04004449 if (peer_sid == SECSID_NULL)
4450 return -ENOPROTOOPT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004451
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004452 err = security_sid_to_context(peer_sid, &scontext, &scontext_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004453 if (err)
Paul Moore253bfae2010-04-22 14:46:19 -04004454 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004455
4456 if (scontext_len > len) {
4457 err = -ERANGE;
4458 goto out_len;
4459 }
4460
4461 if (copy_to_user(optval, scontext, scontext_len))
4462 err = -EFAULT;
4463
4464out_len:
4465 if (put_user(scontext_len, optlen))
4466 err = -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004467 kfree(scontext);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004468 return err;
4469}
4470
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004471static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid)
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004472{
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004473 u32 peer_secid = SECSID_NULL;
Paul Moore75e22912008-01-29 08:38:04 -05004474 u16 family;
Catherine Zhang877ce7c2006-06-29 12:27:47 -07004475
Paul Mooreaa862902008-10-10 10:16:29 -04004476 if (skb && skb->protocol == htons(ETH_P_IP))
4477 family = PF_INET;
4478 else if (skb && skb->protocol == htons(ETH_P_IPV6))
4479 family = PF_INET6;
4480 else if (sock)
Paul Moore75e22912008-01-29 08:38:04 -05004481 family = sock->sk->sk_family;
Paul Moore75e22912008-01-29 08:38:04 -05004482 else
4483 goto out;
4484
4485 if (sock && family == PF_UNIX)
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02004486 selinux_inode_getsecid(SOCK_INODE(sock), &peer_secid);
Paul Moore3de4bab2006-11-17 17:38:54 -05004487 else if (skb)
Paul Moore220deb92008-01-29 08:38:23 -05004488 selinux_skb_peerlbl_sid(skb, family, &peer_secid);
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004489
Paul Moore75e22912008-01-29 08:38:04 -05004490out:
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004491 *secid = peer_secid;
Paul Moore75e22912008-01-29 08:38:04 -05004492 if (peer_secid == SECSID_NULL)
4493 return -EINVAL;
4494 return 0;
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004495}
4496
Al Viro7d877f32005-10-21 03:20:43 -04004497static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004498{
Paul Moore84914b72010-04-22 14:46:18 -04004499 struct sk_security_struct *sksec;
4500
4501 sksec = kzalloc(sizeof(*sksec), priority);
4502 if (!sksec)
4503 return -ENOMEM;
4504
4505 sksec->peer_sid = SECINITSID_UNLABELED;
4506 sksec->sid = SECINITSID_UNLABELED;
4507 selinux_netlbl_sk_security_reset(sksec);
4508 sk->sk_security = sksec;
4509
4510 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004511}
4512
4513static void selinux_sk_free_security(struct sock *sk)
4514{
Paul Moore84914b72010-04-22 14:46:18 -04004515 struct sk_security_struct *sksec = sk->sk_security;
4516
4517 sk->sk_security = NULL;
4518 selinux_netlbl_sk_security_free(sksec);
4519 kfree(sksec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004520}
4521
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004522static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk)
4523{
Eric Parisdd3e7832010-04-07 15:08:46 -04004524 struct sk_security_struct *sksec = sk->sk_security;
4525 struct sk_security_struct *newsksec = newsk->sk_security;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004526
Eric Parisdd3e7832010-04-07 15:08:46 -04004527 newsksec->sid = sksec->sid;
4528 newsksec->peer_sid = sksec->peer_sid;
4529 newsksec->sclass = sksec->sclass;
Paul Moore99f59ed2006-08-29 17:53:48 -07004530
Eric Parisdd3e7832010-04-07 15:08:46 -04004531 selinux_netlbl_sk_security_reset(newsksec);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004532}
4533
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004534static void selinux_sk_getsecid(struct sock *sk, u32 *secid)
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004535{
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004536 if (!sk)
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004537 *secid = SECINITSID_ANY_SOCKET;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004538 else {
4539 struct sk_security_struct *sksec = sk->sk_security;
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004540
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004541 *secid = sksec->sid;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004542 }
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004543}
4544
Eric Paris828dfe12008-04-17 13:17:49 -04004545static void selinux_sock_graft(struct sock *sk, struct socket *parent)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004546{
4547 struct inode_security_struct *isec = SOCK_INODE(parent)->i_security;
4548 struct sk_security_struct *sksec = sk->sk_security;
4549
Paul Moore2873ead2014-07-28 10:42:48 -04004550 if (sk->sk_family == PF_INET || sk->sk_family == PF_INET6 ||
4551 sk->sk_family == PF_UNIX)
David Woodhouse2148ccc2006-09-29 15:50:25 -07004552 isec->sid = sksec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05004553 sksec->sclass = isec->sclass;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004554}
4555
Adrian Bunk9a673e52006-08-15 00:03:53 -07004556static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
4557 struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004558{
4559 struct sk_security_struct *sksec = sk->sk_security;
4560 int err;
Paul Moore0b1f24e2013-12-03 11:39:13 -05004561 u16 family = req->rsk_ops->family;
Paul Moore446b8022013-12-04 16:10:51 -05004562 u32 connsid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004563 u32 peersid;
4564
Paul Mooreaa862902008-10-10 10:16:29 -04004565 err = selinux_skb_peerlbl_sid(skb, family, &peersid);
Paul Moore220deb92008-01-29 08:38:23 -05004566 if (err)
4567 return err;
Paul Moore446b8022013-12-04 16:10:51 -05004568 err = selinux_conn_sid(sksec->sid, peersid, &connsid);
4569 if (err)
4570 return err;
4571 req->secid = connsid;
4572 req->peer_secid = peersid;
Venkat Yekkiralaa51c64f2006-07-27 22:01:34 -07004573
Paul Moore389fb8002009-03-27 17:10:34 -04004574 return selinux_netlbl_inet_conn_request(req, family);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004575}
4576
Adrian Bunk9a673e52006-08-15 00:03:53 -07004577static void selinux_inet_csk_clone(struct sock *newsk,
4578 const struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004579{
4580 struct sk_security_struct *newsksec = newsk->sk_security;
4581
4582 newsksec->sid = req->secid;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004583 newsksec->peer_sid = req->peer_secid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004584 /* NOTE: Ideally, we should also get the isec->sid for the
4585 new socket in sync, but we don't have the isec available yet.
4586 So we will wait until sock_graft to do it, by which
4587 time it will have been created and available. */
Paul Moore99f59ed2006-08-29 17:53:48 -07004588
Paul Moore9f2ad662006-11-17 17:38:53 -05004589 /* We don't need to take any sort of lock here as we are the only
4590 * thread with access to newsksec */
Paul Moore389fb8002009-03-27 17:10:34 -04004591 selinux_netlbl_inet_csk_clone(newsk, req->rsk_ops->family);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004592}
4593
Paul Moore014ab192008-10-10 10:16:33 -04004594static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb)
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004595{
Paul Mooreaa862902008-10-10 10:16:29 -04004596 u16 family = sk->sk_family;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004597 struct sk_security_struct *sksec = sk->sk_security;
4598
Paul Mooreaa862902008-10-10 10:16:29 -04004599 /* handle mapped IPv4 packets arriving via IPv6 sockets */
4600 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
4601 family = PF_INET;
4602
4603 selinux_skb_peerlbl_sid(skb, family, &sksec->peer_sid);
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004604}
4605
Eric Paris2606fd12010-10-13 16:24:41 -04004606static int selinux_secmark_relabel_packet(u32 sid)
4607{
4608 const struct task_security_struct *__tsec;
4609 u32 tsid;
4610
4611 __tsec = current_security();
4612 tsid = __tsec->sid;
4613
4614 return avc_has_perm(tsid, sid, SECCLASS_PACKET, PACKET__RELABELTO, NULL);
4615}
4616
4617static void selinux_secmark_refcount_inc(void)
4618{
4619 atomic_inc(&selinux_secmark_refcount);
4620}
4621
4622static void selinux_secmark_refcount_dec(void)
4623{
4624 atomic_dec(&selinux_secmark_refcount);
4625}
4626
Adrian Bunk9a673e52006-08-15 00:03:53 -07004627static void selinux_req_classify_flow(const struct request_sock *req,
4628 struct flowi *fl)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004629{
David S. Miller1d28f422011-03-12 00:29:39 -05004630 fl->flowi_secid = req->secid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004631}
4632
Paul Moore5dbbaf22013-01-14 07:12:19 +00004633static int selinux_tun_dev_alloc_security(void **security)
4634{
4635 struct tun_security_struct *tunsec;
4636
4637 tunsec = kzalloc(sizeof(*tunsec), GFP_KERNEL);
4638 if (!tunsec)
4639 return -ENOMEM;
4640 tunsec->sid = current_sid();
4641
4642 *security = tunsec;
4643 return 0;
4644}
4645
4646static void selinux_tun_dev_free_security(void *security)
4647{
4648 kfree(security);
4649}
4650
Paul Mooreed6d76e2009-08-28 18:12:49 -04004651static int selinux_tun_dev_create(void)
4652{
4653 u32 sid = current_sid();
4654
4655 /* we aren't taking into account the "sockcreate" SID since the socket
4656 * that is being created here is not a socket in the traditional sense,
4657 * instead it is a private sock, accessible only to the kernel, and
4658 * representing a wide range of network traffic spanning multiple
4659 * connections unlike traditional sockets - check the TUN driver to
4660 * get a better understanding of why this socket is special */
4661
4662 return avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET, TUN_SOCKET__CREATE,
4663 NULL);
4664}
4665
Paul Moore5dbbaf22013-01-14 07:12:19 +00004666static int selinux_tun_dev_attach_queue(void *security)
Paul Mooreed6d76e2009-08-28 18:12:49 -04004667{
Paul Moore5dbbaf22013-01-14 07:12:19 +00004668 struct tun_security_struct *tunsec = security;
4669
4670 return avc_has_perm(current_sid(), tunsec->sid, SECCLASS_TUN_SOCKET,
4671 TUN_SOCKET__ATTACH_QUEUE, NULL);
4672}
4673
4674static int selinux_tun_dev_attach(struct sock *sk, void *security)
4675{
4676 struct tun_security_struct *tunsec = security;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004677 struct sk_security_struct *sksec = sk->sk_security;
4678
4679 /* we don't currently perform any NetLabel based labeling here and it
4680 * isn't clear that we would want to do so anyway; while we could apply
4681 * labeling without the support of the TUN user the resulting labeled
4682 * traffic from the other end of the connection would almost certainly
4683 * cause confusion to the TUN user that had no idea network labeling
4684 * protocols were being used */
4685
Paul Moore5dbbaf22013-01-14 07:12:19 +00004686 sksec->sid = tunsec->sid;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004687 sksec->sclass = SECCLASS_TUN_SOCKET;
Paul Moore5dbbaf22013-01-14 07:12:19 +00004688
4689 return 0;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004690}
4691
Paul Moore5dbbaf22013-01-14 07:12:19 +00004692static int selinux_tun_dev_open(void *security)
Paul Mooreed6d76e2009-08-28 18:12:49 -04004693{
Paul Moore5dbbaf22013-01-14 07:12:19 +00004694 struct tun_security_struct *tunsec = security;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004695 u32 sid = current_sid();
4696 int err;
4697
Paul Moore5dbbaf22013-01-14 07:12:19 +00004698 err = avc_has_perm(sid, tunsec->sid, SECCLASS_TUN_SOCKET,
Paul Mooreed6d76e2009-08-28 18:12:49 -04004699 TUN_SOCKET__RELABELFROM, NULL);
4700 if (err)
4701 return err;
4702 err = avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET,
4703 TUN_SOCKET__RELABELTO, NULL);
4704 if (err)
4705 return err;
Paul Moore5dbbaf22013-01-14 07:12:19 +00004706 tunsec->sid = sid;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004707
4708 return 0;
4709}
4710
Linus Torvalds1da177e2005-04-16 15:20:36 -07004711static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
4712{
4713 int err = 0;
4714 u32 perm;
4715 struct nlmsghdr *nlh;
Paul Moore253bfae2010-04-22 14:46:19 -04004716 struct sk_security_struct *sksec = sk->sk_security;
Eric Paris828dfe12008-04-17 13:17:49 -04004717
Hong zhi guo77954982013-03-27 06:49:35 +00004718 if (skb->len < NLMSG_HDRLEN) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004719 err = -EINVAL;
4720 goto out;
4721 }
Arnaldo Carvalho de Melob529ccf2007-04-25 19:08:35 -07004722 nlh = nlmsg_hdr(skb);
Eric Paris828dfe12008-04-17 13:17:49 -04004723
Paul Moore253bfae2010-04-22 14:46:19 -04004724 err = selinux_nlmsg_lookup(sksec->sclass, nlh->nlmsg_type, &perm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004725 if (err) {
4726 if (err == -EINVAL) {
Richard Guy Briggsd950f842014-11-12 14:01:34 -05004727 printk(KERN_WARNING
4728 "SELinux: unrecognized netlink message:"
Marek Milkoviccded3ff2015-06-04 16:22:16 -04004729 " protocol=%hu nlmsg_type=%hu sclass=%s\n",
4730 sk->sk_protocol, nlh->nlmsg_type,
4731 secclass_map[sksec->sclass - 1].name);
Eric Paris39c9aed2008-11-05 09:34:42 -05004732 if (!selinux_enforcing || security_get_allow_unknown())
Linus Torvalds1da177e2005-04-16 15:20:36 -07004733 err = 0;
4734 }
4735
4736 /* Ignore */
4737 if (err == -ENOENT)
4738 err = 0;
4739 goto out;
4740 }
4741
Paul Moore253bfae2010-04-22 14:46:19 -04004742 err = sock_has_perm(current, sk, perm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004743out:
4744 return err;
4745}
4746
4747#ifdef CONFIG_NETFILTER
4748
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004749static unsigned int selinux_ip_forward(struct sk_buff *skb,
4750 const struct net_device *indev,
Paul Mooreeffad8d2008-01-29 08:49:27 -05004751 u16 family)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004752{
Paul Mooredfaebe92008-10-10 10:16:31 -04004753 int err;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004754 char *addrp;
4755 u32 peer_sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04004756 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004757 struct lsm_network_audit net = {0,};
Paul Mooreeffad8d2008-01-29 08:49:27 -05004758 u8 secmark_active;
Paul Moore948bf852008-10-10 10:16:32 -04004759 u8 netlbl_active;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004760 u8 peerlbl_active;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004761
Paul Mooreeffad8d2008-01-29 08:49:27 -05004762 if (!selinux_policycap_netpeer)
4763 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004764
Paul Mooreeffad8d2008-01-29 08:49:27 -05004765 secmark_active = selinux_secmark_enabled();
Paul Moore948bf852008-10-10 10:16:32 -04004766 netlbl_active = netlbl_enabled();
Chris PeBenito2be4d742013-05-03 09:05:39 -04004767 peerlbl_active = selinux_peerlbl_enabled();
Paul Mooreeffad8d2008-01-29 08:49:27 -05004768 if (!secmark_active && !peerlbl_active)
4769 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004770
Paul Moored8395c82008-10-10 10:16:30 -04004771 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0)
4772 return NF_DROP;
4773
Eric Paris50c205f2012-04-04 15:01:43 -04004774 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004775 ad.u.net = &net;
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004776 ad.u.net->netif = indev->ifindex;
Eric Paris48c62af2012-04-02 13:15:44 -04004777 ad.u.net->family = family;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004778 if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0)
4779 return NF_DROP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004780
Paul Mooredfaebe92008-10-10 10:16:31 -04004781 if (peerlbl_active) {
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004782 err = selinux_inet_sys_rcv_skb(dev_net(indev), indev->ifindex,
4783 addrp, family, peer_sid, &ad);
Paul Mooredfaebe92008-10-10 10:16:31 -04004784 if (err) {
4785 selinux_netlbl_err(skb, err, 1);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004786 return NF_DROP;
Paul Mooredfaebe92008-10-10 10:16:31 -04004787 }
4788 }
Paul Mooreeffad8d2008-01-29 08:49:27 -05004789
4790 if (secmark_active)
4791 if (avc_has_perm(peer_sid, skb->secmark,
4792 SECCLASS_PACKET, PACKET__FORWARD_IN, &ad))
4793 return NF_DROP;
4794
Paul Moore948bf852008-10-10 10:16:32 -04004795 if (netlbl_active)
4796 /* we do this in the FORWARD path and not the POST_ROUTING
4797 * path because we want to make sure we apply the necessary
4798 * labeling before IPsec is applied so we can leverage AH
4799 * protection */
4800 if (selinux_netlbl_skbuff_setsid(skb, family, peer_sid) != 0)
4801 return NF_DROP;
4802
Paul Mooreeffad8d2008-01-29 08:49:27 -05004803 return NF_ACCEPT;
4804}
4805
Patrick McHardy795aa6e2013-10-10 09:21:55 +02004806static unsigned int selinux_ipv4_forward(const struct nf_hook_ops *ops,
Paul Mooreeffad8d2008-01-29 08:49:27 -05004807 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04004808 const struct nf_hook_state *state)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004809{
David S. Miller238e54c2015-04-03 20:32:56 -04004810 return selinux_ip_forward(skb, state->in, PF_INET);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004811}
4812
4813#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Patrick McHardy795aa6e2013-10-10 09:21:55 +02004814static unsigned int selinux_ipv6_forward(const struct nf_hook_ops *ops,
Paul Mooreeffad8d2008-01-29 08:49:27 -05004815 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04004816 const struct nf_hook_state *state)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004817{
David S. Miller238e54c2015-04-03 20:32:56 -04004818 return selinux_ip_forward(skb, state->in, PF_INET6);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004819}
4820#endif /* IPV6 */
4821
Paul Moore948bf852008-10-10 10:16:32 -04004822static unsigned int selinux_ip_output(struct sk_buff *skb,
4823 u16 family)
4824{
Paul Moore47180062013-12-04 16:10:45 -05004825 struct sock *sk;
Paul Moore948bf852008-10-10 10:16:32 -04004826 u32 sid;
4827
4828 if (!netlbl_enabled())
4829 return NF_ACCEPT;
4830
4831 /* we do this in the LOCAL_OUT path and not the POST_ROUTING path
4832 * because we want to make sure we apply the necessary labeling
4833 * before IPsec is applied so we can leverage AH protection */
Paul Moore47180062013-12-04 16:10:45 -05004834 sk = skb->sk;
4835 if (sk) {
4836 struct sk_security_struct *sksec;
4837
4838 if (sk->sk_state == TCP_LISTEN)
4839 /* if the socket is the listening state then this
4840 * packet is a SYN-ACK packet which means it needs to
4841 * be labeled based on the connection/request_sock and
4842 * not the parent socket. unfortunately, we can't
4843 * lookup the request_sock yet as it isn't queued on
4844 * the parent socket until after the SYN-ACK is sent.
4845 * the "solution" is to simply pass the packet as-is
4846 * as any IP option based labeling should be copied
4847 * from the initial connection request (in the IP
4848 * layer). it is far from ideal, but until we get a
4849 * security label in the packet itself this is the
4850 * best we can do. */
4851 return NF_ACCEPT;
4852
4853 /* standard practice, label using the parent socket */
4854 sksec = sk->sk_security;
Paul Moore948bf852008-10-10 10:16:32 -04004855 sid = sksec->sid;
4856 } else
4857 sid = SECINITSID_KERNEL;
4858 if (selinux_netlbl_skbuff_setsid(skb, family, sid) != 0)
4859 return NF_DROP;
4860
4861 return NF_ACCEPT;
4862}
4863
Patrick McHardy795aa6e2013-10-10 09:21:55 +02004864static unsigned int selinux_ipv4_output(const struct nf_hook_ops *ops,
Paul Moore948bf852008-10-10 10:16:32 -04004865 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04004866 const struct nf_hook_state *state)
Paul Moore948bf852008-10-10 10:16:32 -04004867{
4868 return selinux_ip_output(skb, PF_INET);
4869}
4870
Paul Mooreeffad8d2008-01-29 08:49:27 -05004871static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
4872 int ifindex,
Paul Moored8395c82008-10-10 10:16:30 -04004873 u16 family)
James Morris4e5ab4c2006-06-09 00:33:33 -07004874{
Paul Mooreeffad8d2008-01-29 08:49:27 -05004875 struct sock *sk = skb->sk;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004876 struct sk_security_struct *sksec;
Thomas Liu2bf49692009-07-14 12:14:09 -04004877 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004878 struct lsm_network_audit net = {0,};
Paul Moored8395c82008-10-10 10:16:30 -04004879 char *addrp;
4880 u8 proto;
James Morris4e5ab4c2006-06-09 00:33:33 -07004881
Paul Mooreeffad8d2008-01-29 08:49:27 -05004882 if (sk == NULL)
4883 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004884 sksec = sk->sk_security;
James Morris4e5ab4c2006-06-09 00:33:33 -07004885
Eric Paris50c205f2012-04-04 15:01:43 -04004886 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004887 ad.u.net = &net;
4888 ad.u.net->netif = ifindex;
4889 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04004890 if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto))
4891 return NF_DROP;
4892
Paul Moore58bfbb52009-03-27 17:10:41 -04004893 if (selinux_secmark_enabled())
Paul Mooreeffad8d2008-01-29 08:49:27 -05004894 if (avc_has_perm(sksec->sid, skb->secmark,
Paul Moored8395c82008-10-10 10:16:30 -04004895 SECCLASS_PACKET, PACKET__SEND, &ad))
Eric Paris2fe66ec2010-11-23 06:28:08 +00004896 return NF_DROP_ERR(-ECONNREFUSED);
James Morris4e5ab4c2006-06-09 00:33:33 -07004897
Steffen Klassertb9679a72011-02-23 12:55:21 +01004898 if (selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto))
4899 return NF_DROP_ERR(-ECONNREFUSED);
James Morris4e5ab4c2006-06-09 00:33:33 -07004900
Paul Mooreeffad8d2008-01-29 08:49:27 -05004901 return NF_ACCEPT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004902}
4903
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004904static unsigned int selinux_ip_postroute(struct sk_buff *skb,
4905 const struct net_device *outdev,
Paul Mooreeffad8d2008-01-29 08:49:27 -05004906 u16 family)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004907{
Paul Mooreeffad8d2008-01-29 08:49:27 -05004908 u32 secmark_perm;
4909 u32 peer_sid;
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004910 int ifindex = outdev->ifindex;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004911 struct sock *sk;
Thomas Liu2bf49692009-07-14 12:14:09 -04004912 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004913 struct lsm_network_audit net = {0,};
Paul Mooreeffad8d2008-01-29 08:49:27 -05004914 char *addrp;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004915 u8 secmark_active;
4916 u8 peerlbl_active;
4917
Paul Mooreeffad8d2008-01-29 08:49:27 -05004918 /* If any sort of compatibility mode is enabled then handoff processing
4919 * to the selinux_ip_postroute_compat() function to deal with the
4920 * special handling. We do this in an attempt to keep this function
4921 * as fast and as clean as possible. */
Paul Moore58bfbb52009-03-27 17:10:41 -04004922 if (!selinux_policycap_netpeer)
Paul Moored8395c82008-10-10 10:16:30 -04004923 return selinux_ip_postroute_compat(skb, ifindex, family);
Paul Moorec0828e52013-12-10 14:58:01 -05004924
Paul Mooreeffad8d2008-01-29 08:49:27 -05004925 secmark_active = selinux_secmark_enabled();
Chris PeBenito2be4d742013-05-03 09:05:39 -04004926 peerlbl_active = selinux_peerlbl_enabled();
Paul Mooreeffad8d2008-01-29 08:49:27 -05004927 if (!secmark_active && !peerlbl_active)
4928 return NF_ACCEPT;
4929
Paul Mooreeffad8d2008-01-29 08:49:27 -05004930 sk = skb->sk;
Paul Moorec0828e52013-12-10 14:58:01 -05004931
Paul Mooreeffad8d2008-01-29 08:49:27 -05004932#ifdef CONFIG_XFRM
4933 /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec
4934 * packet transformation so allow the packet to pass without any checks
4935 * since we'll have another chance to perform access control checks
4936 * when the packet is on it's final way out.
4937 * NOTE: there appear to be some IPv6 multicast cases where skb->dst
Paul Moorec0828e52013-12-10 14:58:01 -05004938 * is NULL, in this case go ahead and apply access control.
4939 * NOTE: if this is a local socket (skb->sk != NULL) that is in the
4940 * TCP listening state we cannot wait until the XFRM processing
4941 * is done as we will miss out on the SA label if we do;
4942 * unfortunately, this means more work, but it is only once per
4943 * connection. */
4944 if (skb_dst(skb) != NULL && skb_dst(skb)->xfrm != NULL &&
4945 !(sk != NULL && sk->sk_state == TCP_LISTEN))
Paul Mooreeffad8d2008-01-29 08:49:27 -05004946 return NF_ACCEPT;
4947#endif
Paul Mooreeffad8d2008-01-29 08:49:27 -05004948
Paul Moored8395c82008-10-10 10:16:30 -04004949 if (sk == NULL) {
Paul Moore446b8022013-12-04 16:10:51 -05004950 /* Without an associated socket the packet is either coming
4951 * from the kernel or it is being forwarded; check the packet
4952 * to determine which and if the packet is being forwarded
4953 * query the packet directly to determine the security label. */
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01004954 if (skb->skb_iif) {
4955 secmark_perm = PACKET__FORWARD_OUT;
Paul Moored8395c82008-10-10 10:16:30 -04004956 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00004957 return NF_DROP;
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01004958 } else {
4959 secmark_perm = PACKET__SEND;
Paul Moored8395c82008-10-10 10:16:30 -04004960 peer_sid = SECINITSID_KERNEL;
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01004961 }
Paul Moore446b8022013-12-04 16:10:51 -05004962 } else if (sk->sk_state == TCP_LISTEN) {
4963 /* Locally generated packet but the associated socket is in the
4964 * listening state which means this is a SYN-ACK packet. In
4965 * this particular case the correct security label is assigned
4966 * to the connection/request_sock but unfortunately we can't
4967 * query the request_sock as it isn't queued on the parent
4968 * socket until after the SYN-ACK packet is sent; the only
4969 * viable choice is to regenerate the label like we do in
4970 * selinux_inet_conn_request(). See also selinux_ip_output()
4971 * for similar problems. */
4972 u32 skb_sid;
4973 struct sk_security_struct *sksec = sk->sk_security;
4974 if (selinux_skb_peerlbl_sid(skb, family, &skb_sid))
4975 return NF_DROP;
Paul Moorec0828e52013-12-10 14:58:01 -05004976 /* At this point, if the returned skb peerlbl is SECSID_NULL
4977 * and the packet has been through at least one XFRM
4978 * transformation then we must be dealing with the "final"
4979 * form of labeled IPsec packet; since we've already applied
4980 * all of our access controls on this packet we can safely
4981 * pass the packet. */
4982 if (skb_sid == SECSID_NULL) {
4983 switch (family) {
4984 case PF_INET:
4985 if (IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED)
4986 return NF_ACCEPT;
4987 break;
4988 case PF_INET6:
4989 if (IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED)
4990 return NF_ACCEPT;
Paul Moorea7a91a12014-09-03 10:51:59 -04004991 break;
Paul Moorec0828e52013-12-10 14:58:01 -05004992 default:
4993 return NF_DROP_ERR(-ECONNREFUSED);
4994 }
4995 }
Paul Moore446b8022013-12-04 16:10:51 -05004996 if (selinux_conn_sid(sksec->sid, skb_sid, &peer_sid))
4997 return NF_DROP;
4998 secmark_perm = PACKET__SEND;
Paul Moored8395c82008-10-10 10:16:30 -04004999 } else {
Paul Moore446b8022013-12-04 16:10:51 -05005000 /* Locally generated packet, fetch the security label from the
5001 * associated socket. */
Paul Mooreeffad8d2008-01-29 08:49:27 -05005002 struct sk_security_struct *sksec = sk->sk_security;
5003 peer_sid = sksec->sid;
5004 secmark_perm = PACKET__SEND;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005005 }
5006
Eric Paris50c205f2012-04-04 15:01:43 -04005007 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04005008 ad.u.net = &net;
5009 ad.u.net->netif = ifindex;
5010 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04005011 if (selinux_parse_skb(skb, &ad, &addrp, 0, NULL))
Eric Paris04f6d702010-11-23 06:28:02 +00005012 return NF_DROP;
Paul Moored8395c82008-10-10 10:16:30 -04005013
Paul Mooreeffad8d2008-01-29 08:49:27 -05005014 if (secmark_active)
5015 if (avc_has_perm(peer_sid, skb->secmark,
5016 SECCLASS_PACKET, secmark_perm, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00005017 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005018
5019 if (peerlbl_active) {
5020 u32 if_sid;
5021 u32 node_sid;
5022
Paul Moorecbe0d6e2014-09-10 17:09:57 -04005023 if (sel_netif_sid(dev_net(outdev), ifindex, &if_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00005024 return NF_DROP;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005025 if (avc_has_perm(peer_sid, if_sid,
5026 SECCLASS_NETIF, NETIF__EGRESS, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00005027 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005028
5029 if (sel_netnode_sid(addrp, family, &node_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00005030 return NF_DROP;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005031 if (avc_has_perm(peer_sid, node_sid,
5032 SECCLASS_NODE, NODE__SENDTO, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00005033 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005034 }
5035
5036 return NF_ACCEPT;
5037}
5038
Patrick McHardy795aa6e2013-10-10 09:21:55 +02005039static unsigned int selinux_ipv4_postroute(const struct nf_hook_ops *ops,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005040 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04005041 const struct nf_hook_state *state)
Paul Mooreeffad8d2008-01-29 08:49:27 -05005042{
David S. Miller238e54c2015-04-03 20:32:56 -04005043 return selinux_ip_postroute(skb, state->out, PF_INET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005044}
5045
5046#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Patrick McHardy795aa6e2013-10-10 09:21:55 +02005047static unsigned int selinux_ipv6_postroute(const struct nf_hook_ops *ops,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005048 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04005049 const struct nf_hook_state *state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005050{
David S. Miller238e54c2015-04-03 20:32:56 -04005051 return selinux_ip_postroute(skb, state->out, PF_INET6);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005052}
Linus Torvalds1da177e2005-04-16 15:20:36 -07005053#endif /* IPV6 */
5054
5055#endif /* CONFIG_NETFILTER */
5056
Linus Torvalds1da177e2005-04-16 15:20:36 -07005057static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb)
5058{
Stephen Smalley941fc5b2009-10-01 14:48:23 -04005059 return selinux_nlmsg_perm(sk, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005060}
5061
Linus Torvalds1da177e2005-04-16 15:20:36 -07005062static int ipc_alloc_security(struct task_struct *task,
5063 struct kern_ipc_perm *perm,
5064 u16 sclass)
5065{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005066 struct ipc_security_struct *isec;
David Howells275bb412008-11-14 10:39:19 +11005067 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005068
James Morris89d155e2005-10-30 14:59:21 -08005069 isec = kzalloc(sizeof(struct ipc_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005070 if (!isec)
5071 return -ENOMEM;
5072
David Howells275bb412008-11-14 10:39:19 +11005073 sid = task_sid(task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005074 isec->sclass = sclass;
David Howells275bb412008-11-14 10:39:19 +11005075 isec->sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005076 perm->security = isec;
5077
5078 return 0;
5079}
5080
5081static void ipc_free_security(struct kern_ipc_perm *perm)
5082{
5083 struct ipc_security_struct *isec = perm->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005084 perm->security = NULL;
5085 kfree(isec);
5086}
5087
5088static int msg_msg_alloc_security(struct msg_msg *msg)
5089{
5090 struct msg_security_struct *msec;
5091
James Morris89d155e2005-10-30 14:59:21 -08005092 msec = kzalloc(sizeof(struct msg_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005093 if (!msec)
5094 return -ENOMEM;
5095
Linus Torvalds1da177e2005-04-16 15:20:36 -07005096 msec->sid = SECINITSID_UNLABELED;
5097 msg->security = msec;
5098
5099 return 0;
5100}
5101
5102static void msg_msg_free_security(struct msg_msg *msg)
5103{
5104 struct msg_security_struct *msec = msg->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005105
5106 msg->security = NULL;
5107 kfree(msec);
5108}
5109
5110static int ipc_has_perm(struct kern_ipc_perm *ipc_perms,
Stephen Smalley6af963f2005-05-01 08:58:39 -07005111 u32 perms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005112{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005113 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005114 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005115 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005116
Linus Torvalds1da177e2005-04-16 15:20:36 -07005117 isec = ipc_perms->security;
5118
Eric Paris50c205f2012-04-04 15:01:43 -04005119 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005120 ad.u.ipc_id = ipc_perms->key;
5121
David Howells275bb412008-11-14 10:39:19 +11005122 return avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005123}
5124
5125static int selinux_msg_msg_alloc_security(struct msg_msg *msg)
5126{
5127 return msg_msg_alloc_security(msg);
5128}
5129
5130static void selinux_msg_msg_free_security(struct msg_msg *msg)
5131{
5132 msg_msg_free_security(msg);
5133}
5134
5135/* message queue security operations */
5136static int selinux_msg_queue_alloc_security(struct msg_queue *msq)
5137{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005138 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005139 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005140 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005141 int rc;
5142
5143 rc = ipc_alloc_security(current, &msq->q_perm, SECCLASS_MSGQ);
5144 if (rc)
5145 return rc;
5146
Linus Torvalds1da177e2005-04-16 15:20:36 -07005147 isec = msq->q_perm.security;
5148
Eric Paris50c205f2012-04-04 15:01:43 -04005149 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04005150 ad.u.ipc_id = msq->q_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005151
David Howells275bb412008-11-14 10:39:19 +11005152 rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005153 MSGQ__CREATE, &ad);
5154 if (rc) {
5155 ipc_free_security(&msq->q_perm);
5156 return rc;
5157 }
5158 return 0;
5159}
5160
5161static void selinux_msg_queue_free_security(struct msg_queue *msq)
5162{
5163 ipc_free_security(&msq->q_perm);
5164}
5165
5166static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg)
5167{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005168 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005169 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005170 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005171
Linus Torvalds1da177e2005-04-16 15:20:36 -07005172 isec = msq->q_perm.security;
5173
Eric Paris50c205f2012-04-04 15:01:43 -04005174 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005175 ad.u.ipc_id = msq->q_perm.key;
5176
David Howells275bb412008-11-14 10:39:19 +11005177 return avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005178 MSGQ__ASSOCIATE, &ad);
5179}
5180
5181static int selinux_msg_queue_msgctl(struct msg_queue *msq, int cmd)
5182{
5183 int err;
5184 int perms;
5185
Eric Paris828dfe12008-04-17 13:17:49 -04005186 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005187 case IPC_INFO:
5188 case MSG_INFO:
5189 /* No specific object, just general system-wide information. */
5190 return task_has_system(current, SYSTEM__IPC_INFO);
5191 case IPC_STAT:
5192 case MSG_STAT:
5193 perms = MSGQ__GETATTR | MSGQ__ASSOCIATE;
5194 break;
5195 case IPC_SET:
5196 perms = MSGQ__SETATTR;
5197 break;
5198 case IPC_RMID:
5199 perms = MSGQ__DESTROY;
5200 break;
5201 default:
5202 return 0;
5203 }
5204
Stephen Smalley6af963f2005-05-01 08:58:39 -07005205 err = ipc_has_perm(&msq->q_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005206 return err;
5207}
5208
5209static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, int msqflg)
5210{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005211 struct ipc_security_struct *isec;
5212 struct msg_security_struct *msec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005213 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005214 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005215 int rc;
5216
Linus Torvalds1da177e2005-04-16 15:20:36 -07005217 isec = msq->q_perm.security;
5218 msec = msg->security;
5219
5220 /*
5221 * First time through, need to assign label to the message
5222 */
5223 if (msec->sid == SECINITSID_UNLABELED) {
5224 /*
5225 * Compute new sid based on current process and
5226 * message queue this message will be stored in
5227 */
David Howells275bb412008-11-14 10:39:19 +11005228 rc = security_transition_sid(sid, isec->sid, SECCLASS_MSG,
Eric Paris652bb9b2011-02-01 11:05:40 -05005229 NULL, &msec->sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005230 if (rc)
5231 return rc;
5232 }
5233
Eric Paris50c205f2012-04-04 15:01:43 -04005234 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005235 ad.u.ipc_id = msq->q_perm.key;
5236
5237 /* Can this process write to the queue? */
David Howells275bb412008-11-14 10:39:19 +11005238 rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005239 MSGQ__WRITE, &ad);
5240 if (!rc)
5241 /* Can this process send the message */
David Howells275bb412008-11-14 10:39:19 +11005242 rc = avc_has_perm(sid, msec->sid, SECCLASS_MSG,
5243 MSG__SEND, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005244 if (!rc)
5245 /* Can the message be put in the queue? */
David Howells275bb412008-11-14 10:39:19 +11005246 rc = avc_has_perm(msec->sid, isec->sid, SECCLASS_MSGQ,
5247 MSGQ__ENQUEUE, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005248
5249 return rc;
5250}
5251
5252static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
5253 struct task_struct *target,
5254 long type, int mode)
5255{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005256 struct ipc_security_struct *isec;
5257 struct msg_security_struct *msec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005258 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005259 u32 sid = task_sid(target);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005260 int rc;
5261
Linus Torvalds1da177e2005-04-16 15:20:36 -07005262 isec = msq->q_perm.security;
5263 msec = msg->security;
5264
Eric Paris50c205f2012-04-04 15:01:43 -04005265 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04005266 ad.u.ipc_id = msq->q_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005267
David Howells275bb412008-11-14 10:39:19 +11005268 rc = avc_has_perm(sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005269 SECCLASS_MSGQ, MSGQ__READ, &ad);
5270 if (!rc)
David Howells275bb412008-11-14 10:39:19 +11005271 rc = avc_has_perm(sid, msec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005272 SECCLASS_MSG, MSG__RECEIVE, &ad);
5273 return rc;
5274}
5275
5276/* Shared Memory security operations */
5277static int selinux_shm_alloc_security(struct shmid_kernel *shp)
5278{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005279 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005280 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005281 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005282 int rc;
5283
5284 rc = ipc_alloc_security(current, &shp->shm_perm, SECCLASS_SHM);
5285 if (rc)
5286 return rc;
5287
Linus Torvalds1da177e2005-04-16 15:20:36 -07005288 isec = shp->shm_perm.security;
5289
Eric Paris50c205f2012-04-04 15:01:43 -04005290 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04005291 ad.u.ipc_id = shp->shm_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005292
David Howells275bb412008-11-14 10:39:19 +11005293 rc = avc_has_perm(sid, isec->sid, SECCLASS_SHM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005294 SHM__CREATE, &ad);
5295 if (rc) {
5296 ipc_free_security(&shp->shm_perm);
5297 return rc;
5298 }
5299 return 0;
5300}
5301
5302static void selinux_shm_free_security(struct shmid_kernel *shp)
5303{
5304 ipc_free_security(&shp->shm_perm);
5305}
5306
5307static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg)
5308{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005309 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005310 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005311 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005312
Linus Torvalds1da177e2005-04-16 15:20:36 -07005313 isec = shp->shm_perm.security;
5314
Eric Paris50c205f2012-04-04 15:01:43 -04005315 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005316 ad.u.ipc_id = shp->shm_perm.key;
5317
David Howells275bb412008-11-14 10:39:19 +11005318 return avc_has_perm(sid, isec->sid, SECCLASS_SHM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005319 SHM__ASSOCIATE, &ad);
5320}
5321
5322/* Note, at this point, shp is locked down */
5323static int selinux_shm_shmctl(struct shmid_kernel *shp, int cmd)
5324{
5325 int perms;
5326 int err;
5327
Eric Paris828dfe12008-04-17 13:17:49 -04005328 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005329 case IPC_INFO:
5330 case SHM_INFO:
5331 /* No specific object, just general system-wide information. */
5332 return task_has_system(current, SYSTEM__IPC_INFO);
5333 case IPC_STAT:
5334 case SHM_STAT:
5335 perms = SHM__GETATTR | SHM__ASSOCIATE;
5336 break;
5337 case IPC_SET:
5338 perms = SHM__SETATTR;
5339 break;
5340 case SHM_LOCK:
5341 case SHM_UNLOCK:
5342 perms = SHM__LOCK;
5343 break;
5344 case IPC_RMID:
5345 perms = SHM__DESTROY;
5346 break;
5347 default:
5348 return 0;
5349 }
5350
Stephen Smalley6af963f2005-05-01 08:58:39 -07005351 err = ipc_has_perm(&shp->shm_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005352 return err;
5353}
5354
5355static int selinux_shm_shmat(struct shmid_kernel *shp,
5356 char __user *shmaddr, int shmflg)
5357{
5358 u32 perms;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005359
5360 if (shmflg & SHM_RDONLY)
5361 perms = SHM__READ;
5362 else
5363 perms = SHM__READ | SHM__WRITE;
5364
Stephen Smalley6af963f2005-05-01 08:58:39 -07005365 return ipc_has_perm(&shp->shm_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005366}
5367
5368/* Semaphore security operations */
5369static int selinux_sem_alloc_security(struct sem_array *sma)
5370{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005371 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005372 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005373 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005374 int rc;
5375
5376 rc = ipc_alloc_security(current, &sma->sem_perm, SECCLASS_SEM);
5377 if (rc)
5378 return rc;
5379
Linus Torvalds1da177e2005-04-16 15:20:36 -07005380 isec = sma->sem_perm.security;
5381
Eric Paris50c205f2012-04-04 15:01:43 -04005382 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04005383 ad.u.ipc_id = sma->sem_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005384
David Howells275bb412008-11-14 10:39:19 +11005385 rc = avc_has_perm(sid, isec->sid, SECCLASS_SEM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005386 SEM__CREATE, &ad);
5387 if (rc) {
5388 ipc_free_security(&sma->sem_perm);
5389 return rc;
5390 }
5391 return 0;
5392}
5393
5394static void selinux_sem_free_security(struct sem_array *sma)
5395{
5396 ipc_free_security(&sma->sem_perm);
5397}
5398
5399static int selinux_sem_associate(struct sem_array *sma, int semflg)
5400{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005401 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005402 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005403 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005404
Linus Torvalds1da177e2005-04-16 15:20:36 -07005405 isec = sma->sem_perm.security;
5406
Eric Paris50c205f2012-04-04 15:01:43 -04005407 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005408 ad.u.ipc_id = sma->sem_perm.key;
5409
David Howells275bb412008-11-14 10:39:19 +11005410 return avc_has_perm(sid, isec->sid, SECCLASS_SEM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005411 SEM__ASSOCIATE, &ad);
5412}
5413
5414/* Note, at this point, sma is locked down */
5415static int selinux_sem_semctl(struct sem_array *sma, int cmd)
5416{
5417 int err;
5418 u32 perms;
5419
Eric Paris828dfe12008-04-17 13:17:49 -04005420 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005421 case IPC_INFO:
5422 case SEM_INFO:
5423 /* No specific object, just general system-wide information. */
5424 return task_has_system(current, SYSTEM__IPC_INFO);
5425 case GETPID:
5426 case GETNCNT:
5427 case GETZCNT:
5428 perms = SEM__GETATTR;
5429 break;
5430 case GETVAL:
5431 case GETALL:
5432 perms = SEM__READ;
5433 break;
5434 case SETVAL:
5435 case SETALL:
5436 perms = SEM__WRITE;
5437 break;
5438 case IPC_RMID:
5439 perms = SEM__DESTROY;
5440 break;
5441 case IPC_SET:
5442 perms = SEM__SETATTR;
5443 break;
5444 case IPC_STAT:
5445 case SEM_STAT:
5446 perms = SEM__GETATTR | SEM__ASSOCIATE;
5447 break;
5448 default:
5449 return 0;
5450 }
5451
Stephen Smalley6af963f2005-05-01 08:58:39 -07005452 err = ipc_has_perm(&sma->sem_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005453 return err;
5454}
5455
5456static int selinux_sem_semop(struct sem_array *sma,
5457 struct sembuf *sops, unsigned nsops, int alter)
5458{
5459 u32 perms;
5460
5461 if (alter)
5462 perms = SEM__READ | SEM__WRITE;
5463 else
5464 perms = SEM__READ;
5465
Stephen Smalley6af963f2005-05-01 08:58:39 -07005466 return ipc_has_perm(&sma->sem_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005467}
5468
5469static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
5470{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005471 u32 av = 0;
5472
Linus Torvalds1da177e2005-04-16 15:20:36 -07005473 av = 0;
5474 if (flag & S_IRUGO)
5475 av |= IPC__UNIX_READ;
5476 if (flag & S_IWUGO)
5477 av |= IPC__UNIX_WRITE;
5478
5479 if (av == 0)
5480 return 0;
5481
Stephen Smalley6af963f2005-05-01 08:58:39 -07005482 return ipc_has_perm(ipcp, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005483}
5484
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02005485static void selinux_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
5486{
5487 struct ipc_security_struct *isec = ipcp->security;
5488 *secid = isec->sid;
5489}
5490
Eric Paris828dfe12008-04-17 13:17:49 -04005491static void selinux_d_instantiate(struct dentry *dentry, struct inode *inode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005492{
5493 if (inode)
5494 inode_doinit_with_dentry(inode, dentry);
5495}
5496
5497static int selinux_getprocattr(struct task_struct *p,
Al Viro04ff9702007-03-12 16:17:58 +00005498 char *name, char **value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005499{
David Howells275bb412008-11-14 10:39:19 +11005500 const struct task_security_struct *__tsec;
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00005501 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005502 int error;
Al Viro04ff9702007-03-12 16:17:58 +00005503 unsigned len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005504
5505 if (current != p) {
David Howells3b11a1d2008-11-14 10:39:26 +11005506 error = current_has_perm(p, PROCESS__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005507 if (error)
5508 return error;
5509 }
5510
David Howells275bb412008-11-14 10:39:19 +11005511 rcu_read_lock();
5512 __tsec = __task_cred(p)->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005513
5514 if (!strcmp(name, "current"))
David Howells275bb412008-11-14 10:39:19 +11005515 sid = __tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005516 else if (!strcmp(name, "prev"))
David Howells275bb412008-11-14 10:39:19 +11005517 sid = __tsec->osid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005518 else if (!strcmp(name, "exec"))
David Howells275bb412008-11-14 10:39:19 +11005519 sid = __tsec->exec_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005520 else if (!strcmp(name, "fscreate"))
David Howells275bb412008-11-14 10:39:19 +11005521 sid = __tsec->create_sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005522 else if (!strcmp(name, "keycreate"))
David Howells275bb412008-11-14 10:39:19 +11005523 sid = __tsec->keycreate_sid;
Eric Paris42c3e032006-06-26 00:26:03 -07005524 else if (!strcmp(name, "sockcreate"))
David Howells275bb412008-11-14 10:39:19 +11005525 sid = __tsec->sockcreate_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005526 else
David Howells275bb412008-11-14 10:39:19 +11005527 goto invalid;
5528 rcu_read_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005529
5530 if (!sid)
5531 return 0;
5532
Al Viro04ff9702007-03-12 16:17:58 +00005533 error = security_sid_to_context(sid, value, &len);
5534 if (error)
5535 return error;
5536 return len;
David Howells275bb412008-11-14 10:39:19 +11005537
5538invalid:
5539 rcu_read_unlock();
5540 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005541}
5542
5543static int selinux_setprocattr(struct task_struct *p,
5544 char *name, void *value, size_t size)
5545{
5546 struct task_security_struct *tsec;
Roland McGrath03563572008-03-26 15:46:39 -07005547 struct task_struct *tracer;
David Howellsd84f4f92008-11-14 10:39:23 +11005548 struct cred *new;
5549 u32 sid = 0, ptsid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005550 int error;
5551 char *str = value;
5552
5553 if (current != p) {
5554 /* SELinux only allows a process to change its own
5555 security attributes. */
5556 return -EACCES;
5557 }
5558
5559 /*
5560 * Basic control over ability to set these attributes at all.
5561 * current == p, but we'll pass them separately in case the
5562 * above restriction is ever removed.
5563 */
5564 if (!strcmp(name, "exec"))
David Howells3b11a1d2008-11-14 10:39:26 +11005565 error = current_has_perm(p, PROCESS__SETEXEC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005566 else if (!strcmp(name, "fscreate"))
David Howells3b11a1d2008-11-14 10:39:26 +11005567 error = current_has_perm(p, PROCESS__SETFSCREATE);
Michael LeMay4eb582c2006-06-26 00:24:57 -07005568 else if (!strcmp(name, "keycreate"))
David Howells3b11a1d2008-11-14 10:39:26 +11005569 error = current_has_perm(p, PROCESS__SETKEYCREATE);
Eric Paris42c3e032006-06-26 00:26:03 -07005570 else if (!strcmp(name, "sockcreate"))
David Howells3b11a1d2008-11-14 10:39:26 +11005571 error = current_has_perm(p, PROCESS__SETSOCKCREATE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005572 else if (!strcmp(name, "current"))
David Howells3b11a1d2008-11-14 10:39:26 +11005573 error = current_has_perm(p, PROCESS__SETCURRENT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005574 else
5575 error = -EINVAL;
5576 if (error)
5577 return error;
5578
5579 /* Obtain a SID for the context, if one was specified. */
5580 if (size && str[1] && str[1] != '\n') {
5581 if (str[size-1] == '\n') {
5582 str[size-1] = 0;
5583 size--;
5584 }
Nikolay Aleksandrov52a4c642014-03-07 12:44:19 +01005585 error = security_context_to_sid(value, size, &sid, GFP_KERNEL);
Stephen Smalley12b29f32008-05-07 13:03:20 -04005586 if (error == -EINVAL && !strcmp(name, "fscreate")) {
Eric Parisd6ea83e2012-04-04 13:45:49 -04005587 if (!capable(CAP_MAC_ADMIN)) {
5588 struct audit_buffer *ab;
5589 size_t audit_size;
5590
5591 /* We strip a nul only if it is at the end, otherwise the
5592 * context contains a nul and we should audit that */
5593 if (str[size - 1] == '\0')
5594 audit_size = size - 1;
5595 else
5596 audit_size = size;
5597 ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR);
5598 audit_log_format(ab, "op=fscreate invalid_context=");
5599 audit_log_n_untrustedstring(ab, value, audit_size);
5600 audit_log_end(ab);
5601
Stephen Smalley12b29f32008-05-07 13:03:20 -04005602 return error;
Eric Parisd6ea83e2012-04-04 13:45:49 -04005603 }
Stephen Smalley12b29f32008-05-07 13:03:20 -04005604 error = security_context_to_sid_force(value, size,
5605 &sid);
5606 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005607 if (error)
5608 return error;
5609 }
5610
David Howellsd84f4f92008-11-14 10:39:23 +11005611 new = prepare_creds();
5612 if (!new)
5613 return -ENOMEM;
5614
Linus Torvalds1da177e2005-04-16 15:20:36 -07005615 /* Permission checking based on the specified context is
5616 performed during the actual operation (execve,
5617 open/mkdir/...), when we know the full context of the
David Howellsd84f4f92008-11-14 10:39:23 +11005618 operation. See selinux_bprm_set_creds for the execve
Linus Torvalds1da177e2005-04-16 15:20:36 -07005619 checks and may_create for the file creation checks. The
5620 operation will then fail if the context is not permitted. */
David Howellsd84f4f92008-11-14 10:39:23 +11005621 tsec = new->security;
5622 if (!strcmp(name, "exec")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005623 tsec->exec_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005624 } else if (!strcmp(name, "fscreate")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005625 tsec->create_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005626 } else if (!strcmp(name, "keycreate")) {
Michael LeMay4eb582c2006-06-26 00:24:57 -07005627 error = may_create_key(sid, p);
5628 if (error)
David Howellsd84f4f92008-11-14 10:39:23 +11005629 goto abort_change;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005630 tsec->keycreate_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005631 } else if (!strcmp(name, "sockcreate")) {
Eric Paris42c3e032006-06-26 00:26:03 -07005632 tsec->sockcreate_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005633 } else if (!strcmp(name, "current")) {
5634 error = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005635 if (sid == 0)
David Howellsd84f4f92008-11-14 10:39:23 +11005636 goto abort_change;
KaiGai Koheid9250de2008-08-28 16:35:57 +09005637
David Howellsd84f4f92008-11-14 10:39:23 +11005638 /* Only allow single threaded processes to change context */
5639 error = -EPERM;
Oleg Nesterov5bb459b2009-07-10 03:48:23 +02005640 if (!current_is_single_threaded()) {
David Howellsd84f4f92008-11-14 10:39:23 +11005641 error = security_bounded_transition(tsec->sid, sid);
5642 if (error)
5643 goto abort_change;
Eric Paris828dfe12008-04-17 13:17:49 -04005644 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005645
5646 /* Check permissions for the transition. */
5647 error = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS,
Eric Paris828dfe12008-04-17 13:17:49 -04005648 PROCESS__DYNTRANSITION, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005649 if (error)
David Howellsd84f4f92008-11-14 10:39:23 +11005650 goto abort_change;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005651
5652 /* Check for ptracing, and update the task SID if ok.
5653 Otherwise, leave SID unchanged and fail. */
David Howellsd84f4f92008-11-14 10:39:23 +11005654 ptsid = 0;
Oleg Nesterovc0c14392013-12-23 17:45:01 -05005655 rcu_read_lock();
Tejun Heo06d98472011-06-17 16:50:40 +02005656 tracer = ptrace_parent(p);
David Howellsd84f4f92008-11-14 10:39:23 +11005657 if (tracer)
5658 ptsid = task_sid(tracer);
Oleg Nesterovc0c14392013-12-23 17:45:01 -05005659 rcu_read_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005660
David Howellsd84f4f92008-11-14 10:39:23 +11005661 if (tracer) {
5662 error = avc_has_perm(ptsid, sid, SECCLASS_PROCESS,
5663 PROCESS__PTRACE, NULL);
5664 if (error)
5665 goto abort_change;
5666 }
5667
5668 tsec->sid = sid;
5669 } else {
5670 error = -EINVAL;
5671 goto abort_change;
5672 }
5673
5674 commit_creds(new);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005675 return size;
David Howellsd84f4f92008-11-14 10:39:23 +11005676
5677abort_change:
5678 abort_creds(new);
5679 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005680}
5681
David Quigley746df9b2013-05-22 12:50:35 -04005682static int selinux_ismaclabel(const char *name)
5683{
5684 return (strcmp(name, XATTR_SELINUX_SUFFIX) == 0);
5685}
5686
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005687static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
5688{
5689 return security_sid_to_context(secid, secdata, seclen);
5690}
5691
David Howells7bf570d2008-04-29 20:52:51 +01005692static int selinux_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
David Howells63cb3442008-01-15 23:47:35 +00005693{
Nikolay Aleksandrov52a4c642014-03-07 12:44:19 +01005694 return security_context_to_sid(secdata, seclen, secid, GFP_KERNEL);
David Howells63cb3442008-01-15 23:47:35 +00005695}
5696
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005697static void selinux_release_secctx(char *secdata, u32 seclen)
5698{
Paul Moore088999e2007-08-01 11:12:58 -04005699 kfree(secdata);
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005700}
5701
David P. Quigley1ee65e32009-09-03 14:25:57 -04005702/*
5703 * called with inode->i_mutex locked
5704 */
5705static int selinux_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen)
5706{
5707 return selinux_inode_setsecurity(inode, XATTR_SELINUX_SUFFIX, ctx, ctxlen, 0);
5708}
5709
5710/*
5711 * called with inode->i_mutex locked
5712 */
5713static int selinux_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen)
5714{
5715 return __vfs_setxattr_noperm(dentry, XATTR_NAME_SELINUX, ctx, ctxlen, 0);
5716}
5717
5718static int selinux_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen)
5719{
5720 int len = 0;
5721 len = selinux_inode_getsecurity(inode, XATTR_SELINUX_SUFFIX,
5722 ctx, true);
5723 if (len < 0)
5724 return len;
5725 *ctxlen = len;
5726 return 0;
5727}
Michael LeMayd7200242006-06-22 14:47:17 -07005728#ifdef CONFIG_KEYS
5729
David Howellsd84f4f92008-11-14 10:39:23 +11005730static int selinux_key_alloc(struct key *k, const struct cred *cred,
David Howells7e047ef2006-06-26 00:24:50 -07005731 unsigned long flags)
Michael LeMayd7200242006-06-22 14:47:17 -07005732{
David Howellsd84f4f92008-11-14 10:39:23 +11005733 const struct task_security_struct *tsec;
Michael LeMayd7200242006-06-22 14:47:17 -07005734 struct key_security_struct *ksec;
5735
5736 ksec = kzalloc(sizeof(struct key_security_struct), GFP_KERNEL);
5737 if (!ksec)
5738 return -ENOMEM;
5739
David Howellsd84f4f92008-11-14 10:39:23 +11005740 tsec = cred->security;
5741 if (tsec->keycreate_sid)
5742 ksec->sid = tsec->keycreate_sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005743 else
David Howellsd84f4f92008-11-14 10:39:23 +11005744 ksec->sid = tsec->sid;
Michael LeMayd7200242006-06-22 14:47:17 -07005745
David Howells275bb412008-11-14 10:39:19 +11005746 k->security = ksec;
Michael LeMayd7200242006-06-22 14:47:17 -07005747 return 0;
5748}
5749
5750static void selinux_key_free(struct key *k)
5751{
5752 struct key_security_struct *ksec = k->security;
5753
5754 k->security = NULL;
5755 kfree(ksec);
5756}
5757
5758static int selinux_key_permission(key_ref_t key_ref,
David Howellsd84f4f92008-11-14 10:39:23 +11005759 const struct cred *cred,
David Howellsf5895942014-03-14 17:44:49 +00005760 unsigned perm)
Michael LeMayd7200242006-06-22 14:47:17 -07005761{
5762 struct key *key;
Michael LeMayd7200242006-06-22 14:47:17 -07005763 struct key_security_struct *ksec;
David Howells275bb412008-11-14 10:39:19 +11005764 u32 sid;
Michael LeMayd7200242006-06-22 14:47:17 -07005765
5766 /* if no specific permissions are requested, we skip the
5767 permission check. No serious, additional covert channels
5768 appear to be created. */
5769 if (perm == 0)
5770 return 0;
5771
David Howellsd84f4f92008-11-14 10:39:23 +11005772 sid = cred_sid(cred);
David Howells275bb412008-11-14 10:39:19 +11005773
5774 key = key_ref_to_ptr(key_ref);
5775 ksec = key->security;
5776
5777 return avc_has_perm(sid, ksec->sid, SECCLASS_KEY, perm, NULL);
Michael LeMayd7200242006-06-22 14:47:17 -07005778}
5779
David Howells70a5bb72008-04-29 01:01:26 -07005780static int selinux_key_getsecurity(struct key *key, char **_buffer)
5781{
5782 struct key_security_struct *ksec = key->security;
5783 char *context = NULL;
5784 unsigned len;
5785 int rc;
5786
5787 rc = security_sid_to_context(ksec->sid, &context, &len);
5788 if (!rc)
5789 rc = len;
5790 *_buffer = context;
5791 return rc;
5792}
5793
Michael LeMayd7200242006-06-22 14:47:17 -07005794#endif
5795
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07005796static struct security_hook_list selinux_hooks[] = {
Casey Schauflere20b0432015-05-02 15:11:36 -07005797 LSM_HOOK_INIT(binder_set_context_mgr, selinux_binder_set_context_mgr),
5798 LSM_HOOK_INIT(binder_transaction, selinux_binder_transaction),
5799 LSM_HOOK_INIT(binder_transfer_binder, selinux_binder_transfer_binder),
5800 LSM_HOOK_INIT(binder_transfer_file, selinux_binder_transfer_file),
Stephen Smalley79af7302015-01-21 10:54:10 -05005801
Casey Schauflere20b0432015-05-02 15:11:36 -07005802 LSM_HOOK_INIT(ptrace_access_check, selinux_ptrace_access_check),
5803 LSM_HOOK_INIT(ptrace_traceme, selinux_ptrace_traceme),
5804 LSM_HOOK_INIT(capget, selinux_capget),
5805 LSM_HOOK_INIT(capset, selinux_capset),
5806 LSM_HOOK_INIT(capable, selinux_capable),
5807 LSM_HOOK_INIT(quotactl, selinux_quotactl),
5808 LSM_HOOK_INIT(quota_on, selinux_quota_on),
5809 LSM_HOOK_INIT(syslog, selinux_syslog),
5810 LSM_HOOK_INIT(vm_enough_memory, selinux_vm_enough_memory),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005811
Casey Schauflere20b0432015-05-02 15:11:36 -07005812 LSM_HOOK_INIT(netlink_send, selinux_netlink_send),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005813
Casey Schauflere20b0432015-05-02 15:11:36 -07005814 LSM_HOOK_INIT(bprm_set_creds, selinux_bprm_set_creds),
5815 LSM_HOOK_INIT(bprm_committing_creds, selinux_bprm_committing_creds),
5816 LSM_HOOK_INIT(bprm_committed_creds, selinux_bprm_committed_creds),
5817 LSM_HOOK_INIT(bprm_secureexec, selinux_bprm_secureexec),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005818
Casey Schauflere20b0432015-05-02 15:11:36 -07005819 LSM_HOOK_INIT(sb_alloc_security, selinux_sb_alloc_security),
5820 LSM_HOOK_INIT(sb_free_security, selinux_sb_free_security),
5821 LSM_HOOK_INIT(sb_copy_data, selinux_sb_copy_data),
5822 LSM_HOOK_INIT(sb_remount, selinux_sb_remount),
5823 LSM_HOOK_INIT(sb_kern_mount, selinux_sb_kern_mount),
5824 LSM_HOOK_INIT(sb_show_options, selinux_sb_show_options),
5825 LSM_HOOK_INIT(sb_statfs, selinux_sb_statfs),
5826 LSM_HOOK_INIT(sb_mount, selinux_mount),
5827 LSM_HOOK_INIT(sb_umount, selinux_umount),
5828 LSM_HOOK_INIT(sb_set_mnt_opts, selinux_set_mnt_opts),
5829 LSM_HOOK_INIT(sb_clone_mnt_opts, selinux_sb_clone_mnt_opts),
5830 LSM_HOOK_INIT(sb_parse_opts_str, selinux_parse_opts_str),
Eric Parise0007522008-03-05 10:31:54 -05005831
Casey Schauflere20b0432015-05-02 15:11:36 -07005832 LSM_HOOK_INIT(dentry_init_security, selinux_dentry_init_security),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005833
Casey Schauflere20b0432015-05-02 15:11:36 -07005834 LSM_HOOK_INIT(inode_alloc_security, selinux_inode_alloc_security),
5835 LSM_HOOK_INIT(inode_free_security, selinux_inode_free_security),
5836 LSM_HOOK_INIT(inode_init_security, selinux_inode_init_security),
5837 LSM_HOOK_INIT(inode_create, selinux_inode_create),
5838 LSM_HOOK_INIT(inode_link, selinux_inode_link),
5839 LSM_HOOK_INIT(inode_unlink, selinux_inode_unlink),
5840 LSM_HOOK_INIT(inode_symlink, selinux_inode_symlink),
5841 LSM_HOOK_INIT(inode_mkdir, selinux_inode_mkdir),
5842 LSM_HOOK_INIT(inode_rmdir, selinux_inode_rmdir),
5843 LSM_HOOK_INIT(inode_mknod, selinux_inode_mknod),
5844 LSM_HOOK_INIT(inode_rename, selinux_inode_rename),
5845 LSM_HOOK_INIT(inode_readlink, selinux_inode_readlink),
5846 LSM_HOOK_INIT(inode_follow_link, selinux_inode_follow_link),
5847 LSM_HOOK_INIT(inode_permission, selinux_inode_permission),
5848 LSM_HOOK_INIT(inode_setattr, selinux_inode_setattr),
5849 LSM_HOOK_INIT(inode_getattr, selinux_inode_getattr),
5850 LSM_HOOK_INIT(inode_setxattr, selinux_inode_setxattr),
5851 LSM_HOOK_INIT(inode_post_setxattr, selinux_inode_post_setxattr),
5852 LSM_HOOK_INIT(inode_getxattr, selinux_inode_getxattr),
5853 LSM_HOOK_INIT(inode_listxattr, selinux_inode_listxattr),
5854 LSM_HOOK_INIT(inode_removexattr, selinux_inode_removexattr),
5855 LSM_HOOK_INIT(inode_getsecurity, selinux_inode_getsecurity),
5856 LSM_HOOK_INIT(inode_setsecurity, selinux_inode_setsecurity),
5857 LSM_HOOK_INIT(inode_listsecurity, selinux_inode_listsecurity),
5858 LSM_HOOK_INIT(inode_getsecid, selinux_inode_getsecid),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005859
Casey Schauflere20b0432015-05-02 15:11:36 -07005860 LSM_HOOK_INIT(file_permission, selinux_file_permission),
5861 LSM_HOOK_INIT(file_alloc_security, selinux_file_alloc_security),
5862 LSM_HOOK_INIT(file_free_security, selinux_file_free_security),
5863 LSM_HOOK_INIT(file_ioctl, selinux_file_ioctl),
5864 LSM_HOOK_INIT(mmap_file, selinux_mmap_file),
5865 LSM_HOOK_INIT(mmap_addr, selinux_mmap_addr),
5866 LSM_HOOK_INIT(file_mprotect, selinux_file_mprotect),
5867 LSM_HOOK_INIT(file_lock, selinux_file_lock),
5868 LSM_HOOK_INIT(file_fcntl, selinux_file_fcntl),
5869 LSM_HOOK_INIT(file_set_fowner, selinux_file_set_fowner),
5870 LSM_HOOK_INIT(file_send_sigiotask, selinux_file_send_sigiotask),
5871 LSM_HOOK_INIT(file_receive, selinux_file_receive),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005872
Casey Schauflere20b0432015-05-02 15:11:36 -07005873 LSM_HOOK_INIT(file_open, selinux_file_open),
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09005874
Casey Schauflere20b0432015-05-02 15:11:36 -07005875 LSM_HOOK_INIT(task_create, selinux_task_create),
5876 LSM_HOOK_INIT(cred_alloc_blank, selinux_cred_alloc_blank),
5877 LSM_HOOK_INIT(cred_free, selinux_cred_free),
5878 LSM_HOOK_INIT(cred_prepare, selinux_cred_prepare),
5879 LSM_HOOK_INIT(cred_transfer, selinux_cred_transfer),
5880 LSM_HOOK_INIT(kernel_act_as, selinux_kernel_act_as),
5881 LSM_HOOK_INIT(kernel_create_files_as, selinux_kernel_create_files_as),
5882 LSM_HOOK_INIT(kernel_module_request, selinux_kernel_module_request),
5883 LSM_HOOK_INIT(task_setpgid, selinux_task_setpgid),
5884 LSM_HOOK_INIT(task_getpgid, selinux_task_getpgid),
5885 LSM_HOOK_INIT(task_getsid, selinux_task_getsid),
5886 LSM_HOOK_INIT(task_getsecid, selinux_task_getsecid),
5887 LSM_HOOK_INIT(task_setnice, selinux_task_setnice),
5888 LSM_HOOK_INIT(task_setioprio, selinux_task_setioprio),
5889 LSM_HOOK_INIT(task_getioprio, selinux_task_getioprio),
5890 LSM_HOOK_INIT(task_setrlimit, selinux_task_setrlimit),
5891 LSM_HOOK_INIT(task_setscheduler, selinux_task_setscheduler),
5892 LSM_HOOK_INIT(task_getscheduler, selinux_task_getscheduler),
5893 LSM_HOOK_INIT(task_movememory, selinux_task_movememory),
5894 LSM_HOOK_INIT(task_kill, selinux_task_kill),
5895 LSM_HOOK_INIT(task_wait, selinux_task_wait),
5896 LSM_HOOK_INIT(task_to_inode, selinux_task_to_inode),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005897
Casey Schauflere20b0432015-05-02 15:11:36 -07005898 LSM_HOOK_INIT(ipc_permission, selinux_ipc_permission),
5899 LSM_HOOK_INIT(ipc_getsecid, selinux_ipc_getsecid),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005900
Casey Schauflere20b0432015-05-02 15:11:36 -07005901 LSM_HOOK_INIT(msg_msg_alloc_security, selinux_msg_msg_alloc_security),
5902 LSM_HOOK_INIT(msg_msg_free_security, selinux_msg_msg_free_security),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005903
Casey Schauflere20b0432015-05-02 15:11:36 -07005904 LSM_HOOK_INIT(msg_queue_alloc_security,
5905 selinux_msg_queue_alloc_security),
5906 LSM_HOOK_INIT(msg_queue_free_security, selinux_msg_queue_free_security),
5907 LSM_HOOK_INIT(msg_queue_associate, selinux_msg_queue_associate),
5908 LSM_HOOK_INIT(msg_queue_msgctl, selinux_msg_queue_msgctl),
5909 LSM_HOOK_INIT(msg_queue_msgsnd, selinux_msg_queue_msgsnd),
5910 LSM_HOOK_INIT(msg_queue_msgrcv, selinux_msg_queue_msgrcv),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005911
Casey Schauflere20b0432015-05-02 15:11:36 -07005912 LSM_HOOK_INIT(shm_alloc_security, selinux_shm_alloc_security),
5913 LSM_HOOK_INIT(shm_free_security, selinux_shm_free_security),
5914 LSM_HOOK_INIT(shm_associate, selinux_shm_associate),
5915 LSM_HOOK_INIT(shm_shmctl, selinux_shm_shmctl),
5916 LSM_HOOK_INIT(shm_shmat, selinux_shm_shmat),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005917
Casey Schauflere20b0432015-05-02 15:11:36 -07005918 LSM_HOOK_INIT(sem_alloc_security, selinux_sem_alloc_security),
5919 LSM_HOOK_INIT(sem_free_security, selinux_sem_free_security),
5920 LSM_HOOK_INIT(sem_associate, selinux_sem_associate),
5921 LSM_HOOK_INIT(sem_semctl, selinux_sem_semctl),
5922 LSM_HOOK_INIT(sem_semop, selinux_sem_semop),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005923
Casey Schauflere20b0432015-05-02 15:11:36 -07005924 LSM_HOOK_INIT(d_instantiate, selinux_d_instantiate),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005925
Casey Schauflere20b0432015-05-02 15:11:36 -07005926 LSM_HOOK_INIT(getprocattr, selinux_getprocattr),
5927 LSM_HOOK_INIT(setprocattr, selinux_setprocattr),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005928
Casey Schauflere20b0432015-05-02 15:11:36 -07005929 LSM_HOOK_INIT(ismaclabel, selinux_ismaclabel),
5930 LSM_HOOK_INIT(secid_to_secctx, selinux_secid_to_secctx),
5931 LSM_HOOK_INIT(secctx_to_secid, selinux_secctx_to_secid),
5932 LSM_HOOK_INIT(release_secctx, selinux_release_secctx),
5933 LSM_HOOK_INIT(inode_notifysecctx, selinux_inode_notifysecctx),
5934 LSM_HOOK_INIT(inode_setsecctx, selinux_inode_setsecctx),
5935 LSM_HOOK_INIT(inode_getsecctx, selinux_inode_getsecctx),
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005936
Casey Schauflere20b0432015-05-02 15:11:36 -07005937 LSM_HOOK_INIT(unix_stream_connect, selinux_socket_unix_stream_connect),
5938 LSM_HOOK_INIT(unix_may_send, selinux_socket_unix_may_send),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005939
Casey Schauflere20b0432015-05-02 15:11:36 -07005940 LSM_HOOK_INIT(socket_create, selinux_socket_create),
5941 LSM_HOOK_INIT(socket_post_create, selinux_socket_post_create),
5942 LSM_HOOK_INIT(socket_bind, selinux_socket_bind),
5943 LSM_HOOK_INIT(socket_connect, selinux_socket_connect),
5944 LSM_HOOK_INIT(socket_listen, selinux_socket_listen),
5945 LSM_HOOK_INIT(socket_accept, selinux_socket_accept),
5946 LSM_HOOK_INIT(socket_sendmsg, selinux_socket_sendmsg),
5947 LSM_HOOK_INIT(socket_recvmsg, selinux_socket_recvmsg),
5948 LSM_HOOK_INIT(socket_getsockname, selinux_socket_getsockname),
5949 LSM_HOOK_INIT(socket_getpeername, selinux_socket_getpeername),
5950 LSM_HOOK_INIT(socket_getsockopt, selinux_socket_getsockopt),
5951 LSM_HOOK_INIT(socket_setsockopt, selinux_socket_setsockopt),
5952 LSM_HOOK_INIT(socket_shutdown, selinux_socket_shutdown),
5953 LSM_HOOK_INIT(socket_sock_rcv_skb, selinux_socket_sock_rcv_skb),
5954 LSM_HOOK_INIT(socket_getpeersec_stream,
5955 selinux_socket_getpeersec_stream),
5956 LSM_HOOK_INIT(socket_getpeersec_dgram, selinux_socket_getpeersec_dgram),
5957 LSM_HOOK_INIT(sk_alloc_security, selinux_sk_alloc_security),
5958 LSM_HOOK_INIT(sk_free_security, selinux_sk_free_security),
5959 LSM_HOOK_INIT(sk_clone_security, selinux_sk_clone_security),
5960 LSM_HOOK_INIT(sk_getsecid, selinux_sk_getsecid),
5961 LSM_HOOK_INIT(sock_graft, selinux_sock_graft),
5962 LSM_HOOK_INIT(inet_conn_request, selinux_inet_conn_request),
5963 LSM_HOOK_INIT(inet_csk_clone, selinux_inet_csk_clone),
5964 LSM_HOOK_INIT(inet_conn_established, selinux_inet_conn_established),
5965 LSM_HOOK_INIT(secmark_relabel_packet, selinux_secmark_relabel_packet),
5966 LSM_HOOK_INIT(secmark_refcount_inc, selinux_secmark_refcount_inc),
5967 LSM_HOOK_INIT(secmark_refcount_dec, selinux_secmark_refcount_dec),
5968 LSM_HOOK_INIT(req_classify_flow, selinux_req_classify_flow),
5969 LSM_HOOK_INIT(tun_dev_alloc_security, selinux_tun_dev_alloc_security),
5970 LSM_HOOK_INIT(tun_dev_free_security, selinux_tun_dev_free_security),
5971 LSM_HOOK_INIT(tun_dev_create, selinux_tun_dev_create),
5972 LSM_HOOK_INIT(tun_dev_attach_queue, selinux_tun_dev_attach_queue),
5973 LSM_HOOK_INIT(tun_dev_attach, selinux_tun_dev_attach),
5974 LSM_HOOK_INIT(tun_dev_open, selinux_tun_dev_open),
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005975
5976#ifdef CONFIG_SECURITY_NETWORK_XFRM
Casey Schauflere20b0432015-05-02 15:11:36 -07005977 LSM_HOOK_INIT(xfrm_policy_alloc_security, selinux_xfrm_policy_alloc),
5978 LSM_HOOK_INIT(xfrm_policy_clone_security, selinux_xfrm_policy_clone),
5979 LSM_HOOK_INIT(xfrm_policy_free_security, selinux_xfrm_policy_free),
5980 LSM_HOOK_INIT(xfrm_policy_delete_security, selinux_xfrm_policy_delete),
5981 LSM_HOOK_INIT(xfrm_state_alloc, selinux_xfrm_state_alloc),
5982 LSM_HOOK_INIT(xfrm_state_alloc_acquire,
5983 selinux_xfrm_state_alloc_acquire),
5984 LSM_HOOK_INIT(xfrm_state_free_security, selinux_xfrm_state_free),
5985 LSM_HOOK_INIT(xfrm_state_delete_security, selinux_xfrm_state_delete),
5986 LSM_HOOK_INIT(xfrm_policy_lookup, selinux_xfrm_policy_lookup),
5987 LSM_HOOK_INIT(xfrm_state_pol_flow_match,
5988 selinux_xfrm_state_pol_flow_match),
5989 LSM_HOOK_INIT(xfrm_decode_session, selinux_xfrm_decode_session),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005990#endif
Michael LeMayd7200242006-06-22 14:47:17 -07005991
5992#ifdef CONFIG_KEYS
Casey Schauflere20b0432015-05-02 15:11:36 -07005993 LSM_HOOK_INIT(key_alloc, selinux_key_alloc),
5994 LSM_HOOK_INIT(key_free, selinux_key_free),
5995 LSM_HOOK_INIT(key_permission, selinux_key_permission),
5996 LSM_HOOK_INIT(key_getsecurity, selinux_key_getsecurity),
Michael LeMayd7200242006-06-22 14:47:17 -07005997#endif
Ahmed S. Darwish9d57a7f2008-03-01 22:03:14 +02005998
5999#ifdef CONFIG_AUDIT
Casey Schauflere20b0432015-05-02 15:11:36 -07006000 LSM_HOOK_INIT(audit_rule_init, selinux_audit_rule_init),
6001 LSM_HOOK_INIT(audit_rule_known, selinux_audit_rule_known),
6002 LSM_HOOK_INIT(audit_rule_match, selinux_audit_rule_match),
6003 LSM_HOOK_INIT(audit_rule_free, selinux_audit_rule_free),
Ahmed S. Darwish9d57a7f2008-03-01 22:03:14 +02006004#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07006005};
6006
6007static __init int selinux_init(void)
6008{
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07006009 if (!security_module_enable("selinux")) {
Ahmed S. Darwish076c54c2008-03-06 18:09:10 +02006010 selinux_enabled = 0;
6011 return 0;
6012 }
6013
Linus Torvalds1da177e2005-04-16 15:20:36 -07006014 if (!selinux_enabled) {
6015 printk(KERN_INFO "SELinux: Disabled at boot.\n");
6016 return 0;
6017 }
6018
6019 printk(KERN_INFO "SELinux: Initializing.\n");
6020
6021 /* Set the security state for the initial task. */
David Howellsd84f4f92008-11-14 10:39:23 +11006022 cred_init_security();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006023
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04006024 default_noexec = !(VM_DATA_DEFAULT_FLAGS & VM_EXEC);
6025
James Morris7cae7e22006-03-22 00:09:22 -08006026 sel_inode_cache = kmem_cache_create("selinux_inode_security",
6027 sizeof(struct inode_security_struct),
Paul Mundt20c2df82007-07-20 10:11:58 +09006028 0, SLAB_PANIC, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006029 avc_init();
6030
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07006031 security_add_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006032
Paul Moore615e51f2014-06-26 14:33:56 -04006033 if (avc_add_callback(selinux_netcache_avc_callback, AVC_CALLBACK_RESET))
6034 panic("SELinux: Unable to register AVC netcache callback\n");
6035
Eric Paris828dfe12008-04-17 13:17:49 -04006036 if (selinux_enforcing)
Eric Parisfadcdb42007-02-22 18:11:31 -05006037 printk(KERN_DEBUG "SELinux: Starting in enforcing mode\n");
Eric Paris828dfe12008-04-17 13:17:49 -04006038 else
Eric Parisfadcdb42007-02-22 18:11:31 -05006039 printk(KERN_DEBUG "SELinux: Starting in permissive mode\n");
Michael LeMayd7200242006-06-22 14:47:17 -07006040
Linus Torvalds1da177e2005-04-16 15:20:36 -07006041 return 0;
6042}
6043
Al Viroe8c26252010-03-23 06:36:54 -04006044static void delayed_superblock_init(struct super_block *sb, void *unused)
6045{
6046 superblock_doinit(sb, NULL);
6047}
6048
Linus Torvalds1da177e2005-04-16 15:20:36 -07006049void selinux_complete_init(void)
6050{
Eric Parisfadcdb42007-02-22 18:11:31 -05006051 printk(KERN_DEBUG "SELinux: Completing initialization.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07006052
6053 /* Set up any superblocks initialized prior to the policy load. */
Eric Parisfadcdb42007-02-22 18:11:31 -05006054 printk(KERN_DEBUG "SELinux: Setting up existing superblocks.\n");
Al Viroe8c26252010-03-23 06:36:54 -04006055 iterate_supers(delayed_superblock_init, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006056}
6057
6058/* SELinux requires early initialization in order to label
6059 all processes and objects when they are created. */
6060security_initcall(selinux_init);
6061
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08006062#if defined(CONFIG_NETFILTER)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006063
Jiri Pirko25db6be2014-09-03 17:42:13 +02006064static struct nf_hook_ops selinux_nf_ops[] = {
Paul Mooreeffad8d2008-01-29 08:49:27 -05006065 {
6066 .hook = selinux_ipv4_postroute,
6067 .owner = THIS_MODULE,
Alban Crequy2597a832012-05-14 03:56:39 +00006068 .pf = NFPROTO_IPV4,
Paul Mooreeffad8d2008-01-29 08:49:27 -05006069 .hooknum = NF_INET_POST_ROUTING,
6070 .priority = NF_IP_PRI_SELINUX_LAST,
6071 },
6072 {
6073 .hook = selinux_ipv4_forward,
6074 .owner = THIS_MODULE,
Alban Crequy2597a832012-05-14 03:56:39 +00006075 .pf = NFPROTO_IPV4,
Paul Mooreeffad8d2008-01-29 08:49:27 -05006076 .hooknum = NF_INET_FORWARD,
6077 .priority = NF_IP_PRI_SELINUX_FIRST,
Paul Moore948bf852008-10-10 10:16:32 -04006078 },
6079 {
6080 .hook = selinux_ipv4_output,
6081 .owner = THIS_MODULE,
Alban Crequy2597a832012-05-14 03:56:39 +00006082 .pf = NFPROTO_IPV4,
Paul Moore948bf852008-10-10 10:16:32 -04006083 .hooknum = NF_INET_LOCAL_OUT,
6084 .priority = NF_IP_PRI_SELINUX_FIRST,
Jiri Pirko25db6be2014-09-03 17:42:13 +02006085 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07006086#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Paul Mooreeffad8d2008-01-29 08:49:27 -05006087 {
6088 .hook = selinux_ipv6_postroute,
6089 .owner = THIS_MODULE,
Alban Crequy2597a832012-05-14 03:56:39 +00006090 .pf = NFPROTO_IPV6,
Paul Mooreeffad8d2008-01-29 08:49:27 -05006091 .hooknum = NF_INET_POST_ROUTING,
6092 .priority = NF_IP6_PRI_SELINUX_LAST,
6093 },
6094 {
6095 .hook = selinux_ipv6_forward,
6096 .owner = THIS_MODULE,
Alban Crequy2597a832012-05-14 03:56:39 +00006097 .pf = NFPROTO_IPV6,
Paul Mooreeffad8d2008-01-29 08:49:27 -05006098 .hooknum = NF_INET_FORWARD,
6099 .priority = NF_IP6_PRI_SELINUX_FIRST,
Jiri Pirko25db6be2014-09-03 17:42:13 +02006100 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07006101#endif /* IPV6 */
Jiri Pirko25db6be2014-09-03 17:42:13 +02006102};
Linus Torvalds1da177e2005-04-16 15:20:36 -07006103
6104static int __init selinux_nf_ip_init(void)
6105{
Jiri Pirko25db6be2014-09-03 17:42:13 +02006106 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006107
6108 if (!selinux_enabled)
Jiri Pirko25db6be2014-09-03 17:42:13 +02006109 return 0;
Eric Parisfadcdb42007-02-22 18:11:31 -05006110
6111 printk(KERN_DEBUG "SELinux: Registering netfilter hooks\n");
6112
Jiri Pirko25db6be2014-09-03 17:42:13 +02006113 err = nf_register_hooks(selinux_nf_ops, ARRAY_SIZE(selinux_nf_ops));
Alexey Dobriyan6c5a9d22008-07-26 17:48:15 -07006114 if (err)
Jiri Pirko25db6be2014-09-03 17:42:13 +02006115 panic("SELinux: nf_register_hooks: error %d\n", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006116
Jiri Pirko25db6be2014-09-03 17:42:13 +02006117 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006118}
6119
6120__initcall(selinux_nf_ip_init);
6121
6122#ifdef CONFIG_SECURITY_SELINUX_DISABLE
6123static void selinux_nf_ip_exit(void)
6124{
Eric Parisfadcdb42007-02-22 18:11:31 -05006125 printk(KERN_DEBUG "SELinux: Unregistering netfilter hooks\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07006126
Jiri Pirko25db6be2014-09-03 17:42:13 +02006127 nf_unregister_hooks(selinux_nf_ops, ARRAY_SIZE(selinux_nf_ops));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006128}
6129#endif
6130
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08006131#else /* CONFIG_NETFILTER */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006132
6133#ifdef CONFIG_SECURITY_SELINUX_DISABLE
6134#define selinux_nf_ip_exit()
6135#endif
6136
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08006137#endif /* CONFIG_NETFILTER */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006138
6139#ifdef CONFIG_SECURITY_SELINUX_DISABLE
Eric Paris828dfe12008-04-17 13:17:49 -04006140static int selinux_disabled;
6141
Linus Torvalds1da177e2005-04-16 15:20:36 -07006142int selinux_disable(void)
6143{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006144 if (ss_initialized) {
6145 /* Not permitted after initial policy load. */
6146 return -EINVAL;
6147 }
6148
6149 if (selinux_disabled) {
6150 /* Only do this once. */
6151 return -EINVAL;
6152 }
6153
6154 printk(KERN_INFO "SELinux: Disabled at runtime.\n");
6155
6156 selinux_disabled = 1;
Stephen Smalley30d55282006-05-03 10:52:36 -04006157 selinux_enabled = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006158
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07006159 security_delete_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006160
Eric Parisaf8ff042009-09-20 21:23:01 -04006161 /* Try to destroy the avc node cache */
6162 avc_disable();
6163
Linus Torvalds1da177e2005-04-16 15:20:36 -07006164 /* Unregister netfilter hooks. */
6165 selinux_nf_ip_exit();
6166
6167 /* Unregister selinuxfs. */
6168 exit_sel_fs();
6169
6170 return 0;
6171}
6172#endif