blob: cdf4c589a3914bbc7d315b1e55fb1264f4be0309 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * NSA Security-Enhanced Linux (SELinux) security module
3 *
4 * This file contains the SELinux hook function implementations.
5 *
6 * Authors: Stephen Smalley, <sds@epoch.ncsc.mil>
Eric Paris828dfe12008-04-17 13:17:49 -04007 * Chris Vance, <cvance@nai.com>
8 * Wayne Salamon, <wsalamon@nai.com>
9 * James Morris <jmorris@redhat.com>
Linus Torvalds1da177e2005-04-16 15:20:36 -070010 *
11 * Copyright (C) 2001,2002 Networks Associates Technology, Inc.
Eric Paris2069f452008-07-04 09:47:13 +100012 * Copyright (C) 2003-2008 Red Hat, Inc., James Morris <jmorris@redhat.com>
13 * Eric Paris <eparis@redhat.com>
Linus Torvalds1da177e2005-04-16 15:20:36 -070014 * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
Eric Paris828dfe12008-04-17 13:17:49 -040015 * <dgoeddel@trustedcs.com>
Paul Mooreed6d76e2009-08-28 18:12:49 -040016 * Copyright (C) 2006, 2007, 2009 Hewlett-Packard Development Company, L.P.
Paul Moore82c21bf2011-08-01 11:10:33 +000017 * Paul Moore <paul@paul-moore.com>
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +090018 * Copyright (C) 2007 Hitachi Software Engineering Co., Ltd.
Eric Paris828dfe12008-04-17 13:17:49 -040019 * Yuichi Nakamura <ynakam@hitachisoft.jp>
Linus Torvalds1da177e2005-04-16 15:20:36 -070020 *
21 * This program is free software; you can redistribute it and/or modify
22 * it under the terms of the GNU General Public License version 2,
Eric Paris828dfe12008-04-17 13:17:49 -040023 * as published by the Free Software Foundation.
Linus Torvalds1da177e2005-04-16 15:20:36 -070024 */
25
Linus Torvalds1da177e2005-04-16 15:20:36 -070026#include <linux/init.h>
Eric Paris0b24dcb2011-02-25 15:39:20 -050027#include <linux/kd.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070028#include <linux/kernel.h>
Roland McGrath0d094ef2008-07-25 19:45:49 -070029#include <linux/tracehook.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070030#include <linux/errno.h>
31#include <linux/sched.h>
Casey Schaufler3c4ed7b2015-05-02 15:10:46 -070032#include <linux/lsm_hooks.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070033#include <linux/xattr.h>
34#include <linux/capability.h>
35#include <linux/unistd.h>
36#include <linux/mm.h>
37#include <linux/mman.h>
38#include <linux/slab.h>
39#include <linux/pagemap.h>
Eric Paris0b24dcb2011-02-25 15:39:20 -050040#include <linux/proc_fs.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070041#include <linux/swap.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070042#include <linux/spinlock.h>
43#include <linux/syscalls.h>
Eric Paris2a7dba32011-02-01 11:05:39 -050044#include <linux/dcache.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070045#include <linux/file.h>
Al Viro9f3acc32008-04-24 07:44:08 -040046#include <linux/fdtable.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070047#include <linux/namei.h>
48#include <linux/mount.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070049#include <linux/netfilter_ipv4.h>
50#include <linux/netfilter_ipv6.h>
51#include <linux/tty.h>
52#include <net/icmp.h>
Stephen Hemminger227b60f2007-10-10 17:30:46 -070053#include <net/ip.h> /* for local_port_range[] */
Linus Torvalds1da177e2005-04-16 15:20:36 -070054#include <net/tcp.h> /* struct or_callable used in sock_rcv_skb */
Paul Moore47180062013-12-04 16:10:45 -050055#include <net/inet_connection_sock.h>
Paul Moore220deb92008-01-29 08:38:23 -050056#include <net/net_namespace.h>
Paul Moored621d352008-01-29 08:43:36 -050057#include <net/netlabel.h>
Eric Parisf5269712008-05-14 11:27:45 -040058#include <linux/uaccess.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070059#include <asm/ioctls.h>
Arun Sharma600634972011-07-26 16:09:06 -070060#include <linux/atomic.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070061#include <linux/bitops.h>
62#include <linux/interrupt.h>
63#include <linux/netdevice.h> /* for network interface checks */
Hong zhi guo77954982013-03-27 06:49:35 +000064#include <net/netlink.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070065#include <linux/tcp.h>
66#include <linux/udp.h>
James Morris2ee92d42006-11-13 16:09:01 -080067#include <linux/dccp.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070068#include <linux/quota.h>
69#include <linux/un.h> /* for Unix socket types */
70#include <net/af_unix.h> /* for Unix socket types */
71#include <linux/parser.h>
72#include <linux/nfs_mount.h>
73#include <net/ipv6.h>
74#include <linux/hugetlb.h>
75#include <linux/personality.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070076#include <linux/audit.h>
Eric Paris6931dfc2005-06-30 02:58:51 -070077#include <linux/string.h>
Catherine Zhang877ce7c2006-06-29 12:27:47 -070078#include <linux/selinux.h>
Eric Paris23970742006-09-25 23:32:01 -070079#include <linux/mutex.h>
Frank Mayharf06febc2008-09-12 09:54:39 -070080#include <linux/posix-timers.h>
Kees Cook00234592010-02-03 15:36:43 -080081#include <linux/syslog.h>
Serge E. Hallyn34867402011-03-23 16:43:17 -070082#include <linux/user_namespace.h>
Paul Gortmaker44fc7ea2011-05-26 20:52:10 -040083#include <linux/export.h>
Al Viro40401532012-02-13 03:58:52 +000084#include <linux/msg.h>
85#include <linux/shm.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070086
87#include "avc.h"
88#include "objsec.h"
89#include "netif.h"
Paul Moore224dfbd2008-01-29 08:38:13 -050090#include "netnode.h"
Paul Moore3e112172008-04-10 10:48:14 -040091#include "netport.h"
Trent Jaegerd28d1e02005-12-13 23:12:40 -080092#include "xfrm.h"
Paul Moorec60475b2007-02-28 15:14:23 -050093#include "netlabel.h"
Ahmed S. Darwish9d57a7f2008-03-01 22:03:14 +020094#include "audit.h"
James Morris7b98a582011-08-30 12:52:32 +100095#include "avc_ss.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070096
Paul Moored621d352008-01-29 08:43:36 -050097/* SECMARK reference count */
James Morris56a4ca92011-08-17 11:08:43 +100098static atomic_t selinux_secmark_refcount = ATOMIC_INIT(0);
Paul Moored621d352008-01-29 08:43:36 -050099
Linus Torvalds1da177e2005-04-16 15:20:36 -0700100#ifdef CONFIG_SECURITY_SELINUX_DEVELOP
Eric Paris828dfe12008-04-17 13:17:49 -0400101int selinux_enforcing;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700102
103static int __init enforcing_setup(char *str)
104{
Eric Parisf5269712008-05-14 11:27:45 -0400105 unsigned long enforcing;
Jingoo Han29707b22014-02-05 15:13:14 +0900106 if (!kstrtoul(str, 0, &enforcing))
Eric Parisf5269712008-05-14 11:27:45 -0400107 selinux_enforcing = enforcing ? 1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108 return 1;
109}
110__setup("enforcing=", enforcing_setup);
111#endif
112
113#ifdef CONFIG_SECURITY_SELINUX_BOOTPARAM
114int selinux_enabled = CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE;
115
116static int __init selinux_enabled_setup(char *str)
117{
Eric Parisf5269712008-05-14 11:27:45 -0400118 unsigned long enabled;
Jingoo Han29707b22014-02-05 15:13:14 +0900119 if (!kstrtoul(str, 0, &enabled))
Eric Parisf5269712008-05-14 11:27:45 -0400120 selinux_enabled = enabled ? 1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700121 return 1;
122}
123__setup("selinux=", selinux_enabled_setup);
Stephen Smalley30d55282006-05-03 10:52:36 -0400124#else
125int selinux_enabled = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126#endif
127
Christoph Lametere18b8902006-12-06 20:33:20 -0800128static struct kmem_cache *sel_inode_cache;
James Morris7cae7e22006-03-22 00:09:22 -0800129
Paul Moored621d352008-01-29 08:43:36 -0500130/**
131 * selinux_secmark_enabled - Check to see if SECMARK is currently enabled
132 *
133 * Description:
134 * This function checks the SECMARK reference counter to see if any SECMARK
135 * targets are currently configured, if the reference counter is greater than
136 * zero SECMARK is considered to be enabled. Returns true (1) if SECMARK is
Chris PeBenito2be4d742013-05-03 09:05:39 -0400137 * enabled, false (0) if SECMARK is disabled. If the always_check_network
138 * policy capability is enabled, SECMARK is always considered enabled.
Paul Moored621d352008-01-29 08:43:36 -0500139 *
140 */
141static int selinux_secmark_enabled(void)
142{
Chris PeBenito2be4d742013-05-03 09:05:39 -0400143 return (selinux_policycap_alwaysnetwork || atomic_read(&selinux_secmark_refcount));
144}
145
146/**
147 * selinux_peerlbl_enabled - Check to see if peer labeling is currently enabled
148 *
149 * Description:
150 * This function checks if NetLabel or labeled IPSEC is enabled. Returns true
151 * (1) if any are enabled or false (0) if neither are enabled. If the
152 * always_check_network policy capability is enabled, peer labeling
153 * is always considered enabled.
154 *
155 */
156static int selinux_peerlbl_enabled(void)
157{
158 return (selinux_policycap_alwaysnetwork || netlbl_enabled() || selinux_xfrm_enabled());
Paul Moored621d352008-01-29 08:43:36 -0500159}
160
Paul Moore615e51f2014-06-26 14:33:56 -0400161static int selinux_netcache_avc_callback(u32 event)
162{
163 if (event == AVC_CALLBACK_RESET) {
164 sel_netif_flush();
165 sel_netnode_flush();
166 sel_netport_flush();
167 synchronize_net();
168 }
169 return 0;
170}
171
David Howellsd84f4f92008-11-14 10:39:23 +1100172/*
173 * initialise the security for the init task
174 */
175static void cred_init_security(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700176{
David Howells3b11a1d2008-11-14 10:39:26 +1100177 struct cred *cred = (struct cred *) current->real_cred;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700178 struct task_security_struct *tsec;
179
James Morris89d155e2005-10-30 14:59:21 -0800180 tsec = kzalloc(sizeof(struct task_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700181 if (!tsec)
David Howellsd84f4f92008-11-14 10:39:23 +1100182 panic("SELinux: Failed to initialize initial task.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700183
David Howellsd84f4f92008-11-14 10:39:23 +1100184 tsec->osid = tsec->sid = SECINITSID_KERNEL;
David Howellsf1752ee2008-11-14 10:39:17 +1100185 cred->security = tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700186}
187
David Howells275bb412008-11-14 10:39:19 +1100188/*
David Howells88e67f32008-11-14 10:39:21 +1100189 * get the security ID of a set of credentials
190 */
191static inline u32 cred_sid(const struct cred *cred)
192{
193 const struct task_security_struct *tsec;
194
195 tsec = cred->security;
196 return tsec->sid;
197}
198
199/*
David Howells3b11a1d2008-11-14 10:39:26 +1100200 * get the objective security ID of a task
David Howells275bb412008-11-14 10:39:19 +1100201 */
202static inline u32 task_sid(const struct task_struct *task)
203{
David Howells275bb412008-11-14 10:39:19 +1100204 u32 sid;
205
206 rcu_read_lock();
David Howells88e67f32008-11-14 10:39:21 +1100207 sid = cred_sid(__task_cred(task));
David Howells275bb412008-11-14 10:39:19 +1100208 rcu_read_unlock();
209 return sid;
210}
211
212/*
David Howells3b11a1d2008-11-14 10:39:26 +1100213 * get the subjective security ID of the current task
David Howells275bb412008-11-14 10:39:19 +1100214 */
215static inline u32 current_sid(void)
216{
Paul Moore5fb49872010-04-22 14:46:19 -0400217 const struct task_security_struct *tsec = current_security();
David Howells275bb412008-11-14 10:39:19 +1100218
219 return tsec->sid;
220}
221
David Howells88e67f32008-11-14 10:39:21 +1100222/* Allocate and free functions for each kind of security blob. */
223
Linus Torvalds1da177e2005-04-16 15:20:36 -0700224static int inode_alloc_security(struct inode *inode)
225{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700226 struct inode_security_struct *isec;
David Howells275bb412008-11-14 10:39:19 +1100227 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700228
Josef Bacika02fe132008-04-04 09:35:05 +1100229 isec = kmem_cache_zalloc(sel_inode_cache, GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700230 if (!isec)
231 return -ENOMEM;
232
Eric Paris23970742006-09-25 23:32:01 -0700233 mutex_init(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234 INIT_LIST_HEAD(&isec->list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700235 isec->inode = inode;
236 isec->sid = SECINITSID_UNLABELED;
237 isec->sclass = SECCLASS_FILE;
David Howells275bb412008-11-14 10:39:19 +1100238 isec->task_sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239 inode->i_security = isec;
240
241 return 0;
242}
243
Steven Rostedt3dc91d42014-01-09 21:46:34 -0500244static void inode_free_rcu(struct rcu_head *head)
245{
246 struct inode_security_struct *isec;
247
248 isec = container_of(head, struct inode_security_struct, rcu);
249 kmem_cache_free(sel_inode_cache, isec);
250}
251
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252static void inode_free_security(struct inode *inode)
253{
254 struct inode_security_struct *isec = inode->i_security;
255 struct superblock_security_struct *sbsec = inode->i_sb->s_security;
256
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257 spin_lock(&sbsec->isec_lock);
258 if (!list_empty(&isec->list))
259 list_del_init(&isec->list);
260 spin_unlock(&sbsec->isec_lock);
261
Steven Rostedt3dc91d42014-01-09 21:46:34 -0500262 /*
263 * The inode may still be referenced in a path walk and
264 * a call to selinux_inode_permission() can be made
265 * after inode_free_security() is called. Ideally, the VFS
266 * wouldn't do this, but fixing that is a much harder
267 * job. For now, simply free the i_security via RCU, and
268 * leave the current inode->i_security pointer intact.
269 * The inode will be freed after the RCU grace period too.
270 */
271 call_rcu(&isec->rcu, inode_free_rcu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700272}
273
274static int file_alloc_security(struct file *file)
275{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700276 struct file_security_struct *fsec;
David Howells275bb412008-11-14 10:39:19 +1100277 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278
Stephen Smalley26d2a4b2006-02-01 03:05:55 -0800279 fsec = kzalloc(sizeof(struct file_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700280 if (!fsec)
281 return -ENOMEM;
282
David Howells275bb412008-11-14 10:39:19 +1100283 fsec->sid = sid;
284 fsec->fown_sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285 file->f_security = fsec;
286
287 return 0;
288}
289
290static void file_free_security(struct file *file)
291{
292 struct file_security_struct *fsec = file->f_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293 file->f_security = NULL;
294 kfree(fsec);
295}
296
297static int superblock_alloc_security(struct super_block *sb)
298{
299 struct superblock_security_struct *sbsec;
300
James Morris89d155e2005-10-30 14:59:21 -0800301 sbsec = kzalloc(sizeof(struct superblock_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700302 if (!sbsec)
303 return -ENOMEM;
304
Eric Parisbc7e9822006-09-25 23:32:02 -0700305 mutex_init(&sbsec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700306 INIT_LIST_HEAD(&sbsec->isec_head);
307 spin_lock_init(&sbsec->isec_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700308 sbsec->sb = sb;
309 sbsec->sid = SECINITSID_UNLABELED;
310 sbsec->def_sid = SECINITSID_FILE;
Eric Parisc312feb2006-07-10 04:43:53 -0700311 sbsec->mntpoint_sid = SECINITSID_UNLABELED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700312 sb->s_security = sbsec;
313
314 return 0;
315}
316
317static void superblock_free_security(struct super_block *sb)
318{
319 struct superblock_security_struct *sbsec = sb->s_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320 sb->s_security = NULL;
321 kfree(sbsec);
322}
323
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324/* The file system's label must be initialized prior to use. */
325
David Quigleyeb9ae682013-05-22 12:50:37 -0400326static const char *labeling_behaviors[7] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700327 "uses xattr",
328 "uses transition SIDs",
329 "uses task SIDs",
330 "uses genfs_contexts",
331 "not configured for labeling",
332 "uses mountpoint labeling",
David Quigleyeb9ae682013-05-22 12:50:37 -0400333 "uses native labeling",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334};
335
336static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry);
337
338static inline int inode_doinit(struct inode *inode)
339{
340 return inode_doinit_with_dentry(inode, NULL);
341}
342
343enum {
Eric Paris31e87932007-09-19 17:19:12 -0400344 Opt_error = -1,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700345 Opt_context = 1,
346 Opt_fscontext = 2,
Eric Parisc9180a52007-11-30 13:00:35 -0500347 Opt_defcontext = 3,
348 Opt_rootcontext = 4,
David P. Quigley11689d42009-01-16 09:22:03 -0500349 Opt_labelsupport = 5,
Eric Parisd355987f2012-08-24 15:58:53 -0400350 Opt_nextmntopt = 6,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351};
352
Eric Parisd355987f2012-08-24 15:58:53 -0400353#define NUM_SEL_MNT_OPTS (Opt_nextmntopt - 1)
354
Steven Whitehousea447c092008-10-13 10:46:57 +0100355static const match_table_t tokens = {
Eric Paris832cbd92008-04-01 13:24:09 -0400356 {Opt_context, CONTEXT_STR "%s"},
357 {Opt_fscontext, FSCONTEXT_STR "%s"},
358 {Opt_defcontext, DEFCONTEXT_STR "%s"},
359 {Opt_rootcontext, ROOTCONTEXT_STR "%s"},
David P. Quigley11689d42009-01-16 09:22:03 -0500360 {Opt_labelsupport, LABELSUPP_STR},
Eric Paris31e87932007-09-19 17:19:12 -0400361 {Opt_error, NULL},
Linus Torvalds1da177e2005-04-16 15:20:36 -0700362};
363
364#define SEL_MOUNT_FAIL_MSG "SELinux: duplicate or incompatible mount options\n"
365
Eric Parisc312feb2006-07-10 04:43:53 -0700366static int may_context_mount_sb_relabel(u32 sid,
367 struct superblock_security_struct *sbsec,
David Howells275bb412008-11-14 10:39:19 +1100368 const struct cred *cred)
Eric Parisc312feb2006-07-10 04:43:53 -0700369{
David Howells275bb412008-11-14 10:39:19 +1100370 const struct task_security_struct *tsec = cred->security;
Eric Parisc312feb2006-07-10 04:43:53 -0700371 int rc;
372
373 rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
374 FILESYSTEM__RELABELFROM, NULL);
375 if (rc)
376 return rc;
377
378 rc = avc_has_perm(tsec->sid, sid, SECCLASS_FILESYSTEM,
379 FILESYSTEM__RELABELTO, NULL);
380 return rc;
381}
382
Eric Paris08089252006-07-10 04:43:55 -0700383static int may_context_mount_inode_relabel(u32 sid,
384 struct superblock_security_struct *sbsec,
David Howells275bb412008-11-14 10:39:19 +1100385 const struct cred *cred)
Eric Paris08089252006-07-10 04:43:55 -0700386{
David Howells275bb412008-11-14 10:39:19 +1100387 const struct task_security_struct *tsec = cred->security;
Eric Paris08089252006-07-10 04:43:55 -0700388 int rc;
389 rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
390 FILESYSTEM__RELABELFROM, NULL);
391 if (rc)
392 return rc;
393
394 rc = avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM,
395 FILESYSTEM__ASSOCIATE, NULL);
396 return rc;
397}
398
Eric Parisb43e7252012-10-10 14:27:35 -0400399static int selinux_is_sblabel_mnt(struct super_block *sb)
400{
401 struct superblock_security_struct *sbsec = sb->s_security;
402
Mark Salyzynd5f3a5f2015-02-04 11:34:30 -0500403 return sbsec->behavior == SECURITY_FS_USE_XATTR ||
404 sbsec->behavior == SECURITY_FS_USE_TRANS ||
405 sbsec->behavior == SECURITY_FS_USE_TASK ||
J. Bruce Fields9fc2b4b2015-06-04 15:57:25 -0400406 sbsec->behavior == SECURITY_FS_USE_NATIVE ||
Mark Salyzynd5f3a5f2015-02-04 11:34:30 -0500407 /* Special handling. Genfs but also in-core setxattr handler */
408 !strcmp(sb->s_type->name, "sysfs") ||
409 !strcmp(sb->s_type->name, "pstore") ||
410 !strcmp(sb->s_type->name, "debugfs") ||
411 !strcmp(sb->s_type->name, "rootfs");
Eric Parisb43e7252012-10-10 14:27:35 -0400412}
413
Eric Parisc9180a52007-11-30 13:00:35 -0500414static int sb_finish_set_opts(struct super_block *sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415{
416 struct superblock_security_struct *sbsec = sb->s_security;
417 struct dentry *root = sb->s_root;
David Howellsc6f493d2015-03-17 22:26:22 +0000418 struct inode *root_inode = d_backing_inode(root);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419 int rc = 0;
420
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421 if (sbsec->behavior == SECURITY_FS_USE_XATTR) {
422 /* Make sure that the xattr handler exists and that no
423 error other than -ENODATA is returned by getxattr on
424 the root directory. -ENODATA is ok, as this may be
425 the first boot of the SELinux kernel before we have
426 assigned xattr values to the filesystem. */
Eric Parisc9180a52007-11-30 13:00:35 -0500427 if (!root_inode->i_op->getxattr) {
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800428 printk(KERN_WARNING "SELinux: (dev %s, type %s) has no "
429 "xattr support\n", sb->s_id, sb->s_type->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430 rc = -EOPNOTSUPP;
431 goto out;
432 }
Eric Parisc9180a52007-11-30 13:00:35 -0500433 rc = root_inode->i_op->getxattr(root, XATTR_NAME_SELINUX, NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434 if (rc < 0 && rc != -ENODATA) {
435 if (rc == -EOPNOTSUPP)
436 printk(KERN_WARNING "SELinux: (dev %s, type "
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800437 "%s) has no security xattr handler\n",
438 sb->s_id, sb->s_type->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439 else
440 printk(KERN_WARNING "SELinux: (dev %s, type "
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800441 "%s) getxattr errno %d\n", sb->s_id,
442 sb->s_type->name, -rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443 goto out;
444 }
445 }
446
Eric Parisc9180a52007-11-30 13:00:35 -0500447 if (sbsec->behavior > ARRAY_SIZE(labeling_behaviors))
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800448 printk(KERN_ERR "SELinux: initialized (dev %s, type %s), unknown behavior\n",
449 sb->s_id, sb->s_type->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700450
Eric Pariseadcabc2012-08-24 15:59:14 -0400451 sbsec->flags |= SE_SBINITIALIZED;
Eric Parisb43e7252012-10-10 14:27:35 -0400452 if (selinux_is_sblabel_mnt(sb))
Eric Paris12f348b2012-10-09 10:56:25 -0400453 sbsec->flags |= SBLABEL_MNT;
David P. Quigleyddd29ec2009-09-09 14:25:37 -0400454
Linus Torvalds1da177e2005-04-16 15:20:36 -0700455 /* Initialize the root inode. */
Eric Parisc9180a52007-11-30 13:00:35 -0500456 rc = inode_doinit_with_dentry(root_inode, root);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700457
458 /* Initialize any other inodes associated with the superblock, e.g.
459 inodes created prior to initial policy load or inodes created
460 during get_sb by a pseudo filesystem that directly
461 populates itself. */
462 spin_lock(&sbsec->isec_lock);
463next_inode:
464 if (!list_empty(&sbsec->isec_head)) {
465 struct inode_security_struct *isec =
466 list_entry(sbsec->isec_head.next,
Eric Parisc9180a52007-11-30 13:00:35 -0500467 struct inode_security_struct, list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700468 struct inode *inode = isec->inode;
Stephen Smalley923190d2014-10-06 16:32:52 -0400469 list_del_init(&isec->list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700470 spin_unlock(&sbsec->isec_lock);
471 inode = igrab(inode);
472 if (inode) {
Eric Parisc9180a52007-11-30 13:00:35 -0500473 if (!IS_PRIVATE(inode))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474 inode_doinit(inode);
475 iput(inode);
476 }
477 spin_lock(&sbsec->isec_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478 goto next_inode;
479 }
480 spin_unlock(&sbsec->isec_lock);
481out:
Eric Parisc9180a52007-11-30 13:00:35 -0500482 return rc;
483}
484
485/*
486 * This function should allow an FS to ask what it's mount security
487 * options were so it can use those later for submounts, displaying
488 * mount options, or whatever.
489 */
490static int selinux_get_mnt_opts(const struct super_block *sb,
Eric Parise0007522008-03-05 10:31:54 -0500491 struct security_mnt_opts *opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500492{
493 int rc = 0, i;
494 struct superblock_security_struct *sbsec = sb->s_security;
495 char *context = NULL;
496 u32 len;
497 char tmp;
498
Eric Parise0007522008-03-05 10:31:54 -0500499 security_init_mnt_opts(opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500500
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500501 if (!(sbsec->flags & SE_SBINITIALIZED))
Eric Parisc9180a52007-11-30 13:00:35 -0500502 return -EINVAL;
503
504 if (!ss_initialized)
505 return -EINVAL;
506
Eric Parisaf8e50c2012-08-24 15:59:00 -0400507 /* make sure we always check enough bits to cover the mask */
508 BUILD_BUG_ON(SE_MNTMASK >= (1 << NUM_SEL_MNT_OPTS));
509
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500510 tmp = sbsec->flags & SE_MNTMASK;
Eric Parisc9180a52007-11-30 13:00:35 -0500511 /* count the number of mount options for this sb */
Eric Parisaf8e50c2012-08-24 15:59:00 -0400512 for (i = 0; i < NUM_SEL_MNT_OPTS; i++) {
Eric Parisc9180a52007-11-30 13:00:35 -0500513 if (tmp & 0x01)
Eric Parise0007522008-03-05 10:31:54 -0500514 opts->num_mnt_opts++;
Eric Parisc9180a52007-11-30 13:00:35 -0500515 tmp >>= 1;
516 }
David P. Quigley11689d42009-01-16 09:22:03 -0500517 /* Check if the Label support flag is set */
Eric Paris0b4bdb32013-08-28 13:32:42 -0400518 if (sbsec->flags & SBLABEL_MNT)
David P. Quigley11689d42009-01-16 09:22:03 -0500519 opts->num_mnt_opts++;
Eric Parisc9180a52007-11-30 13:00:35 -0500520
Eric Parise0007522008-03-05 10:31:54 -0500521 opts->mnt_opts = kcalloc(opts->num_mnt_opts, sizeof(char *), GFP_ATOMIC);
522 if (!opts->mnt_opts) {
Eric Parisc9180a52007-11-30 13:00:35 -0500523 rc = -ENOMEM;
524 goto out_free;
525 }
526
Eric Parise0007522008-03-05 10:31:54 -0500527 opts->mnt_opts_flags = kcalloc(opts->num_mnt_opts, sizeof(int), GFP_ATOMIC);
528 if (!opts->mnt_opts_flags) {
Eric Parisc9180a52007-11-30 13:00:35 -0500529 rc = -ENOMEM;
530 goto out_free;
531 }
532
533 i = 0;
534 if (sbsec->flags & FSCONTEXT_MNT) {
535 rc = security_sid_to_context(sbsec->sid, &context, &len);
536 if (rc)
537 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500538 opts->mnt_opts[i] = context;
539 opts->mnt_opts_flags[i++] = FSCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500540 }
541 if (sbsec->flags & CONTEXT_MNT) {
542 rc = security_sid_to_context(sbsec->mntpoint_sid, &context, &len);
543 if (rc)
544 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500545 opts->mnt_opts[i] = context;
546 opts->mnt_opts_flags[i++] = CONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500547 }
548 if (sbsec->flags & DEFCONTEXT_MNT) {
549 rc = security_sid_to_context(sbsec->def_sid, &context, &len);
550 if (rc)
551 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500552 opts->mnt_opts[i] = context;
553 opts->mnt_opts_flags[i++] = DEFCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500554 }
555 if (sbsec->flags & ROOTCONTEXT_MNT) {
David Howellsc6f493d2015-03-17 22:26:22 +0000556 struct inode *root = d_backing_inode(sbsec->sb->s_root);
Eric Parisc9180a52007-11-30 13:00:35 -0500557 struct inode_security_struct *isec = root->i_security;
558
559 rc = security_sid_to_context(isec->sid, &context, &len);
560 if (rc)
561 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500562 opts->mnt_opts[i] = context;
563 opts->mnt_opts_flags[i++] = ROOTCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500564 }
Eric Paris12f348b2012-10-09 10:56:25 -0400565 if (sbsec->flags & SBLABEL_MNT) {
David P. Quigley11689d42009-01-16 09:22:03 -0500566 opts->mnt_opts[i] = NULL;
Eric Paris12f348b2012-10-09 10:56:25 -0400567 opts->mnt_opts_flags[i++] = SBLABEL_MNT;
David P. Quigley11689d42009-01-16 09:22:03 -0500568 }
Eric Parisc9180a52007-11-30 13:00:35 -0500569
Eric Parise0007522008-03-05 10:31:54 -0500570 BUG_ON(i != opts->num_mnt_opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500571
572 return 0;
573
574out_free:
Eric Parise0007522008-03-05 10:31:54 -0500575 security_free_mnt_opts(opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500576 return rc;
577}
578
579static int bad_option(struct superblock_security_struct *sbsec, char flag,
580 u32 old_sid, u32 new_sid)
581{
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500582 char mnt_flags = sbsec->flags & SE_MNTMASK;
583
Eric Parisc9180a52007-11-30 13:00:35 -0500584 /* check if the old mount command had the same options */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500585 if (sbsec->flags & SE_SBINITIALIZED)
Eric Parisc9180a52007-11-30 13:00:35 -0500586 if (!(sbsec->flags & flag) ||
587 (old_sid != new_sid))
588 return 1;
589
590 /* check if we were passed the same options twice,
591 * aka someone passed context=a,context=b
592 */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500593 if (!(sbsec->flags & SE_SBINITIALIZED))
594 if (mnt_flags & flag)
Eric Parisc9180a52007-11-30 13:00:35 -0500595 return 1;
596 return 0;
597}
Eric Parise0007522008-03-05 10:31:54 -0500598
Eric Parisc9180a52007-11-30 13:00:35 -0500599/*
600 * Allow filesystems with binary mount data to explicitly set mount point
601 * labeling information.
602 */
Eric Parise0007522008-03-05 10:31:54 -0500603static int selinux_set_mnt_opts(struct super_block *sb,
David Quigley649f6e72013-05-22 12:50:36 -0400604 struct security_mnt_opts *opts,
605 unsigned long kern_flags,
606 unsigned long *set_kern_flags)
Eric Parisc9180a52007-11-30 13:00:35 -0500607{
David Howells275bb412008-11-14 10:39:19 +1100608 const struct cred *cred = current_cred();
Eric Parisc9180a52007-11-30 13:00:35 -0500609 int rc = 0, i;
Eric Parisc9180a52007-11-30 13:00:35 -0500610 struct superblock_security_struct *sbsec = sb->s_security;
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800611 const char *name = sb->s_type->name;
David Howellsc6f493d2015-03-17 22:26:22 +0000612 struct inode *inode = d_backing_inode(sbsec->sb->s_root);
James Morris089be432008-07-15 18:32:49 +1000613 struct inode_security_struct *root_isec = inode->i_security;
Eric Parisc9180a52007-11-30 13:00:35 -0500614 u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0;
615 u32 defcontext_sid = 0;
Eric Parise0007522008-03-05 10:31:54 -0500616 char **mount_options = opts->mnt_opts;
617 int *flags = opts->mnt_opts_flags;
618 int num_opts = opts->num_mnt_opts;
Eric Parisc9180a52007-11-30 13:00:35 -0500619
620 mutex_lock(&sbsec->lock);
621
622 if (!ss_initialized) {
623 if (!num_opts) {
624 /* Defer initialization until selinux_complete_init,
625 after the initial policy is loaded and the security
626 server is ready to handle calls. */
Eric Parisc9180a52007-11-30 13:00:35 -0500627 goto out;
628 }
629 rc = -EINVAL;
Eric Paris744ba352008-04-17 11:52:44 -0400630 printk(KERN_WARNING "SELinux: Unable to set superblock options "
631 "before the security server is initialized\n");
Eric Parisc9180a52007-11-30 13:00:35 -0500632 goto out;
633 }
David Quigley649f6e72013-05-22 12:50:36 -0400634 if (kern_flags && !set_kern_flags) {
635 /* Specifying internal flags without providing a place to
636 * place the results is not allowed */
637 rc = -EINVAL;
638 goto out;
639 }
Eric Parisc9180a52007-11-30 13:00:35 -0500640
641 /*
Eric Parise0007522008-03-05 10:31:54 -0500642 * Binary mount data FS will come through this function twice. Once
643 * from an explicit call and once from the generic calls from the vfs.
644 * Since the generic VFS calls will not contain any security mount data
645 * we need to skip the double mount verification.
646 *
647 * This does open a hole in which we will not notice if the first
648 * mount using this sb set explict options and a second mount using
649 * this sb does not set any security options. (The first options
650 * will be used for both mounts)
651 */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500652 if ((sbsec->flags & SE_SBINITIALIZED) && (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)
Eric Parise0007522008-03-05 10:31:54 -0500653 && (num_opts == 0))
Eric Parisf5269712008-05-14 11:27:45 -0400654 goto out;
Eric Parise0007522008-03-05 10:31:54 -0500655
656 /*
Eric Parisc9180a52007-11-30 13:00:35 -0500657 * parse the mount options, check if they are valid sids.
658 * also check if someone is trying to mount the same sb more
659 * than once with different security options.
660 */
661 for (i = 0; i < num_opts; i++) {
662 u32 sid;
David P. Quigley11689d42009-01-16 09:22:03 -0500663
Eric Paris12f348b2012-10-09 10:56:25 -0400664 if (flags[i] == SBLABEL_MNT)
David P. Quigley11689d42009-01-16 09:22:03 -0500665 continue;
Eric Parisc9180a52007-11-30 13:00:35 -0500666 rc = security_context_to_sid(mount_options[i],
Nikolay Aleksandrov52a4c642014-03-07 12:44:19 +0100667 strlen(mount_options[i]), &sid, GFP_KERNEL);
Eric Parisc9180a52007-11-30 13:00:35 -0500668 if (rc) {
669 printk(KERN_WARNING "SELinux: security_context_to_sid"
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800670 "(%s) failed for (dev %s, type %s) errno=%d\n",
671 mount_options[i], sb->s_id, name, rc);
Eric Parisc9180a52007-11-30 13:00:35 -0500672 goto out;
673 }
674 switch (flags[i]) {
675 case FSCONTEXT_MNT:
676 fscontext_sid = sid;
677
678 if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid,
679 fscontext_sid))
680 goto out_double_mount;
681
682 sbsec->flags |= FSCONTEXT_MNT;
683 break;
684 case CONTEXT_MNT:
685 context_sid = sid;
686
687 if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid,
688 context_sid))
689 goto out_double_mount;
690
691 sbsec->flags |= CONTEXT_MNT;
692 break;
693 case ROOTCONTEXT_MNT:
694 rootcontext_sid = sid;
695
696 if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid,
697 rootcontext_sid))
698 goto out_double_mount;
699
700 sbsec->flags |= ROOTCONTEXT_MNT;
701
702 break;
703 case DEFCONTEXT_MNT:
704 defcontext_sid = sid;
705
706 if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid,
707 defcontext_sid))
708 goto out_double_mount;
709
710 sbsec->flags |= DEFCONTEXT_MNT;
711
712 break;
713 default:
714 rc = -EINVAL;
715 goto out;
716 }
717 }
718
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500719 if (sbsec->flags & SE_SBINITIALIZED) {
Eric Parisc9180a52007-11-30 13:00:35 -0500720 /* previously mounted with options, but not on this attempt? */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500721 if ((sbsec->flags & SE_MNTMASK) && !num_opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500722 goto out_double_mount;
723 rc = 0;
724 goto out;
725 }
726
James Morris089be432008-07-15 18:32:49 +1000727 if (strcmp(sb->s_type->name, "proc") == 0)
Stephen Smalley134509d2015-06-04 16:22:17 -0400728 sbsec->flags |= SE_SBPROC | SE_SBGENFS;
729
Stephen Smalley8e014722015-06-04 16:22:17 -0400730 if (!strcmp(sb->s_type->name, "debugfs") ||
731 !strcmp(sb->s_type->name, "sysfs") ||
732 !strcmp(sb->s_type->name, "pstore"))
Stephen Smalley134509d2015-06-04 16:22:17 -0400733 sbsec->flags |= SE_SBGENFS;
Eric Parisc9180a52007-11-30 13:00:35 -0500734
David Quigleyeb9ae682013-05-22 12:50:37 -0400735 if (!sbsec->behavior) {
736 /*
737 * Determine the labeling behavior to use for this
738 * filesystem type.
739 */
Paul Moore98f700f2013-09-18 13:52:20 -0400740 rc = security_fs_use(sb);
David Quigleyeb9ae682013-05-22 12:50:37 -0400741 if (rc) {
742 printk(KERN_WARNING
743 "%s: security_fs_use(%s) returned %d\n",
744 __func__, sb->s_type->name, rc);
745 goto out;
746 }
Eric Parisc9180a52007-11-30 13:00:35 -0500747 }
Eric Parisc9180a52007-11-30 13:00:35 -0500748 /* sets the context of the superblock for the fs being mounted. */
749 if (fscontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100750 rc = may_context_mount_sb_relabel(fscontext_sid, sbsec, cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500751 if (rc)
752 goto out;
753
754 sbsec->sid = fscontext_sid;
755 }
756
757 /*
758 * Switch to using mount point labeling behavior.
759 * sets the label used on all file below the mountpoint, and will set
760 * the superblock context if not already set.
761 */
David Quigleyeb9ae682013-05-22 12:50:37 -0400762 if (kern_flags & SECURITY_LSM_NATIVE_LABELS && !context_sid) {
763 sbsec->behavior = SECURITY_FS_USE_NATIVE;
764 *set_kern_flags |= SECURITY_LSM_NATIVE_LABELS;
765 }
766
Eric Parisc9180a52007-11-30 13:00:35 -0500767 if (context_sid) {
768 if (!fscontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100769 rc = may_context_mount_sb_relabel(context_sid, sbsec,
770 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500771 if (rc)
772 goto out;
773 sbsec->sid = context_sid;
774 } else {
David Howells275bb412008-11-14 10:39:19 +1100775 rc = may_context_mount_inode_relabel(context_sid, sbsec,
776 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500777 if (rc)
778 goto out;
779 }
780 if (!rootcontext_sid)
781 rootcontext_sid = context_sid;
782
783 sbsec->mntpoint_sid = context_sid;
784 sbsec->behavior = SECURITY_FS_USE_MNTPOINT;
785 }
786
787 if (rootcontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100788 rc = may_context_mount_inode_relabel(rootcontext_sid, sbsec,
789 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500790 if (rc)
791 goto out;
792
793 root_isec->sid = rootcontext_sid;
794 root_isec->initialized = 1;
795 }
796
797 if (defcontext_sid) {
David Quigleyeb9ae682013-05-22 12:50:37 -0400798 if (sbsec->behavior != SECURITY_FS_USE_XATTR &&
799 sbsec->behavior != SECURITY_FS_USE_NATIVE) {
Eric Parisc9180a52007-11-30 13:00:35 -0500800 rc = -EINVAL;
801 printk(KERN_WARNING "SELinux: defcontext option is "
802 "invalid for this filesystem type\n");
803 goto out;
804 }
805
806 if (defcontext_sid != sbsec->def_sid) {
807 rc = may_context_mount_inode_relabel(defcontext_sid,
David Howells275bb412008-11-14 10:39:19 +1100808 sbsec, cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500809 if (rc)
810 goto out;
811 }
812
813 sbsec->def_sid = defcontext_sid;
814 }
815
816 rc = sb_finish_set_opts(sb);
817out:
Eric Parisbc7e9822006-09-25 23:32:02 -0700818 mutex_unlock(&sbsec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700819 return rc;
Eric Parisc9180a52007-11-30 13:00:35 -0500820out_double_mount:
821 rc = -EINVAL;
822 printk(KERN_WARNING "SELinux: mount invalid. Same superblock, different "
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800823 "security settings for (dev %s, type %s)\n", sb->s_id, name);
Eric Parisc9180a52007-11-30 13:00:35 -0500824 goto out;
825}
826
Jeff Layton094f7b62013-04-01 08:14:24 -0400827static int selinux_cmp_sb_context(const struct super_block *oldsb,
828 const struct super_block *newsb)
829{
830 struct superblock_security_struct *old = oldsb->s_security;
831 struct superblock_security_struct *new = newsb->s_security;
832 char oldflags = old->flags & SE_MNTMASK;
833 char newflags = new->flags & SE_MNTMASK;
834
835 if (oldflags != newflags)
836 goto mismatch;
837 if ((oldflags & FSCONTEXT_MNT) && old->sid != new->sid)
838 goto mismatch;
839 if ((oldflags & CONTEXT_MNT) && old->mntpoint_sid != new->mntpoint_sid)
840 goto mismatch;
841 if ((oldflags & DEFCONTEXT_MNT) && old->def_sid != new->def_sid)
842 goto mismatch;
843 if (oldflags & ROOTCONTEXT_MNT) {
David Howellsc6f493d2015-03-17 22:26:22 +0000844 struct inode_security_struct *oldroot = d_backing_inode(oldsb->s_root)->i_security;
845 struct inode_security_struct *newroot = d_backing_inode(newsb->s_root)->i_security;
Jeff Layton094f7b62013-04-01 08:14:24 -0400846 if (oldroot->sid != newroot->sid)
847 goto mismatch;
848 }
849 return 0;
850mismatch:
851 printk(KERN_WARNING "SELinux: mount invalid. Same superblock, "
852 "different security settings for (dev %s, "
853 "type %s)\n", newsb->s_id, newsb->s_type->name);
854 return -EBUSY;
855}
856
857static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
Eric Parisc9180a52007-11-30 13:00:35 -0500858 struct super_block *newsb)
859{
860 const struct superblock_security_struct *oldsbsec = oldsb->s_security;
861 struct superblock_security_struct *newsbsec = newsb->s_security;
862
863 int set_fscontext = (oldsbsec->flags & FSCONTEXT_MNT);
864 int set_context = (oldsbsec->flags & CONTEXT_MNT);
865 int set_rootcontext = (oldsbsec->flags & ROOTCONTEXT_MNT);
866
Eric Paris0f5e6422008-04-21 16:24:11 -0400867 /*
868 * if the parent was able to be mounted it clearly had no special lsm
Al Viroe8c26252010-03-23 06:36:54 -0400869 * mount options. thus we can safely deal with this superblock later
Eric Paris0f5e6422008-04-21 16:24:11 -0400870 */
Al Viroe8c26252010-03-23 06:36:54 -0400871 if (!ss_initialized)
Jeff Layton094f7b62013-04-01 08:14:24 -0400872 return 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500873
Eric Parisc9180a52007-11-30 13:00:35 -0500874 /* how can we clone if the old one wasn't set up?? */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500875 BUG_ON(!(oldsbsec->flags & SE_SBINITIALIZED));
Eric Parisc9180a52007-11-30 13:00:35 -0500876
Jeff Layton094f7b62013-04-01 08:14:24 -0400877 /* if fs is reusing a sb, make sure that the contexts match */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500878 if (newsbsec->flags & SE_SBINITIALIZED)
Jeff Layton094f7b62013-04-01 08:14:24 -0400879 return selinux_cmp_sb_context(oldsb, newsb);
Eric Paris5a552612008-04-09 14:08:35 -0400880
Eric Parisc9180a52007-11-30 13:00:35 -0500881 mutex_lock(&newsbsec->lock);
882
883 newsbsec->flags = oldsbsec->flags;
884
885 newsbsec->sid = oldsbsec->sid;
886 newsbsec->def_sid = oldsbsec->def_sid;
887 newsbsec->behavior = oldsbsec->behavior;
888
889 if (set_context) {
890 u32 sid = oldsbsec->mntpoint_sid;
891
892 if (!set_fscontext)
893 newsbsec->sid = sid;
894 if (!set_rootcontext) {
David Howellsc6f493d2015-03-17 22:26:22 +0000895 struct inode *newinode = d_backing_inode(newsb->s_root);
Eric Parisc9180a52007-11-30 13:00:35 -0500896 struct inode_security_struct *newisec = newinode->i_security;
897 newisec->sid = sid;
898 }
899 newsbsec->mntpoint_sid = sid;
900 }
901 if (set_rootcontext) {
David Howellsc6f493d2015-03-17 22:26:22 +0000902 const struct inode *oldinode = d_backing_inode(oldsb->s_root);
Eric Parisc9180a52007-11-30 13:00:35 -0500903 const struct inode_security_struct *oldisec = oldinode->i_security;
David Howellsc6f493d2015-03-17 22:26:22 +0000904 struct inode *newinode = d_backing_inode(newsb->s_root);
Eric Parisc9180a52007-11-30 13:00:35 -0500905 struct inode_security_struct *newisec = newinode->i_security;
906
907 newisec->sid = oldisec->sid;
908 }
909
910 sb_finish_set_opts(newsb);
911 mutex_unlock(&newsbsec->lock);
Jeff Layton094f7b62013-04-01 08:14:24 -0400912 return 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500913}
914
Adrian Bunk2e1479d2008-03-17 22:29:23 +0200915static int selinux_parse_opts_str(char *options,
916 struct security_mnt_opts *opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500917{
Eric Parise0007522008-03-05 10:31:54 -0500918 char *p;
Eric Parisc9180a52007-11-30 13:00:35 -0500919 char *context = NULL, *defcontext = NULL;
920 char *fscontext = NULL, *rootcontext = NULL;
Eric Parise0007522008-03-05 10:31:54 -0500921 int rc, num_mnt_opts = 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500922
Eric Parise0007522008-03-05 10:31:54 -0500923 opts->num_mnt_opts = 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500924
925 /* Standard string-based options. */
926 while ((p = strsep(&options, "|")) != NULL) {
927 int token;
928 substring_t args[MAX_OPT_ARGS];
929
930 if (!*p)
931 continue;
932
933 token = match_token(p, tokens, args);
934
935 switch (token) {
936 case Opt_context:
937 if (context || defcontext) {
938 rc = -EINVAL;
939 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
940 goto out_err;
941 }
942 context = match_strdup(&args[0]);
943 if (!context) {
944 rc = -ENOMEM;
945 goto out_err;
946 }
947 break;
948
949 case Opt_fscontext:
950 if (fscontext) {
951 rc = -EINVAL;
952 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
953 goto out_err;
954 }
955 fscontext = match_strdup(&args[0]);
956 if (!fscontext) {
957 rc = -ENOMEM;
958 goto out_err;
959 }
960 break;
961
962 case Opt_rootcontext:
963 if (rootcontext) {
964 rc = -EINVAL;
965 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
966 goto out_err;
967 }
968 rootcontext = match_strdup(&args[0]);
969 if (!rootcontext) {
970 rc = -ENOMEM;
971 goto out_err;
972 }
973 break;
974
975 case Opt_defcontext:
976 if (context || defcontext) {
977 rc = -EINVAL;
978 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
979 goto out_err;
980 }
981 defcontext = match_strdup(&args[0]);
982 if (!defcontext) {
983 rc = -ENOMEM;
984 goto out_err;
985 }
986 break;
David P. Quigley11689d42009-01-16 09:22:03 -0500987 case Opt_labelsupport:
988 break;
Eric Parisc9180a52007-11-30 13:00:35 -0500989 default:
990 rc = -EINVAL;
991 printk(KERN_WARNING "SELinux: unknown mount option\n");
992 goto out_err;
993
994 }
995 }
996
Eric Parise0007522008-03-05 10:31:54 -0500997 rc = -ENOMEM;
998 opts->mnt_opts = kcalloc(NUM_SEL_MNT_OPTS, sizeof(char *), GFP_ATOMIC);
999 if (!opts->mnt_opts)
1000 goto out_err;
1001
1002 opts->mnt_opts_flags = kcalloc(NUM_SEL_MNT_OPTS, sizeof(int), GFP_ATOMIC);
1003 if (!opts->mnt_opts_flags) {
1004 kfree(opts->mnt_opts);
1005 goto out_err;
Eric Parisc9180a52007-11-30 13:00:35 -05001006 }
1007
Eric Parise0007522008-03-05 10:31:54 -05001008 if (fscontext) {
1009 opts->mnt_opts[num_mnt_opts] = fscontext;
1010 opts->mnt_opts_flags[num_mnt_opts++] = FSCONTEXT_MNT;
1011 }
1012 if (context) {
1013 opts->mnt_opts[num_mnt_opts] = context;
1014 opts->mnt_opts_flags[num_mnt_opts++] = CONTEXT_MNT;
1015 }
1016 if (rootcontext) {
1017 opts->mnt_opts[num_mnt_opts] = rootcontext;
1018 opts->mnt_opts_flags[num_mnt_opts++] = ROOTCONTEXT_MNT;
1019 }
1020 if (defcontext) {
1021 opts->mnt_opts[num_mnt_opts] = defcontext;
1022 opts->mnt_opts_flags[num_mnt_opts++] = DEFCONTEXT_MNT;
1023 }
1024
1025 opts->num_mnt_opts = num_mnt_opts;
1026 return 0;
1027
Eric Parisc9180a52007-11-30 13:00:35 -05001028out_err:
1029 kfree(context);
1030 kfree(defcontext);
1031 kfree(fscontext);
1032 kfree(rootcontext);
1033 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001034}
Eric Parise0007522008-03-05 10:31:54 -05001035/*
1036 * string mount options parsing and call set the sbsec
1037 */
1038static int superblock_doinit(struct super_block *sb, void *data)
1039{
1040 int rc = 0;
1041 char *options = data;
1042 struct security_mnt_opts opts;
1043
1044 security_init_mnt_opts(&opts);
1045
1046 if (!data)
1047 goto out;
1048
1049 BUG_ON(sb->s_type->fs_flags & FS_BINARY_MOUNTDATA);
1050
1051 rc = selinux_parse_opts_str(options, &opts);
1052 if (rc)
1053 goto out_err;
1054
1055out:
David Quigley649f6e72013-05-22 12:50:36 -04001056 rc = selinux_set_mnt_opts(sb, &opts, 0, NULL);
Eric Parise0007522008-03-05 10:31:54 -05001057
1058out_err:
1059 security_free_mnt_opts(&opts);
1060 return rc;
1061}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062
Adrian Bunk3583a712008-07-22 20:21:23 +03001063static void selinux_write_opts(struct seq_file *m,
1064 struct security_mnt_opts *opts)
Eric Paris2069f452008-07-04 09:47:13 +10001065{
1066 int i;
1067 char *prefix;
1068
1069 for (i = 0; i < opts->num_mnt_opts; i++) {
David P. Quigley11689d42009-01-16 09:22:03 -05001070 char *has_comma;
1071
1072 if (opts->mnt_opts[i])
1073 has_comma = strchr(opts->mnt_opts[i], ',');
1074 else
1075 has_comma = NULL;
Eric Paris2069f452008-07-04 09:47:13 +10001076
1077 switch (opts->mnt_opts_flags[i]) {
1078 case CONTEXT_MNT:
1079 prefix = CONTEXT_STR;
1080 break;
1081 case FSCONTEXT_MNT:
1082 prefix = FSCONTEXT_STR;
1083 break;
1084 case ROOTCONTEXT_MNT:
1085 prefix = ROOTCONTEXT_STR;
1086 break;
1087 case DEFCONTEXT_MNT:
1088 prefix = DEFCONTEXT_STR;
1089 break;
Eric Paris12f348b2012-10-09 10:56:25 -04001090 case SBLABEL_MNT:
David P. Quigley11689d42009-01-16 09:22:03 -05001091 seq_putc(m, ',');
1092 seq_puts(m, LABELSUPP_STR);
1093 continue;
Eric Paris2069f452008-07-04 09:47:13 +10001094 default:
1095 BUG();
Eric Parisa35c6c82011-04-20 10:21:28 -04001096 return;
Eric Paris2069f452008-07-04 09:47:13 +10001097 };
1098 /* we need a comma before each option */
1099 seq_putc(m, ',');
1100 seq_puts(m, prefix);
1101 if (has_comma)
1102 seq_putc(m, '\"');
Kees Cooka068acf2015-09-04 15:44:57 -07001103 seq_escape(m, opts->mnt_opts[i], "\"\n\\");
Eric Paris2069f452008-07-04 09:47:13 +10001104 if (has_comma)
1105 seq_putc(m, '\"');
1106 }
1107}
1108
1109static int selinux_sb_show_options(struct seq_file *m, struct super_block *sb)
1110{
1111 struct security_mnt_opts opts;
1112 int rc;
1113
1114 rc = selinux_get_mnt_opts(sb, &opts);
Eric Paris383795c2008-07-29 17:07:26 -04001115 if (rc) {
1116 /* before policy load we may get EINVAL, don't show anything */
1117 if (rc == -EINVAL)
1118 rc = 0;
Eric Paris2069f452008-07-04 09:47:13 +10001119 return rc;
Eric Paris383795c2008-07-29 17:07:26 -04001120 }
Eric Paris2069f452008-07-04 09:47:13 +10001121
1122 selinux_write_opts(m, &opts);
1123
1124 security_free_mnt_opts(&opts);
1125
1126 return rc;
1127}
1128
Linus Torvalds1da177e2005-04-16 15:20:36 -07001129static inline u16 inode_mode_to_security_class(umode_t mode)
1130{
1131 switch (mode & S_IFMT) {
1132 case S_IFSOCK:
1133 return SECCLASS_SOCK_FILE;
1134 case S_IFLNK:
1135 return SECCLASS_LNK_FILE;
1136 case S_IFREG:
1137 return SECCLASS_FILE;
1138 case S_IFBLK:
1139 return SECCLASS_BLK_FILE;
1140 case S_IFDIR:
1141 return SECCLASS_DIR;
1142 case S_IFCHR:
1143 return SECCLASS_CHR_FILE;
1144 case S_IFIFO:
1145 return SECCLASS_FIFO_FILE;
1146
1147 }
1148
1149 return SECCLASS_FILE;
1150}
1151
James Morris13402582005-09-30 14:24:34 -04001152static inline int default_protocol_stream(int protocol)
1153{
1154 return (protocol == IPPROTO_IP || protocol == IPPROTO_TCP);
1155}
1156
1157static inline int default_protocol_dgram(int protocol)
1158{
1159 return (protocol == IPPROTO_IP || protocol == IPPROTO_UDP);
1160}
1161
Linus Torvalds1da177e2005-04-16 15:20:36 -07001162static inline u16 socket_type_to_security_class(int family, int type, int protocol)
1163{
1164 switch (family) {
1165 case PF_UNIX:
1166 switch (type) {
1167 case SOCK_STREAM:
1168 case SOCK_SEQPACKET:
1169 return SECCLASS_UNIX_STREAM_SOCKET;
1170 case SOCK_DGRAM:
1171 return SECCLASS_UNIX_DGRAM_SOCKET;
1172 }
1173 break;
1174 case PF_INET:
1175 case PF_INET6:
1176 switch (type) {
1177 case SOCK_STREAM:
James Morris13402582005-09-30 14:24:34 -04001178 if (default_protocol_stream(protocol))
1179 return SECCLASS_TCP_SOCKET;
1180 else
1181 return SECCLASS_RAWIP_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001182 case SOCK_DGRAM:
James Morris13402582005-09-30 14:24:34 -04001183 if (default_protocol_dgram(protocol))
1184 return SECCLASS_UDP_SOCKET;
1185 else
1186 return SECCLASS_RAWIP_SOCKET;
James Morris2ee92d42006-11-13 16:09:01 -08001187 case SOCK_DCCP:
1188 return SECCLASS_DCCP_SOCKET;
James Morris13402582005-09-30 14:24:34 -04001189 default:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001190 return SECCLASS_RAWIP_SOCKET;
1191 }
1192 break;
1193 case PF_NETLINK:
1194 switch (protocol) {
1195 case NETLINK_ROUTE:
1196 return SECCLASS_NETLINK_ROUTE_SOCKET;
Pavel Emelyanov7f1fb602011-12-06 07:56:43 +00001197 case NETLINK_SOCK_DIAG:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001198 return SECCLASS_NETLINK_TCPDIAG_SOCKET;
1199 case NETLINK_NFLOG:
1200 return SECCLASS_NETLINK_NFLOG_SOCKET;
1201 case NETLINK_XFRM:
1202 return SECCLASS_NETLINK_XFRM_SOCKET;
1203 case NETLINK_SELINUX:
1204 return SECCLASS_NETLINK_SELINUX_SOCKET;
Stephen Smalley6c6d2e92015-06-04 16:22:16 -04001205 case NETLINK_ISCSI:
1206 return SECCLASS_NETLINK_ISCSI_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001207 case NETLINK_AUDIT:
1208 return SECCLASS_NETLINK_AUDIT_SOCKET;
Stephen Smalley6c6d2e92015-06-04 16:22:16 -04001209 case NETLINK_FIB_LOOKUP:
1210 return SECCLASS_NETLINK_FIB_LOOKUP_SOCKET;
1211 case NETLINK_CONNECTOR:
1212 return SECCLASS_NETLINK_CONNECTOR_SOCKET;
1213 case NETLINK_NETFILTER:
1214 return SECCLASS_NETLINK_NETFILTER_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215 case NETLINK_DNRTMSG:
1216 return SECCLASS_NETLINK_DNRT_SOCKET;
James Morris0c9b7942005-04-16 15:24:13 -07001217 case NETLINK_KOBJECT_UEVENT:
1218 return SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET;
Stephen Smalley6c6d2e92015-06-04 16:22:16 -04001219 case NETLINK_GENERIC:
1220 return SECCLASS_NETLINK_GENERIC_SOCKET;
1221 case NETLINK_SCSITRANSPORT:
1222 return SECCLASS_NETLINK_SCSITRANSPORT_SOCKET;
1223 case NETLINK_RDMA:
1224 return SECCLASS_NETLINK_RDMA_SOCKET;
1225 case NETLINK_CRYPTO:
1226 return SECCLASS_NETLINK_CRYPTO_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001227 default:
1228 return SECCLASS_NETLINK_SOCKET;
1229 }
1230 case PF_PACKET:
1231 return SECCLASS_PACKET_SOCKET;
1232 case PF_KEY:
1233 return SECCLASS_KEY_SOCKET;
Christopher J. PeBenito3e3ff152006-06-09 00:25:03 -07001234 case PF_APPLETALK:
1235 return SECCLASS_APPLETALK_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001236 }
1237
1238 return SECCLASS_SOCKET;
1239}
1240
Stephen Smalley134509d2015-06-04 16:22:17 -04001241static int selinux_genfs_get_sid(struct dentry *dentry,
1242 u16 tclass,
1243 u16 flags,
1244 u32 *sid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001245{
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001246 int rc;
Stephen Smalley134509d2015-06-04 16:22:17 -04001247 struct super_block *sb = dentry->d_inode->i_sb;
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001248 char *buffer, *path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001249
Eric Paris828dfe12008-04-17 13:17:49 -04001250 buffer = (char *)__get_free_page(GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001251 if (!buffer)
1252 return -ENOMEM;
1253
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001254 path = dentry_path_raw(dentry, buffer, PAGE_SIZE);
1255 if (IS_ERR(path))
1256 rc = PTR_ERR(path);
1257 else {
Stephen Smalley134509d2015-06-04 16:22:17 -04001258 if (flags & SE_SBPROC) {
1259 /* each process gets a /proc/PID/ entry. Strip off the
1260 * PID part to get a valid selinux labeling.
1261 * e.g. /proc/1/net/rpc/nfs -> /net/rpc/nfs */
1262 while (path[1] >= '0' && path[1] <= '9') {
1263 path[1] = '/';
1264 path++;
1265 }
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001266 }
Stephen Smalley134509d2015-06-04 16:22:17 -04001267 rc = security_genfs_sid(sb->s_type->name, path, tclass, sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001268 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001269 free_page((unsigned long)buffer);
1270 return rc;
1271}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001272
1273/* The inode's security attributes must be initialized before first use. */
1274static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry)
1275{
1276 struct superblock_security_struct *sbsec = NULL;
1277 struct inode_security_struct *isec = inode->i_security;
1278 u32 sid;
1279 struct dentry *dentry;
1280#define INITCONTEXTLEN 255
1281 char *context = NULL;
1282 unsigned len = 0;
1283 int rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001284
1285 if (isec->initialized)
1286 goto out;
1287
Eric Paris23970742006-09-25 23:32:01 -07001288 mutex_lock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001289 if (isec->initialized)
Eric Paris23970742006-09-25 23:32:01 -07001290 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001291
1292 sbsec = inode->i_sb->s_security;
David P. Quigley0d90a7e2009-01-16 09:22:02 -05001293 if (!(sbsec->flags & SE_SBINITIALIZED)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001294 /* Defer initialization until selinux_complete_init,
1295 after the initial policy is loaded and the security
1296 server is ready to handle calls. */
1297 spin_lock(&sbsec->isec_lock);
1298 if (list_empty(&isec->list))
1299 list_add(&isec->list, &sbsec->isec_head);
1300 spin_unlock(&sbsec->isec_lock);
Eric Paris23970742006-09-25 23:32:01 -07001301 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001302 }
1303
1304 switch (sbsec->behavior) {
David Quigleyeb9ae682013-05-22 12:50:37 -04001305 case SECURITY_FS_USE_NATIVE:
1306 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001307 case SECURITY_FS_USE_XATTR:
1308 if (!inode->i_op->getxattr) {
1309 isec->sid = sbsec->def_sid;
1310 break;
1311 }
1312
1313 /* Need a dentry, since the xattr API requires one.
1314 Life would be simpler if we could just pass the inode. */
1315 if (opt_dentry) {
1316 /* Called from d_instantiate or d_splice_alias. */
1317 dentry = dget(opt_dentry);
1318 } else {
1319 /* Called from selinux_complete_init, try to find a dentry. */
1320 dentry = d_find_alias(inode);
1321 }
1322 if (!dentry) {
Eric Parisdf7f54c2009-03-09 14:35:58 -04001323 /*
1324 * this is can be hit on boot when a file is accessed
1325 * before the policy is loaded. When we load policy we
1326 * may find inodes that have no dentry on the
1327 * sbsec->isec_head list. No reason to complain as these
1328 * will get fixed up the next time we go through
1329 * inode_doinit with a dentry, before these inodes could
1330 * be used again by userspace.
1331 */
Eric Paris23970742006-09-25 23:32:01 -07001332 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001333 }
1334
1335 len = INITCONTEXTLEN;
Eric Paris4cb912f2009-02-12 14:50:05 -05001336 context = kmalloc(len+1, GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001337 if (!context) {
1338 rc = -ENOMEM;
1339 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001340 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001341 }
Eric Paris4cb912f2009-02-12 14:50:05 -05001342 context[len] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001343 rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX,
1344 context, len);
1345 if (rc == -ERANGE) {
James Morris314dabb2009-08-10 22:00:13 +10001346 kfree(context);
1347
Linus Torvalds1da177e2005-04-16 15:20:36 -07001348 /* Need a larger buffer. Query for the right size. */
1349 rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX,
1350 NULL, 0);
1351 if (rc < 0) {
1352 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001353 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001354 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001355 len = rc;
Eric Paris4cb912f2009-02-12 14:50:05 -05001356 context = kmalloc(len+1, GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001357 if (!context) {
1358 rc = -ENOMEM;
1359 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001360 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001361 }
Eric Paris4cb912f2009-02-12 14:50:05 -05001362 context[len] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001363 rc = inode->i_op->getxattr(dentry,
1364 XATTR_NAME_SELINUX,
1365 context, len);
1366 }
1367 dput(dentry);
1368 if (rc < 0) {
1369 if (rc != -ENODATA) {
Eric Paris744ba352008-04-17 11:52:44 -04001370 printk(KERN_WARNING "SELinux: %s: getxattr returned "
Harvey Harrisondd6f9532008-03-06 10:03:59 +11001371 "%d for dev=%s ino=%ld\n", __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001372 -rc, inode->i_sb->s_id, inode->i_ino);
1373 kfree(context);
Eric Paris23970742006-09-25 23:32:01 -07001374 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001375 }
1376 /* Map ENODATA to the default file SID */
1377 sid = sbsec->def_sid;
1378 rc = 0;
1379 } else {
James Morrisf5c1d5b2005-07-28 01:07:37 -07001380 rc = security_context_to_sid_default(context, rc, &sid,
Stephen Smalley869ab512008-04-04 08:46:05 -04001381 sbsec->def_sid,
1382 GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001383 if (rc) {
Eric Paris4ba0a8a2009-02-12 15:01:10 -05001384 char *dev = inode->i_sb->s_id;
1385 unsigned long ino = inode->i_ino;
1386
1387 if (rc == -EINVAL) {
1388 if (printk_ratelimit())
1389 printk(KERN_NOTICE "SELinux: inode=%lu on dev=%s was found to have an invalid "
1390 "context=%s. This indicates you may need to relabel the inode or the "
1391 "filesystem in question.\n", ino, dev, context);
1392 } else {
1393 printk(KERN_WARNING "SELinux: %s: context_to_sid(%s) "
1394 "returned %d for dev=%s ino=%ld\n",
1395 __func__, context, -rc, dev, ino);
1396 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001397 kfree(context);
1398 /* Leave with the unlabeled SID */
1399 rc = 0;
1400 break;
1401 }
1402 }
1403 kfree(context);
1404 isec->sid = sid;
1405 break;
1406 case SECURITY_FS_USE_TASK:
1407 isec->sid = isec->task_sid;
1408 break;
1409 case SECURITY_FS_USE_TRANS:
1410 /* Default to the fs SID. */
1411 isec->sid = sbsec->sid;
1412
1413 /* Try to obtain a transition SID. */
1414 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Eric Paris652bb9b2011-02-01 11:05:40 -05001415 rc = security_transition_sid(isec->task_sid, sbsec->sid,
1416 isec->sclass, NULL, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001417 if (rc)
Eric Paris23970742006-09-25 23:32:01 -07001418 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001419 isec->sid = sid;
1420 break;
Eric Parisc312feb2006-07-10 04:43:53 -07001421 case SECURITY_FS_USE_MNTPOINT:
1422 isec->sid = sbsec->mntpoint_sid;
1423 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001424 default:
Eric Parisc312feb2006-07-10 04:43:53 -07001425 /* Default to the fs superblock SID. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001426 isec->sid = sbsec->sid;
1427
Stephen Smalley134509d2015-06-04 16:22:17 -04001428 if ((sbsec->flags & SE_SBGENFS) && !S_ISLNK(inode->i_mode)) {
Paul Mooref64410e2014-03-19 16:46:18 -04001429 /* We must have a dentry to determine the label on
1430 * procfs inodes */
1431 if (opt_dentry)
1432 /* Called from d_instantiate or
1433 * d_splice_alias. */
1434 dentry = dget(opt_dentry);
1435 else
1436 /* Called from selinux_complete_init, try to
1437 * find a dentry. */
1438 dentry = d_find_alias(inode);
1439 /*
1440 * This can be hit on boot when a file is accessed
1441 * before the policy is loaded. When we load policy we
1442 * may find inodes that have no dentry on the
1443 * sbsec->isec_head list. No reason to complain as
1444 * these will get fixed up the next time we go through
1445 * inode_doinit() with a dentry, before these inodes
1446 * could be used again by userspace.
1447 */
1448 if (!dentry)
1449 goto out_unlock;
1450 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Stephen Smalley134509d2015-06-04 16:22:17 -04001451 rc = selinux_genfs_get_sid(dentry, isec->sclass,
1452 sbsec->flags, &sid);
Paul Mooref64410e2014-03-19 16:46:18 -04001453 dput(dentry);
1454 if (rc)
1455 goto out_unlock;
1456 isec->sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001457 }
1458 break;
1459 }
1460
1461 isec->initialized = 1;
1462
Eric Paris23970742006-09-25 23:32:01 -07001463out_unlock:
1464 mutex_unlock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001465out:
1466 if (isec->sclass == SECCLASS_FILE)
1467 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468 return rc;
1469}
1470
1471/* Convert a Linux signal to an access vector. */
1472static inline u32 signal_to_av(int sig)
1473{
1474 u32 perm = 0;
1475
1476 switch (sig) {
1477 case SIGCHLD:
1478 /* Commonly granted from child to parent. */
1479 perm = PROCESS__SIGCHLD;
1480 break;
1481 case SIGKILL:
1482 /* Cannot be caught or ignored */
1483 perm = PROCESS__SIGKILL;
1484 break;
1485 case SIGSTOP:
1486 /* Cannot be caught or ignored */
1487 perm = PROCESS__SIGSTOP;
1488 break;
1489 default:
1490 /* All other signals. */
1491 perm = PROCESS__SIGNAL;
1492 break;
1493 }
1494
1495 return perm;
1496}
1497
David Howells275bb412008-11-14 10:39:19 +11001498/*
David Howellsd84f4f92008-11-14 10:39:23 +11001499 * Check permission between a pair of credentials
1500 * fork check, ptrace check, etc.
1501 */
1502static int cred_has_perm(const struct cred *actor,
1503 const struct cred *target,
1504 u32 perms)
1505{
1506 u32 asid = cred_sid(actor), tsid = cred_sid(target);
1507
1508 return avc_has_perm(asid, tsid, SECCLASS_PROCESS, perms, NULL);
1509}
1510
1511/*
David Howells88e67f32008-11-14 10:39:21 +11001512 * Check permission between a pair of tasks, e.g. signal checks,
David Howells275bb412008-11-14 10:39:19 +11001513 * fork check, ptrace check, etc.
1514 * tsk1 is the actor and tsk2 is the target
David Howells3b11a1d2008-11-14 10:39:26 +11001515 * - this uses the default subjective creds of tsk1
David Howells275bb412008-11-14 10:39:19 +11001516 */
1517static int task_has_perm(const struct task_struct *tsk1,
1518 const struct task_struct *tsk2,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001519 u32 perms)
1520{
David Howells275bb412008-11-14 10:39:19 +11001521 const struct task_security_struct *__tsec1, *__tsec2;
1522 u32 sid1, sid2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001523
David Howells275bb412008-11-14 10:39:19 +11001524 rcu_read_lock();
1525 __tsec1 = __task_cred(tsk1)->security; sid1 = __tsec1->sid;
1526 __tsec2 = __task_cred(tsk2)->security; sid2 = __tsec2->sid;
1527 rcu_read_unlock();
1528 return avc_has_perm(sid1, sid2, SECCLASS_PROCESS, perms, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001529}
1530
David Howells3b11a1d2008-11-14 10:39:26 +11001531/*
1532 * Check permission between current and another task, e.g. signal checks,
1533 * fork check, ptrace check, etc.
1534 * current is the actor and tsk2 is the target
1535 * - this uses current's subjective creds
1536 */
1537static int current_has_perm(const struct task_struct *tsk,
1538 u32 perms)
1539{
1540 u32 sid, tsid;
1541
1542 sid = current_sid();
1543 tsid = task_sid(tsk);
1544 return avc_has_perm(sid, tsid, SECCLASS_PROCESS, perms, NULL);
1545}
1546
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001547#if CAP_LAST_CAP > 63
1548#error Fix SELinux to handle capabilities > 63.
1549#endif
1550
Linus Torvalds1da177e2005-04-16 15:20:36 -07001551/* Check whether a task is allowed to use a capability. */
Eric Paris6a9de492012-01-03 12:25:14 -05001552static int cred_has_capability(const struct cred *cred,
Eric Paris06112162008-11-11 22:02:50 +11001553 int cap, int audit)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001554{
Thomas Liu2bf49692009-07-14 12:14:09 -04001555 struct common_audit_data ad;
Eric Paris06112162008-11-11 22:02:50 +11001556 struct av_decision avd;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001557 u16 sclass;
David Howells3699c532009-01-06 22:27:01 +00001558 u32 sid = cred_sid(cred);
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001559 u32 av = CAP_TO_MASK(cap);
Eric Paris06112162008-11-11 22:02:50 +11001560 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001561
Eric Paris50c205f2012-04-04 15:01:43 -04001562 ad.type = LSM_AUDIT_DATA_CAP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001563 ad.u.cap = cap;
1564
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001565 switch (CAP_TO_INDEX(cap)) {
1566 case 0:
1567 sclass = SECCLASS_CAPABILITY;
1568 break;
1569 case 1:
1570 sclass = SECCLASS_CAPABILITY2;
1571 break;
1572 default:
1573 printk(KERN_ERR
1574 "SELinux: out of range capability %d\n", cap);
1575 BUG();
Eric Parisa35c6c82011-04-20 10:21:28 -04001576 return -EINVAL;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001577 }
Eric Paris06112162008-11-11 22:02:50 +11001578
David Howells275bb412008-11-14 10:39:19 +11001579 rc = avc_has_perm_noaudit(sid, sid, sclass, av, 0, &avd);
Eric Paris9ade0cf2011-04-25 16:26:29 -04001580 if (audit == SECURITY_CAP_AUDIT) {
NeilBrown7b20ea22015-03-23 13:37:39 +11001581 int rc2 = avc_audit(sid, sid, sclass, av, &avd, rc, &ad, 0);
Eric Paris9ade0cf2011-04-25 16:26:29 -04001582 if (rc2)
1583 return rc2;
1584 }
Eric Paris06112162008-11-11 22:02:50 +11001585 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001586}
1587
1588/* Check whether a task is allowed to use a system operation. */
1589static int task_has_system(struct task_struct *tsk,
1590 u32 perms)
1591{
David Howells275bb412008-11-14 10:39:19 +11001592 u32 sid = task_sid(tsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001593
David Howells275bb412008-11-14 10:39:19 +11001594 return avc_has_perm(sid, SECINITSID_KERNEL,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001595 SECCLASS_SYSTEM, perms, NULL);
1596}
1597
1598/* Check whether a task has a particular permission to an inode.
1599 The 'adp' parameter is optional and allows other audit
1600 data to be passed (e.g. the dentry). */
David Howells88e67f32008-11-14 10:39:21 +11001601static int inode_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001602 struct inode *inode,
1603 u32 perms,
Linus Torvalds19e49832013-10-04 12:54:11 -07001604 struct common_audit_data *adp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001605{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001606 struct inode_security_struct *isec;
David Howells275bb412008-11-14 10:39:19 +11001607 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001608
David Howellse0e81732009-09-02 09:13:40 +01001609 validate_creds(cred);
1610
Eric Paris828dfe12008-04-17 13:17:49 -04001611 if (unlikely(IS_PRIVATE(inode)))
Stephen Smalleybbaca6c2007-02-14 00:34:16 -08001612 return 0;
1613
David Howells88e67f32008-11-14 10:39:21 +11001614 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001615 isec = inode->i_security;
1616
Linus Torvalds19e49832013-10-04 12:54:11 -07001617 return avc_has_perm(sid, isec->sid, isec->sclass, perms, adp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001618}
1619
1620/* Same as inode_has_perm, but pass explicit audit data containing
1621 the dentry to help the auditing code to more easily generate the
1622 pathname if needed. */
David Howells88e67f32008-11-14 10:39:21 +11001623static inline int dentry_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001624 struct dentry *dentry,
1625 u32 av)
1626{
David Howellsc6f493d2015-03-17 22:26:22 +00001627 struct inode *inode = d_backing_inode(dentry);
Thomas Liu2bf49692009-07-14 12:14:09 -04001628 struct common_audit_data ad;
David Howells88e67f32008-11-14 10:39:21 +11001629
Eric Paris50c205f2012-04-04 15:01:43 -04001630 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Paris2875fa02011-04-28 16:04:24 -04001631 ad.u.dentry = dentry;
Linus Torvalds19e49832013-10-04 12:54:11 -07001632 return inode_has_perm(cred, inode, av, &ad);
Eric Paris2875fa02011-04-28 16:04:24 -04001633}
1634
1635/* Same as inode_has_perm, but pass explicit audit data containing
1636 the path to help the auditing code to more easily generate the
1637 pathname if needed. */
1638static inline int path_has_perm(const struct cred *cred,
Al Viro3f7036a2015-03-08 19:28:30 -04001639 const struct path *path,
Eric Paris2875fa02011-04-28 16:04:24 -04001640 u32 av)
1641{
David Howellsc6f493d2015-03-17 22:26:22 +00001642 struct inode *inode = d_backing_inode(path->dentry);
Eric Paris2875fa02011-04-28 16:04:24 -04001643 struct common_audit_data ad;
1644
Eric Paris50c205f2012-04-04 15:01:43 -04001645 ad.type = LSM_AUDIT_DATA_PATH;
Eric Paris2875fa02011-04-28 16:04:24 -04001646 ad.u.path = *path;
Linus Torvalds19e49832013-10-04 12:54:11 -07001647 return inode_has_perm(cred, inode, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001648}
1649
David Howells13f8e982013-06-13 23:37:55 +01001650/* Same as path_has_perm, but uses the inode from the file struct. */
1651static inline int file_path_has_perm(const struct cred *cred,
1652 struct file *file,
1653 u32 av)
1654{
1655 struct common_audit_data ad;
1656
1657 ad.type = LSM_AUDIT_DATA_PATH;
1658 ad.u.path = file->f_path;
Linus Torvalds19e49832013-10-04 12:54:11 -07001659 return inode_has_perm(cred, file_inode(file), av, &ad);
David Howells13f8e982013-06-13 23:37:55 +01001660}
1661
Linus Torvalds1da177e2005-04-16 15:20:36 -07001662/* Check whether a task can use an open file descriptor to
1663 access an inode in a given way. Check access to the
1664 descriptor itself, and then use dentry_has_perm to
1665 check a particular permission to the file.
1666 Access to the descriptor is implicitly granted if it
1667 has the same SID as the process. If av is zero, then
1668 access to the file is not checked, e.g. for cases
1669 where only the descriptor is affected like seek. */
David Howells88e67f32008-11-14 10:39:21 +11001670static int file_has_perm(const struct cred *cred,
1671 struct file *file,
1672 u32 av)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001673{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001674 struct file_security_struct *fsec = file->f_security;
Al Viro496ad9a2013-01-23 17:07:38 -05001675 struct inode *inode = file_inode(file);
Thomas Liu2bf49692009-07-14 12:14:09 -04001676 struct common_audit_data ad;
David Howells88e67f32008-11-14 10:39:21 +11001677 u32 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001678 int rc;
1679
Eric Paris50c205f2012-04-04 15:01:43 -04001680 ad.type = LSM_AUDIT_DATA_PATH;
Eric Parisf48b7392011-04-25 12:54:27 -04001681 ad.u.path = file->f_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001682
David Howells275bb412008-11-14 10:39:19 +11001683 if (sid != fsec->sid) {
1684 rc = avc_has_perm(sid, fsec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001685 SECCLASS_FD,
1686 FD__USE,
1687 &ad);
1688 if (rc)
David Howells88e67f32008-11-14 10:39:21 +11001689 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001690 }
1691
1692 /* av is zero if only checking access to the descriptor. */
David Howells88e67f32008-11-14 10:39:21 +11001693 rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001694 if (av)
Linus Torvalds19e49832013-10-04 12:54:11 -07001695 rc = inode_has_perm(cred, inode, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001696
David Howells88e67f32008-11-14 10:39:21 +11001697out:
1698 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001699}
1700
1701/* Check whether a task can create a file. */
1702static int may_create(struct inode *dir,
1703 struct dentry *dentry,
1704 u16 tclass)
1705{
Paul Moore5fb49872010-04-22 14:46:19 -04001706 const struct task_security_struct *tsec = current_security();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001707 struct inode_security_struct *dsec;
1708 struct superblock_security_struct *sbsec;
David Howells275bb412008-11-14 10:39:19 +11001709 u32 sid, newsid;
Thomas Liu2bf49692009-07-14 12:14:09 -04001710 struct common_audit_data ad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001711 int rc;
1712
Linus Torvalds1da177e2005-04-16 15:20:36 -07001713 dsec = dir->i_security;
1714 sbsec = dir->i_sb->s_security;
1715
David Howells275bb412008-11-14 10:39:19 +11001716 sid = tsec->sid;
1717 newsid = tsec->create_sid;
1718
Eric Paris50c205f2012-04-04 15:01:43 -04001719 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04001720 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001721
David Howells275bb412008-11-14 10:39:19 +11001722 rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001723 DIR__ADD_NAME | DIR__SEARCH,
1724 &ad);
1725 if (rc)
1726 return rc;
1727
Eric Paris12f348b2012-10-09 10:56:25 -04001728 if (!newsid || !(sbsec->flags & SBLABEL_MNT)) {
Eric Pariscb1e9222011-04-28 15:11:21 -04001729 rc = security_transition_sid(sid, dsec->sid, tclass,
1730 &dentry->d_name, &newsid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001731 if (rc)
1732 return rc;
1733 }
1734
David Howells275bb412008-11-14 10:39:19 +11001735 rc = avc_has_perm(sid, newsid, tclass, FILE__CREATE, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001736 if (rc)
1737 return rc;
1738
1739 return avc_has_perm(newsid, sbsec->sid,
1740 SECCLASS_FILESYSTEM,
1741 FILESYSTEM__ASSOCIATE, &ad);
1742}
1743
Michael LeMay4eb582c2006-06-26 00:24:57 -07001744/* Check whether a task can create a key. */
1745static int may_create_key(u32 ksid,
1746 struct task_struct *ctx)
1747{
David Howells275bb412008-11-14 10:39:19 +11001748 u32 sid = task_sid(ctx);
Michael LeMay4eb582c2006-06-26 00:24:57 -07001749
David Howells275bb412008-11-14 10:39:19 +11001750 return avc_has_perm(sid, ksid, SECCLASS_KEY, KEY__CREATE, NULL);
Michael LeMay4eb582c2006-06-26 00:24:57 -07001751}
1752
Eric Paris828dfe12008-04-17 13:17:49 -04001753#define MAY_LINK 0
1754#define MAY_UNLINK 1
1755#define MAY_RMDIR 2
Linus Torvalds1da177e2005-04-16 15:20:36 -07001756
1757/* Check whether a task can link, unlink, or rmdir a file/directory. */
1758static int may_link(struct inode *dir,
1759 struct dentry *dentry,
1760 int kind)
1761
1762{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001763 struct inode_security_struct *dsec, *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04001764 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11001765 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001766 u32 av;
1767 int rc;
1768
Linus Torvalds1da177e2005-04-16 15:20:36 -07001769 dsec = dir->i_security;
David Howellsc6f493d2015-03-17 22:26:22 +00001770 isec = d_backing_inode(dentry)->i_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001771
Eric Paris50c205f2012-04-04 15:01:43 -04001772 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04001773 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001774
1775 av = DIR__SEARCH;
1776 av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME);
David Howells275bb412008-11-14 10:39:19 +11001777 rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001778 if (rc)
1779 return rc;
1780
1781 switch (kind) {
1782 case MAY_LINK:
1783 av = FILE__LINK;
1784 break;
1785 case MAY_UNLINK:
1786 av = FILE__UNLINK;
1787 break;
1788 case MAY_RMDIR:
1789 av = DIR__RMDIR;
1790 break;
1791 default:
Eric Paris744ba352008-04-17 11:52:44 -04001792 printk(KERN_WARNING "SELinux: %s: unrecognized kind %d\n",
1793 __func__, kind);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001794 return 0;
1795 }
1796
David Howells275bb412008-11-14 10:39:19 +11001797 rc = avc_has_perm(sid, isec->sid, isec->sclass, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001798 return rc;
1799}
1800
1801static inline int may_rename(struct inode *old_dir,
1802 struct dentry *old_dentry,
1803 struct inode *new_dir,
1804 struct dentry *new_dentry)
1805{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001806 struct inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04001807 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11001808 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001809 u32 av;
1810 int old_is_dir, new_is_dir;
1811 int rc;
1812
Linus Torvalds1da177e2005-04-16 15:20:36 -07001813 old_dsec = old_dir->i_security;
David Howellsc6f493d2015-03-17 22:26:22 +00001814 old_isec = d_backing_inode(old_dentry)->i_security;
David Howellse36cb0b2015-01-29 12:02:35 +00001815 old_is_dir = d_is_dir(old_dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001816 new_dsec = new_dir->i_security;
1817
Eric Paris50c205f2012-04-04 15:01:43 -04001818 ad.type = LSM_AUDIT_DATA_DENTRY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001819
Eric Parisa2694342011-04-25 13:10:27 -04001820 ad.u.dentry = old_dentry;
David Howells275bb412008-11-14 10:39:19 +11001821 rc = avc_has_perm(sid, old_dsec->sid, SECCLASS_DIR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001822 DIR__REMOVE_NAME | DIR__SEARCH, &ad);
1823 if (rc)
1824 return rc;
David Howells275bb412008-11-14 10:39:19 +11001825 rc = avc_has_perm(sid, old_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001826 old_isec->sclass, FILE__RENAME, &ad);
1827 if (rc)
1828 return rc;
1829 if (old_is_dir && new_dir != old_dir) {
David Howells275bb412008-11-14 10:39:19 +11001830 rc = avc_has_perm(sid, old_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001831 old_isec->sclass, DIR__REPARENT, &ad);
1832 if (rc)
1833 return rc;
1834 }
1835
Eric Parisa2694342011-04-25 13:10:27 -04001836 ad.u.dentry = new_dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001837 av = DIR__ADD_NAME | DIR__SEARCH;
David Howells2c616d42015-01-29 12:02:33 +00001838 if (d_is_positive(new_dentry))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001839 av |= DIR__REMOVE_NAME;
David Howells275bb412008-11-14 10:39:19 +11001840 rc = avc_has_perm(sid, new_dsec->sid, SECCLASS_DIR, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001841 if (rc)
1842 return rc;
David Howells2c616d42015-01-29 12:02:33 +00001843 if (d_is_positive(new_dentry)) {
David Howellsc6f493d2015-03-17 22:26:22 +00001844 new_isec = d_backing_inode(new_dentry)->i_security;
David Howellse36cb0b2015-01-29 12:02:35 +00001845 new_is_dir = d_is_dir(new_dentry);
David Howells275bb412008-11-14 10:39:19 +11001846 rc = avc_has_perm(sid, new_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001847 new_isec->sclass,
1848 (new_is_dir ? DIR__RMDIR : FILE__UNLINK), &ad);
1849 if (rc)
1850 return rc;
1851 }
1852
1853 return 0;
1854}
1855
1856/* Check whether a task can perform a filesystem operation. */
David Howells88e67f32008-11-14 10:39:21 +11001857static int superblock_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001858 struct super_block *sb,
1859 u32 perms,
Thomas Liu2bf49692009-07-14 12:14:09 -04001860 struct common_audit_data *ad)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001861{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001862 struct superblock_security_struct *sbsec;
David Howells88e67f32008-11-14 10:39:21 +11001863 u32 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001864
Linus Torvalds1da177e2005-04-16 15:20:36 -07001865 sbsec = sb->s_security;
David Howells275bb412008-11-14 10:39:19 +11001866 return avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM, perms, ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001867}
1868
1869/* Convert a Linux mode and permission mask to an access vector. */
1870static inline u32 file_mask_to_av(int mode, int mask)
1871{
1872 u32 av = 0;
1873
Al Virodba19c62011-07-25 20:49:29 -04001874 if (!S_ISDIR(mode)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001875 if (mask & MAY_EXEC)
1876 av |= FILE__EXECUTE;
1877 if (mask & MAY_READ)
1878 av |= FILE__READ;
1879
1880 if (mask & MAY_APPEND)
1881 av |= FILE__APPEND;
1882 else if (mask & MAY_WRITE)
1883 av |= FILE__WRITE;
1884
1885 } else {
1886 if (mask & MAY_EXEC)
1887 av |= DIR__SEARCH;
1888 if (mask & MAY_WRITE)
1889 av |= DIR__WRITE;
1890 if (mask & MAY_READ)
1891 av |= DIR__READ;
1892 }
1893
1894 return av;
1895}
1896
1897/* Convert a Linux file to an access vector. */
1898static inline u32 file_to_av(struct file *file)
1899{
1900 u32 av = 0;
1901
1902 if (file->f_mode & FMODE_READ)
1903 av |= FILE__READ;
1904 if (file->f_mode & FMODE_WRITE) {
1905 if (file->f_flags & O_APPEND)
1906 av |= FILE__APPEND;
1907 else
1908 av |= FILE__WRITE;
1909 }
Stephen Smalley0794c662008-03-17 08:55:18 -04001910 if (!av) {
1911 /*
1912 * Special file opened with flags 3 for ioctl-only use.
1913 */
1914 av = FILE__IOCTL;
1915 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001916
1917 return av;
1918}
1919
Eric Paris8b6a5a32008-10-29 17:06:46 -04001920/*
1921 * Convert a file to an access vector and include the correct open
1922 * open permission.
1923 */
1924static inline u32 open_file_to_av(struct file *file)
1925{
1926 u32 av = file_to_av(file);
1927
Eric Paris49b7b8d2010-07-23 11:44:09 -04001928 if (selinux_policycap_openperm)
1929 av |= FILE__OPEN;
1930
Eric Paris8b6a5a32008-10-29 17:06:46 -04001931 return av;
1932}
1933
Linus Torvalds1da177e2005-04-16 15:20:36 -07001934/* Hook functions begin here. */
1935
Stephen Smalley79af7302015-01-21 10:54:10 -05001936static int selinux_binder_set_context_mgr(struct task_struct *mgr)
1937{
1938 u32 mysid = current_sid();
1939 u32 mgrsid = task_sid(mgr);
1940
1941 return avc_has_perm(mysid, mgrsid, SECCLASS_BINDER,
1942 BINDER__SET_CONTEXT_MGR, NULL);
1943}
1944
1945static int selinux_binder_transaction(struct task_struct *from,
1946 struct task_struct *to)
1947{
1948 u32 mysid = current_sid();
1949 u32 fromsid = task_sid(from);
1950 u32 tosid = task_sid(to);
1951 int rc;
1952
1953 if (mysid != fromsid) {
1954 rc = avc_has_perm(mysid, fromsid, SECCLASS_BINDER,
1955 BINDER__IMPERSONATE, NULL);
1956 if (rc)
1957 return rc;
1958 }
1959
1960 return avc_has_perm(fromsid, tosid, SECCLASS_BINDER, BINDER__CALL,
1961 NULL);
1962}
1963
1964static int selinux_binder_transfer_binder(struct task_struct *from,
1965 struct task_struct *to)
1966{
1967 u32 fromsid = task_sid(from);
1968 u32 tosid = task_sid(to);
1969
1970 return avc_has_perm(fromsid, tosid, SECCLASS_BINDER, BINDER__TRANSFER,
1971 NULL);
1972}
1973
1974static int selinux_binder_transfer_file(struct task_struct *from,
1975 struct task_struct *to,
1976 struct file *file)
1977{
1978 u32 sid = task_sid(to);
1979 struct file_security_struct *fsec = file->f_security;
David Howellsc6f493d2015-03-17 22:26:22 +00001980 struct inode *inode = d_backing_inode(file->f_path.dentry);
Stephen Smalley79af7302015-01-21 10:54:10 -05001981 struct inode_security_struct *isec = inode->i_security;
1982 struct common_audit_data ad;
1983 int rc;
1984
1985 ad.type = LSM_AUDIT_DATA_PATH;
1986 ad.u.path = file->f_path;
1987
1988 if (sid != fsec->sid) {
1989 rc = avc_has_perm(sid, fsec->sid,
1990 SECCLASS_FD,
1991 FD__USE,
1992 &ad);
1993 if (rc)
1994 return rc;
1995 }
1996
1997 if (unlikely(IS_PRIVATE(inode)))
1998 return 0;
1999
2000 return avc_has_perm(sid, isec->sid, isec->sclass, file_to_av(file),
2001 &ad);
2002}
2003
Ingo Molnar9e488582009-05-07 19:26:19 +10002004static int selinux_ptrace_access_check(struct task_struct *child,
David Howells5cd9c582008-08-14 11:37:28 +01002005 unsigned int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002006{
Eric Paris69f594a2012-01-03 12:25:15 -05002007 if (mode & PTRACE_MODE_READ) {
David Howells275bb412008-11-14 10:39:19 +11002008 u32 sid = current_sid();
2009 u32 csid = task_sid(child);
2010 return avc_has_perm(sid, csid, SECCLASS_FILE, FILE__READ, NULL);
Stephen Smalley006ebb42008-05-19 08:32:49 -04002011 }
2012
David Howells3b11a1d2008-11-14 10:39:26 +11002013 return current_has_perm(child, PROCESS__PTRACE);
David Howells5cd9c582008-08-14 11:37:28 +01002014}
2015
2016static int selinux_ptrace_traceme(struct task_struct *parent)
2017{
David Howells5cd9c582008-08-14 11:37:28 +01002018 return task_has_perm(parent, current, PROCESS__PTRACE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002019}
2020
2021static int selinux_capget(struct task_struct *target, kernel_cap_t *effective,
Eric Paris828dfe12008-04-17 13:17:49 -04002022 kernel_cap_t *inheritable, kernel_cap_t *permitted)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002023{
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07002024 return current_has_perm(target, PROCESS__GETCAP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002025}
2026
David Howellsd84f4f92008-11-14 10:39:23 +11002027static int selinux_capset(struct cred *new, const struct cred *old,
2028 const kernel_cap_t *effective,
2029 const kernel_cap_t *inheritable,
2030 const kernel_cap_t *permitted)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002031{
David Howellsd84f4f92008-11-14 10:39:23 +11002032 return cred_has_perm(old, new, PROCESS__SETCAP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002033}
2034
James Morris5626d3e2009-01-30 10:05:06 +11002035/*
2036 * (This comment used to live with the selinux_task_setuid hook,
2037 * which was removed).
2038 *
2039 * Since setuid only affects the current process, and since the SELinux
2040 * controls are not based on the Linux identity attributes, SELinux does not
2041 * need to control this operation. However, SELinux does control the use of
2042 * the CAP_SETUID and CAP_SETGID capabilities using the capable hook.
2043 */
2044
Eric Paris6a9de492012-01-03 12:25:14 -05002045static int selinux_capable(const struct cred *cred, struct user_namespace *ns,
2046 int cap, int audit)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002047{
Eric Paris6a9de492012-01-03 12:25:14 -05002048 return cred_has_capability(cred, cap, audit);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002049}
2050
Linus Torvalds1da177e2005-04-16 15:20:36 -07002051static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb)
2052{
David Howells88e67f32008-11-14 10:39:21 +11002053 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002054 int rc = 0;
2055
2056 if (!sb)
2057 return 0;
2058
2059 switch (cmds) {
Eric Paris828dfe12008-04-17 13:17:49 -04002060 case Q_SYNC:
2061 case Q_QUOTAON:
2062 case Q_QUOTAOFF:
2063 case Q_SETINFO:
2064 case Q_SETQUOTA:
David Howells88e67f32008-11-14 10:39:21 +11002065 rc = superblock_has_perm(cred, sb, FILESYSTEM__QUOTAMOD, NULL);
Eric Paris828dfe12008-04-17 13:17:49 -04002066 break;
2067 case Q_GETFMT:
2068 case Q_GETINFO:
2069 case Q_GETQUOTA:
David Howells88e67f32008-11-14 10:39:21 +11002070 rc = superblock_has_perm(cred, sb, FILESYSTEM__QUOTAGET, NULL);
Eric Paris828dfe12008-04-17 13:17:49 -04002071 break;
2072 default:
2073 rc = 0; /* let the kernel handle invalid cmds */
2074 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002075 }
2076 return rc;
2077}
2078
2079static int selinux_quota_on(struct dentry *dentry)
2080{
David Howells88e67f32008-11-14 10:39:21 +11002081 const struct cred *cred = current_cred();
2082
Eric Paris2875fa02011-04-28 16:04:24 -04002083 return dentry_has_perm(cred, dentry, FILE__QUOTAON);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002084}
2085
Eric Paris12b30522010-11-15 18:36:29 -05002086static int selinux_syslog(int type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002087{
2088 int rc;
2089
Linus Torvalds1da177e2005-04-16 15:20:36 -07002090 switch (type) {
Kees Cookd78ca3c2010-02-03 15:37:13 -08002091 case SYSLOG_ACTION_READ_ALL: /* Read last kernel messages */
2092 case SYSLOG_ACTION_SIZE_BUFFER: /* Return size of the log buffer */
Eric Paris828dfe12008-04-17 13:17:49 -04002093 rc = task_has_system(current, SYSTEM__SYSLOG_READ);
2094 break;
Kees Cookd78ca3c2010-02-03 15:37:13 -08002095 case SYSLOG_ACTION_CONSOLE_OFF: /* Disable logging to console */
2096 case SYSLOG_ACTION_CONSOLE_ON: /* Enable logging to console */
2097 /* Set level of messages printed to console */
2098 case SYSLOG_ACTION_CONSOLE_LEVEL:
Eric Paris828dfe12008-04-17 13:17:49 -04002099 rc = task_has_system(current, SYSTEM__SYSLOG_CONSOLE);
2100 break;
Kees Cookd78ca3c2010-02-03 15:37:13 -08002101 case SYSLOG_ACTION_CLOSE: /* Close log */
2102 case SYSLOG_ACTION_OPEN: /* Open log */
2103 case SYSLOG_ACTION_READ: /* Read from log */
2104 case SYSLOG_ACTION_READ_CLEAR: /* Read/clear last kernel messages */
2105 case SYSLOG_ACTION_CLEAR: /* Clear ring buffer */
Eric Paris828dfe12008-04-17 13:17:49 -04002106 default:
2107 rc = task_has_system(current, SYSTEM__SYSLOG_MOD);
2108 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002109 }
2110 return rc;
2111}
2112
2113/*
2114 * Check that a process has enough memory to allocate a new virtual
2115 * mapping. 0 means there is enough memory for the allocation to
2116 * succeed and -ENOMEM implies there is not.
2117 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07002118 * Do not audit the selinux permission check, as this is applied to all
2119 * processes that allocate mappings.
2120 */
Alan Cox34b4e4a2007-08-22 14:01:28 -07002121static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002122{
2123 int rc, cap_sys_admin = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002124
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07002125 rc = cred_has_capability(current_cred(), CAP_SYS_ADMIN,
2126 SECURITY_CAP_NOAUDIT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002127 if (rc == 0)
2128 cap_sys_admin = 1;
2129
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07002130 return cap_sys_admin;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002131}
2132
2133/* binprm security operations */
2134
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002135static int check_nnp_nosuid(const struct linux_binprm *bprm,
2136 const struct task_security_struct *old_tsec,
2137 const struct task_security_struct *new_tsec)
2138{
2139 int nnp = (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS);
2140 int nosuid = (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID);
2141 int rc;
2142
2143 if (!nnp && !nosuid)
2144 return 0; /* neither NNP nor nosuid */
2145
2146 if (new_tsec->sid == old_tsec->sid)
2147 return 0; /* No change in credentials */
2148
2149 /*
2150 * The only transitions we permit under NNP or nosuid
2151 * are transitions to bounded SIDs, i.e. SIDs that are
2152 * guaranteed to only be allowed a subset of the permissions
2153 * of the current SID.
2154 */
2155 rc = security_bounded_transition(old_tsec->sid, new_tsec->sid);
2156 if (rc) {
2157 /*
2158 * On failure, preserve the errno values for NNP vs nosuid.
2159 * NNP: Operation not permitted for caller.
2160 * nosuid: Permission denied to file.
2161 */
2162 if (nnp)
2163 return -EPERM;
2164 else
2165 return -EACCES;
2166 }
2167 return 0;
2168}
2169
David Howellsa6f76f22008-11-14 10:39:24 +11002170static int selinux_bprm_set_creds(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002171{
David Howellsa6f76f22008-11-14 10:39:24 +11002172 const struct task_security_struct *old_tsec;
2173 struct task_security_struct *new_tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002174 struct inode_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04002175 struct common_audit_data ad;
Al Viro496ad9a2013-01-23 17:07:38 -05002176 struct inode *inode = file_inode(bprm->file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002177 int rc;
2178
David Howellsa6f76f22008-11-14 10:39:24 +11002179 /* SELinux context only depends on initial program or script and not
2180 * the script interpreter */
2181 if (bprm->cred_prepared)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002182 return 0;
2183
David Howellsa6f76f22008-11-14 10:39:24 +11002184 old_tsec = current_security();
2185 new_tsec = bprm->cred->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002186 isec = inode->i_security;
2187
2188 /* Default to the current task SID. */
David Howellsa6f76f22008-11-14 10:39:24 +11002189 new_tsec->sid = old_tsec->sid;
2190 new_tsec->osid = old_tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002191
Michael LeMay28eba5b2006-06-27 02:53:42 -07002192 /* Reset fs, key, and sock SIDs on execve. */
David Howellsa6f76f22008-11-14 10:39:24 +11002193 new_tsec->create_sid = 0;
2194 new_tsec->keycreate_sid = 0;
2195 new_tsec->sockcreate_sid = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002196
David Howellsa6f76f22008-11-14 10:39:24 +11002197 if (old_tsec->exec_sid) {
2198 new_tsec->sid = old_tsec->exec_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002199 /* Reset exec SID on execve. */
David Howellsa6f76f22008-11-14 10:39:24 +11002200 new_tsec->exec_sid = 0;
Andy Lutomirski259e5e62012-04-12 16:47:50 -05002201
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002202 /* Fail on NNP or nosuid if not an allowed transition. */
2203 rc = check_nnp_nosuid(bprm, old_tsec, new_tsec);
2204 if (rc)
2205 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002206 } else {
2207 /* Check for a default transition on this program. */
David Howellsa6f76f22008-11-14 10:39:24 +11002208 rc = security_transition_sid(old_tsec->sid, isec->sid,
Eric Paris652bb9b2011-02-01 11:05:40 -05002209 SECCLASS_PROCESS, NULL,
2210 &new_tsec->sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002211 if (rc)
2212 return rc;
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002213
2214 /*
2215 * Fallback to old SID on NNP or nosuid if not an allowed
2216 * transition.
2217 */
2218 rc = check_nnp_nosuid(bprm, old_tsec, new_tsec);
2219 if (rc)
2220 new_tsec->sid = old_tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002221 }
2222
Eric Paris50c205f2012-04-04 15:01:43 -04002223 ad.type = LSM_AUDIT_DATA_PATH;
Eric Parisf48b7392011-04-25 12:54:27 -04002224 ad.u.path = bprm->file->f_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002225
David Howellsa6f76f22008-11-14 10:39:24 +11002226 if (new_tsec->sid == old_tsec->sid) {
2227 rc = avc_has_perm(old_tsec->sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002228 SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, &ad);
2229 if (rc)
2230 return rc;
2231 } else {
2232 /* Check permissions for the transition. */
David Howellsa6f76f22008-11-14 10:39:24 +11002233 rc = avc_has_perm(old_tsec->sid, new_tsec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002234 SECCLASS_PROCESS, PROCESS__TRANSITION, &ad);
2235 if (rc)
2236 return rc;
2237
David Howellsa6f76f22008-11-14 10:39:24 +11002238 rc = avc_has_perm(new_tsec->sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002239 SECCLASS_FILE, FILE__ENTRYPOINT, &ad);
2240 if (rc)
2241 return rc;
2242
David Howellsa6f76f22008-11-14 10:39:24 +11002243 /* Check for shared state */
2244 if (bprm->unsafe & LSM_UNSAFE_SHARE) {
2245 rc = avc_has_perm(old_tsec->sid, new_tsec->sid,
2246 SECCLASS_PROCESS, PROCESS__SHARE,
2247 NULL);
2248 if (rc)
2249 return -EPERM;
2250 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002251
David Howellsa6f76f22008-11-14 10:39:24 +11002252 /* Make sure that anyone attempting to ptrace over a task that
2253 * changes its SID has the appropriate permit */
2254 if (bprm->unsafe &
2255 (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) {
2256 struct task_struct *tracer;
2257 struct task_security_struct *sec;
2258 u32 ptsid = 0;
2259
2260 rcu_read_lock();
Tejun Heo06d98472011-06-17 16:50:40 +02002261 tracer = ptrace_parent(current);
David Howellsa6f76f22008-11-14 10:39:24 +11002262 if (likely(tracer != NULL)) {
2263 sec = __task_cred(tracer)->security;
2264 ptsid = sec->sid;
2265 }
2266 rcu_read_unlock();
2267
2268 if (ptsid != 0) {
2269 rc = avc_has_perm(ptsid, new_tsec->sid,
2270 SECCLASS_PROCESS,
2271 PROCESS__PTRACE, NULL);
2272 if (rc)
2273 return -EPERM;
2274 }
2275 }
2276
2277 /* Clear any possibly unsafe personality bits on exec: */
2278 bprm->per_clear |= PER_CLEAR_ON_SETID;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002279 }
2280
Linus Torvalds1da177e2005-04-16 15:20:36 -07002281 return 0;
2282}
2283
Eric Paris828dfe12008-04-17 13:17:49 -04002284static int selinux_bprm_secureexec(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002285{
Paul Moore5fb49872010-04-22 14:46:19 -04002286 const struct task_security_struct *tsec = current_security();
David Howells275bb412008-11-14 10:39:19 +11002287 u32 sid, osid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002288 int atsecure = 0;
2289
David Howells275bb412008-11-14 10:39:19 +11002290 sid = tsec->sid;
2291 osid = tsec->osid;
2292
2293 if (osid != sid) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002294 /* Enable secure mode for SIDs transitions unless
2295 the noatsecure permission is granted between
2296 the two SIDs, i.e. ahp returns 0. */
David Howells275bb412008-11-14 10:39:19 +11002297 atsecure = avc_has_perm(osid, sid,
David Howellsa6f76f22008-11-14 10:39:24 +11002298 SECCLASS_PROCESS,
2299 PROCESS__NOATSECURE, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002300 }
2301
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07002302 return !!atsecure;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002303}
2304
Al Viroc3c073f2012-08-21 22:32:06 -04002305static int match_file(const void *p, struct file *file, unsigned fd)
2306{
2307 return file_has_perm(p, file, file_to_av(file)) ? fd + 1 : 0;
2308}
2309
Linus Torvalds1da177e2005-04-16 15:20:36 -07002310/* Derived from fs/exec.c:flush_old_files. */
David Howells745ca242008-11-14 10:39:22 +11002311static inline void flush_unauthorized_files(const struct cred *cred,
2312 struct files_struct *files)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002313{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002314 struct file *file, *devnull = NULL;
Stephen Smalleyb20c8122006-09-25 23:32:03 -07002315 struct tty_struct *tty;
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002316 int drop_tty = 0;
Al Viroc3c073f2012-08-21 22:32:06 -04002317 unsigned n;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002318
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002319 tty = get_current_tty();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002320 if (tty) {
Nick Pigginee2ffa02010-08-18 04:37:35 +10002321 spin_lock(&tty_files_lock);
Eric Paris37dd0bd2008-10-31 17:40:00 -04002322 if (!list_empty(&tty->tty_files)) {
Nick Piggind996b622010-08-18 04:37:36 +10002323 struct tty_file_private *file_priv;
Eric Paris37dd0bd2008-10-31 17:40:00 -04002324
Linus Torvalds1da177e2005-04-16 15:20:36 -07002325 /* Revalidate access to controlling tty.
David Howells13f8e982013-06-13 23:37:55 +01002326 Use file_path_has_perm on the tty path directly
2327 rather than using file_has_perm, as this particular
2328 open file may belong to another process and we are
2329 only interested in the inode-based check here. */
Nick Piggind996b622010-08-18 04:37:36 +10002330 file_priv = list_first_entry(&tty->tty_files,
2331 struct tty_file_private, list);
2332 file = file_priv->file;
David Howells13f8e982013-06-13 23:37:55 +01002333 if (file_path_has_perm(cred, file, FILE__READ | FILE__WRITE))
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002334 drop_tty = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002335 }
Nick Pigginee2ffa02010-08-18 04:37:35 +10002336 spin_unlock(&tty_files_lock);
Alan Cox452a00d2008-10-13 10:39:13 +01002337 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002338 }
Eric W. Biederman98a27ba2007-05-08 00:26:56 -07002339 /* Reset controlling tty. */
2340 if (drop_tty)
2341 no_tty();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002342
2343 /* Revalidate access to inherited open files. */
Al Viroc3c073f2012-08-21 22:32:06 -04002344 n = iterate_fd(files, 0, match_file, cred);
2345 if (!n) /* none found? */
2346 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002347
Al Viroc3c073f2012-08-21 22:32:06 -04002348 devnull = dentry_open(&selinux_null, O_RDWR, cred);
Al Viro45525b22012-10-16 13:30:07 -04002349 if (IS_ERR(devnull))
2350 devnull = NULL;
2351 /* replace all the matching ones with this */
2352 do {
2353 replace_fd(n - 1, devnull, 0);
2354 } while ((n = iterate_fd(files, n, match_file, cred)) != 0);
2355 if (devnull)
Al Viroc3c073f2012-08-21 22:32:06 -04002356 fput(devnull);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002357}
2358
Linus Torvalds1da177e2005-04-16 15:20:36 -07002359/*
David Howellsa6f76f22008-11-14 10:39:24 +11002360 * Prepare a process for imminent new credential changes due to exec
Linus Torvalds1da177e2005-04-16 15:20:36 -07002361 */
David Howellsa6f76f22008-11-14 10:39:24 +11002362static void selinux_bprm_committing_creds(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002363{
David Howellsa6f76f22008-11-14 10:39:24 +11002364 struct task_security_struct *new_tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002365 struct rlimit *rlim, *initrlim;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002366 int rc, i;
2367
David Howellsa6f76f22008-11-14 10:39:24 +11002368 new_tsec = bprm->cred->security;
2369 if (new_tsec->sid == new_tsec->osid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002370 return;
2371
2372 /* Close files for which the new task SID is not authorized. */
David Howellsa6f76f22008-11-14 10:39:24 +11002373 flush_unauthorized_files(bprm->cred, current->files);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002374
David Howellsa6f76f22008-11-14 10:39:24 +11002375 /* Always clear parent death signal on SID transitions. */
2376 current->pdeath_signal = 0;
2377
2378 /* Check whether the new SID can inherit resource limits from the old
2379 * SID. If not, reset all soft limits to the lower of the current
2380 * task's hard limit and the init task's soft limit.
2381 *
2382 * Note that the setting of hard limits (even to lower them) can be
2383 * controlled by the setrlimit check. The inclusion of the init task's
2384 * soft limit into the computation is to avoid resetting soft limits
2385 * higher than the default soft limit for cases where the default is
2386 * lower than the hard limit, e.g. RLIMIT_CORE or RLIMIT_STACK.
2387 */
2388 rc = avc_has_perm(new_tsec->osid, new_tsec->sid, SECCLASS_PROCESS,
2389 PROCESS__RLIMITINH, NULL);
2390 if (rc) {
Oleg Nesteroveb2d55a2010-06-23 22:43:32 +02002391 /* protect against do_prlimit() */
2392 task_lock(current);
David Howellsa6f76f22008-11-14 10:39:24 +11002393 for (i = 0; i < RLIM_NLIMITS; i++) {
2394 rlim = current->signal->rlim + i;
2395 initrlim = init_task.signal->rlim + i;
2396 rlim->rlim_cur = min(rlim->rlim_max, initrlim->rlim_cur);
2397 }
Oleg Nesteroveb2d55a2010-06-23 22:43:32 +02002398 task_unlock(current);
2399 update_rlimit_cpu(current, rlimit(RLIMIT_CPU));
David Howellsa6f76f22008-11-14 10:39:24 +11002400 }
2401}
2402
2403/*
2404 * Clean up the process immediately after the installation of new credentials
2405 * due to exec
2406 */
2407static void selinux_bprm_committed_creds(struct linux_binprm *bprm)
2408{
2409 const struct task_security_struct *tsec = current_security();
2410 struct itimerval itimer;
David Howellsa6f76f22008-11-14 10:39:24 +11002411 u32 osid, sid;
2412 int rc, i;
David Howellsa6f76f22008-11-14 10:39:24 +11002413
David Howellsa6f76f22008-11-14 10:39:24 +11002414 osid = tsec->osid;
2415 sid = tsec->sid;
2416
2417 if (sid == osid)
2418 return;
2419
2420 /* Check whether the new SID can inherit signal state from the old SID.
2421 * If not, clear itimers to avoid subsequent signal generation and
2422 * flush and unblock signals.
2423 *
2424 * This must occur _after_ the task SID has been updated so that any
2425 * kill done after the flush will be checked against the new SID.
2426 */
2427 rc = avc_has_perm(osid, sid, SECCLASS_PROCESS, PROCESS__SIGINH, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002428 if (rc) {
2429 memset(&itimer, 0, sizeof itimer);
2430 for (i = 0; i < 3; i++)
2431 do_setitimer(i, &itimer, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002432 spin_lock_irq(&current->sighand->siglock);
Oleg Nesterov9e7c8f82015-06-04 16:22:16 -04002433 if (!fatal_signal_pending(current)) {
2434 flush_sigqueue(&current->pending);
2435 flush_sigqueue(&current->signal->shared_pending);
David Howells3bcac022009-04-29 13:45:05 +01002436 flush_signal_handlers(current, 1);
2437 sigemptyset(&current->blocked);
Oleg Nesterov9e7c8f82015-06-04 16:22:16 -04002438 recalc_sigpending();
David Howells3bcac022009-04-29 13:45:05 +01002439 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002440 spin_unlock_irq(&current->sighand->siglock);
2441 }
2442
David Howellsa6f76f22008-11-14 10:39:24 +11002443 /* Wake up the parent if it is waiting so that it can recheck
2444 * wait permission to the new task SID. */
Oleg Nesterovecd6de32009-04-29 16:02:24 +02002445 read_lock(&tasklist_lock);
Oleg Nesterov0b7570e2009-09-23 15:56:46 -07002446 __wake_up_parent(current, current->real_parent);
Oleg Nesterovecd6de32009-04-29 16:02:24 +02002447 read_unlock(&tasklist_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002448}
2449
2450/* superblock security operations */
2451
2452static int selinux_sb_alloc_security(struct super_block *sb)
2453{
2454 return superblock_alloc_security(sb);
2455}
2456
2457static void selinux_sb_free_security(struct super_block *sb)
2458{
2459 superblock_free_security(sb);
2460}
2461
2462static inline int match_prefix(char *prefix, int plen, char *option, int olen)
2463{
2464 if (plen > olen)
2465 return 0;
2466
2467 return !memcmp(prefix, option, plen);
2468}
2469
2470static inline int selinux_option(char *option, int len)
2471{
Eric Paris832cbd92008-04-01 13:24:09 -04002472 return (match_prefix(CONTEXT_STR, sizeof(CONTEXT_STR)-1, option, len) ||
2473 match_prefix(FSCONTEXT_STR, sizeof(FSCONTEXT_STR)-1, option, len) ||
2474 match_prefix(DEFCONTEXT_STR, sizeof(DEFCONTEXT_STR)-1, option, len) ||
David P. Quigley11689d42009-01-16 09:22:03 -05002475 match_prefix(ROOTCONTEXT_STR, sizeof(ROOTCONTEXT_STR)-1, option, len) ||
2476 match_prefix(LABELSUPP_STR, sizeof(LABELSUPP_STR)-1, option, len));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002477}
2478
2479static inline void take_option(char **to, char *from, int *first, int len)
2480{
2481 if (!*first) {
2482 **to = ',';
2483 *to += 1;
Cory Olmo3528a952006-09-29 01:58:44 -07002484 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002485 *first = 0;
2486 memcpy(*to, from, len);
2487 *to += len;
2488}
2489
Eric Paris828dfe12008-04-17 13:17:49 -04002490static inline void take_selinux_option(char **to, char *from, int *first,
2491 int len)
Cory Olmo3528a952006-09-29 01:58:44 -07002492{
2493 int current_size = 0;
2494
2495 if (!*first) {
2496 **to = '|';
2497 *to += 1;
Eric Paris828dfe12008-04-17 13:17:49 -04002498 } else
Cory Olmo3528a952006-09-29 01:58:44 -07002499 *first = 0;
2500
2501 while (current_size < len) {
2502 if (*from != '"') {
2503 **to = *from;
2504 *to += 1;
2505 }
2506 from += 1;
2507 current_size += 1;
2508 }
2509}
2510
Eric Parise0007522008-03-05 10:31:54 -05002511static int selinux_sb_copy_data(char *orig, char *copy)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002512{
2513 int fnosec, fsec, rc = 0;
2514 char *in_save, *in_curr, *in_end;
2515 char *sec_curr, *nosec_save, *nosec;
Cory Olmo3528a952006-09-29 01:58:44 -07002516 int open_quote = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002517
2518 in_curr = orig;
2519 sec_curr = copy;
2520
Linus Torvalds1da177e2005-04-16 15:20:36 -07002521 nosec = (char *)get_zeroed_page(GFP_KERNEL);
2522 if (!nosec) {
2523 rc = -ENOMEM;
2524 goto out;
2525 }
2526
2527 nosec_save = nosec;
2528 fnosec = fsec = 1;
2529 in_save = in_end = orig;
2530
2531 do {
Cory Olmo3528a952006-09-29 01:58:44 -07002532 if (*in_end == '"')
2533 open_quote = !open_quote;
2534 if ((*in_end == ',' && open_quote == 0) ||
2535 *in_end == '\0') {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002536 int len = in_end - in_curr;
2537
2538 if (selinux_option(in_curr, len))
Cory Olmo3528a952006-09-29 01:58:44 -07002539 take_selinux_option(&sec_curr, in_curr, &fsec, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002540 else
2541 take_option(&nosec, in_curr, &fnosec, len);
2542
2543 in_curr = in_end + 1;
2544 }
2545 } while (*in_end++);
2546
Eric Paris6931dfc2005-06-30 02:58:51 -07002547 strcpy(in_save, nosec_save);
Gerald Schaeferda3caa22005-06-21 17:15:18 -07002548 free_page((unsigned long)nosec_save);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002549out:
2550 return rc;
2551}
2552
Eric Paris026eb162011-03-03 16:09:14 -05002553static int selinux_sb_remount(struct super_block *sb, void *data)
2554{
2555 int rc, i, *flags;
2556 struct security_mnt_opts opts;
2557 char *secdata, **mount_options;
2558 struct superblock_security_struct *sbsec = sb->s_security;
2559
2560 if (!(sbsec->flags & SE_SBINITIALIZED))
2561 return 0;
2562
2563 if (!data)
2564 return 0;
2565
2566 if (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)
2567 return 0;
2568
2569 security_init_mnt_opts(&opts);
2570 secdata = alloc_secdata();
2571 if (!secdata)
2572 return -ENOMEM;
2573 rc = selinux_sb_copy_data(data, secdata);
2574 if (rc)
2575 goto out_free_secdata;
2576
2577 rc = selinux_parse_opts_str(secdata, &opts);
2578 if (rc)
2579 goto out_free_secdata;
2580
2581 mount_options = opts.mnt_opts;
2582 flags = opts.mnt_opts_flags;
2583
2584 for (i = 0; i < opts.num_mnt_opts; i++) {
2585 u32 sid;
2586 size_t len;
2587
Eric Paris12f348b2012-10-09 10:56:25 -04002588 if (flags[i] == SBLABEL_MNT)
Eric Paris026eb162011-03-03 16:09:14 -05002589 continue;
2590 len = strlen(mount_options[i]);
Nikolay Aleksandrov52a4c642014-03-07 12:44:19 +01002591 rc = security_context_to_sid(mount_options[i], len, &sid,
2592 GFP_KERNEL);
Eric Paris026eb162011-03-03 16:09:14 -05002593 if (rc) {
2594 printk(KERN_WARNING "SELinux: security_context_to_sid"
Linus Torvalds29b1deb2013-12-15 11:17:45 -08002595 "(%s) failed for (dev %s, type %s) errno=%d\n",
2596 mount_options[i], sb->s_id, sb->s_type->name, rc);
Eric Paris026eb162011-03-03 16:09:14 -05002597 goto out_free_opts;
2598 }
2599 rc = -EINVAL;
2600 switch (flags[i]) {
2601 case FSCONTEXT_MNT:
2602 if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid, sid))
2603 goto out_bad_option;
2604 break;
2605 case CONTEXT_MNT:
2606 if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid, sid))
2607 goto out_bad_option;
2608 break;
2609 case ROOTCONTEXT_MNT: {
2610 struct inode_security_struct *root_isec;
David Howellsc6f493d2015-03-17 22:26:22 +00002611 root_isec = d_backing_inode(sb->s_root)->i_security;
Eric Paris026eb162011-03-03 16:09:14 -05002612
2613 if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid, sid))
2614 goto out_bad_option;
2615 break;
2616 }
2617 case DEFCONTEXT_MNT:
2618 if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid, sid))
2619 goto out_bad_option;
2620 break;
2621 default:
2622 goto out_free_opts;
2623 }
2624 }
2625
2626 rc = 0;
2627out_free_opts:
2628 security_free_mnt_opts(&opts);
2629out_free_secdata:
2630 free_secdata(secdata);
2631 return rc;
2632out_bad_option:
2633 printk(KERN_WARNING "SELinux: unable to change security options "
Linus Torvalds29b1deb2013-12-15 11:17:45 -08002634 "during remount (dev %s, type=%s)\n", sb->s_id,
2635 sb->s_type->name);
Eric Paris026eb162011-03-03 16:09:14 -05002636 goto out_free_opts;
2637}
2638
James Morris12204e22008-12-19 10:44:42 +11002639static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002640{
David Howells88e67f32008-11-14 10:39:21 +11002641 const struct cred *cred = current_cred();
Thomas Liu2bf49692009-07-14 12:14:09 -04002642 struct common_audit_data ad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002643 int rc;
2644
2645 rc = superblock_doinit(sb, data);
2646 if (rc)
2647 return rc;
2648
James Morris74192242008-12-19 11:41:10 +11002649 /* Allow all mounts performed by the kernel */
2650 if (flags & MS_KERNMOUNT)
2651 return 0;
2652
Eric Paris50c205f2012-04-04 15:01:43 -04002653 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04002654 ad.u.dentry = sb->s_root;
David Howells88e67f32008-11-14 10:39:21 +11002655 return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002656}
2657
David Howells726c3342006-06-23 02:02:58 -07002658static int selinux_sb_statfs(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002659{
David Howells88e67f32008-11-14 10:39:21 +11002660 const struct cred *cred = current_cred();
Thomas Liu2bf49692009-07-14 12:14:09 -04002661 struct common_audit_data ad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002662
Eric Paris50c205f2012-04-04 15:01:43 -04002663 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04002664 ad.u.dentry = dentry->d_sb->s_root;
David Howells88e67f32008-11-14 10:39:21 +11002665 return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002666}
2667
Al Viro808d4e32012-10-11 11:42:01 -04002668static int selinux_mount(const char *dev_name,
Al Virob5266eb2008-03-22 17:48:24 -04002669 struct path *path,
Al Viro808d4e32012-10-11 11:42:01 -04002670 const char *type,
Eric Paris828dfe12008-04-17 13:17:49 -04002671 unsigned long flags,
2672 void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002673{
David Howells88e67f32008-11-14 10:39:21 +11002674 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002675
2676 if (flags & MS_REMOUNT)
Al Virod8c95842011-12-07 18:16:57 -05002677 return superblock_has_perm(cred, path->dentry->d_sb,
Eric Paris828dfe12008-04-17 13:17:49 -04002678 FILESYSTEM__REMOUNT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002679 else
Eric Paris2875fa02011-04-28 16:04:24 -04002680 return path_has_perm(cred, path, FILE__MOUNTON);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002681}
2682
2683static int selinux_umount(struct vfsmount *mnt, int flags)
2684{
David Howells88e67f32008-11-14 10:39:21 +11002685 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002686
David Howells88e67f32008-11-14 10:39:21 +11002687 return superblock_has_perm(cred, mnt->mnt_sb,
Eric Paris828dfe12008-04-17 13:17:49 -04002688 FILESYSTEM__UNMOUNT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002689}
2690
2691/* inode security operations */
2692
2693static int selinux_inode_alloc_security(struct inode *inode)
2694{
2695 return inode_alloc_security(inode);
2696}
2697
2698static void selinux_inode_free_security(struct inode *inode)
2699{
2700 inode_free_security(inode);
2701}
2702
David Quigleyd47be3d2013-05-22 12:50:34 -04002703static int selinux_dentry_init_security(struct dentry *dentry, int mode,
2704 struct qstr *name, void **ctx,
2705 u32 *ctxlen)
2706{
2707 const struct cred *cred = current_cred();
2708 struct task_security_struct *tsec;
2709 struct inode_security_struct *dsec;
2710 struct superblock_security_struct *sbsec;
David Howellsc6f493d2015-03-17 22:26:22 +00002711 struct inode *dir = d_backing_inode(dentry->d_parent);
David Quigleyd47be3d2013-05-22 12:50:34 -04002712 u32 newsid;
2713 int rc;
2714
2715 tsec = cred->security;
2716 dsec = dir->i_security;
2717 sbsec = dir->i_sb->s_security;
2718
2719 if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) {
2720 newsid = tsec->create_sid;
2721 } else {
2722 rc = security_transition_sid(tsec->sid, dsec->sid,
2723 inode_mode_to_security_class(mode),
2724 name,
2725 &newsid);
2726 if (rc) {
2727 printk(KERN_WARNING
2728 "%s: security_transition_sid failed, rc=%d\n",
2729 __func__, -rc);
2730 return rc;
2731 }
2732 }
2733
2734 return security_sid_to_context(newsid, (char **)ctx, ctxlen);
2735}
2736
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002737static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
Tetsuo Handa95489062013-07-25 05:44:02 +09002738 const struct qstr *qstr,
2739 const char **name,
Eric Paris2a7dba32011-02-01 11:05:39 -05002740 void **value, size_t *len)
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002741{
Paul Moore5fb49872010-04-22 14:46:19 -04002742 const struct task_security_struct *tsec = current_security();
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002743 struct inode_security_struct *dsec;
2744 struct superblock_security_struct *sbsec;
David Howells275bb412008-11-14 10:39:19 +11002745 u32 sid, newsid, clen;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002746 int rc;
Tetsuo Handa95489062013-07-25 05:44:02 +09002747 char *context;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002748
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002749 dsec = dir->i_security;
2750 sbsec = dir->i_sb->s_security;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002751
David Howells275bb412008-11-14 10:39:19 +11002752 sid = tsec->sid;
2753 newsid = tsec->create_sid;
2754
Eric Paris415103f2010-12-02 16:13:40 -05002755 if ((sbsec->flags & SE_SBINITIALIZED) &&
2756 (sbsec->behavior == SECURITY_FS_USE_MNTPOINT))
2757 newsid = sbsec->mntpoint_sid;
Eric Paris12f348b2012-10-09 10:56:25 -04002758 else if (!newsid || !(sbsec->flags & SBLABEL_MNT)) {
David Howells275bb412008-11-14 10:39:19 +11002759 rc = security_transition_sid(sid, dsec->sid,
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002760 inode_mode_to_security_class(inode->i_mode),
Eric Paris652bb9b2011-02-01 11:05:40 -05002761 qstr, &newsid);
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002762 if (rc) {
2763 printk(KERN_WARNING "%s: "
2764 "security_transition_sid failed, rc=%d (dev=%s "
2765 "ino=%ld)\n",
Harvey Harrisondd6f9532008-03-06 10:03:59 +11002766 __func__,
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002767 -rc, inode->i_sb->s_id, inode->i_ino);
2768 return rc;
2769 }
2770 }
2771
Eric Paris296fddf2006-09-25 23:32:00 -07002772 /* Possibly defer initialization to selinux_complete_init. */
David P. Quigley0d90a7e2009-01-16 09:22:02 -05002773 if (sbsec->flags & SE_SBINITIALIZED) {
Eric Paris296fddf2006-09-25 23:32:00 -07002774 struct inode_security_struct *isec = inode->i_security;
2775 isec->sclass = inode_mode_to_security_class(inode->i_mode);
2776 isec->sid = newsid;
2777 isec->initialized = 1;
2778 }
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002779
Eric Paris12f348b2012-10-09 10:56:25 -04002780 if (!ss_initialized || !(sbsec->flags & SBLABEL_MNT))
Stephen Smalley25a74f32005-11-08 21:34:33 -08002781 return -EOPNOTSUPP;
2782
Tetsuo Handa95489062013-07-25 05:44:02 +09002783 if (name)
2784 *name = XATTR_SELINUX_SUFFIX;
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002785
2786 if (value && len) {
Stephen Smalley12b29f32008-05-07 13:03:20 -04002787 rc = security_sid_to_context_force(newsid, &context, &clen);
Tetsuo Handa95489062013-07-25 05:44:02 +09002788 if (rc)
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002789 return rc;
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002790 *value = context;
2791 *len = clen;
2792 }
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002793
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002794 return 0;
2795}
2796
Al Viro4acdaf22011-07-26 01:42:34 -04002797static int selinux_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002798{
2799 return may_create(dir, dentry, SECCLASS_FILE);
2800}
2801
Linus Torvalds1da177e2005-04-16 15:20:36 -07002802static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
2803{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002804 return may_link(dir, old_dentry, MAY_LINK);
2805}
2806
Linus Torvalds1da177e2005-04-16 15:20:36 -07002807static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry)
2808{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002809 return may_link(dir, dentry, MAY_UNLINK);
2810}
2811
2812static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry, const char *name)
2813{
2814 return may_create(dir, dentry, SECCLASS_LNK_FILE);
2815}
2816
Al Viro18bb1db2011-07-26 01:41:39 -04002817static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry, umode_t mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002818{
2819 return may_create(dir, dentry, SECCLASS_DIR);
2820}
2821
Linus Torvalds1da177e2005-04-16 15:20:36 -07002822static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry)
2823{
2824 return may_link(dir, dentry, MAY_RMDIR);
2825}
2826
Al Viro1a67aaf2011-07-26 01:52:52 -04002827static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002828{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002829 return may_create(dir, dentry, inode_mode_to_security_class(mode));
2830}
2831
Linus Torvalds1da177e2005-04-16 15:20:36 -07002832static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
Eric Paris828dfe12008-04-17 13:17:49 -04002833 struct inode *new_inode, struct dentry *new_dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002834{
2835 return may_rename(old_inode, old_dentry, new_inode, new_dentry);
2836}
2837
Linus Torvalds1da177e2005-04-16 15:20:36 -07002838static int selinux_inode_readlink(struct dentry *dentry)
2839{
David Howells88e67f32008-11-14 10:39:21 +11002840 const struct cred *cred = current_cred();
2841
Eric Paris2875fa02011-04-28 16:04:24 -04002842 return dentry_has_perm(cred, dentry, FILE__READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002843}
2844
NeilBrownbda0be72015-03-23 13:37:39 +11002845static int selinux_inode_follow_link(struct dentry *dentry, struct inode *inode,
2846 bool rcu)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002847{
David Howells88e67f32008-11-14 10:39:21 +11002848 const struct cred *cred = current_cred();
NeilBrownbda0be72015-03-23 13:37:39 +11002849 struct common_audit_data ad;
2850 struct inode_security_struct *isec;
2851 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002852
NeilBrownbda0be72015-03-23 13:37:39 +11002853 validate_creds(cred);
2854
2855 ad.type = LSM_AUDIT_DATA_DENTRY;
2856 ad.u.dentry = dentry;
2857 sid = cred_sid(cred);
2858 isec = inode->i_security;
2859
2860 return avc_has_perm_flags(sid, isec->sid, isec->sclass, FILE__READ, &ad,
2861 rcu ? MAY_NOT_BLOCK : 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002862}
2863
Eric Parisd4cf970d2012-04-04 15:01:42 -04002864static noinline int audit_inode_permission(struct inode *inode,
2865 u32 perms, u32 audited, u32 denied,
Stephen Smalley626b9742014-04-29 11:29:04 -07002866 int result,
Eric Parisd4cf970d2012-04-04 15:01:42 -04002867 unsigned flags)
2868{
2869 struct common_audit_data ad;
Eric Parisd4cf970d2012-04-04 15:01:42 -04002870 struct inode_security_struct *isec = inode->i_security;
2871 int rc;
2872
Eric Paris50c205f2012-04-04 15:01:43 -04002873 ad.type = LSM_AUDIT_DATA_INODE;
Eric Parisd4cf970d2012-04-04 15:01:42 -04002874 ad.u.inode = inode;
2875
2876 rc = slow_avc_audit(current_sid(), isec->sid, isec->sclass, perms,
Stephen Smalley626b9742014-04-29 11:29:04 -07002877 audited, denied, result, &ad, flags);
Eric Parisd4cf970d2012-04-04 15:01:42 -04002878 if (rc)
2879 return rc;
2880 return 0;
2881}
2882
Al Viroe74f71e2011-06-20 19:38:15 -04002883static int selinux_inode_permission(struct inode *inode, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002884{
David Howells88e67f32008-11-14 10:39:21 +11002885 const struct cred *cred = current_cred();
Eric Parisb782e0a2010-07-23 11:44:03 -04002886 u32 perms;
2887 bool from_access;
Al Virocf1dd1d2011-06-20 19:44:08 -04002888 unsigned flags = mask & MAY_NOT_BLOCK;
Eric Paris2e334052012-04-04 15:01:42 -04002889 struct inode_security_struct *isec;
2890 u32 sid;
2891 struct av_decision avd;
2892 int rc, rc2;
2893 u32 audited, denied;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002894
Eric Parisb782e0a2010-07-23 11:44:03 -04002895 from_access = mask & MAY_ACCESS;
Eric Parisd09ca732010-07-23 11:43:57 -04002896 mask &= (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND);
2897
Eric Parisb782e0a2010-07-23 11:44:03 -04002898 /* No permission to check. Existence test. */
2899 if (!mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002900 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002901
Eric Paris2e334052012-04-04 15:01:42 -04002902 validate_creds(cred);
Eric Parisb782e0a2010-07-23 11:44:03 -04002903
Eric Paris2e334052012-04-04 15:01:42 -04002904 if (unlikely(IS_PRIVATE(inode)))
2905 return 0;
Eric Parisb782e0a2010-07-23 11:44:03 -04002906
2907 perms = file_mask_to_av(inode->i_mode, mask);
2908
Eric Paris2e334052012-04-04 15:01:42 -04002909 sid = cred_sid(cred);
2910 isec = inode->i_security;
2911
2912 rc = avc_has_perm_noaudit(sid, isec->sid, isec->sclass, perms, 0, &avd);
2913 audited = avc_audit_required(perms, &avd, rc,
2914 from_access ? FILE__AUDIT_ACCESS : 0,
2915 &denied);
2916 if (likely(!audited))
2917 return rc;
2918
Stephen Smalley626b9742014-04-29 11:29:04 -07002919 rc2 = audit_inode_permission(inode, perms, audited, denied, rc, flags);
Eric Paris2e334052012-04-04 15:01:42 -04002920 if (rc2)
2921 return rc2;
2922 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002923}
2924
2925static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
2926{
David Howells88e67f32008-11-14 10:39:21 +11002927 const struct cred *cred = current_cred();
Amerigo Wangbc6a6002009-08-20 19:29:02 -07002928 unsigned int ia_valid = iattr->ia_valid;
Eric Paris95dbf732012-04-04 13:45:34 -04002929 __u32 av = FILE__WRITE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002930
Amerigo Wangbc6a6002009-08-20 19:29:02 -07002931 /* ATTR_FORCE is just used for ATTR_KILL_S[UG]ID. */
2932 if (ia_valid & ATTR_FORCE) {
2933 ia_valid &= ~(ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_MODE |
2934 ATTR_FORCE);
2935 if (!ia_valid)
2936 return 0;
2937 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002938
Amerigo Wangbc6a6002009-08-20 19:29:02 -07002939 if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID |
2940 ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_TIMES_SET))
Eric Paris2875fa02011-04-28 16:04:24 -04002941 return dentry_has_perm(cred, dentry, FILE__SETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002942
Eric Paris3d2195c2012-07-06 14:13:30 -04002943 if (selinux_policycap_openperm && (ia_valid & ATTR_SIZE))
Eric Paris95dbf732012-04-04 13:45:34 -04002944 av |= FILE__OPEN;
2945
2946 return dentry_has_perm(cred, dentry, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002947}
2948
Al Viro3f7036a2015-03-08 19:28:30 -04002949static int selinux_inode_getattr(const struct path *path)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002950{
Al Viro3f7036a2015-03-08 19:28:30 -04002951 return path_has_perm(current_cred(), path, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002952}
2953
David Howells8f0cfa52008-04-29 00:59:41 -07002954static int selinux_inode_setotherxattr(struct dentry *dentry, const char *name)
Serge E. Hallynb5376772007-10-16 23:31:36 -07002955{
David Howells88e67f32008-11-14 10:39:21 +11002956 const struct cred *cred = current_cred();
2957
Serge E. Hallynb5376772007-10-16 23:31:36 -07002958 if (!strncmp(name, XATTR_SECURITY_PREFIX,
2959 sizeof XATTR_SECURITY_PREFIX - 1)) {
2960 if (!strcmp(name, XATTR_NAME_CAPS)) {
2961 if (!capable(CAP_SETFCAP))
2962 return -EPERM;
2963 } else if (!capable(CAP_SYS_ADMIN)) {
2964 /* A different attribute in the security namespace.
2965 Restrict to administrator. */
2966 return -EPERM;
2967 }
2968 }
2969
2970 /* Not an attribute we recognize, so just check the
2971 ordinary setattr permission. */
Eric Paris2875fa02011-04-28 16:04:24 -04002972 return dentry_has_perm(cred, dentry, FILE__SETATTR);
Serge E. Hallynb5376772007-10-16 23:31:36 -07002973}
2974
David Howells8f0cfa52008-04-29 00:59:41 -07002975static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
2976 const void *value, size_t size, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002977{
David Howellsc6f493d2015-03-17 22:26:22 +00002978 struct inode *inode = d_backing_inode(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002979 struct inode_security_struct *isec = inode->i_security;
2980 struct superblock_security_struct *sbsec;
Thomas Liu2bf49692009-07-14 12:14:09 -04002981 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11002982 u32 newsid, sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002983 int rc = 0;
2984
Serge E. Hallynb5376772007-10-16 23:31:36 -07002985 if (strcmp(name, XATTR_NAME_SELINUX))
2986 return selinux_inode_setotherxattr(dentry, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002987
2988 sbsec = inode->i_sb->s_security;
Eric Paris12f348b2012-10-09 10:56:25 -04002989 if (!(sbsec->flags & SBLABEL_MNT))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002990 return -EOPNOTSUPP;
2991
Serge E. Hallyn2e149672011-03-23 16:43:26 -07002992 if (!inode_owner_or_capable(inode))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002993 return -EPERM;
2994
Eric Paris50c205f2012-04-04 15:01:43 -04002995 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04002996 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002997
David Howells275bb412008-11-14 10:39:19 +11002998 rc = avc_has_perm(sid, isec->sid, isec->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002999 FILE__RELABELFROM, &ad);
3000 if (rc)
3001 return rc;
3002
Nikolay Aleksandrov52a4c642014-03-07 12:44:19 +01003003 rc = security_context_to_sid(value, size, &newsid, GFP_KERNEL);
Stephen Smalley12b29f32008-05-07 13:03:20 -04003004 if (rc == -EINVAL) {
Eric Parisd6ea83e2012-04-04 13:45:49 -04003005 if (!capable(CAP_MAC_ADMIN)) {
3006 struct audit_buffer *ab;
3007 size_t audit_size;
3008 const char *str;
3009
3010 /* We strip a nul only if it is at the end, otherwise the
3011 * context contains a nul and we should audit that */
Al Viroe3fea3f2012-06-09 08:15:16 +01003012 if (value) {
3013 str = value;
3014 if (str[size - 1] == '\0')
3015 audit_size = size - 1;
3016 else
3017 audit_size = size;
3018 } else {
3019 str = "";
3020 audit_size = 0;
3021 }
Eric Parisd6ea83e2012-04-04 13:45:49 -04003022 ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR);
3023 audit_log_format(ab, "op=setxattr invalid_context=");
3024 audit_log_n_untrustedstring(ab, value, audit_size);
3025 audit_log_end(ab);
3026
Stephen Smalley12b29f32008-05-07 13:03:20 -04003027 return rc;
Eric Parisd6ea83e2012-04-04 13:45:49 -04003028 }
Stephen Smalley12b29f32008-05-07 13:03:20 -04003029 rc = security_context_to_sid_force(value, size, &newsid);
3030 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003031 if (rc)
3032 return rc;
3033
David Howells275bb412008-11-14 10:39:19 +11003034 rc = avc_has_perm(sid, newsid, isec->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003035 FILE__RELABELTO, &ad);
3036 if (rc)
3037 return rc;
3038
David Howells275bb412008-11-14 10:39:19 +11003039 rc = security_validate_transition(isec->sid, newsid, sid,
Eric Paris828dfe12008-04-17 13:17:49 -04003040 isec->sclass);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003041 if (rc)
3042 return rc;
3043
3044 return avc_has_perm(newsid,
3045 sbsec->sid,
3046 SECCLASS_FILESYSTEM,
3047 FILESYSTEM__ASSOCIATE,
3048 &ad);
3049}
3050
David Howells8f0cfa52008-04-29 00:59:41 -07003051static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
Eric Parisf5269712008-05-14 11:27:45 -04003052 const void *value, size_t size,
David Howells8f0cfa52008-04-29 00:59:41 -07003053 int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003054{
David Howellsc6f493d2015-03-17 22:26:22 +00003055 struct inode *inode = d_backing_inode(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003056 struct inode_security_struct *isec = inode->i_security;
3057 u32 newsid;
3058 int rc;
3059
3060 if (strcmp(name, XATTR_NAME_SELINUX)) {
3061 /* Not an attribute we recognize, so nothing to do. */
3062 return;
3063 }
3064
Stephen Smalley12b29f32008-05-07 13:03:20 -04003065 rc = security_context_to_sid_force(value, size, &newsid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003066 if (rc) {
Stephen Smalley12b29f32008-05-07 13:03:20 -04003067 printk(KERN_ERR "SELinux: unable to map context to SID"
3068 "for (%s, %lu), rc=%d\n",
3069 inode->i_sb->s_id, inode->i_ino, -rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003070 return;
3071 }
3072
David Quigleyaa9c2662013-05-22 12:50:44 -04003073 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003074 isec->sid = newsid;
David Quigleyaa9c2662013-05-22 12:50:44 -04003075 isec->initialized = 1;
3076
Linus Torvalds1da177e2005-04-16 15:20:36 -07003077 return;
3078}
3079
David Howells8f0cfa52008-04-29 00:59:41 -07003080static int selinux_inode_getxattr(struct dentry *dentry, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003081{
David Howells88e67f32008-11-14 10:39:21 +11003082 const struct cred *cred = current_cred();
3083
Eric Paris2875fa02011-04-28 16:04:24 -04003084 return dentry_has_perm(cred, dentry, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003085}
3086
Eric Paris828dfe12008-04-17 13:17:49 -04003087static int selinux_inode_listxattr(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003088{
David Howells88e67f32008-11-14 10:39:21 +11003089 const struct cred *cred = current_cred();
3090
Eric Paris2875fa02011-04-28 16:04:24 -04003091 return dentry_has_perm(cred, dentry, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003092}
3093
David Howells8f0cfa52008-04-29 00:59:41 -07003094static int selinux_inode_removexattr(struct dentry *dentry, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003095{
Serge E. Hallynb5376772007-10-16 23:31:36 -07003096 if (strcmp(name, XATTR_NAME_SELINUX))
3097 return selinux_inode_setotherxattr(dentry, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003098
3099 /* No one is allowed to remove a SELinux security label.
3100 You can change the label, but all data must be labeled. */
3101 return -EACCES;
3102}
3103
James Morrisd381d8a2005-10-30 14:59:22 -08003104/*
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04003105 * Copy the inode security context value to the user.
James Morrisd381d8a2005-10-30 14:59:22 -08003106 *
3107 * Permission check is handled by selinux_inode_getxattr hook.
3108 */
David P. Quigley42492592008-02-04 22:29:39 -08003109static int selinux_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003110{
David P. Quigley42492592008-02-04 22:29:39 -08003111 u32 size;
3112 int error;
3113 char *context = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003114 struct inode_security_struct *isec = inode->i_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003115
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00003116 if (strcmp(name, XATTR_SELINUX_SUFFIX))
3117 return -EOPNOTSUPP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003118
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04003119 /*
3120 * If the caller has CAP_MAC_ADMIN, then get the raw context
3121 * value even if it is not defined by current policy; otherwise,
3122 * use the in-core value under current policy.
3123 * Use the non-auditing forms of the permission checks since
3124 * getxattr may be called by unprivileged processes commonly
3125 * and lack of permission just means that we fall back to the
3126 * in-core context value, not a denial.
3127 */
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07003128 error = cap_capable(current_cred(), &init_user_ns, CAP_MAC_ADMIN,
3129 SECURITY_CAP_NOAUDIT);
3130 if (!error)
3131 error = cred_has_capability(current_cred(), CAP_MAC_ADMIN,
3132 SECURITY_CAP_NOAUDIT);
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04003133 if (!error)
3134 error = security_sid_to_context_force(isec->sid, &context,
3135 &size);
3136 else
3137 error = security_sid_to_context(isec->sid, &context, &size);
David P. Quigley42492592008-02-04 22:29:39 -08003138 if (error)
3139 return error;
3140 error = size;
3141 if (alloc) {
3142 *buffer = context;
3143 goto out_nofree;
3144 }
3145 kfree(context);
3146out_nofree:
3147 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003148}
3149
3150static int selinux_inode_setsecurity(struct inode *inode, const char *name,
Eric Paris828dfe12008-04-17 13:17:49 -04003151 const void *value, size_t size, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003152{
3153 struct inode_security_struct *isec = inode->i_security;
3154 u32 newsid;
3155 int rc;
3156
3157 if (strcmp(name, XATTR_SELINUX_SUFFIX))
3158 return -EOPNOTSUPP;
3159
3160 if (!value || !size)
3161 return -EACCES;
3162
Nikolay Aleksandrov52a4c642014-03-07 12:44:19 +01003163 rc = security_context_to_sid((void *)value, size, &newsid, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003164 if (rc)
3165 return rc;
3166
David Quigleyaa9c2662013-05-22 12:50:44 -04003167 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003168 isec->sid = newsid;
David P. Quigleyddd29ec2009-09-09 14:25:37 -04003169 isec->initialized = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003170 return 0;
3171}
3172
3173static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size)
3174{
3175 const int len = sizeof(XATTR_NAME_SELINUX);
3176 if (buffer && len <= buffer_size)
3177 memcpy(buffer, XATTR_NAME_SELINUX, len);
3178 return len;
3179}
3180
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02003181static void selinux_inode_getsecid(const struct inode *inode, u32 *secid)
3182{
3183 struct inode_security_struct *isec = inode->i_security;
3184 *secid = isec->sid;
3185}
3186
Linus Torvalds1da177e2005-04-16 15:20:36 -07003187/* file security operations */
3188
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003189static int selinux_revalidate_file_permission(struct file *file, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003190{
David Howells88e67f32008-11-14 10:39:21 +11003191 const struct cred *cred = current_cred();
Al Viro496ad9a2013-01-23 17:07:38 -05003192 struct inode *inode = file_inode(file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003193
Linus Torvalds1da177e2005-04-16 15:20:36 -07003194 /* file_mask_to_av won't add FILE__WRITE if MAY_APPEND is set */
3195 if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE))
3196 mask |= MAY_APPEND;
3197
Paul Moore389fb8002009-03-27 17:10:34 -04003198 return file_has_perm(cred, file,
3199 file_mask_to_av(inode->i_mode, mask));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003200}
3201
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003202static int selinux_file_permission(struct file *file, int mask)
3203{
Al Viro496ad9a2013-01-23 17:07:38 -05003204 struct inode *inode = file_inode(file);
Stephen Smalley20dda182009-06-22 14:54:53 -04003205 struct file_security_struct *fsec = file->f_security;
3206 struct inode_security_struct *isec = inode->i_security;
3207 u32 sid = current_sid();
3208
Paul Moore389fb8002009-03-27 17:10:34 -04003209 if (!mask)
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003210 /* No permission to check. Existence test. */
3211 return 0;
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003212
Stephen Smalley20dda182009-06-22 14:54:53 -04003213 if (sid == fsec->sid && fsec->isid == isec->sid &&
3214 fsec->pseqno == avc_policy_seqno())
Eric Paris83d49852012-04-04 13:45:40 -04003215 /* No change since file_open check. */
Stephen Smalley20dda182009-06-22 14:54:53 -04003216 return 0;
3217
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003218 return selinux_revalidate_file_permission(file, mask);
3219}
3220
Linus Torvalds1da177e2005-04-16 15:20:36 -07003221static int selinux_file_alloc_security(struct file *file)
3222{
3223 return file_alloc_security(file);
3224}
3225
3226static void selinux_file_free_security(struct file *file)
3227{
3228 file_free_security(file);
3229}
3230
3231static int selinux_file_ioctl(struct file *file, unsigned int cmd,
3232 unsigned long arg)
3233{
David Howells88e67f32008-11-14 10:39:21 +11003234 const struct cred *cred = current_cred();
Eric Paris0b24dcb2011-02-25 15:39:20 -05003235 int error = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003236
Eric Paris0b24dcb2011-02-25 15:39:20 -05003237 switch (cmd) {
3238 case FIONREAD:
3239 /* fall through */
3240 case FIBMAP:
3241 /* fall through */
3242 case FIGETBSZ:
3243 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003244 case FS_IOC_GETFLAGS:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003245 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003246 case FS_IOC_GETVERSION:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003247 error = file_has_perm(cred, file, FILE__GETATTR);
3248 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003249
Al Viro2f99c362012-03-23 16:04:05 -04003250 case FS_IOC_SETFLAGS:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003251 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003252 case FS_IOC_SETVERSION:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003253 error = file_has_perm(cred, file, FILE__SETATTR);
3254 break;
3255
3256 /* sys_ioctl() checks */
3257 case FIONBIO:
3258 /* fall through */
3259 case FIOASYNC:
3260 error = file_has_perm(cred, file, 0);
3261 break;
3262
3263 case KDSKBENT:
3264 case KDSKBSENT:
Eric Paris6a9de492012-01-03 12:25:14 -05003265 error = cred_has_capability(cred, CAP_SYS_TTY_CONFIG,
3266 SECURITY_CAP_AUDIT);
Eric Paris0b24dcb2011-02-25 15:39:20 -05003267 break;
3268
3269 /* default case assumes that the command will go
3270 * to the file's ioctl() function.
3271 */
3272 default:
3273 error = file_has_perm(cred, file, FILE__IOCTL);
3274 }
3275 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003276}
3277
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003278static int default_noexec;
3279
Linus Torvalds1da177e2005-04-16 15:20:36 -07003280static int file_map_prot_check(struct file *file, unsigned long prot, int shared)
3281{
David Howells88e67f32008-11-14 10:39:21 +11003282 const struct cred *cred = current_cred();
David Howellsd84f4f92008-11-14 10:39:23 +11003283 int rc = 0;
David Howells88e67f32008-11-14 10:39:21 +11003284
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003285 if (default_noexec &&
Stephen Smalley892e8ca2015-07-10 09:40:59 -04003286 (prot & PROT_EXEC) && (!file || IS_PRIVATE(file_inode(file)) ||
3287 (!shared && (prot & PROT_WRITE)))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003288 /*
3289 * We are making executable an anonymous mapping or a
3290 * private file mapping that will also be writable.
3291 * This has an additional check.
3292 */
David Howellsd84f4f92008-11-14 10:39:23 +11003293 rc = cred_has_perm(cred, cred, PROCESS__EXECMEM);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003294 if (rc)
David Howellsd84f4f92008-11-14 10:39:23 +11003295 goto error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003296 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003297
3298 if (file) {
3299 /* read access is always possible with a mapping */
3300 u32 av = FILE__READ;
3301
3302 /* write access only matters if the mapping is shared */
3303 if (shared && (prot & PROT_WRITE))
3304 av |= FILE__WRITE;
3305
3306 if (prot & PROT_EXEC)
3307 av |= FILE__EXECUTE;
3308
David Howells88e67f32008-11-14 10:39:21 +11003309 return file_has_perm(cred, file, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003310 }
David Howellsd84f4f92008-11-14 10:39:23 +11003311
3312error:
3313 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003314}
3315
Al Viroe5467852012-05-30 13:30:51 -04003316static int selinux_mmap_addr(unsigned long addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003317{
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07003318 int rc = 0;
Paul Moore98883bf2014-03-19 16:46:11 -04003319
3320 if (addr < CONFIG_LSM_MMAP_MIN_ADDR) {
3321 u32 sid = current_sid();
3322 rc = avc_has_perm(sid, sid, SECCLASS_MEMPROTECT,
3323 MEMPROTECT__MMAP_ZERO, NULL);
3324 }
3325
3326 return rc;
Al Viroe5467852012-05-30 13:30:51 -04003327}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003328
Al Viroe5467852012-05-30 13:30:51 -04003329static int selinux_mmap_file(struct file *file, unsigned long reqprot,
3330 unsigned long prot, unsigned long flags)
3331{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003332 if (selinux_checkreqprot)
3333 prot = reqprot;
3334
3335 return file_map_prot_check(file, prot,
3336 (flags & MAP_TYPE) == MAP_SHARED);
3337}
3338
3339static int selinux_file_mprotect(struct vm_area_struct *vma,
3340 unsigned long reqprot,
3341 unsigned long prot)
3342{
David Howells88e67f32008-11-14 10:39:21 +11003343 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003344
3345 if (selinux_checkreqprot)
3346 prot = reqprot;
3347
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003348 if (default_noexec &&
3349 (prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) {
James Morrisd541bbe2009-01-29 12:19:51 +11003350 int rc = 0;
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003351 if (vma->vm_start >= vma->vm_mm->start_brk &&
3352 vma->vm_end <= vma->vm_mm->brk) {
David Howellsd84f4f92008-11-14 10:39:23 +11003353 rc = cred_has_perm(cred, cred, PROCESS__EXECHEAP);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003354 } else if (!vma->vm_file &&
3355 vma->vm_start <= vma->vm_mm->start_stack &&
3356 vma->vm_end >= vma->vm_mm->start_stack) {
David Howells3b11a1d2008-11-14 10:39:26 +11003357 rc = current_has_perm(current, PROCESS__EXECSTACK);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003358 } else if (vma->vm_file && vma->anon_vma) {
3359 /*
3360 * We are making executable a file mapping that has
3361 * had some COW done. Since pages might have been
3362 * written, check ability to execute the possibly
3363 * modified content. This typically should only
3364 * occur for text relocations.
3365 */
David Howellsd84f4f92008-11-14 10:39:23 +11003366 rc = file_has_perm(cred, vma->vm_file, FILE__EXECMOD);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003367 }
Lorenzo Hernandez García-Hierro6b992192005-06-25 14:54:34 -07003368 if (rc)
3369 return rc;
3370 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003371
3372 return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED);
3373}
3374
3375static int selinux_file_lock(struct file *file, unsigned int cmd)
3376{
David Howells88e67f32008-11-14 10:39:21 +11003377 const struct cred *cred = current_cred();
3378
3379 return file_has_perm(cred, file, FILE__LOCK);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003380}
3381
3382static int selinux_file_fcntl(struct file *file, unsigned int cmd,
3383 unsigned long arg)
3384{
David Howells88e67f32008-11-14 10:39:21 +11003385 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003386 int err = 0;
3387
3388 switch (cmd) {
Eric Paris828dfe12008-04-17 13:17:49 -04003389 case F_SETFL:
Eric Paris828dfe12008-04-17 13:17:49 -04003390 if ((file->f_flags & O_APPEND) && !(arg & O_APPEND)) {
David Howells88e67f32008-11-14 10:39:21 +11003391 err = file_has_perm(cred, file, FILE__WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003392 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003393 }
3394 /* fall through */
3395 case F_SETOWN:
3396 case F_SETSIG:
3397 case F_GETFL:
3398 case F_GETOWN:
3399 case F_GETSIG:
Cyrill Gorcunov1d151c32012-07-30 14:43:00 -07003400 case F_GETOWNER_UIDS:
Eric Paris828dfe12008-04-17 13:17:49 -04003401 /* Just check FD__USE permission */
David Howells88e67f32008-11-14 10:39:21 +11003402 err = file_has_perm(cred, file, 0);
Eric Paris828dfe12008-04-17 13:17:49 -04003403 break;
3404 case F_GETLK:
3405 case F_SETLK:
3406 case F_SETLKW:
Jeff Layton0d3f7a22014-04-22 08:23:58 -04003407 case F_OFD_GETLK:
3408 case F_OFD_SETLK:
3409 case F_OFD_SETLKW:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003410#if BITS_PER_LONG == 32
Eric Paris828dfe12008-04-17 13:17:49 -04003411 case F_GETLK64:
3412 case F_SETLK64:
3413 case F_SETLKW64:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003414#endif
David Howells88e67f32008-11-14 10:39:21 +11003415 err = file_has_perm(cred, file, FILE__LOCK);
Eric Paris828dfe12008-04-17 13:17:49 -04003416 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003417 }
3418
3419 return err;
3420}
3421
Jeff Laytone0b93ed2014-08-22 11:27:32 -04003422static void selinux_file_set_fowner(struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003423{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003424 struct file_security_struct *fsec;
3425
Linus Torvalds1da177e2005-04-16 15:20:36 -07003426 fsec = file->f_security;
David Howells275bb412008-11-14 10:39:19 +11003427 fsec->fown_sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003428}
3429
3430static int selinux_file_send_sigiotask(struct task_struct *tsk,
3431 struct fown_struct *fown, int signum)
3432{
Eric Paris828dfe12008-04-17 13:17:49 -04003433 struct file *file;
Stephen Smalley65c90bc2009-05-04 15:43:18 -04003434 u32 sid = task_sid(tsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003435 u32 perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003436 struct file_security_struct *fsec;
3437
3438 /* struct fown_struct is never outside the context of a struct file */
Eric Paris828dfe12008-04-17 13:17:49 -04003439 file = container_of(fown, struct file, f_owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003440
Linus Torvalds1da177e2005-04-16 15:20:36 -07003441 fsec = file->f_security;
3442
3443 if (!signum)
3444 perm = signal_to_av(SIGIO); /* as per send_sigio_to_task */
3445 else
3446 perm = signal_to_av(signum);
3447
David Howells275bb412008-11-14 10:39:19 +11003448 return avc_has_perm(fsec->fown_sid, sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003449 SECCLASS_PROCESS, perm, NULL);
3450}
3451
3452static int selinux_file_receive(struct file *file)
3453{
David Howells88e67f32008-11-14 10:39:21 +11003454 const struct cred *cred = current_cred();
3455
3456 return file_has_perm(cred, file, file_to_av(file));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003457}
3458
Eric Paris83d49852012-04-04 13:45:40 -04003459static int selinux_file_open(struct file *file, const struct cred *cred)
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003460{
3461 struct file_security_struct *fsec;
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003462 struct inode_security_struct *isec;
David Howellsd84f4f92008-11-14 10:39:23 +11003463
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003464 fsec = file->f_security;
Al Viro496ad9a2013-01-23 17:07:38 -05003465 isec = file_inode(file)->i_security;
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003466 /*
3467 * Save inode label and policy sequence number
3468 * at open-time so that selinux_file_permission
3469 * can determine whether revalidation is necessary.
3470 * Task label is already saved in the file security
3471 * struct as its SID.
3472 */
3473 fsec->isid = isec->sid;
3474 fsec->pseqno = avc_policy_seqno();
3475 /*
3476 * Since the inode label or policy seqno may have changed
3477 * between the selinux_inode_permission check and the saving
3478 * of state above, recheck that access is still permitted.
3479 * Otherwise, access might never be revalidated against the
3480 * new inode label or new policy.
3481 * This check is not redundant - do not remove.
3482 */
David Howells13f8e982013-06-13 23:37:55 +01003483 return file_path_has_perm(cred, file, open_file_to_av(file));
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003484}
3485
Linus Torvalds1da177e2005-04-16 15:20:36 -07003486/* task security operations */
3487
3488static int selinux_task_create(unsigned long clone_flags)
3489{
David Howells3b11a1d2008-11-14 10:39:26 +11003490 return current_has_perm(current, PROCESS__FORK);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003491}
3492
David Howellsf1752ee2008-11-14 10:39:17 +11003493/*
David Howellsee18d642009-09-02 09:14:21 +01003494 * allocate the SELinux part of blank credentials
3495 */
3496static int selinux_cred_alloc_blank(struct cred *cred, gfp_t gfp)
3497{
3498 struct task_security_struct *tsec;
3499
3500 tsec = kzalloc(sizeof(struct task_security_struct), gfp);
3501 if (!tsec)
3502 return -ENOMEM;
3503
3504 cred->security = tsec;
3505 return 0;
3506}
3507
3508/*
David Howellsf1752ee2008-11-14 10:39:17 +11003509 * detach and free the LSM part of a set of credentials
3510 */
3511static void selinux_cred_free(struct cred *cred)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003512{
David Howellsf1752ee2008-11-14 10:39:17 +11003513 struct task_security_struct *tsec = cred->security;
David Howellse0e81732009-09-02 09:13:40 +01003514
Tetsuo Handa2edeaa32011-02-07 13:36:10 +00003515 /*
3516 * cred->security == NULL if security_cred_alloc_blank() or
3517 * security_prepare_creds() returned an error.
3518 */
3519 BUG_ON(cred->security && (unsigned long) cred->security < PAGE_SIZE);
David Howellse0e81732009-09-02 09:13:40 +01003520 cred->security = (void *) 0x7UL;
David Howellsf1752ee2008-11-14 10:39:17 +11003521 kfree(tsec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003522}
3523
David Howellsd84f4f92008-11-14 10:39:23 +11003524/*
3525 * prepare a new set of credentials for modification
3526 */
3527static int selinux_cred_prepare(struct cred *new, const struct cred *old,
3528 gfp_t gfp)
3529{
3530 const struct task_security_struct *old_tsec;
3531 struct task_security_struct *tsec;
3532
3533 old_tsec = old->security;
3534
3535 tsec = kmemdup(old_tsec, sizeof(struct task_security_struct), gfp);
3536 if (!tsec)
3537 return -ENOMEM;
3538
3539 new->security = tsec;
3540 return 0;
3541}
3542
3543/*
David Howellsee18d642009-09-02 09:14:21 +01003544 * transfer the SELinux data to a blank set of creds
3545 */
3546static void selinux_cred_transfer(struct cred *new, const struct cred *old)
3547{
3548 const struct task_security_struct *old_tsec = old->security;
3549 struct task_security_struct *tsec = new->security;
3550
3551 *tsec = *old_tsec;
3552}
3553
3554/*
David Howells3a3b7ce2008-11-14 10:39:28 +11003555 * set the security data for a kernel service
3556 * - all the creation contexts are set to unlabelled
3557 */
3558static int selinux_kernel_act_as(struct cred *new, u32 secid)
3559{
3560 struct task_security_struct *tsec = new->security;
3561 u32 sid = current_sid();
3562 int ret;
3563
3564 ret = avc_has_perm(sid, secid,
3565 SECCLASS_KERNEL_SERVICE,
3566 KERNEL_SERVICE__USE_AS_OVERRIDE,
3567 NULL);
3568 if (ret == 0) {
3569 tsec->sid = secid;
3570 tsec->create_sid = 0;
3571 tsec->keycreate_sid = 0;
3572 tsec->sockcreate_sid = 0;
3573 }
3574 return ret;
3575}
3576
3577/*
3578 * set the file creation context in a security record to the same as the
3579 * objective context of the specified inode
3580 */
3581static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode)
3582{
3583 struct inode_security_struct *isec = inode->i_security;
3584 struct task_security_struct *tsec = new->security;
3585 u32 sid = current_sid();
3586 int ret;
3587
3588 ret = avc_has_perm(sid, isec->sid,
3589 SECCLASS_KERNEL_SERVICE,
3590 KERNEL_SERVICE__CREATE_FILES_AS,
3591 NULL);
3592
3593 if (ret == 0)
3594 tsec->create_sid = isec->sid;
David Howellsef574712010-02-26 01:56:16 +00003595 return ret;
David Howells3a3b7ce2008-11-14 10:39:28 +11003596}
3597
Eric Parisdd8dbf22009-11-03 16:35:32 +11003598static int selinux_kernel_module_request(char *kmod_name)
Eric Paris25354c42009-08-13 09:45:03 -04003599{
Eric Parisdd8dbf22009-11-03 16:35:32 +11003600 u32 sid;
3601 struct common_audit_data ad;
3602
3603 sid = task_sid(current);
3604
Eric Paris50c205f2012-04-04 15:01:43 -04003605 ad.type = LSM_AUDIT_DATA_KMOD;
Eric Parisdd8dbf22009-11-03 16:35:32 +11003606 ad.u.kmod_name = kmod_name;
3607
3608 return avc_has_perm(sid, SECINITSID_KERNEL, SECCLASS_SYSTEM,
3609 SYSTEM__MODULE_REQUEST, &ad);
Eric Paris25354c42009-08-13 09:45:03 -04003610}
3611
Linus Torvalds1da177e2005-04-16 15:20:36 -07003612static int selinux_task_setpgid(struct task_struct *p, pid_t pgid)
3613{
David Howells3b11a1d2008-11-14 10:39:26 +11003614 return current_has_perm(p, PROCESS__SETPGID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003615}
3616
3617static int selinux_task_getpgid(struct task_struct *p)
3618{
David Howells3b11a1d2008-11-14 10:39:26 +11003619 return current_has_perm(p, PROCESS__GETPGID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003620}
3621
3622static int selinux_task_getsid(struct task_struct *p)
3623{
David Howells3b11a1d2008-11-14 10:39:26 +11003624 return current_has_perm(p, PROCESS__GETSESSION);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003625}
3626
David Quigleyf9008e42006-06-30 01:55:46 -07003627static void selinux_task_getsecid(struct task_struct *p, u32 *secid)
3628{
David Howells275bb412008-11-14 10:39:19 +11003629 *secid = task_sid(p);
David Quigleyf9008e42006-06-30 01:55:46 -07003630}
3631
Linus Torvalds1da177e2005-04-16 15:20:36 -07003632static int selinux_task_setnice(struct task_struct *p, int nice)
3633{
David Howells3b11a1d2008-11-14 10:39:26 +11003634 return current_has_perm(p, PROCESS__SETSCHED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003635}
3636
James Morris03e68062006-06-23 02:03:58 -07003637static int selinux_task_setioprio(struct task_struct *p, int ioprio)
3638{
David Howells3b11a1d2008-11-14 10:39:26 +11003639 return current_has_perm(p, PROCESS__SETSCHED);
James Morris03e68062006-06-23 02:03:58 -07003640}
3641
David Quigleya1836a42006-06-30 01:55:49 -07003642static int selinux_task_getioprio(struct task_struct *p)
3643{
David Howells3b11a1d2008-11-14 10:39:26 +11003644 return current_has_perm(p, PROCESS__GETSCHED);
David Quigleya1836a42006-06-30 01:55:49 -07003645}
3646
Jiri Slaby8fd00b42009-08-26 18:41:16 +02003647static int selinux_task_setrlimit(struct task_struct *p, unsigned int resource,
3648 struct rlimit *new_rlim)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003649{
Jiri Slaby8fd00b42009-08-26 18:41:16 +02003650 struct rlimit *old_rlim = p->signal->rlim + resource;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003651
3652 /* Control the ability to change the hard limit (whether
3653 lowering or raising it), so that the hard limit can
3654 later be used as a safe reset point for the soft limit
David Howellsd84f4f92008-11-14 10:39:23 +11003655 upon context transitions. See selinux_bprm_committing_creds. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003656 if (old_rlim->rlim_max != new_rlim->rlim_max)
Jiri Slaby8fd00b42009-08-26 18:41:16 +02003657 return current_has_perm(p, PROCESS__SETRLIMIT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003658
3659 return 0;
3660}
3661
KOSAKI Motohirob0ae1982010-10-15 04:21:18 +09003662static int selinux_task_setscheduler(struct task_struct *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003663{
David Howells3b11a1d2008-11-14 10:39:26 +11003664 return current_has_perm(p, PROCESS__SETSCHED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003665}
3666
3667static int selinux_task_getscheduler(struct task_struct *p)
3668{
David Howells3b11a1d2008-11-14 10:39:26 +11003669 return current_has_perm(p, PROCESS__GETSCHED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003670}
3671
David Quigley35601542006-06-23 02:04:01 -07003672static int selinux_task_movememory(struct task_struct *p)
3673{
David Howells3b11a1d2008-11-14 10:39:26 +11003674 return current_has_perm(p, PROCESS__SETSCHED);
David Quigley35601542006-06-23 02:04:01 -07003675}
3676
David Quigleyf9008e42006-06-30 01:55:46 -07003677static int selinux_task_kill(struct task_struct *p, struct siginfo *info,
3678 int sig, u32 secid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003679{
3680 u32 perm;
3681 int rc;
3682
Linus Torvalds1da177e2005-04-16 15:20:36 -07003683 if (!sig)
3684 perm = PROCESS__SIGNULL; /* null signal; existence test */
3685 else
3686 perm = signal_to_av(sig);
David Quigleyf9008e42006-06-30 01:55:46 -07003687 if (secid)
David Howells275bb412008-11-14 10:39:19 +11003688 rc = avc_has_perm(secid, task_sid(p),
3689 SECCLASS_PROCESS, perm, NULL);
David Quigleyf9008e42006-06-30 01:55:46 -07003690 else
David Howells3b11a1d2008-11-14 10:39:26 +11003691 rc = current_has_perm(p, perm);
David Quigleyf9008e42006-06-30 01:55:46 -07003692 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003693}
3694
Linus Torvalds1da177e2005-04-16 15:20:36 -07003695static int selinux_task_wait(struct task_struct *p)
3696{
Eric Paris8a535142007-10-22 16:10:31 -04003697 return task_has_perm(p, current, PROCESS__SIGCHLD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003698}
3699
Linus Torvalds1da177e2005-04-16 15:20:36 -07003700static void selinux_task_to_inode(struct task_struct *p,
3701 struct inode *inode)
3702{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003703 struct inode_security_struct *isec = inode->i_security;
David Howells275bb412008-11-14 10:39:19 +11003704 u32 sid = task_sid(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003705
David Howells275bb412008-11-14 10:39:19 +11003706 isec->sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003707 isec->initialized = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003708}
3709
Linus Torvalds1da177e2005-04-16 15:20:36 -07003710/* Returns error only if unable to parse addresses */
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003711static int selinux_parse_skb_ipv4(struct sk_buff *skb,
Thomas Liu2bf49692009-07-14 12:14:09 -04003712 struct common_audit_data *ad, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003713{
3714 int offset, ihlen, ret = -EINVAL;
3715 struct iphdr _iph, *ih;
3716
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03003717 offset = skb_network_offset(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003718 ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph);
3719 if (ih == NULL)
3720 goto out;
3721
3722 ihlen = ih->ihl * 4;
3723 if (ihlen < sizeof(_iph))
3724 goto out;
3725
Eric Paris48c62af2012-04-02 13:15:44 -04003726 ad->u.net->v4info.saddr = ih->saddr;
3727 ad->u.net->v4info.daddr = ih->daddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003728 ret = 0;
3729
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003730 if (proto)
3731 *proto = ih->protocol;
3732
Linus Torvalds1da177e2005-04-16 15:20:36 -07003733 switch (ih->protocol) {
Eric Paris828dfe12008-04-17 13:17:49 -04003734 case IPPROTO_TCP: {
3735 struct tcphdr _tcph, *th;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003736
Eric Paris828dfe12008-04-17 13:17:49 -04003737 if (ntohs(ih->frag_off) & IP_OFFSET)
3738 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003739
3740 offset += ihlen;
3741 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
3742 if (th == NULL)
3743 break;
3744
Eric Paris48c62af2012-04-02 13:15:44 -04003745 ad->u.net->sport = th->source;
3746 ad->u.net->dport = th->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003747 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003748 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003749
Eric Paris828dfe12008-04-17 13:17:49 -04003750 case IPPROTO_UDP: {
3751 struct udphdr _udph, *uh;
3752
3753 if (ntohs(ih->frag_off) & IP_OFFSET)
3754 break;
3755
3756 offset += ihlen;
3757 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
3758 if (uh == NULL)
3759 break;
3760
Eric Paris48c62af2012-04-02 13:15:44 -04003761 ad->u.net->sport = uh->source;
3762 ad->u.net->dport = uh->dest;
Eric Paris828dfe12008-04-17 13:17:49 -04003763 break;
3764 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003765
James Morris2ee92d42006-11-13 16:09:01 -08003766 case IPPROTO_DCCP: {
3767 struct dccp_hdr _dccph, *dh;
3768
3769 if (ntohs(ih->frag_off) & IP_OFFSET)
3770 break;
3771
3772 offset += ihlen;
3773 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
3774 if (dh == NULL)
3775 break;
3776
Eric Paris48c62af2012-04-02 13:15:44 -04003777 ad->u.net->sport = dh->dccph_sport;
3778 ad->u.net->dport = dh->dccph_dport;
James Morris2ee92d42006-11-13 16:09:01 -08003779 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003780 }
James Morris2ee92d42006-11-13 16:09:01 -08003781
Eric Paris828dfe12008-04-17 13:17:49 -04003782 default:
3783 break;
3784 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003785out:
3786 return ret;
3787}
3788
3789#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
3790
3791/* Returns error only if unable to parse addresses */
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003792static int selinux_parse_skb_ipv6(struct sk_buff *skb,
Thomas Liu2bf49692009-07-14 12:14:09 -04003793 struct common_audit_data *ad, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003794{
3795 u8 nexthdr;
3796 int ret = -EINVAL, offset;
3797 struct ipv6hdr _ipv6h, *ip6;
Jesse Gross75f28112011-11-30 17:05:51 -08003798 __be16 frag_off;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003799
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03003800 offset = skb_network_offset(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003801 ip6 = skb_header_pointer(skb, offset, sizeof(_ipv6h), &_ipv6h);
3802 if (ip6 == NULL)
3803 goto out;
3804
Eric Paris48c62af2012-04-02 13:15:44 -04003805 ad->u.net->v6info.saddr = ip6->saddr;
3806 ad->u.net->v6info.daddr = ip6->daddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003807 ret = 0;
3808
3809 nexthdr = ip6->nexthdr;
3810 offset += sizeof(_ipv6h);
Jesse Gross75f28112011-11-30 17:05:51 -08003811 offset = ipv6_skip_exthdr(skb, offset, &nexthdr, &frag_off);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003812 if (offset < 0)
3813 goto out;
3814
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003815 if (proto)
3816 *proto = nexthdr;
3817
Linus Torvalds1da177e2005-04-16 15:20:36 -07003818 switch (nexthdr) {
3819 case IPPROTO_TCP: {
Eric Paris828dfe12008-04-17 13:17:49 -04003820 struct tcphdr _tcph, *th;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003821
3822 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
3823 if (th == NULL)
3824 break;
3825
Eric Paris48c62af2012-04-02 13:15:44 -04003826 ad->u.net->sport = th->source;
3827 ad->u.net->dport = th->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003828 break;
3829 }
3830
3831 case IPPROTO_UDP: {
3832 struct udphdr _udph, *uh;
3833
3834 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
3835 if (uh == NULL)
3836 break;
3837
Eric Paris48c62af2012-04-02 13:15:44 -04003838 ad->u.net->sport = uh->source;
3839 ad->u.net->dport = uh->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003840 break;
3841 }
3842
James Morris2ee92d42006-11-13 16:09:01 -08003843 case IPPROTO_DCCP: {
3844 struct dccp_hdr _dccph, *dh;
3845
3846 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
3847 if (dh == NULL)
3848 break;
3849
Eric Paris48c62af2012-04-02 13:15:44 -04003850 ad->u.net->sport = dh->dccph_sport;
3851 ad->u.net->dport = dh->dccph_dport;
James Morris2ee92d42006-11-13 16:09:01 -08003852 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003853 }
James Morris2ee92d42006-11-13 16:09:01 -08003854
Linus Torvalds1da177e2005-04-16 15:20:36 -07003855 /* includes fragments */
3856 default:
3857 break;
3858 }
3859out:
3860 return ret;
3861}
3862
3863#endif /* IPV6 */
3864
Thomas Liu2bf49692009-07-14 12:14:09 -04003865static int selinux_parse_skb(struct sk_buff *skb, struct common_audit_data *ad,
David Howellscf9481e2008-07-27 21:31:07 +10003866 char **_addrp, int src, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003867{
David Howellscf9481e2008-07-27 21:31:07 +10003868 char *addrp;
3869 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003870
Eric Paris48c62af2012-04-02 13:15:44 -04003871 switch (ad->u.net->family) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003872 case PF_INET:
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003873 ret = selinux_parse_skb_ipv4(skb, ad, proto);
David Howellscf9481e2008-07-27 21:31:07 +10003874 if (ret)
3875 goto parse_error;
Eric Paris48c62af2012-04-02 13:15:44 -04003876 addrp = (char *)(src ? &ad->u.net->v4info.saddr :
3877 &ad->u.net->v4info.daddr);
David Howellscf9481e2008-07-27 21:31:07 +10003878 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003879
3880#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
3881 case PF_INET6:
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003882 ret = selinux_parse_skb_ipv6(skb, ad, proto);
David Howellscf9481e2008-07-27 21:31:07 +10003883 if (ret)
3884 goto parse_error;
Eric Paris48c62af2012-04-02 13:15:44 -04003885 addrp = (char *)(src ? &ad->u.net->v6info.saddr :
3886 &ad->u.net->v6info.daddr);
David Howellscf9481e2008-07-27 21:31:07 +10003887 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003888#endif /* IPV6 */
3889 default:
David Howellscf9481e2008-07-27 21:31:07 +10003890 addrp = NULL;
3891 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003892 }
3893
David Howellscf9481e2008-07-27 21:31:07 +10003894parse_error:
3895 printk(KERN_WARNING
3896 "SELinux: failure in selinux_parse_skb(),"
3897 " unable to parse packet\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003898 return ret;
David Howellscf9481e2008-07-27 21:31:07 +10003899
3900okay:
3901 if (_addrp)
3902 *_addrp = addrp;
3903 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003904}
3905
Paul Moore4f6a9932007-03-01 14:35:22 -05003906/**
Paul Moore220deb92008-01-29 08:38:23 -05003907 * selinux_skb_peerlbl_sid - Determine the peer label of a packet
Paul Moore4f6a9932007-03-01 14:35:22 -05003908 * @skb: the packet
Paul Moore75e22912008-01-29 08:38:04 -05003909 * @family: protocol family
Paul Moore220deb92008-01-29 08:38:23 -05003910 * @sid: the packet's peer label SID
Paul Moore4f6a9932007-03-01 14:35:22 -05003911 *
3912 * Description:
Paul Moore220deb92008-01-29 08:38:23 -05003913 * Check the various different forms of network peer labeling and determine
3914 * the peer label/SID for the packet; most of the magic actually occurs in
3915 * the security server function security_net_peersid_cmp(). The function
3916 * returns zero if the value in @sid is valid (although it may be SECSID_NULL)
3917 * or -EACCES if @sid is invalid due to inconsistencies with the different
3918 * peer labels.
Paul Moore4f6a9932007-03-01 14:35:22 -05003919 *
3920 */
Paul Moore220deb92008-01-29 08:38:23 -05003921static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)
Paul Moore4f6a9932007-03-01 14:35:22 -05003922{
Paul Moore71f1cb02008-01-29 08:51:16 -05003923 int err;
Paul Moore4f6a9932007-03-01 14:35:22 -05003924 u32 xfrm_sid;
3925 u32 nlbl_sid;
Paul Moore220deb92008-01-29 08:38:23 -05003926 u32 nlbl_type;
Paul Moore4f6a9932007-03-01 14:35:22 -05003927
Paul Moore817eff72013-12-10 14:57:54 -05003928 err = selinux_xfrm_skb_sid(skb, &xfrm_sid);
Paul Moorebed4d7e2013-07-23 17:38:40 -04003929 if (unlikely(err))
3930 return -EACCES;
3931 err = selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid);
3932 if (unlikely(err))
3933 return -EACCES;
Paul Moore220deb92008-01-29 08:38:23 -05003934
Paul Moore71f1cb02008-01-29 08:51:16 -05003935 err = security_net_peersid_resolve(nlbl_sid, nlbl_type, xfrm_sid, sid);
3936 if (unlikely(err)) {
3937 printk(KERN_WARNING
3938 "SELinux: failure in selinux_skb_peerlbl_sid(),"
3939 " unable to determine packet's peer label\n");
Paul Moore220deb92008-01-29 08:38:23 -05003940 return -EACCES;
Paul Moore71f1cb02008-01-29 08:51:16 -05003941 }
Paul Moore220deb92008-01-29 08:38:23 -05003942
3943 return 0;
Paul Moore4f6a9932007-03-01 14:35:22 -05003944}
3945
Paul Moore446b8022013-12-04 16:10:51 -05003946/**
3947 * selinux_conn_sid - Determine the child socket label for a connection
3948 * @sk_sid: the parent socket's SID
3949 * @skb_sid: the packet's SID
3950 * @conn_sid: the resulting connection SID
3951 *
3952 * If @skb_sid is valid then the user:role:type information from @sk_sid is
3953 * combined with the MLS information from @skb_sid in order to create
3954 * @conn_sid. If @skb_sid is not valid then then @conn_sid is simply a copy
3955 * of @sk_sid. Returns zero on success, negative values on failure.
3956 *
3957 */
3958static int selinux_conn_sid(u32 sk_sid, u32 skb_sid, u32 *conn_sid)
3959{
3960 int err = 0;
3961
3962 if (skb_sid != SECSID_NULL)
3963 err = security_sid_mls_copy(sk_sid, skb_sid, conn_sid);
3964 else
3965 *conn_sid = sk_sid;
3966
3967 return err;
3968}
3969
Linus Torvalds1da177e2005-04-16 15:20:36 -07003970/* socket security operations */
Paul Moored4f2d972010-04-22 14:46:18 -04003971
Harry Ciao2ad18bd2011-03-02 13:32:34 +08003972static int socket_sockcreate_sid(const struct task_security_struct *tsec,
3973 u16 secclass, u32 *socksid)
Paul Moored4f2d972010-04-22 14:46:18 -04003974{
Harry Ciao2ad18bd2011-03-02 13:32:34 +08003975 if (tsec->sockcreate_sid > SECSID_NULL) {
3976 *socksid = tsec->sockcreate_sid;
3977 return 0;
3978 }
3979
3980 return security_transition_sid(tsec->sid, tsec->sid, secclass, NULL,
3981 socksid);
Paul Moored4f2d972010-04-22 14:46:18 -04003982}
3983
Paul Moore253bfae2010-04-22 14:46:19 -04003984static int sock_has_perm(struct task_struct *task, struct sock *sk, u32 perms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003985{
Paul Moore253bfae2010-04-22 14:46:19 -04003986 struct sk_security_struct *sksec = sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04003987 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04003988 struct lsm_network_audit net = {0,};
Paul Moore253bfae2010-04-22 14:46:19 -04003989 u32 tsid = task_sid(task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003990
Paul Moore253bfae2010-04-22 14:46:19 -04003991 if (sksec->sid == SECINITSID_KERNEL)
3992 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003993
Eric Paris50c205f2012-04-04 15:01:43 -04003994 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04003995 ad.u.net = &net;
3996 ad.u.net->sk = sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003997
Paul Moore253bfae2010-04-22 14:46:19 -04003998 return avc_has_perm(tsid, sksec->sid, sksec->sclass, perms, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003999}
4000
4001static int selinux_socket_create(int family, int type,
4002 int protocol, int kern)
4003{
Paul Moore5fb49872010-04-22 14:46:19 -04004004 const struct task_security_struct *tsec = current_security();
Paul Moored4f2d972010-04-22 14:46:18 -04004005 u32 newsid;
David Howells275bb412008-11-14 10:39:19 +11004006 u16 secclass;
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004007 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004008
4009 if (kern)
Paul Moored4f2d972010-04-22 14:46:18 -04004010 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004011
David Howells275bb412008-11-14 10:39:19 +11004012 secclass = socket_type_to_security_class(family, type, protocol);
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004013 rc = socket_sockcreate_sid(tsec, secclass, &newsid);
4014 if (rc)
4015 return rc;
4016
Paul Moored4f2d972010-04-22 14:46:18 -04004017 return avc_has_perm(tsec->sid, newsid, secclass, SOCKET__CREATE, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004018}
4019
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07004020static int selinux_socket_post_create(struct socket *sock, int family,
4021 int type, int protocol, int kern)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004022{
Paul Moore5fb49872010-04-22 14:46:19 -04004023 const struct task_security_struct *tsec = current_security();
Paul Moored4f2d972010-04-22 14:46:18 -04004024 struct inode_security_struct *isec = SOCK_INODE(sock)->i_security;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004025 struct sk_security_struct *sksec;
David Howells275bb412008-11-14 10:39:19 +11004026 int err = 0;
4027
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004028 isec->sclass = socket_type_to_security_class(family, type, protocol);
4029
David Howells275bb412008-11-14 10:39:19 +11004030 if (kern)
4031 isec->sid = SECINITSID_KERNEL;
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004032 else {
4033 err = socket_sockcreate_sid(tsec, isec->sclass, &(isec->sid));
4034 if (err)
4035 return err;
4036 }
David Howells275bb412008-11-14 10:39:19 +11004037
Linus Torvalds1da177e2005-04-16 15:20:36 -07004038 isec->initialized = 1;
4039
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004040 if (sock->sk) {
4041 sksec = sock->sk->sk_security;
4042 sksec->sid = isec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05004043 sksec->sclass = isec->sclass;
Paul Moore389fb8002009-03-27 17:10:34 -04004044 err = selinux_netlbl_socket_post_create(sock->sk, family);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004045 }
4046
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07004047 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004048}
4049
4050/* Range of port numbers used to automatically bind.
4051 Need to determine whether we should perform a name_bind
4052 permission check between the socket and the port number. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004053
4054static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen)
4055{
Paul Moore253bfae2010-04-22 14:46:19 -04004056 struct sock *sk = sock->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004057 u16 family;
4058 int err;
4059
Paul Moore253bfae2010-04-22 14:46:19 -04004060 err = sock_has_perm(current, sk, SOCKET__BIND);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004061 if (err)
4062 goto out;
4063
4064 /*
4065 * If PF_INET or PF_INET6, check name_bind permission for the port.
James Morris13402582005-09-30 14:24:34 -04004066 * Multiple address binding for SCTP is not supported yet: we just
4067 * check the first address now.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004068 */
Paul Moore253bfae2010-04-22 14:46:19 -04004069 family = sk->sk_family;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004070 if (family == PF_INET || family == PF_INET6) {
4071 char *addrp;
Paul Moore253bfae2010-04-22 14:46:19 -04004072 struct sk_security_struct *sksec = sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004073 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004074 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004075 struct sockaddr_in *addr4 = NULL;
4076 struct sockaddr_in6 *addr6 = NULL;
4077 unsigned short snum;
James Morrise399f982008-06-12 01:39:58 +10004078 u32 sid, node_perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004079
Linus Torvalds1da177e2005-04-16 15:20:36 -07004080 if (family == PF_INET) {
4081 addr4 = (struct sockaddr_in *)address;
4082 snum = ntohs(addr4->sin_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004083 addrp = (char *)&addr4->sin_addr.s_addr;
4084 } else {
4085 addr6 = (struct sockaddr_in6 *)address;
4086 snum = ntohs(addr6->sin6_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004087 addrp = (char *)&addr6->sin6_addr.s6_addr;
4088 }
4089
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004090 if (snum) {
4091 int low, high;
4092
Eric W. Biederman0bbf87d2013-09-28 14:10:59 -07004093 inet_get_local_port_range(sock_net(sk), &low, &high);
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004094
4095 if (snum < max(PROT_SOCK, low) || snum > high) {
Paul Moore3e112172008-04-10 10:48:14 -04004096 err = sel_netport_sid(sk->sk_protocol,
4097 snum, &sid);
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004098 if (err)
4099 goto out;
Eric Paris50c205f2012-04-04 15:01:43 -04004100 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004101 ad.u.net = &net;
4102 ad.u.net->sport = htons(snum);
4103 ad.u.net->family = family;
Paul Moore253bfae2010-04-22 14:46:19 -04004104 err = avc_has_perm(sksec->sid, sid,
4105 sksec->sclass,
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004106 SOCKET__NAME_BIND, &ad);
4107 if (err)
4108 goto out;
4109 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004110 }
Eric Paris828dfe12008-04-17 13:17:49 -04004111
Paul Moore253bfae2010-04-22 14:46:19 -04004112 switch (sksec->sclass) {
James Morris13402582005-09-30 14:24:34 -04004113 case SECCLASS_TCP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004114 node_perm = TCP_SOCKET__NODE_BIND;
4115 break;
Eric Paris828dfe12008-04-17 13:17:49 -04004116
James Morris13402582005-09-30 14:24:34 -04004117 case SECCLASS_UDP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004118 node_perm = UDP_SOCKET__NODE_BIND;
4119 break;
James Morris2ee92d42006-11-13 16:09:01 -08004120
4121 case SECCLASS_DCCP_SOCKET:
4122 node_perm = DCCP_SOCKET__NODE_BIND;
4123 break;
4124
Linus Torvalds1da177e2005-04-16 15:20:36 -07004125 default:
4126 node_perm = RAWIP_SOCKET__NODE_BIND;
4127 break;
4128 }
Eric Paris828dfe12008-04-17 13:17:49 -04004129
Paul Moore224dfbd2008-01-29 08:38:13 -05004130 err = sel_netnode_sid(addrp, family, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004131 if (err)
4132 goto out;
Eric Paris828dfe12008-04-17 13:17:49 -04004133
Eric Paris50c205f2012-04-04 15:01:43 -04004134 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004135 ad.u.net = &net;
4136 ad.u.net->sport = htons(snum);
4137 ad.u.net->family = family;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004138
4139 if (family == PF_INET)
Eric Paris48c62af2012-04-02 13:15:44 -04004140 ad.u.net->v4info.saddr = addr4->sin_addr.s_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004141 else
Eric Paris48c62af2012-04-02 13:15:44 -04004142 ad.u.net->v6info.saddr = addr6->sin6_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004143
Paul Moore253bfae2010-04-22 14:46:19 -04004144 err = avc_has_perm(sksec->sid, sid,
4145 sksec->sclass, node_perm, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004146 if (err)
4147 goto out;
4148 }
4149out:
4150 return err;
4151}
4152
4153static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen)
4154{
Paul Moore014ab192008-10-10 10:16:33 -04004155 struct sock *sk = sock->sk;
Paul Moore253bfae2010-04-22 14:46:19 -04004156 struct sk_security_struct *sksec = sk->sk_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004157 int err;
4158
Paul Moore253bfae2010-04-22 14:46:19 -04004159 err = sock_has_perm(current, sk, SOCKET__CONNECT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004160 if (err)
4161 return err;
4162
4163 /*
James Morris2ee92d42006-11-13 16:09:01 -08004164 * If a TCP or DCCP socket, check name_connect permission for the port.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004165 */
Paul Moore253bfae2010-04-22 14:46:19 -04004166 if (sksec->sclass == SECCLASS_TCP_SOCKET ||
4167 sksec->sclass == SECCLASS_DCCP_SOCKET) {
Thomas Liu2bf49692009-07-14 12:14:09 -04004168 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004169 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004170 struct sockaddr_in *addr4 = NULL;
4171 struct sockaddr_in6 *addr6 = NULL;
4172 unsigned short snum;
James Morris2ee92d42006-11-13 16:09:01 -08004173 u32 sid, perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004174
4175 if (sk->sk_family == PF_INET) {
4176 addr4 = (struct sockaddr_in *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07004177 if (addrlen < sizeof(struct sockaddr_in))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004178 return -EINVAL;
4179 snum = ntohs(addr4->sin_port);
4180 } else {
4181 addr6 = (struct sockaddr_in6 *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07004182 if (addrlen < SIN6_LEN_RFC2133)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004183 return -EINVAL;
4184 snum = ntohs(addr6->sin6_port);
4185 }
4186
Paul Moore3e112172008-04-10 10:48:14 -04004187 err = sel_netport_sid(sk->sk_protocol, snum, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004188 if (err)
4189 goto out;
4190
Paul Moore253bfae2010-04-22 14:46:19 -04004191 perm = (sksec->sclass == SECCLASS_TCP_SOCKET) ?
James Morris2ee92d42006-11-13 16:09:01 -08004192 TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT;
4193
Eric Paris50c205f2012-04-04 15:01:43 -04004194 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004195 ad.u.net = &net;
4196 ad.u.net->dport = htons(snum);
4197 ad.u.net->family = sk->sk_family;
Paul Moore253bfae2010-04-22 14:46:19 -04004198 err = avc_has_perm(sksec->sid, sid, sksec->sclass, perm, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004199 if (err)
4200 goto out;
4201 }
4202
Paul Moore014ab192008-10-10 10:16:33 -04004203 err = selinux_netlbl_socket_connect(sk, address);
4204
Linus Torvalds1da177e2005-04-16 15:20:36 -07004205out:
4206 return err;
4207}
4208
4209static int selinux_socket_listen(struct socket *sock, int backlog)
4210{
Paul Moore253bfae2010-04-22 14:46:19 -04004211 return sock_has_perm(current, sock->sk, SOCKET__LISTEN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004212}
4213
4214static int selinux_socket_accept(struct socket *sock, struct socket *newsock)
4215{
4216 int err;
4217 struct inode_security_struct *isec;
4218 struct inode_security_struct *newisec;
4219
Paul Moore253bfae2010-04-22 14:46:19 -04004220 err = sock_has_perm(current, sock->sk, SOCKET__ACCEPT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004221 if (err)
4222 return err;
4223
4224 newisec = SOCK_INODE(newsock)->i_security;
4225
4226 isec = SOCK_INODE(sock)->i_security;
4227 newisec->sclass = isec->sclass;
4228 newisec->sid = isec->sid;
4229 newisec->initialized = 1;
4230
4231 return 0;
4232}
4233
4234static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg,
Eric Paris828dfe12008-04-17 13:17:49 -04004235 int size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004236{
Paul Moore253bfae2010-04-22 14:46:19 -04004237 return sock_has_perm(current, sock->sk, SOCKET__WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004238}
4239
4240static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg,
4241 int size, int flags)
4242{
Paul Moore253bfae2010-04-22 14:46:19 -04004243 return sock_has_perm(current, sock->sk, SOCKET__READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004244}
4245
4246static int selinux_socket_getsockname(struct socket *sock)
4247{
Paul Moore253bfae2010-04-22 14:46:19 -04004248 return sock_has_perm(current, sock->sk, SOCKET__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004249}
4250
4251static int selinux_socket_getpeername(struct socket *sock)
4252{
Paul Moore253bfae2010-04-22 14:46:19 -04004253 return sock_has_perm(current, sock->sk, SOCKET__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004254}
4255
Eric Paris828dfe12008-04-17 13:17:49 -04004256static int selinux_socket_setsockopt(struct socket *sock, int level, int optname)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004257{
Paul Mooref8687af2006-10-30 15:22:15 -08004258 int err;
4259
Paul Moore253bfae2010-04-22 14:46:19 -04004260 err = sock_has_perm(current, sock->sk, SOCKET__SETOPT);
Paul Mooref8687af2006-10-30 15:22:15 -08004261 if (err)
4262 return err;
4263
4264 return selinux_netlbl_socket_setsockopt(sock, level, optname);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004265}
4266
4267static int selinux_socket_getsockopt(struct socket *sock, int level,
4268 int optname)
4269{
Paul Moore253bfae2010-04-22 14:46:19 -04004270 return sock_has_perm(current, sock->sk, SOCKET__GETOPT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004271}
4272
4273static int selinux_socket_shutdown(struct socket *sock, int how)
4274{
Paul Moore253bfae2010-04-22 14:46:19 -04004275 return sock_has_perm(current, sock->sk, SOCKET__SHUTDOWN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004276}
4277
David S. Miller3610cda2011-01-05 15:38:53 -08004278static int selinux_socket_unix_stream_connect(struct sock *sock,
4279 struct sock *other,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004280 struct sock *newsk)
4281{
David S. Miller3610cda2011-01-05 15:38:53 -08004282 struct sk_security_struct *sksec_sock = sock->sk_security;
4283 struct sk_security_struct *sksec_other = other->sk_security;
Paul Moore4d1e2452010-04-22 14:46:18 -04004284 struct sk_security_struct *sksec_new = newsk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004285 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004286 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004287 int err;
4288
Eric Paris50c205f2012-04-04 15:01:43 -04004289 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004290 ad.u.net = &net;
4291 ad.u.net->sk = other;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004292
Paul Moore4d1e2452010-04-22 14:46:18 -04004293 err = avc_has_perm(sksec_sock->sid, sksec_other->sid,
4294 sksec_other->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004295 UNIX_STREAM_SOCKET__CONNECTTO, &ad);
4296 if (err)
4297 return err;
4298
Linus Torvalds1da177e2005-04-16 15:20:36 -07004299 /* server child socket */
Paul Moore4d1e2452010-04-22 14:46:18 -04004300 sksec_new->peer_sid = sksec_sock->sid;
4301 err = security_sid_mls_copy(sksec_other->sid, sksec_sock->sid,
4302 &sksec_new->sid);
4303 if (err)
4304 return err;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004305
Paul Moore4d1e2452010-04-22 14:46:18 -04004306 /* connecting socket */
4307 sksec_sock->peer_sid = sksec_new->sid;
4308
4309 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004310}
4311
4312static int selinux_socket_unix_may_send(struct socket *sock,
4313 struct socket *other)
4314{
Paul Moore253bfae2010-04-22 14:46:19 -04004315 struct sk_security_struct *ssec = sock->sk->sk_security;
4316 struct sk_security_struct *osec = other->sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004317 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004318 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004319
Eric Paris50c205f2012-04-04 15:01:43 -04004320 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004321 ad.u.net = &net;
4322 ad.u.net->sk = other->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004323
Paul Moore253bfae2010-04-22 14:46:19 -04004324 return avc_has_perm(ssec->sid, osec->sid, osec->sclass, SOCKET__SENDTO,
4325 &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004326}
4327
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004328static int selinux_inet_sys_rcv_skb(struct net *ns, int ifindex,
4329 char *addrp, u16 family, u32 peer_sid,
Thomas Liu2bf49692009-07-14 12:14:09 -04004330 struct common_audit_data *ad)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004331{
4332 int err;
4333 u32 if_sid;
4334 u32 node_sid;
4335
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004336 err = sel_netif_sid(ns, ifindex, &if_sid);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004337 if (err)
4338 return err;
4339 err = avc_has_perm(peer_sid, if_sid,
4340 SECCLASS_NETIF, NETIF__INGRESS, ad);
4341 if (err)
4342 return err;
4343
4344 err = sel_netnode_sid(addrp, family, &node_sid);
4345 if (err)
4346 return err;
4347 return avc_has_perm(peer_sid, node_sid,
4348 SECCLASS_NODE, NODE__RECVFROM, ad);
4349}
4350
Paul Moore220deb92008-01-29 08:38:23 -05004351static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
Paul Moored8395c82008-10-10 10:16:30 -04004352 u16 family)
Paul Moore220deb92008-01-29 08:38:23 -05004353{
Paul Moore277d3422008-12-31 12:54:11 -05004354 int err = 0;
Paul Moore220deb92008-01-29 08:38:23 -05004355 struct sk_security_struct *sksec = sk->sk_security;
Paul Moore220deb92008-01-29 08:38:23 -05004356 u32 sk_sid = sksec->sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04004357 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004358 struct lsm_network_audit net = {0,};
Paul Moored8395c82008-10-10 10:16:30 -04004359 char *addrp;
4360
Eric Paris50c205f2012-04-04 15:01:43 -04004361 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004362 ad.u.net = &net;
4363 ad.u.net->netif = skb->skb_iif;
4364 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04004365 err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
4366 if (err)
4367 return err;
Paul Moore220deb92008-01-29 08:38:23 -05004368
Paul Moore58bfbb52009-03-27 17:10:41 -04004369 if (selinux_secmark_enabled()) {
Paul Moore220deb92008-01-29 08:38:23 -05004370 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
Paul Moored8395c82008-10-10 10:16:30 -04004371 PACKET__RECV, &ad);
Paul Moore58bfbb52009-03-27 17:10:41 -04004372 if (err)
4373 return err;
4374 }
Paul Moore220deb92008-01-29 08:38:23 -05004375
Steffen Klassertb9679a72011-02-23 12:55:21 +01004376 err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, &ad);
4377 if (err)
4378 return err;
4379 err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, &ad);
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004380
James Morris4e5ab4c2006-06-09 00:33:33 -07004381 return err;
4382}
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004383
James Morris4e5ab4c2006-06-09 00:33:33 -07004384static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
4385{
Paul Moore220deb92008-01-29 08:38:23 -05004386 int err;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004387 struct sk_security_struct *sksec = sk->sk_security;
Paul Moore220deb92008-01-29 08:38:23 -05004388 u16 family = sk->sk_family;
4389 u32 sk_sid = sksec->sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04004390 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004391 struct lsm_network_audit net = {0,};
Paul Moore220deb92008-01-29 08:38:23 -05004392 char *addrp;
Paul Moored8395c82008-10-10 10:16:30 -04004393 u8 secmark_active;
4394 u8 peerlbl_active;
James Morris4e5ab4c2006-06-09 00:33:33 -07004395
James Morris4e5ab4c2006-06-09 00:33:33 -07004396 if (family != PF_INET && family != PF_INET6)
Paul Moore220deb92008-01-29 08:38:23 -05004397 return 0;
James Morris4e5ab4c2006-06-09 00:33:33 -07004398
4399 /* Handle mapped IPv4 packets arriving via IPv6 sockets */
Al Viro87fcd702006-12-04 22:00:55 +00004400 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
James Morris4e5ab4c2006-06-09 00:33:33 -07004401 family = PF_INET;
4402
Paul Moored8395c82008-10-10 10:16:30 -04004403 /* If any sort of compatibility mode is enabled then handoff processing
4404 * to the selinux_sock_rcv_skb_compat() function to deal with the
4405 * special handling. We do this in an attempt to keep this function
4406 * as fast and as clean as possible. */
Paul Moore58bfbb52009-03-27 17:10:41 -04004407 if (!selinux_policycap_netpeer)
Paul Moored8395c82008-10-10 10:16:30 -04004408 return selinux_sock_rcv_skb_compat(sk, skb, family);
4409
4410 secmark_active = selinux_secmark_enabled();
Chris PeBenito2be4d742013-05-03 09:05:39 -04004411 peerlbl_active = selinux_peerlbl_enabled();
Paul Moored8395c82008-10-10 10:16:30 -04004412 if (!secmark_active && !peerlbl_active)
4413 return 0;
4414
Eric Paris50c205f2012-04-04 15:01:43 -04004415 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004416 ad.u.net = &net;
4417 ad.u.net->netif = skb->skb_iif;
4418 ad.u.net->family = family;
Paul Moore224dfbd2008-01-29 08:38:13 -05004419 err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
James Morris4e5ab4c2006-06-09 00:33:33 -07004420 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05004421 return err;
James Morris4e5ab4c2006-06-09 00:33:33 -07004422
Paul Moored8395c82008-10-10 10:16:30 -04004423 if (peerlbl_active) {
Paul Moored621d352008-01-29 08:43:36 -05004424 u32 peer_sid;
4425
4426 err = selinux_skb_peerlbl_sid(skb, family, &peer_sid);
4427 if (err)
4428 return err;
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004429 err = selinux_inet_sys_rcv_skb(sock_net(sk), skb->skb_iif,
4430 addrp, family, peer_sid, &ad);
Paul Mooredfaebe92008-10-10 10:16:31 -04004431 if (err) {
4432 selinux_netlbl_err(skb, err, 0);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004433 return err;
Paul Mooredfaebe92008-10-10 10:16:31 -04004434 }
Paul Moored621d352008-01-29 08:43:36 -05004435 err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER,
4436 PEER__RECV, &ad);
Chad Hanson46d01d62013-12-23 17:45:01 -05004437 if (err) {
Paul Mooredfaebe92008-10-10 10:16:31 -04004438 selinux_netlbl_err(skb, err, 0);
Chad Hanson46d01d62013-12-23 17:45:01 -05004439 return err;
4440 }
Paul Moored621d352008-01-29 08:43:36 -05004441 }
4442
Paul Moored8395c82008-10-10 10:16:30 -04004443 if (secmark_active) {
Paul Mooreeffad8d2008-01-29 08:49:27 -05004444 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
4445 PACKET__RECV, &ad);
4446 if (err)
4447 return err;
4448 }
4449
Paul Moored621d352008-01-29 08:43:36 -05004450 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004451}
4452
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004453static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *optval,
4454 int __user *optlen, unsigned len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004455{
4456 int err = 0;
4457 char *scontext;
4458 u32 scontext_len;
Paul Moore253bfae2010-04-22 14:46:19 -04004459 struct sk_security_struct *sksec = sock->sk->sk_security;
Paul Moore3de4bab2006-11-17 17:38:54 -05004460 u32 peer_sid = SECSID_NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004461
Paul Moore253bfae2010-04-22 14:46:19 -04004462 if (sksec->sclass == SECCLASS_UNIX_STREAM_SOCKET ||
4463 sksec->sclass == SECCLASS_TCP_SOCKET)
Eric Parisdd3e7832010-04-07 15:08:46 -04004464 peer_sid = sksec->peer_sid;
Paul Moore253bfae2010-04-22 14:46:19 -04004465 if (peer_sid == SECSID_NULL)
4466 return -ENOPROTOOPT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004467
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004468 err = security_sid_to_context(peer_sid, &scontext, &scontext_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004469 if (err)
Paul Moore253bfae2010-04-22 14:46:19 -04004470 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004471
4472 if (scontext_len > len) {
4473 err = -ERANGE;
4474 goto out_len;
4475 }
4476
4477 if (copy_to_user(optval, scontext, scontext_len))
4478 err = -EFAULT;
4479
4480out_len:
4481 if (put_user(scontext_len, optlen))
4482 err = -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004483 kfree(scontext);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004484 return err;
4485}
4486
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004487static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid)
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004488{
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004489 u32 peer_secid = SECSID_NULL;
Paul Moore75e22912008-01-29 08:38:04 -05004490 u16 family;
Catherine Zhang877ce7c2006-06-29 12:27:47 -07004491
Paul Mooreaa862902008-10-10 10:16:29 -04004492 if (skb && skb->protocol == htons(ETH_P_IP))
4493 family = PF_INET;
4494 else if (skb && skb->protocol == htons(ETH_P_IPV6))
4495 family = PF_INET6;
4496 else if (sock)
Paul Moore75e22912008-01-29 08:38:04 -05004497 family = sock->sk->sk_family;
Paul Moore75e22912008-01-29 08:38:04 -05004498 else
4499 goto out;
4500
4501 if (sock && family == PF_UNIX)
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02004502 selinux_inode_getsecid(SOCK_INODE(sock), &peer_secid);
Paul Moore3de4bab2006-11-17 17:38:54 -05004503 else if (skb)
Paul Moore220deb92008-01-29 08:38:23 -05004504 selinux_skb_peerlbl_sid(skb, family, &peer_secid);
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004505
Paul Moore75e22912008-01-29 08:38:04 -05004506out:
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004507 *secid = peer_secid;
Paul Moore75e22912008-01-29 08:38:04 -05004508 if (peer_secid == SECSID_NULL)
4509 return -EINVAL;
4510 return 0;
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004511}
4512
Al Viro7d877f32005-10-21 03:20:43 -04004513static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004514{
Paul Moore84914b72010-04-22 14:46:18 -04004515 struct sk_security_struct *sksec;
4516
4517 sksec = kzalloc(sizeof(*sksec), priority);
4518 if (!sksec)
4519 return -ENOMEM;
4520
4521 sksec->peer_sid = SECINITSID_UNLABELED;
4522 sksec->sid = SECINITSID_UNLABELED;
4523 selinux_netlbl_sk_security_reset(sksec);
4524 sk->sk_security = sksec;
4525
4526 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004527}
4528
4529static void selinux_sk_free_security(struct sock *sk)
4530{
Paul Moore84914b72010-04-22 14:46:18 -04004531 struct sk_security_struct *sksec = sk->sk_security;
4532
4533 sk->sk_security = NULL;
4534 selinux_netlbl_sk_security_free(sksec);
4535 kfree(sksec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004536}
4537
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004538static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk)
4539{
Eric Parisdd3e7832010-04-07 15:08:46 -04004540 struct sk_security_struct *sksec = sk->sk_security;
4541 struct sk_security_struct *newsksec = newsk->sk_security;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004542
Eric Parisdd3e7832010-04-07 15:08:46 -04004543 newsksec->sid = sksec->sid;
4544 newsksec->peer_sid = sksec->peer_sid;
4545 newsksec->sclass = sksec->sclass;
Paul Moore99f59ed2006-08-29 17:53:48 -07004546
Eric Parisdd3e7832010-04-07 15:08:46 -04004547 selinux_netlbl_sk_security_reset(newsksec);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004548}
4549
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004550static void selinux_sk_getsecid(struct sock *sk, u32 *secid)
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004551{
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004552 if (!sk)
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004553 *secid = SECINITSID_ANY_SOCKET;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004554 else {
4555 struct sk_security_struct *sksec = sk->sk_security;
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004556
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004557 *secid = sksec->sid;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004558 }
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004559}
4560
Eric Paris828dfe12008-04-17 13:17:49 -04004561static void selinux_sock_graft(struct sock *sk, struct socket *parent)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004562{
4563 struct inode_security_struct *isec = SOCK_INODE(parent)->i_security;
4564 struct sk_security_struct *sksec = sk->sk_security;
4565
Paul Moore2873ead2014-07-28 10:42:48 -04004566 if (sk->sk_family == PF_INET || sk->sk_family == PF_INET6 ||
4567 sk->sk_family == PF_UNIX)
David Woodhouse2148ccc2006-09-29 15:50:25 -07004568 isec->sid = sksec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05004569 sksec->sclass = isec->sclass;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004570}
4571
Adrian Bunk9a673e52006-08-15 00:03:53 -07004572static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
4573 struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004574{
4575 struct sk_security_struct *sksec = sk->sk_security;
4576 int err;
Paul Moore0b1f24e2013-12-03 11:39:13 -05004577 u16 family = req->rsk_ops->family;
Paul Moore446b8022013-12-04 16:10:51 -05004578 u32 connsid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004579 u32 peersid;
4580
Paul Mooreaa862902008-10-10 10:16:29 -04004581 err = selinux_skb_peerlbl_sid(skb, family, &peersid);
Paul Moore220deb92008-01-29 08:38:23 -05004582 if (err)
4583 return err;
Paul Moore446b8022013-12-04 16:10:51 -05004584 err = selinux_conn_sid(sksec->sid, peersid, &connsid);
4585 if (err)
4586 return err;
4587 req->secid = connsid;
4588 req->peer_secid = peersid;
Venkat Yekkiralaa51c64f2006-07-27 22:01:34 -07004589
Paul Moore389fb8002009-03-27 17:10:34 -04004590 return selinux_netlbl_inet_conn_request(req, family);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004591}
4592
Adrian Bunk9a673e52006-08-15 00:03:53 -07004593static void selinux_inet_csk_clone(struct sock *newsk,
4594 const struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004595{
4596 struct sk_security_struct *newsksec = newsk->sk_security;
4597
4598 newsksec->sid = req->secid;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004599 newsksec->peer_sid = req->peer_secid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004600 /* NOTE: Ideally, we should also get the isec->sid for the
4601 new socket in sync, but we don't have the isec available yet.
4602 So we will wait until sock_graft to do it, by which
4603 time it will have been created and available. */
Paul Moore99f59ed2006-08-29 17:53:48 -07004604
Paul Moore9f2ad662006-11-17 17:38:53 -05004605 /* We don't need to take any sort of lock here as we are the only
4606 * thread with access to newsksec */
Paul Moore389fb8002009-03-27 17:10:34 -04004607 selinux_netlbl_inet_csk_clone(newsk, req->rsk_ops->family);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004608}
4609
Paul Moore014ab192008-10-10 10:16:33 -04004610static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb)
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004611{
Paul Mooreaa862902008-10-10 10:16:29 -04004612 u16 family = sk->sk_family;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004613 struct sk_security_struct *sksec = sk->sk_security;
4614
Paul Mooreaa862902008-10-10 10:16:29 -04004615 /* handle mapped IPv4 packets arriving via IPv6 sockets */
4616 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
4617 family = PF_INET;
4618
4619 selinux_skb_peerlbl_sid(skb, family, &sksec->peer_sid);
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004620}
4621
Eric Paris2606fd12010-10-13 16:24:41 -04004622static int selinux_secmark_relabel_packet(u32 sid)
4623{
4624 const struct task_security_struct *__tsec;
4625 u32 tsid;
4626
4627 __tsec = current_security();
4628 tsid = __tsec->sid;
4629
4630 return avc_has_perm(tsid, sid, SECCLASS_PACKET, PACKET__RELABELTO, NULL);
4631}
4632
4633static void selinux_secmark_refcount_inc(void)
4634{
4635 atomic_inc(&selinux_secmark_refcount);
4636}
4637
4638static void selinux_secmark_refcount_dec(void)
4639{
4640 atomic_dec(&selinux_secmark_refcount);
4641}
4642
Adrian Bunk9a673e52006-08-15 00:03:53 -07004643static void selinux_req_classify_flow(const struct request_sock *req,
4644 struct flowi *fl)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004645{
David S. Miller1d28f422011-03-12 00:29:39 -05004646 fl->flowi_secid = req->secid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004647}
4648
Paul Moore5dbbaf22013-01-14 07:12:19 +00004649static int selinux_tun_dev_alloc_security(void **security)
4650{
4651 struct tun_security_struct *tunsec;
4652
4653 tunsec = kzalloc(sizeof(*tunsec), GFP_KERNEL);
4654 if (!tunsec)
4655 return -ENOMEM;
4656 tunsec->sid = current_sid();
4657
4658 *security = tunsec;
4659 return 0;
4660}
4661
4662static void selinux_tun_dev_free_security(void *security)
4663{
4664 kfree(security);
4665}
4666
Paul Mooreed6d76e2009-08-28 18:12:49 -04004667static int selinux_tun_dev_create(void)
4668{
4669 u32 sid = current_sid();
4670
4671 /* we aren't taking into account the "sockcreate" SID since the socket
4672 * that is being created here is not a socket in the traditional sense,
4673 * instead it is a private sock, accessible only to the kernel, and
4674 * representing a wide range of network traffic spanning multiple
4675 * connections unlike traditional sockets - check the TUN driver to
4676 * get a better understanding of why this socket is special */
4677
4678 return avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET, TUN_SOCKET__CREATE,
4679 NULL);
4680}
4681
Paul Moore5dbbaf22013-01-14 07:12:19 +00004682static int selinux_tun_dev_attach_queue(void *security)
Paul Mooreed6d76e2009-08-28 18:12:49 -04004683{
Paul Moore5dbbaf22013-01-14 07:12:19 +00004684 struct tun_security_struct *tunsec = security;
4685
4686 return avc_has_perm(current_sid(), tunsec->sid, SECCLASS_TUN_SOCKET,
4687 TUN_SOCKET__ATTACH_QUEUE, NULL);
4688}
4689
4690static int selinux_tun_dev_attach(struct sock *sk, void *security)
4691{
4692 struct tun_security_struct *tunsec = security;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004693 struct sk_security_struct *sksec = sk->sk_security;
4694
4695 /* we don't currently perform any NetLabel based labeling here and it
4696 * isn't clear that we would want to do so anyway; while we could apply
4697 * labeling without the support of the TUN user the resulting labeled
4698 * traffic from the other end of the connection would almost certainly
4699 * cause confusion to the TUN user that had no idea network labeling
4700 * protocols were being used */
4701
Paul Moore5dbbaf22013-01-14 07:12:19 +00004702 sksec->sid = tunsec->sid;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004703 sksec->sclass = SECCLASS_TUN_SOCKET;
Paul Moore5dbbaf22013-01-14 07:12:19 +00004704
4705 return 0;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004706}
4707
Paul Moore5dbbaf22013-01-14 07:12:19 +00004708static int selinux_tun_dev_open(void *security)
Paul Mooreed6d76e2009-08-28 18:12:49 -04004709{
Paul Moore5dbbaf22013-01-14 07:12:19 +00004710 struct tun_security_struct *tunsec = security;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004711 u32 sid = current_sid();
4712 int err;
4713
Paul Moore5dbbaf22013-01-14 07:12:19 +00004714 err = avc_has_perm(sid, tunsec->sid, SECCLASS_TUN_SOCKET,
Paul Mooreed6d76e2009-08-28 18:12:49 -04004715 TUN_SOCKET__RELABELFROM, NULL);
4716 if (err)
4717 return err;
4718 err = avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET,
4719 TUN_SOCKET__RELABELTO, NULL);
4720 if (err)
4721 return err;
Paul Moore5dbbaf22013-01-14 07:12:19 +00004722 tunsec->sid = sid;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004723
4724 return 0;
4725}
4726
Linus Torvalds1da177e2005-04-16 15:20:36 -07004727static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
4728{
4729 int err = 0;
4730 u32 perm;
4731 struct nlmsghdr *nlh;
Paul Moore253bfae2010-04-22 14:46:19 -04004732 struct sk_security_struct *sksec = sk->sk_security;
Eric Paris828dfe12008-04-17 13:17:49 -04004733
Hong zhi guo77954982013-03-27 06:49:35 +00004734 if (skb->len < NLMSG_HDRLEN) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004735 err = -EINVAL;
4736 goto out;
4737 }
Arnaldo Carvalho de Melob529ccf2007-04-25 19:08:35 -07004738 nlh = nlmsg_hdr(skb);
Eric Paris828dfe12008-04-17 13:17:49 -04004739
Paul Moore253bfae2010-04-22 14:46:19 -04004740 err = selinux_nlmsg_lookup(sksec->sclass, nlh->nlmsg_type, &perm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004741 if (err) {
4742 if (err == -EINVAL) {
Richard Guy Briggsd950f842014-11-12 14:01:34 -05004743 printk(KERN_WARNING
4744 "SELinux: unrecognized netlink message:"
Marek Milkoviccded3ff2015-06-04 16:22:16 -04004745 " protocol=%hu nlmsg_type=%hu sclass=%s\n",
4746 sk->sk_protocol, nlh->nlmsg_type,
4747 secclass_map[sksec->sclass - 1].name);
Eric Paris39c9aed2008-11-05 09:34:42 -05004748 if (!selinux_enforcing || security_get_allow_unknown())
Linus Torvalds1da177e2005-04-16 15:20:36 -07004749 err = 0;
4750 }
4751
4752 /* Ignore */
4753 if (err == -ENOENT)
4754 err = 0;
4755 goto out;
4756 }
4757
Paul Moore253bfae2010-04-22 14:46:19 -04004758 err = sock_has_perm(current, sk, perm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004759out:
4760 return err;
4761}
4762
4763#ifdef CONFIG_NETFILTER
4764
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004765static unsigned int selinux_ip_forward(struct sk_buff *skb,
4766 const struct net_device *indev,
Paul Mooreeffad8d2008-01-29 08:49:27 -05004767 u16 family)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004768{
Paul Mooredfaebe92008-10-10 10:16:31 -04004769 int err;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004770 char *addrp;
4771 u32 peer_sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04004772 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004773 struct lsm_network_audit net = {0,};
Paul Mooreeffad8d2008-01-29 08:49:27 -05004774 u8 secmark_active;
Paul Moore948bf852008-10-10 10:16:32 -04004775 u8 netlbl_active;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004776 u8 peerlbl_active;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004777
Paul Mooreeffad8d2008-01-29 08:49:27 -05004778 if (!selinux_policycap_netpeer)
4779 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004780
Paul Mooreeffad8d2008-01-29 08:49:27 -05004781 secmark_active = selinux_secmark_enabled();
Paul Moore948bf852008-10-10 10:16:32 -04004782 netlbl_active = netlbl_enabled();
Chris PeBenito2be4d742013-05-03 09:05:39 -04004783 peerlbl_active = selinux_peerlbl_enabled();
Paul Mooreeffad8d2008-01-29 08:49:27 -05004784 if (!secmark_active && !peerlbl_active)
4785 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004786
Paul Moored8395c82008-10-10 10:16:30 -04004787 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0)
4788 return NF_DROP;
4789
Eric Paris50c205f2012-04-04 15:01:43 -04004790 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004791 ad.u.net = &net;
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004792 ad.u.net->netif = indev->ifindex;
Eric Paris48c62af2012-04-02 13:15:44 -04004793 ad.u.net->family = family;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004794 if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0)
4795 return NF_DROP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004796
Paul Mooredfaebe92008-10-10 10:16:31 -04004797 if (peerlbl_active) {
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004798 err = selinux_inet_sys_rcv_skb(dev_net(indev), indev->ifindex,
4799 addrp, family, peer_sid, &ad);
Paul Mooredfaebe92008-10-10 10:16:31 -04004800 if (err) {
4801 selinux_netlbl_err(skb, err, 1);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004802 return NF_DROP;
Paul Mooredfaebe92008-10-10 10:16:31 -04004803 }
4804 }
Paul Mooreeffad8d2008-01-29 08:49:27 -05004805
4806 if (secmark_active)
4807 if (avc_has_perm(peer_sid, skb->secmark,
4808 SECCLASS_PACKET, PACKET__FORWARD_IN, &ad))
4809 return NF_DROP;
4810
Paul Moore948bf852008-10-10 10:16:32 -04004811 if (netlbl_active)
4812 /* we do this in the FORWARD path and not the POST_ROUTING
4813 * path because we want to make sure we apply the necessary
4814 * labeling before IPsec is applied so we can leverage AH
4815 * protection */
4816 if (selinux_netlbl_skbuff_setsid(skb, family, peer_sid) != 0)
4817 return NF_DROP;
4818
Paul Mooreeffad8d2008-01-29 08:49:27 -05004819 return NF_ACCEPT;
4820}
4821
Patrick McHardy795aa6e2013-10-10 09:21:55 +02004822static unsigned int selinux_ipv4_forward(const struct nf_hook_ops *ops,
Paul Mooreeffad8d2008-01-29 08:49:27 -05004823 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04004824 const struct nf_hook_state *state)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004825{
David S. Miller238e54c2015-04-03 20:32:56 -04004826 return selinux_ip_forward(skb, state->in, PF_INET);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004827}
4828
4829#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Patrick McHardy795aa6e2013-10-10 09:21:55 +02004830static unsigned int selinux_ipv6_forward(const struct nf_hook_ops *ops,
Paul Mooreeffad8d2008-01-29 08:49:27 -05004831 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04004832 const struct nf_hook_state *state)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004833{
David S. Miller238e54c2015-04-03 20:32:56 -04004834 return selinux_ip_forward(skb, state->in, PF_INET6);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004835}
4836#endif /* IPV6 */
4837
Paul Moore948bf852008-10-10 10:16:32 -04004838static unsigned int selinux_ip_output(struct sk_buff *skb,
4839 u16 family)
4840{
Paul Moore47180062013-12-04 16:10:45 -05004841 struct sock *sk;
Paul Moore948bf852008-10-10 10:16:32 -04004842 u32 sid;
4843
4844 if (!netlbl_enabled())
4845 return NF_ACCEPT;
4846
4847 /* we do this in the LOCAL_OUT path and not the POST_ROUTING path
4848 * because we want to make sure we apply the necessary labeling
4849 * before IPsec is applied so we can leverage AH protection */
Paul Moore47180062013-12-04 16:10:45 -05004850 sk = skb->sk;
4851 if (sk) {
4852 struct sk_security_struct *sksec;
4853
4854 if (sk->sk_state == TCP_LISTEN)
4855 /* if the socket is the listening state then this
4856 * packet is a SYN-ACK packet which means it needs to
4857 * be labeled based on the connection/request_sock and
4858 * not the parent socket. unfortunately, we can't
4859 * lookup the request_sock yet as it isn't queued on
4860 * the parent socket until after the SYN-ACK is sent.
4861 * the "solution" is to simply pass the packet as-is
4862 * as any IP option based labeling should be copied
4863 * from the initial connection request (in the IP
4864 * layer). it is far from ideal, but until we get a
4865 * security label in the packet itself this is the
4866 * best we can do. */
4867 return NF_ACCEPT;
4868
4869 /* standard practice, label using the parent socket */
4870 sksec = sk->sk_security;
Paul Moore948bf852008-10-10 10:16:32 -04004871 sid = sksec->sid;
4872 } else
4873 sid = SECINITSID_KERNEL;
4874 if (selinux_netlbl_skbuff_setsid(skb, family, sid) != 0)
4875 return NF_DROP;
4876
4877 return NF_ACCEPT;
4878}
4879
Patrick McHardy795aa6e2013-10-10 09:21:55 +02004880static unsigned int selinux_ipv4_output(const struct nf_hook_ops *ops,
Paul Moore948bf852008-10-10 10:16:32 -04004881 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04004882 const struct nf_hook_state *state)
Paul Moore948bf852008-10-10 10:16:32 -04004883{
4884 return selinux_ip_output(skb, PF_INET);
4885}
4886
Paul Mooreeffad8d2008-01-29 08:49:27 -05004887static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
4888 int ifindex,
Paul Moored8395c82008-10-10 10:16:30 -04004889 u16 family)
James Morris4e5ab4c2006-06-09 00:33:33 -07004890{
Paul Mooreeffad8d2008-01-29 08:49:27 -05004891 struct sock *sk = skb->sk;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004892 struct sk_security_struct *sksec;
Thomas Liu2bf49692009-07-14 12:14:09 -04004893 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004894 struct lsm_network_audit net = {0,};
Paul Moored8395c82008-10-10 10:16:30 -04004895 char *addrp;
4896 u8 proto;
James Morris4e5ab4c2006-06-09 00:33:33 -07004897
Paul Mooreeffad8d2008-01-29 08:49:27 -05004898 if (sk == NULL)
4899 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004900 sksec = sk->sk_security;
James Morris4e5ab4c2006-06-09 00:33:33 -07004901
Eric Paris50c205f2012-04-04 15:01:43 -04004902 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004903 ad.u.net = &net;
4904 ad.u.net->netif = ifindex;
4905 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04004906 if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto))
4907 return NF_DROP;
4908
Paul Moore58bfbb52009-03-27 17:10:41 -04004909 if (selinux_secmark_enabled())
Paul Mooreeffad8d2008-01-29 08:49:27 -05004910 if (avc_has_perm(sksec->sid, skb->secmark,
Paul Moored8395c82008-10-10 10:16:30 -04004911 SECCLASS_PACKET, PACKET__SEND, &ad))
Eric Paris2fe66ec2010-11-23 06:28:08 +00004912 return NF_DROP_ERR(-ECONNREFUSED);
James Morris4e5ab4c2006-06-09 00:33:33 -07004913
Steffen Klassertb9679a72011-02-23 12:55:21 +01004914 if (selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto))
4915 return NF_DROP_ERR(-ECONNREFUSED);
James Morris4e5ab4c2006-06-09 00:33:33 -07004916
Paul Mooreeffad8d2008-01-29 08:49:27 -05004917 return NF_ACCEPT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004918}
4919
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004920static unsigned int selinux_ip_postroute(struct sk_buff *skb,
4921 const struct net_device *outdev,
Paul Mooreeffad8d2008-01-29 08:49:27 -05004922 u16 family)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004923{
Paul Mooreeffad8d2008-01-29 08:49:27 -05004924 u32 secmark_perm;
4925 u32 peer_sid;
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004926 int ifindex = outdev->ifindex;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004927 struct sock *sk;
Thomas Liu2bf49692009-07-14 12:14:09 -04004928 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004929 struct lsm_network_audit net = {0,};
Paul Mooreeffad8d2008-01-29 08:49:27 -05004930 char *addrp;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004931 u8 secmark_active;
4932 u8 peerlbl_active;
4933
Paul Mooreeffad8d2008-01-29 08:49:27 -05004934 /* If any sort of compatibility mode is enabled then handoff processing
4935 * to the selinux_ip_postroute_compat() function to deal with the
4936 * special handling. We do this in an attempt to keep this function
4937 * as fast and as clean as possible. */
Paul Moore58bfbb52009-03-27 17:10:41 -04004938 if (!selinux_policycap_netpeer)
Paul Moored8395c82008-10-10 10:16:30 -04004939 return selinux_ip_postroute_compat(skb, ifindex, family);
Paul Moorec0828e52013-12-10 14:58:01 -05004940
Paul Mooreeffad8d2008-01-29 08:49:27 -05004941 secmark_active = selinux_secmark_enabled();
Chris PeBenito2be4d742013-05-03 09:05:39 -04004942 peerlbl_active = selinux_peerlbl_enabled();
Paul Mooreeffad8d2008-01-29 08:49:27 -05004943 if (!secmark_active && !peerlbl_active)
4944 return NF_ACCEPT;
4945
Paul Mooreeffad8d2008-01-29 08:49:27 -05004946 sk = skb->sk;
Paul Moorec0828e52013-12-10 14:58:01 -05004947
Paul Mooreeffad8d2008-01-29 08:49:27 -05004948#ifdef CONFIG_XFRM
4949 /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec
4950 * packet transformation so allow the packet to pass without any checks
4951 * since we'll have another chance to perform access control checks
4952 * when the packet is on it's final way out.
4953 * NOTE: there appear to be some IPv6 multicast cases where skb->dst
Paul Moorec0828e52013-12-10 14:58:01 -05004954 * is NULL, in this case go ahead and apply access control.
4955 * NOTE: if this is a local socket (skb->sk != NULL) that is in the
4956 * TCP listening state we cannot wait until the XFRM processing
4957 * is done as we will miss out on the SA label if we do;
4958 * unfortunately, this means more work, but it is only once per
4959 * connection. */
4960 if (skb_dst(skb) != NULL && skb_dst(skb)->xfrm != NULL &&
4961 !(sk != NULL && sk->sk_state == TCP_LISTEN))
Paul Mooreeffad8d2008-01-29 08:49:27 -05004962 return NF_ACCEPT;
4963#endif
Paul Mooreeffad8d2008-01-29 08:49:27 -05004964
Paul Moored8395c82008-10-10 10:16:30 -04004965 if (sk == NULL) {
Paul Moore446b8022013-12-04 16:10:51 -05004966 /* Without an associated socket the packet is either coming
4967 * from the kernel or it is being forwarded; check the packet
4968 * to determine which and if the packet is being forwarded
4969 * query the packet directly to determine the security label. */
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01004970 if (skb->skb_iif) {
4971 secmark_perm = PACKET__FORWARD_OUT;
Paul Moored8395c82008-10-10 10:16:30 -04004972 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00004973 return NF_DROP;
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01004974 } else {
4975 secmark_perm = PACKET__SEND;
Paul Moored8395c82008-10-10 10:16:30 -04004976 peer_sid = SECINITSID_KERNEL;
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01004977 }
Paul Moore446b8022013-12-04 16:10:51 -05004978 } else if (sk->sk_state == TCP_LISTEN) {
4979 /* Locally generated packet but the associated socket is in the
4980 * listening state which means this is a SYN-ACK packet. In
4981 * this particular case the correct security label is assigned
4982 * to the connection/request_sock but unfortunately we can't
4983 * query the request_sock as it isn't queued on the parent
4984 * socket until after the SYN-ACK packet is sent; the only
4985 * viable choice is to regenerate the label like we do in
4986 * selinux_inet_conn_request(). See also selinux_ip_output()
4987 * for similar problems. */
4988 u32 skb_sid;
4989 struct sk_security_struct *sksec = sk->sk_security;
4990 if (selinux_skb_peerlbl_sid(skb, family, &skb_sid))
4991 return NF_DROP;
Paul Moorec0828e52013-12-10 14:58:01 -05004992 /* At this point, if the returned skb peerlbl is SECSID_NULL
4993 * and the packet has been through at least one XFRM
4994 * transformation then we must be dealing with the "final"
4995 * form of labeled IPsec packet; since we've already applied
4996 * all of our access controls on this packet we can safely
4997 * pass the packet. */
4998 if (skb_sid == SECSID_NULL) {
4999 switch (family) {
5000 case PF_INET:
5001 if (IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED)
5002 return NF_ACCEPT;
5003 break;
5004 case PF_INET6:
5005 if (IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED)
5006 return NF_ACCEPT;
Paul Moorea7a91a12014-09-03 10:51:59 -04005007 break;
Paul Moorec0828e52013-12-10 14:58:01 -05005008 default:
5009 return NF_DROP_ERR(-ECONNREFUSED);
5010 }
5011 }
Paul Moore446b8022013-12-04 16:10:51 -05005012 if (selinux_conn_sid(sksec->sid, skb_sid, &peer_sid))
5013 return NF_DROP;
5014 secmark_perm = PACKET__SEND;
Paul Moored8395c82008-10-10 10:16:30 -04005015 } else {
Paul Moore446b8022013-12-04 16:10:51 -05005016 /* Locally generated packet, fetch the security label from the
5017 * associated socket. */
Paul Mooreeffad8d2008-01-29 08:49:27 -05005018 struct sk_security_struct *sksec = sk->sk_security;
5019 peer_sid = sksec->sid;
5020 secmark_perm = PACKET__SEND;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005021 }
5022
Eric Paris50c205f2012-04-04 15:01:43 -04005023 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04005024 ad.u.net = &net;
5025 ad.u.net->netif = ifindex;
5026 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04005027 if (selinux_parse_skb(skb, &ad, &addrp, 0, NULL))
Eric Paris04f6d702010-11-23 06:28:02 +00005028 return NF_DROP;
Paul Moored8395c82008-10-10 10:16:30 -04005029
Paul Mooreeffad8d2008-01-29 08:49:27 -05005030 if (secmark_active)
5031 if (avc_has_perm(peer_sid, skb->secmark,
5032 SECCLASS_PACKET, secmark_perm, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00005033 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005034
5035 if (peerlbl_active) {
5036 u32 if_sid;
5037 u32 node_sid;
5038
Paul Moorecbe0d6e2014-09-10 17:09:57 -04005039 if (sel_netif_sid(dev_net(outdev), ifindex, &if_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00005040 return NF_DROP;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005041 if (avc_has_perm(peer_sid, if_sid,
5042 SECCLASS_NETIF, NETIF__EGRESS, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00005043 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005044
5045 if (sel_netnode_sid(addrp, family, &node_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00005046 return NF_DROP;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005047 if (avc_has_perm(peer_sid, node_sid,
5048 SECCLASS_NODE, NODE__SENDTO, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00005049 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005050 }
5051
5052 return NF_ACCEPT;
5053}
5054
Patrick McHardy795aa6e2013-10-10 09:21:55 +02005055static unsigned int selinux_ipv4_postroute(const struct nf_hook_ops *ops,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005056 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04005057 const struct nf_hook_state *state)
Paul Mooreeffad8d2008-01-29 08:49:27 -05005058{
David S. Miller238e54c2015-04-03 20:32:56 -04005059 return selinux_ip_postroute(skb, state->out, PF_INET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005060}
5061
5062#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Patrick McHardy795aa6e2013-10-10 09:21:55 +02005063static unsigned int selinux_ipv6_postroute(const struct nf_hook_ops *ops,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005064 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04005065 const struct nf_hook_state *state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005066{
David S. Miller238e54c2015-04-03 20:32:56 -04005067 return selinux_ip_postroute(skb, state->out, PF_INET6);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005068}
Linus Torvalds1da177e2005-04-16 15:20:36 -07005069#endif /* IPV6 */
5070
5071#endif /* CONFIG_NETFILTER */
5072
Linus Torvalds1da177e2005-04-16 15:20:36 -07005073static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb)
5074{
Stephen Smalley941fc5b2009-10-01 14:48:23 -04005075 return selinux_nlmsg_perm(sk, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005076}
5077
Linus Torvalds1da177e2005-04-16 15:20:36 -07005078static int ipc_alloc_security(struct task_struct *task,
5079 struct kern_ipc_perm *perm,
5080 u16 sclass)
5081{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005082 struct ipc_security_struct *isec;
David Howells275bb412008-11-14 10:39:19 +11005083 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005084
James Morris89d155e2005-10-30 14:59:21 -08005085 isec = kzalloc(sizeof(struct ipc_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005086 if (!isec)
5087 return -ENOMEM;
5088
David Howells275bb412008-11-14 10:39:19 +11005089 sid = task_sid(task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005090 isec->sclass = sclass;
David Howells275bb412008-11-14 10:39:19 +11005091 isec->sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005092 perm->security = isec;
5093
5094 return 0;
5095}
5096
5097static void ipc_free_security(struct kern_ipc_perm *perm)
5098{
5099 struct ipc_security_struct *isec = perm->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005100 perm->security = NULL;
5101 kfree(isec);
5102}
5103
5104static int msg_msg_alloc_security(struct msg_msg *msg)
5105{
5106 struct msg_security_struct *msec;
5107
James Morris89d155e2005-10-30 14:59:21 -08005108 msec = kzalloc(sizeof(struct msg_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005109 if (!msec)
5110 return -ENOMEM;
5111
Linus Torvalds1da177e2005-04-16 15:20:36 -07005112 msec->sid = SECINITSID_UNLABELED;
5113 msg->security = msec;
5114
5115 return 0;
5116}
5117
5118static void msg_msg_free_security(struct msg_msg *msg)
5119{
5120 struct msg_security_struct *msec = msg->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005121
5122 msg->security = NULL;
5123 kfree(msec);
5124}
5125
5126static int ipc_has_perm(struct kern_ipc_perm *ipc_perms,
Stephen Smalley6af963f2005-05-01 08:58:39 -07005127 u32 perms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005128{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005129 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005130 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005131 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005132
Linus Torvalds1da177e2005-04-16 15:20:36 -07005133 isec = ipc_perms->security;
5134
Eric Paris50c205f2012-04-04 15:01:43 -04005135 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005136 ad.u.ipc_id = ipc_perms->key;
5137
David Howells275bb412008-11-14 10:39:19 +11005138 return avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005139}
5140
5141static int selinux_msg_msg_alloc_security(struct msg_msg *msg)
5142{
5143 return msg_msg_alloc_security(msg);
5144}
5145
5146static void selinux_msg_msg_free_security(struct msg_msg *msg)
5147{
5148 msg_msg_free_security(msg);
5149}
5150
5151/* message queue security operations */
5152static int selinux_msg_queue_alloc_security(struct msg_queue *msq)
5153{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005154 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005155 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005156 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005157 int rc;
5158
5159 rc = ipc_alloc_security(current, &msq->q_perm, SECCLASS_MSGQ);
5160 if (rc)
5161 return rc;
5162
Linus Torvalds1da177e2005-04-16 15:20:36 -07005163 isec = msq->q_perm.security;
5164
Eric Paris50c205f2012-04-04 15:01:43 -04005165 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04005166 ad.u.ipc_id = msq->q_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005167
David Howells275bb412008-11-14 10:39:19 +11005168 rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005169 MSGQ__CREATE, &ad);
5170 if (rc) {
5171 ipc_free_security(&msq->q_perm);
5172 return rc;
5173 }
5174 return 0;
5175}
5176
5177static void selinux_msg_queue_free_security(struct msg_queue *msq)
5178{
5179 ipc_free_security(&msq->q_perm);
5180}
5181
5182static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg)
5183{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005184 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005185 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005186 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005187
Linus Torvalds1da177e2005-04-16 15:20:36 -07005188 isec = msq->q_perm.security;
5189
Eric Paris50c205f2012-04-04 15:01:43 -04005190 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005191 ad.u.ipc_id = msq->q_perm.key;
5192
David Howells275bb412008-11-14 10:39:19 +11005193 return avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005194 MSGQ__ASSOCIATE, &ad);
5195}
5196
5197static int selinux_msg_queue_msgctl(struct msg_queue *msq, int cmd)
5198{
5199 int err;
5200 int perms;
5201
Eric Paris828dfe12008-04-17 13:17:49 -04005202 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005203 case IPC_INFO:
5204 case MSG_INFO:
5205 /* No specific object, just general system-wide information. */
5206 return task_has_system(current, SYSTEM__IPC_INFO);
5207 case IPC_STAT:
5208 case MSG_STAT:
5209 perms = MSGQ__GETATTR | MSGQ__ASSOCIATE;
5210 break;
5211 case IPC_SET:
5212 perms = MSGQ__SETATTR;
5213 break;
5214 case IPC_RMID:
5215 perms = MSGQ__DESTROY;
5216 break;
5217 default:
5218 return 0;
5219 }
5220
Stephen Smalley6af963f2005-05-01 08:58:39 -07005221 err = ipc_has_perm(&msq->q_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005222 return err;
5223}
5224
5225static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, int msqflg)
5226{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005227 struct ipc_security_struct *isec;
5228 struct msg_security_struct *msec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005229 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005230 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005231 int rc;
5232
Linus Torvalds1da177e2005-04-16 15:20:36 -07005233 isec = msq->q_perm.security;
5234 msec = msg->security;
5235
5236 /*
5237 * First time through, need to assign label to the message
5238 */
5239 if (msec->sid == SECINITSID_UNLABELED) {
5240 /*
5241 * Compute new sid based on current process and
5242 * message queue this message will be stored in
5243 */
David Howells275bb412008-11-14 10:39:19 +11005244 rc = security_transition_sid(sid, isec->sid, SECCLASS_MSG,
Eric Paris652bb9b2011-02-01 11:05:40 -05005245 NULL, &msec->sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005246 if (rc)
5247 return rc;
5248 }
5249
Eric Paris50c205f2012-04-04 15:01:43 -04005250 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005251 ad.u.ipc_id = msq->q_perm.key;
5252
5253 /* Can this process write to the queue? */
David Howells275bb412008-11-14 10:39:19 +11005254 rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005255 MSGQ__WRITE, &ad);
5256 if (!rc)
5257 /* Can this process send the message */
David Howells275bb412008-11-14 10:39:19 +11005258 rc = avc_has_perm(sid, msec->sid, SECCLASS_MSG,
5259 MSG__SEND, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005260 if (!rc)
5261 /* Can the message be put in the queue? */
David Howells275bb412008-11-14 10:39:19 +11005262 rc = avc_has_perm(msec->sid, isec->sid, SECCLASS_MSGQ,
5263 MSGQ__ENQUEUE, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005264
5265 return rc;
5266}
5267
5268static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
5269 struct task_struct *target,
5270 long type, int mode)
5271{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005272 struct ipc_security_struct *isec;
5273 struct msg_security_struct *msec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005274 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005275 u32 sid = task_sid(target);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005276 int rc;
5277
Linus Torvalds1da177e2005-04-16 15:20:36 -07005278 isec = msq->q_perm.security;
5279 msec = msg->security;
5280
Eric Paris50c205f2012-04-04 15:01:43 -04005281 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04005282 ad.u.ipc_id = msq->q_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005283
David Howells275bb412008-11-14 10:39:19 +11005284 rc = avc_has_perm(sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005285 SECCLASS_MSGQ, MSGQ__READ, &ad);
5286 if (!rc)
David Howells275bb412008-11-14 10:39:19 +11005287 rc = avc_has_perm(sid, msec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005288 SECCLASS_MSG, MSG__RECEIVE, &ad);
5289 return rc;
5290}
5291
5292/* Shared Memory security operations */
5293static int selinux_shm_alloc_security(struct shmid_kernel *shp)
5294{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005295 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005296 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005297 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005298 int rc;
5299
5300 rc = ipc_alloc_security(current, &shp->shm_perm, SECCLASS_SHM);
5301 if (rc)
5302 return rc;
5303
Linus Torvalds1da177e2005-04-16 15:20:36 -07005304 isec = shp->shm_perm.security;
5305
Eric Paris50c205f2012-04-04 15:01:43 -04005306 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04005307 ad.u.ipc_id = shp->shm_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005308
David Howells275bb412008-11-14 10:39:19 +11005309 rc = avc_has_perm(sid, isec->sid, SECCLASS_SHM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005310 SHM__CREATE, &ad);
5311 if (rc) {
5312 ipc_free_security(&shp->shm_perm);
5313 return rc;
5314 }
5315 return 0;
5316}
5317
5318static void selinux_shm_free_security(struct shmid_kernel *shp)
5319{
5320 ipc_free_security(&shp->shm_perm);
5321}
5322
5323static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg)
5324{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005325 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005326 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005327 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005328
Linus Torvalds1da177e2005-04-16 15:20:36 -07005329 isec = shp->shm_perm.security;
5330
Eric Paris50c205f2012-04-04 15:01:43 -04005331 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005332 ad.u.ipc_id = shp->shm_perm.key;
5333
David Howells275bb412008-11-14 10:39:19 +11005334 return avc_has_perm(sid, isec->sid, SECCLASS_SHM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005335 SHM__ASSOCIATE, &ad);
5336}
5337
5338/* Note, at this point, shp is locked down */
5339static int selinux_shm_shmctl(struct shmid_kernel *shp, int cmd)
5340{
5341 int perms;
5342 int err;
5343
Eric Paris828dfe12008-04-17 13:17:49 -04005344 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005345 case IPC_INFO:
5346 case SHM_INFO:
5347 /* No specific object, just general system-wide information. */
5348 return task_has_system(current, SYSTEM__IPC_INFO);
5349 case IPC_STAT:
5350 case SHM_STAT:
5351 perms = SHM__GETATTR | SHM__ASSOCIATE;
5352 break;
5353 case IPC_SET:
5354 perms = SHM__SETATTR;
5355 break;
5356 case SHM_LOCK:
5357 case SHM_UNLOCK:
5358 perms = SHM__LOCK;
5359 break;
5360 case IPC_RMID:
5361 perms = SHM__DESTROY;
5362 break;
5363 default:
5364 return 0;
5365 }
5366
Stephen Smalley6af963f2005-05-01 08:58:39 -07005367 err = ipc_has_perm(&shp->shm_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005368 return err;
5369}
5370
5371static int selinux_shm_shmat(struct shmid_kernel *shp,
5372 char __user *shmaddr, int shmflg)
5373{
5374 u32 perms;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005375
5376 if (shmflg & SHM_RDONLY)
5377 perms = SHM__READ;
5378 else
5379 perms = SHM__READ | SHM__WRITE;
5380
Stephen Smalley6af963f2005-05-01 08:58:39 -07005381 return ipc_has_perm(&shp->shm_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005382}
5383
5384/* Semaphore security operations */
5385static int selinux_sem_alloc_security(struct sem_array *sma)
5386{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005387 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005388 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005389 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005390 int rc;
5391
5392 rc = ipc_alloc_security(current, &sma->sem_perm, SECCLASS_SEM);
5393 if (rc)
5394 return rc;
5395
Linus Torvalds1da177e2005-04-16 15:20:36 -07005396 isec = sma->sem_perm.security;
5397
Eric Paris50c205f2012-04-04 15:01:43 -04005398 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04005399 ad.u.ipc_id = sma->sem_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005400
David Howells275bb412008-11-14 10:39:19 +11005401 rc = avc_has_perm(sid, isec->sid, SECCLASS_SEM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005402 SEM__CREATE, &ad);
5403 if (rc) {
5404 ipc_free_security(&sma->sem_perm);
5405 return rc;
5406 }
5407 return 0;
5408}
5409
5410static void selinux_sem_free_security(struct sem_array *sma)
5411{
5412 ipc_free_security(&sma->sem_perm);
5413}
5414
5415static int selinux_sem_associate(struct sem_array *sma, int semflg)
5416{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005417 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005418 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005419 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005420
Linus Torvalds1da177e2005-04-16 15:20:36 -07005421 isec = sma->sem_perm.security;
5422
Eric Paris50c205f2012-04-04 15:01:43 -04005423 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005424 ad.u.ipc_id = sma->sem_perm.key;
5425
David Howells275bb412008-11-14 10:39:19 +11005426 return avc_has_perm(sid, isec->sid, SECCLASS_SEM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005427 SEM__ASSOCIATE, &ad);
5428}
5429
5430/* Note, at this point, sma is locked down */
5431static int selinux_sem_semctl(struct sem_array *sma, int cmd)
5432{
5433 int err;
5434 u32 perms;
5435
Eric Paris828dfe12008-04-17 13:17:49 -04005436 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005437 case IPC_INFO:
5438 case SEM_INFO:
5439 /* No specific object, just general system-wide information. */
5440 return task_has_system(current, SYSTEM__IPC_INFO);
5441 case GETPID:
5442 case GETNCNT:
5443 case GETZCNT:
5444 perms = SEM__GETATTR;
5445 break;
5446 case GETVAL:
5447 case GETALL:
5448 perms = SEM__READ;
5449 break;
5450 case SETVAL:
5451 case SETALL:
5452 perms = SEM__WRITE;
5453 break;
5454 case IPC_RMID:
5455 perms = SEM__DESTROY;
5456 break;
5457 case IPC_SET:
5458 perms = SEM__SETATTR;
5459 break;
5460 case IPC_STAT:
5461 case SEM_STAT:
5462 perms = SEM__GETATTR | SEM__ASSOCIATE;
5463 break;
5464 default:
5465 return 0;
5466 }
5467
Stephen Smalley6af963f2005-05-01 08:58:39 -07005468 err = ipc_has_perm(&sma->sem_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005469 return err;
5470}
5471
5472static int selinux_sem_semop(struct sem_array *sma,
5473 struct sembuf *sops, unsigned nsops, int alter)
5474{
5475 u32 perms;
5476
5477 if (alter)
5478 perms = SEM__READ | SEM__WRITE;
5479 else
5480 perms = SEM__READ;
5481
Stephen Smalley6af963f2005-05-01 08:58:39 -07005482 return ipc_has_perm(&sma->sem_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005483}
5484
5485static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
5486{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005487 u32 av = 0;
5488
Linus Torvalds1da177e2005-04-16 15:20:36 -07005489 av = 0;
5490 if (flag & S_IRUGO)
5491 av |= IPC__UNIX_READ;
5492 if (flag & S_IWUGO)
5493 av |= IPC__UNIX_WRITE;
5494
5495 if (av == 0)
5496 return 0;
5497
Stephen Smalley6af963f2005-05-01 08:58:39 -07005498 return ipc_has_perm(ipcp, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005499}
5500
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02005501static void selinux_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
5502{
5503 struct ipc_security_struct *isec = ipcp->security;
5504 *secid = isec->sid;
5505}
5506
Eric Paris828dfe12008-04-17 13:17:49 -04005507static void selinux_d_instantiate(struct dentry *dentry, struct inode *inode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005508{
5509 if (inode)
5510 inode_doinit_with_dentry(inode, dentry);
5511}
5512
5513static int selinux_getprocattr(struct task_struct *p,
Al Viro04ff9702007-03-12 16:17:58 +00005514 char *name, char **value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005515{
David Howells275bb412008-11-14 10:39:19 +11005516 const struct task_security_struct *__tsec;
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00005517 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005518 int error;
Al Viro04ff9702007-03-12 16:17:58 +00005519 unsigned len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005520
5521 if (current != p) {
David Howells3b11a1d2008-11-14 10:39:26 +11005522 error = current_has_perm(p, PROCESS__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005523 if (error)
5524 return error;
5525 }
5526
David Howells275bb412008-11-14 10:39:19 +11005527 rcu_read_lock();
5528 __tsec = __task_cred(p)->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005529
5530 if (!strcmp(name, "current"))
David Howells275bb412008-11-14 10:39:19 +11005531 sid = __tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005532 else if (!strcmp(name, "prev"))
David Howells275bb412008-11-14 10:39:19 +11005533 sid = __tsec->osid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005534 else if (!strcmp(name, "exec"))
David Howells275bb412008-11-14 10:39:19 +11005535 sid = __tsec->exec_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005536 else if (!strcmp(name, "fscreate"))
David Howells275bb412008-11-14 10:39:19 +11005537 sid = __tsec->create_sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005538 else if (!strcmp(name, "keycreate"))
David Howells275bb412008-11-14 10:39:19 +11005539 sid = __tsec->keycreate_sid;
Eric Paris42c3e032006-06-26 00:26:03 -07005540 else if (!strcmp(name, "sockcreate"))
David Howells275bb412008-11-14 10:39:19 +11005541 sid = __tsec->sockcreate_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005542 else
David Howells275bb412008-11-14 10:39:19 +11005543 goto invalid;
5544 rcu_read_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005545
5546 if (!sid)
5547 return 0;
5548
Al Viro04ff9702007-03-12 16:17:58 +00005549 error = security_sid_to_context(sid, value, &len);
5550 if (error)
5551 return error;
5552 return len;
David Howells275bb412008-11-14 10:39:19 +11005553
5554invalid:
5555 rcu_read_unlock();
5556 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005557}
5558
5559static int selinux_setprocattr(struct task_struct *p,
5560 char *name, void *value, size_t size)
5561{
5562 struct task_security_struct *tsec;
Roland McGrath03563572008-03-26 15:46:39 -07005563 struct task_struct *tracer;
David Howellsd84f4f92008-11-14 10:39:23 +11005564 struct cred *new;
5565 u32 sid = 0, ptsid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005566 int error;
5567 char *str = value;
5568
5569 if (current != p) {
5570 /* SELinux only allows a process to change its own
5571 security attributes. */
5572 return -EACCES;
5573 }
5574
5575 /*
5576 * Basic control over ability to set these attributes at all.
5577 * current == p, but we'll pass them separately in case the
5578 * above restriction is ever removed.
5579 */
5580 if (!strcmp(name, "exec"))
David Howells3b11a1d2008-11-14 10:39:26 +11005581 error = current_has_perm(p, PROCESS__SETEXEC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005582 else if (!strcmp(name, "fscreate"))
David Howells3b11a1d2008-11-14 10:39:26 +11005583 error = current_has_perm(p, PROCESS__SETFSCREATE);
Michael LeMay4eb582c2006-06-26 00:24:57 -07005584 else if (!strcmp(name, "keycreate"))
David Howells3b11a1d2008-11-14 10:39:26 +11005585 error = current_has_perm(p, PROCESS__SETKEYCREATE);
Eric Paris42c3e032006-06-26 00:26:03 -07005586 else if (!strcmp(name, "sockcreate"))
David Howells3b11a1d2008-11-14 10:39:26 +11005587 error = current_has_perm(p, PROCESS__SETSOCKCREATE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005588 else if (!strcmp(name, "current"))
David Howells3b11a1d2008-11-14 10:39:26 +11005589 error = current_has_perm(p, PROCESS__SETCURRENT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005590 else
5591 error = -EINVAL;
5592 if (error)
5593 return error;
5594
5595 /* Obtain a SID for the context, if one was specified. */
5596 if (size && str[1] && str[1] != '\n') {
5597 if (str[size-1] == '\n') {
5598 str[size-1] = 0;
5599 size--;
5600 }
Nikolay Aleksandrov52a4c642014-03-07 12:44:19 +01005601 error = security_context_to_sid(value, size, &sid, GFP_KERNEL);
Stephen Smalley12b29f32008-05-07 13:03:20 -04005602 if (error == -EINVAL && !strcmp(name, "fscreate")) {
Eric Parisd6ea83e2012-04-04 13:45:49 -04005603 if (!capable(CAP_MAC_ADMIN)) {
5604 struct audit_buffer *ab;
5605 size_t audit_size;
5606
5607 /* We strip a nul only if it is at the end, otherwise the
5608 * context contains a nul and we should audit that */
5609 if (str[size - 1] == '\0')
5610 audit_size = size - 1;
5611 else
5612 audit_size = size;
5613 ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR);
5614 audit_log_format(ab, "op=fscreate invalid_context=");
5615 audit_log_n_untrustedstring(ab, value, audit_size);
5616 audit_log_end(ab);
5617
Stephen Smalley12b29f32008-05-07 13:03:20 -04005618 return error;
Eric Parisd6ea83e2012-04-04 13:45:49 -04005619 }
Stephen Smalley12b29f32008-05-07 13:03:20 -04005620 error = security_context_to_sid_force(value, size,
5621 &sid);
5622 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005623 if (error)
5624 return error;
5625 }
5626
David Howellsd84f4f92008-11-14 10:39:23 +11005627 new = prepare_creds();
5628 if (!new)
5629 return -ENOMEM;
5630
Linus Torvalds1da177e2005-04-16 15:20:36 -07005631 /* Permission checking based on the specified context is
5632 performed during the actual operation (execve,
5633 open/mkdir/...), when we know the full context of the
David Howellsd84f4f92008-11-14 10:39:23 +11005634 operation. See selinux_bprm_set_creds for the execve
Linus Torvalds1da177e2005-04-16 15:20:36 -07005635 checks and may_create for the file creation checks. The
5636 operation will then fail if the context is not permitted. */
David Howellsd84f4f92008-11-14 10:39:23 +11005637 tsec = new->security;
5638 if (!strcmp(name, "exec")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005639 tsec->exec_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005640 } else if (!strcmp(name, "fscreate")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005641 tsec->create_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005642 } else if (!strcmp(name, "keycreate")) {
Michael LeMay4eb582c2006-06-26 00:24:57 -07005643 error = may_create_key(sid, p);
5644 if (error)
David Howellsd84f4f92008-11-14 10:39:23 +11005645 goto abort_change;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005646 tsec->keycreate_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005647 } else if (!strcmp(name, "sockcreate")) {
Eric Paris42c3e032006-06-26 00:26:03 -07005648 tsec->sockcreate_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005649 } else if (!strcmp(name, "current")) {
5650 error = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005651 if (sid == 0)
David Howellsd84f4f92008-11-14 10:39:23 +11005652 goto abort_change;
KaiGai Koheid9250de2008-08-28 16:35:57 +09005653
David Howellsd84f4f92008-11-14 10:39:23 +11005654 /* Only allow single threaded processes to change context */
5655 error = -EPERM;
Oleg Nesterov5bb459b2009-07-10 03:48:23 +02005656 if (!current_is_single_threaded()) {
David Howellsd84f4f92008-11-14 10:39:23 +11005657 error = security_bounded_transition(tsec->sid, sid);
5658 if (error)
5659 goto abort_change;
Eric Paris828dfe12008-04-17 13:17:49 -04005660 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005661
5662 /* Check permissions for the transition. */
5663 error = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS,
Eric Paris828dfe12008-04-17 13:17:49 -04005664 PROCESS__DYNTRANSITION, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005665 if (error)
David Howellsd84f4f92008-11-14 10:39:23 +11005666 goto abort_change;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005667
5668 /* Check for ptracing, and update the task SID if ok.
5669 Otherwise, leave SID unchanged and fail. */
David Howellsd84f4f92008-11-14 10:39:23 +11005670 ptsid = 0;
Oleg Nesterovc0c14392013-12-23 17:45:01 -05005671 rcu_read_lock();
Tejun Heo06d98472011-06-17 16:50:40 +02005672 tracer = ptrace_parent(p);
David Howellsd84f4f92008-11-14 10:39:23 +11005673 if (tracer)
5674 ptsid = task_sid(tracer);
Oleg Nesterovc0c14392013-12-23 17:45:01 -05005675 rcu_read_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005676
David Howellsd84f4f92008-11-14 10:39:23 +11005677 if (tracer) {
5678 error = avc_has_perm(ptsid, sid, SECCLASS_PROCESS,
5679 PROCESS__PTRACE, NULL);
5680 if (error)
5681 goto abort_change;
5682 }
5683
5684 tsec->sid = sid;
5685 } else {
5686 error = -EINVAL;
5687 goto abort_change;
5688 }
5689
5690 commit_creds(new);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005691 return size;
David Howellsd84f4f92008-11-14 10:39:23 +11005692
5693abort_change:
5694 abort_creds(new);
5695 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005696}
5697
David Quigley746df9b2013-05-22 12:50:35 -04005698static int selinux_ismaclabel(const char *name)
5699{
5700 return (strcmp(name, XATTR_SELINUX_SUFFIX) == 0);
5701}
5702
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005703static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
5704{
5705 return security_sid_to_context(secid, secdata, seclen);
5706}
5707
David Howells7bf570d2008-04-29 20:52:51 +01005708static int selinux_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
David Howells63cb3442008-01-15 23:47:35 +00005709{
Nikolay Aleksandrov52a4c642014-03-07 12:44:19 +01005710 return security_context_to_sid(secdata, seclen, secid, GFP_KERNEL);
David Howells63cb3442008-01-15 23:47:35 +00005711}
5712
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005713static void selinux_release_secctx(char *secdata, u32 seclen)
5714{
Paul Moore088999e2007-08-01 11:12:58 -04005715 kfree(secdata);
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005716}
5717
David P. Quigley1ee65e32009-09-03 14:25:57 -04005718/*
5719 * called with inode->i_mutex locked
5720 */
5721static int selinux_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen)
5722{
5723 return selinux_inode_setsecurity(inode, XATTR_SELINUX_SUFFIX, ctx, ctxlen, 0);
5724}
5725
5726/*
5727 * called with inode->i_mutex locked
5728 */
5729static int selinux_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen)
5730{
5731 return __vfs_setxattr_noperm(dentry, XATTR_NAME_SELINUX, ctx, ctxlen, 0);
5732}
5733
5734static int selinux_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen)
5735{
5736 int len = 0;
5737 len = selinux_inode_getsecurity(inode, XATTR_SELINUX_SUFFIX,
5738 ctx, true);
5739 if (len < 0)
5740 return len;
5741 *ctxlen = len;
5742 return 0;
5743}
Michael LeMayd7200242006-06-22 14:47:17 -07005744#ifdef CONFIG_KEYS
5745
David Howellsd84f4f92008-11-14 10:39:23 +11005746static int selinux_key_alloc(struct key *k, const struct cred *cred,
David Howells7e047ef2006-06-26 00:24:50 -07005747 unsigned long flags)
Michael LeMayd7200242006-06-22 14:47:17 -07005748{
David Howellsd84f4f92008-11-14 10:39:23 +11005749 const struct task_security_struct *tsec;
Michael LeMayd7200242006-06-22 14:47:17 -07005750 struct key_security_struct *ksec;
5751
5752 ksec = kzalloc(sizeof(struct key_security_struct), GFP_KERNEL);
5753 if (!ksec)
5754 return -ENOMEM;
5755
David Howellsd84f4f92008-11-14 10:39:23 +11005756 tsec = cred->security;
5757 if (tsec->keycreate_sid)
5758 ksec->sid = tsec->keycreate_sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005759 else
David Howellsd84f4f92008-11-14 10:39:23 +11005760 ksec->sid = tsec->sid;
Michael LeMayd7200242006-06-22 14:47:17 -07005761
David Howells275bb412008-11-14 10:39:19 +11005762 k->security = ksec;
Michael LeMayd7200242006-06-22 14:47:17 -07005763 return 0;
5764}
5765
5766static void selinux_key_free(struct key *k)
5767{
5768 struct key_security_struct *ksec = k->security;
5769
5770 k->security = NULL;
5771 kfree(ksec);
5772}
5773
5774static int selinux_key_permission(key_ref_t key_ref,
David Howellsd84f4f92008-11-14 10:39:23 +11005775 const struct cred *cred,
David Howellsf5895942014-03-14 17:44:49 +00005776 unsigned perm)
Michael LeMayd7200242006-06-22 14:47:17 -07005777{
5778 struct key *key;
Michael LeMayd7200242006-06-22 14:47:17 -07005779 struct key_security_struct *ksec;
David Howells275bb412008-11-14 10:39:19 +11005780 u32 sid;
Michael LeMayd7200242006-06-22 14:47:17 -07005781
5782 /* if no specific permissions are requested, we skip the
5783 permission check. No serious, additional covert channels
5784 appear to be created. */
5785 if (perm == 0)
5786 return 0;
5787
David Howellsd84f4f92008-11-14 10:39:23 +11005788 sid = cred_sid(cred);
David Howells275bb412008-11-14 10:39:19 +11005789
5790 key = key_ref_to_ptr(key_ref);
5791 ksec = key->security;
5792
5793 return avc_has_perm(sid, ksec->sid, SECCLASS_KEY, perm, NULL);
Michael LeMayd7200242006-06-22 14:47:17 -07005794}
5795
David Howells70a5bb72008-04-29 01:01:26 -07005796static int selinux_key_getsecurity(struct key *key, char **_buffer)
5797{
5798 struct key_security_struct *ksec = key->security;
5799 char *context = NULL;
5800 unsigned len;
5801 int rc;
5802
5803 rc = security_sid_to_context(ksec->sid, &context, &len);
5804 if (!rc)
5805 rc = len;
5806 *_buffer = context;
5807 return rc;
5808}
5809
Michael LeMayd7200242006-06-22 14:47:17 -07005810#endif
5811
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07005812static struct security_hook_list selinux_hooks[] = {
Casey Schauflere20b0432015-05-02 15:11:36 -07005813 LSM_HOOK_INIT(binder_set_context_mgr, selinux_binder_set_context_mgr),
5814 LSM_HOOK_INIT(binder_transaction, selinux_binder_transaction),
5815 LSM_HOOK_INIT(binder_transfer_binder, selinux_binder_transfer_binder),
5816 LSM_HOOK_INIT(binder_transfer_file, selinux_binder_transfer_file),
Ahmed S. Darwish076c54c2008-03-06 18:09:10 +02005817
Casey Schauflere20b0432015-05-02 15:11:36 -07005818 LSM_HOOK_INIT(ptrace_access_check, selinux_ptrace_access_check),
5819 LSM_HOOK_INIT(ptrace_traceme, selinux_ptrace_traceme),
5820 LSM_HOOK_INIT(capget, selinux_capget),
5821 LSM_HOOK_INIT(capset, selinux_capset),
5822 LSM_HOOK_INIT(capable, selinux_capable),
5823 LSM_HOOK_INIT(quotactl, selinux_quotactl),
5824 LSM_HOOK_INIT(quota_on, selinux_quota_on),
5825 LSM_HOOK_INIT(syslog, selinux_syslog),
5826 LSM_HOOK_INIT(vm_enough_memory, selinux_vm_enough_memory),
Stephen Smalley79af7302015-01-21 10:54:10 -05005827
Casey Schauflere20b0432015-05-02 15:11:36 -07005828 LSM_HOOK_INIT(netlink_send, selinux_netlink_send),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005829
Casey Schauflere20b0432015-05-02 15:11:36 -07005830 LSM_HOOK_INIT(bprm_set_creds, selinux_bprm_set_creds),
5831 LSM_HOOK_INIT(bprm_committing_creds, selinux_bprm_committing_creds),
5832 LSM_HOOK_INIT(bprm_committed_creds, selinux_bprm_committed_creds),
5833 LSM_HOOK_INIT(bprm_secureexec, selinux_bprm_secureexec),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005834
Casey Schauflere20b0432015-05-02 15:11:36 -07005835 LSM_HOOK_INIT(sb_alloc_security, selinux_sb_alloc_security),
5836 LSM_HOOK_INIT(sb_free_security, selinux_sb_free_security),
5837 LSM_HOOK_INIT(sb_copy_data, selinux_sb_copy_data),
5838 LSM_HOOK_INIT(sb_remount, selinux_sb_remount),
5839 LSM_HOOK_INIT(sb_kern_mount, selinux_sb_kern_mount),
5840 LSM_HOOK_INIT(sb_show_options, selinux_sb_show_options),
5841 LSM_HOOK_INIT(sb_statfs, selinux_sb_statfs),
5842 LSM_HOOK_INIT(sb_mount, selinux_mount),
5843 LSM_HOOK_INIT(sb_umount, selinux_umount),
5844 LSM_HOOK_INIT(sb_set_mnt_opts, selinux_set_mnt_opts),
5845 LSM_HOOK_INIT(sb_clone_mnt_opts, selinux_sb_clone_mnt_opts),
5846 LSM_HOOK_INIT(sb_parse_opts_str, selinux_parse_opts_str),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005847
Casey Schauflere20b0432015-05-02 15:11:36 -07005848 LSM_HOOK_INIT(dentry_init_security, selinux_dentry_init_security),
Eric Parise0007522008-03-05 10:31:54 -05005849
Casey Schauflere20b0432015-05-02 15:11:36 -07005850 LSM_HOOK_INIT(inode_alloc_security, selinux_inode_alloc_security),
5851 LSM_HOOK_INIT(inode_free_security, selinux_inode_free_security),
5852 LSM_HOOK_INIT(inode_init_security, selinux_inode_init_security),
5853 LSM_HOOK_INIT(inode_create, selinux_inode_create),
5854 LSM_HOOK_INIT(inode_link, selinux_inode_link),
5855 LSM_HOOK_INIT(inode_unlink, selinux_inode_unlink),
5856 LSM_HOOK_INIT(inode_symlink, selinux_inode_symlink),
5857 LSM_HOOK_INIT(inode_mkdir, selinux_inode_mkdir),
5858 LSM_HOOK_INIT(inode_rmdir, selinux_inode_rmdir),
5859 LSM_HOOK_INIT(inode_mknod, selinux_inode_mknod),
5860 LSM_HOOK_INIT(inode_rename, selinux_inode_rename),
5861 LSM_HOOK_INIT(inode_readlink, selinux_inode_readlink),
5862 LSM_HOOK_INIT(inode_follow_link, selinux_inode_follow_link),
5863 LSM_HOOK_INIT(inode_permission, selinux_inode_permission),
5864 LSM_HOOK_INIT(inode_setattr, selinux_inode_setattr),
5865 LSM_HOOK_INIT(inode_getattr, selinux_inode_getattr),
5866 LSM_HOOK_INIT(inode_setxattr, selinux_inode_setxattr),
5867 LSM_HOOK_INIT(inode_post_setxattr, selinux_inode_post_setxattr),
5868 LSM_HOOK_INIT(inode_getxattr, selinux_inode_getxattr),
5869 LSM_HOOK_INIT(inode_listxattr, selinux_inode_listxattr),
5870 LSM_HOOK_INIT(inode_removexattr, selinux_inode_removexattr),
5871 LSM_HOOK_INIT(inode_getsecurity, selinux_inode_getsecurity),
5872 LSM_HOOK_INIT(inode_setsecurity, selinux_inode_setsecurity),
5873 LSM_HOOK_INIT(inode_listsecurity, selinux_inode_listsecurity),
5874 LSM_HOOK_INIT(inode_getsecid, selinux_inode_getsecid),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005875
Casey Schauflere20b0432015-05-02 15:11:36 -07005876 LSM_HOOK_INIT(file_permission, selinux_file_permission),
5877 LSM_HOOK_INIT(file_alloc_security, selinux_file_alloc_security),
5878 LSM_HOOK_INIT(file_free_security, selinux_file_free_security),
5879 LSM_HOOK_INIT(file_ioctl, selinux_file_ioctl),
5880 LSM_HOOK_INIT(mmap_file, selinux_mmap_file),
5881 LSM_HOOK_INIT(mmap_addr, selinux_mmap_addr),
5882 LSM_HOOK_INIT(file_mprotect, selinux_file_mprotect),
5883 LSM_HOOK_INIT(file_lock, selinux_file_lock),
5884 LSM_HOOK_INIT(file_fcntl, selinux_file_fcntl),
5885 LSM_HOOK_INIT(file_set_fowner, selinux_file_set_fowner),
5886 LSM_HOOK_INIT(file_send_sigiotask, selinux_file_send_sigiotask),
5887 LSM_HOOK_INIT(file_receive, selinux_file_receive),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005888
Casey Schauflere20b0432015-05-02 15:11:36 -07005889 LSM_HOOK_INIT(file_open, selinux_file_open),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005890
Casey Schauflere20b0432015-05-02 15:11:36 -07005891 LSM_HOOK_INIT(task_create, selinux_task_create),
5892 LSM_HOOK_INIT(cred_alloc_blank, selinux_cred_alloc_blank),
5893 LSM_HOOK_INIT(cred_free, selinux_cred_free),
5894 LSM_HOOK_INIT(cred_prepare, selinux_cred_prepare),
5895 LSM_HOOK_INIT(cred_transfer, selinux_cred_transfer),
5896 LSM_HOOK_INIT(kernel_act_as, selinux_kernel_act_as),
5897 LSM_HOOK_INIT(kernel_create_files_as, selinux_kernel_create_files_as),
5898 LSM_HOOK_INIT(kernel_module_request, selinux_kernel_module_request),
5899 LSM_HOOK_INIT(task_setpgid, selinux_task_setpgid),
5900 LSM_HOOK_INIT(task_getpgid, selinux_task_getpgid),
5901 LSM_HOOK_INIT(task_getsid, selinux_task_getsid),
5902 LSM_HOOK_INIT(task_getsecid, selinux_task_getsecid),
5903 LSM_HOOK_INIT(task_setnice, selinux_task_setnice),
5904 LSM_HOOK_INIT(task_setioprio, selinux_task_setioprio),
5905 LSM_HOOK_INIT(task_getioprio, selinux_task_getioprio),
5906 LSM_HOOK_INIT(task_setrlimit, selinux_task_setrlimit),
5907 LSM_HOOK_INIT(task_setscheduler, selinux_task_setscheduler),
5908 LSM_HOOK_INIT(task_getscheduler, selinux_task_getscheduler),
5909 LSM_HOOK_INIT(task_movememory, selinux_task_movememory),
5910 LSM_HOOK_INIT(task_kill, selinux_task_kill),
5911 LSM_HOOK_INIT(task_wait, selinux_task_wait),
5912 LSM_HOOK_INIT(task_to_inode, selinux_task_to_inode),
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09005913
Casey Schauflere20b0432015-05-02 15:11:36 -07005914 LSM_HOOK_INIT(ipc_permission, selinux_ipc_permission),
5915 LSM_HOOK_INIT(ipc_getsecid, selinux_ipc_getsecid),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005916
Casey Schauflere20b0432015-05-02 15:11:36 -07005917 LSM_HOOK_INIT(msg_msg_alloc_security, selinux_msg_msg_alloc_security),
5918 LSM_HOOK_INIT(msg_msg_free_security, selinux_msg_msg_free_security),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005919
Casey Schauflere20b0432015-05-02 15:11:36 -07005920 LSM_HOOK_INIT(msg_queue_alloc_security,
5921 selinux_msg_queue_alloc_security),
5922 LSM_HOOK_INIT(msg_queue_free_security, selinux_msg_queue_free_security),
5923 LSM_HOOK_INIT(msg_queue_associate, selinux_msg_queue_associate),
5924 LSM_HOOK_INIT(msg_queue_msgctl, selinux_msg_queue_msgctl),
5925 LSM_HOOK_INIT(msg_queue_msgsnd, selinux_msg_queue_msgsnd),
5926 LSM_HOOK_INIT(msg_queue_msgrcv, selinux_msg_queue_msgrcv),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005927
Casey Schauflere20b0432015-05-02 15:11:36 -07005928 LSM_HOOK_INIT(shm_alloc_security, selinux_shm_alloc_security),
5929 LSM_HOOK_INIT(shm_free_security, selinux_shm_free_security),
5930 LSM_HOOK_INIT(shm_associate, selinux_shm_associate),
5931 LSM_HOOK_INIT(shm_shmctl, selinux_shm_shmctl),
5932 LSM_HOOK_INIT(shm_shmat, selinux_shm_shmat),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005933
Casey Schauflere20b0432015-05-02 15:11:36 -07005934 LSM_HOOK_INIT(sem_alloc_security, selinux_sem_alloc_security),
5935 LSM_HOOK_INIT(sem_free_security, selinux_sem_free_security),
5936 LSM_HOOK_INIT(sem_associate, selinux_sem_associate),
5937 LSM_HOOK_INIT(sem_semctl, selinux_sem_semctl),
5938 LSM_HOOK_INIT(sem_semop, selinux_sem_semop),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005939
Casey Schauflere20b0432015-05-02 15:11:36 -07005940 LSM_HOOK_INIT(d_instantiate, selinux_d_instantiate),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005941
Casey Schauflere20b0432015-05-02 15:11:36 -07005942 LSM_HOOK_INIT(getprocattr, selinux_getprocattr),
5943 LSM_HOOK_INIT(setprocattr, selinux_setprocattr),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005944
Casey Schauflere20b0432015-05-02 15:11:36 -07005945 LSM_HOOK_INIT(ismaclabel, selinux_ismaclabel),
5946 LSM_HOOK_INIT(secid_to_secctx, selinux_secid_to_secctx),
5947 LSM_HOOK_INIT(secctx_to_secid, selinux_secctx_to_secid),
5948 LSM_HOOK_INIT(release_secctx, selinux_release_secctx),
5949 LSM_HOOK_INIT(inode_notifysecctx, selinux_inode_notifysecctx),
5950 LSM_HOOK_INIT(inode_setsecctx, selinux_inode_setsecctx),
5951 LSM_HOOK_INIT(inode_getsecctx, selinux_inode_getsecctx),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005952
Casey Schauflere20b0432015-05-02 15:11:36 -07005953 LSM_HOOK_INIT(unix_stream_connect, selinux_socket_unix_stream_connect),
5954 LSM_HOOK_INIT(unix_may_send, selinux_socket_unix_may_send),
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005955
Casey Schauflere20b0432015-05-02 15:11:36 -07005956 LSM_HOOK_INIT(socket_create, selinux_socket_create),
5957 LSM_HOOK_INIT(socket_post_create, selinux_socket_post_create),
5958 LSM_HOOK_INIT(socket_bind, selinux_socket_bind),
5959 LSM_HOOK_INIT(socket_connect, selinux_socket_connect),
5960 LSM_HOOK_INIT(socket_listen, selinux_socket_listen),
5961 LSM_HOOK_INIT(socket_accept, selinux_socket_accept),
5962 LSM_HOOK_INIT(socket_sendmsg, selinux_socket_sendmsg),
5963 LSM_HOOK_INIT(socket_recvmsg, selinux_socket_recvmsg),
5964 LSM_HOOK_INIT(socket_getsockname, selinux_socket_getsockname),
5965 LSM_HOOK_INIT(socket_getpeername, selinux_socket_getpeername),
5966 LSM_HOOK_INIT(socket_getsockopt, selinux_socket_getsockopt),
5967 LSM_HOOK_INIT(socket_setsockopt, selinux_socket_setsockopt),
5968 LSM_HOOK_INIT(socket_shutdown, selinux_socket_shutdown),
5969 LSM_HOOK_INIT(socket_sock_rcv_skb, selinux_socket_sock_rcv_skb),
5970 LSM_HOOK_INIT(socket_getpeersec_stream,
5971 selinux_socket_getpeersec_stream),
5972 LSM_HOOK_INIT(socket_getpeersec_dgram, selinux_socket_getpeersec_dgram),
5973 LSM_HOOK_INIT(sk_alloc_security, selinux_sk_alloc_security),
5974 LSM_HOOK_INIT(sk_free_security, selinux_sk_free_security),
5975 LSM_HOOK_INIT(sk_clone_security, selinux_sk_clone_security),
5976 LSM_HOOK_INIT(sk_getsecid, selinux_sk_getsecid),
5977 LSM_HOOK_INIT(sock_graft, selinux_sock_graft),
5978 LSM_HOOK_INIT(inet_conn_request, selinux_inet_conn_request),
5979 LSM_HOOK_INIT(inet_csk_clone, selinux_inet_csk_clone),
5980 LSM_HOOK_INIT(inet_conn_established, selinux_inet_conn_established),
5981 LSM_HOOK_INIT(secmark_relabel_packet, selinux_secmark_relabel_packet),
5982 LSM_HOOK_INIT(secmark_refcount_inc, selinux_secmark_refcount_inc),
5983 LSM_HOOK_INIT(secmark_refcount_dec, selinux_secmark_refcount_dec),
5984 LSM_HOOK_INIT(req_classify_flow, selinux_req_classify_flow),
5985 LSM_HOOK_INIT(tun_dev_alloc_security, selinux_tun_dev_alloc_security),
5986 LSM_HOOK_INIT(tun_dev_free_security, selinux_tun_dev_free_security),
5987 LSM_HOOK_INIT(tun_dev_create, selinux_tun_dev_create),
5988 LSM_HOOK_INIT(tun_dev_attach_queue, selinux_tun_dev_attach_queue),
5989 LSM_HOOK_INIT(tun_dev_attach, selinux_tun_dev_attach),
5990 LSM_HOOK_INIT(tun_dev_open, selinux_tun_dev_open),
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005991
5992#ifdef CONFIG_SECURITY_NETWORK_XFRM
Casey Schauflere20b0432015-05-02 15:11:36 -07005993 LSM_HOOK_INIT(xfrm_policy_alloc_security, selinux_xfrm_policy_alloc),
5994 LSM_HOOK_INIT(xfrm_policy_clone_security, selinux_xfrm_policy_clone),
5995 LSM_HOOK_INIT(xfrm_policy_free_security, selinux_xfrm_policy_free),
5996 LSM_HOOK_INIT(xfrm_policy_delete_security, selinux_xfrm_policy_delete),
5997 LSM_HOOK_INIT(xfrm_state_alloc, selinux_xfrm_state_alloc),
5998 LSM_HOOK_INIT(xfrm_state_alloc_acquire,
5999 selinux_xfrm_state_alloc_acquire),
6000 LSM_HOOK_INIT(xfrm_state_free_security, selinux_xfrm_state_free),
6001 LSM_HOOK_INIT(xfrm_state_delete_security, selinux_xfrm_state_delete),
6002 LSM_HOOK_INIT(xfrm_policy_lookup, selinux_xfrm_policy_lookup),
6003 LSM_HOOK_INIT(xfrm_state_pol_flow_match,
6004 selinux_xfrm_state_pol_flow_match),
6005 LSM_HOOK_INIT(xfrm_decode_session, selinux_xfrm_decode_session),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006006#endif
Michael LeMayd7200242006-06-22 14:47:17 -07006007
6008#ifdef CONFIG_KEYS
Casey Schauflere20b0432015-05-02 15:11:36 -07006009 LSM_HOOK_INIT(key_alloc, selinux_key_alloc),
6010 LSM_HOOK_INIT(key_free, selinux_key_free),
6011 LSM_HOOK_INIT(key_permission, selinux_key_permission),
6012 LSM_HOOK_INIT(key_getsecurity, selinux_key_getsecurity),
Michael LeMayd7200242006-06-22 14:47:17 -07006013#endif
Ahmed S. Darwish9d57a7f2008-03-01 22:03:14 +02006014
6015#ifdef CONFIG_AUDIT
Casey Schauflere20b0432015-05-02 15:11:36 -07006016 LSM_HOOK_INIT(audit_rule_init, selinux_audit_rule_init),
6017 LSM_HOOK_INIT(audit_rule_known, selinux_audit_rule_known),
6018 LSM_HOOK_INIT(audit_rule_match, selinux_audit_rule_match),
6019 LSM_HOOK_INIT(audit_rule_free, selinux_audit_rule_free),
Ahmed S. Darwish9d57a7f2008-03-01 22:03:14 +02006020#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07006021};
6022
6023static __init int selinux_init(void)
6024{
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07006025 if (!security_module_enable("selinux")) {
Ahmed S. Darwish076c54c2008-03-06 18:09:10 +02006026 selinux_enabled = 0;
6027 return 0;
6028 }
6029
Linus Torvalds1da177e2005-04-16 15:20:36 -07006030 if (!selinux_enabled) {
6031 printk(KERN_INFO "SELinux: Disabled at boot.\n");
6032 return 0;
6033 }
6034
6035 printk(KERN_INFO "SELinux: Initializing.\n");
6036
6037 /* Set the security state for the initial task. */
David Howellsd84f4f92008-11-14 10:39:23 +11006038 cred_init_security();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006039
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04006040 default_noexec = !(VM_DATA_DEFAULT_FLAGS & VM_EXEC);
6041
James Morris7cae7e22006-03-22 00:09:22 -08006042 sel_inode_cache = kmem_cache_create("selinux_inode_security",
6043 sizeof(struct inode_security_struct),
Paul Mundt20c2df82007-07-20 10:11:58 +09006044 0, SLAB_PANIC, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006045 avc_init();
6046
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07006047 security_add_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006048
Paul Moore615e51f2014-06-26 14:33:56 -04006049 if (avc_add_callback(selinux_netcache_avc_callback, AVC_CALLBACK_RESET))
6050 panic("SELinux: Unable to register AVC netcache callback\n");
6051
Eric Paris828dfe12008-04-17 13:17:49 -04006052 if (selinux_enforcing)
Eric Parisfadcdb42007-02-22 18:11:31 -05006053 printk(KERN_DEBUG "SELinux: Starting in enforcing mode\n");
Eric Paris828dfe12008-04-17 13:17:49 -04006054 else
Eric Parisfadcdb42007-02-22 18:11:31 -05006055 printk(KERN_DEBUG "SELinux: Starting in permissive mode\n");
Michael LeMayd7200242006-06-22 14:47:17 -07006056
Linus Torvalds1da177e2005-04-16 15:20:36 -07006057 return 0;
6058}
6059
Al Viroe8c26252010-03-23 06:36:54 -04006060static void delayed_superblock_init(struct super_block *sb, void *unused)
6061{
6062 superblock_doinit(sb, NULL);
6063}
6064
Linus Torvalds1da177e2005-04-16 15:20:36 -07006065void selinux_complete_init(void)
6066{
Eric Parisfadcdb42007-02-22 18:11:31 -05006067 printk(KERN_DEBUG "SELinux: Completing initialization.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07006068
6069 /* Set up any superblocks initialized prior to the policy load. */
Eric Parisfadcdb42007-02-22 18:11:31 -05006070 printk(KERN_DEBUG "SELinux: Setting up existing superblocks.\n");
Al Viroe8c26252010-03-23 06:36:54 -04006071 iterate_supers(delayed_superblock_init, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006072}
6073
6074/* SELinux requires early initialization in order to label
6075 all processes and objects when they are created. */
6076security_initcall(selinux_init);
6077
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08006078#if defined(CONFIG_NETFILTER)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006079
Jiri Pirko25db6be2014-09-03 17:42:13 +02006080static struct nf_hook_ops selinux_nf_ops[] = {
Paul Mooreeffad8d2008-01-29 08:49:27 -05006081 {
6082 .hook = selinux_ipv4_postroute,
6083 .owner = THIS_MODULE,
Alban Crequy2597a832012-05-14 03:56:39 +00006084 .pf = NFPROTO_IPV4,
Paul Mooreeffad8d2008-01-29 08:49:27 -05006085 .hooknum = NF_INET_POST_ROUTING,
6086 .priority = NF_IP_PRI_SELINUX_LAST,
6087 },
6088 {
6089 .hook = selinux_ipv4_forward,
6090 .owner = THIS_MODULE,
Alban Crequy2597a832012-05-14 03:56:39 +00006091 .pf = NFPROTO_IPV4,
Paul Mooreeffad8d2008-01-29 08:49:27 -05006092 .hooknum = NF_INET_FORWARD,
6093 .priority = NF_IP_PRI_SELINUX_FIRST,
Paul Moore948bf852008-10-10 10:16:32 -04006094 },
6095 {
6096 .hook = selinux_ipv4_output,
6097 .owner = THIS_MODULE,
Alban Crequy2597a832012-05-14 03:56:39 +00006098 .pf = NFPROTO_IPV4,
Paul Moore948bf852008-10-10 10:16:32 -04006099 .hooknum = NF_INET_LOCAL_OUT,
6100 .priority = NF_IP_PRI_SELINUX_FIRST,
Jiri Pirko25db6be2014-09-03 17:42:13 +02006101 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07006102#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Paul Mooreeffad8d2008-01-29 08:49:27 -05006103 {
6104 .hook = selinux_ipv6_postroute,
6105 .owner = THIS_MODULE,
Alban Crequy2597a832012-05-14 03:56:39 +00006106 .pf = NFPROTO_IPV6,
Paul Mooreeffad8d2008-01-29 08:49:27 -05006107 .hooknum = NF_INET_POST_ROUTING,
6108 .priority = NF_IP6_PRI_SELINUX_LAST,
6109 },
6110 {
6111 .hook = selinux_ipv6_forward,
6112 .owner = THIS_MODULE,
Alban Crequy2597a832012-05-14 03:56:39 +00006113 .pf = NFPROTO_IPV6,
Paul Mooreeffad8d2008-01-29 08:49:27 -05006114 .hooknum = NF_INET_FORWARD,
6115 .priority = NF_IP6_PRI_SELINUX_FIRST,
Jiri Pirko25db6be2014-09-03 17:42:13 +02006116 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07006117#endif /* IPV6 */
Jiri Pirko25db6be2014-09-03 17:42:13 +02006118};
Linus Torvalds1da177e2005-04-16 15:20:36 -07006119
6120static int __init selinux_nf_ip_init(void)
6121{
Jiri Pirko25db6be2014-09-03 17:42:13 +02006122 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006123
6124 if (!selinux_enabled)
Jiri Pirko25db6be2014-09-03 17:42:13 +02006125 return 0;
Eric Parisfadcdb42007-02-22 18:11:31 -05006126
6127 printk(KERN_DEBUG "SELinux: Registering netfilter hooks\n");
6128
Jiri Pirko25db6be2014-09-03 17:42:13 +02006129 err = nf_register_hooks(selinux_nf_ops, ARRAY_SIZE(selinux_nf_ops));
Alexey Dobriyan6c5a9d22008-07-26 17:48:15 -07006130 if (err)
Jiri Pirko25db6be2014-09-03 17:42:13 +02006131 panic("SELinux: nf_register_hooks: error %d\n", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006132
Jiri Pirko25db6be2014-09-03 17:42:13 +02006133 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006134}
6135
6136__initcall(selinux_nf_ip_init);
6137
6138#ifdef CONFIG_SECURITY_SELINUX_DISABLE
6139static void selinux_nf_ip_exit(void)
6140{
Eric Parisfadcdb42007-02-22 18:11:31 -05006141 printk(KERN_DEBUG "SELinux: Unregistering netfilter hooks\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07006142
Jiri Pirko25db6be2014-09-03 17:42:13 +02006143 nf_unregister_hooks(selinux_nf_ops, ARRAY_SIZE(selinux_nf_ops));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006144}
6145#endif
6146
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08006147#else /* CONFIG_NETFILTER */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006148
6149#ifdef CONFIG_SECURITY_SELINUX_DISABLE
6150#define selinux_nf_ip_exit()
6151#endif
6152
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08006153#endif /* CONFIG_NETFILTER */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006154
6155#ifdef CONFIG_SECURITY_SELINUX_DISABLE
Eric Paris828dfe12008-04-17 13:17:49 -04006156static int selinux_disabled;
6157
Linus Torvalds1da177e2005-04-16 15:20:36 -07006158int selinux_disable(void)
6159{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006160 if (ss_initialized) {
6161 /* Not permitted after initial policy load. */
6162 return -EINVAL;
6163 }
6164
6165 if (selinux_disabled) {
6166 /* Only do this once. */
6167 return -EINVAL;
6168 }
6169
6170 printk(KERN_INFO "SELinux: Disabled at runtime.\n");
6171
6172 selinux_disabled = 1;
Stephen Smalley30d55282006-05-03 10:52:36 -04006173 selinux_enabled = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006174
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07006175 security_delete_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006176
Eric Parisaf8ff042009-09-20 21:23:01 -04006177 /* Try to destroy the avc node cache */
6178 avc_disable();
6179
Linus Torvalds1da177e2005-04-16 15:20:36 -07006180 /* Unregister netfilter hooks. */
6181 selinux_nf_ip_exit();
6182
6183 /* Unregister selinuxfs. */
6184 exit_sel_fs();
6185
6186 return 0;
6187}
6188#endif