blob: 799d15aa35f9d6b0df95caaa960d1d02d2a5377a [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
Waiman Long9629d042015-07-10 17:19:56 -0400257 /*
258 * As not all inode security structures are in a list, we check for
259 * empty list outside of the lock to make sure that we won't waste
260 * time taking a lock doing nothing.
261 *
262 * The list_del_init() function can be safely called more than once.
263 * It should not be possible for this function to be called with
264 * concurrent list_add(), but for better safety against future changes
265 * in the code, we use list_empty_careful() here.
266 */
267 if (!list_empty_careful(&isec->list)) {
268 spin_lock(&sbsec->isec_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269 list_del_init(&isec->list);
Waiman Long9629d042015-07-10 17:19:56 -0400270 spin_unlock(&sbsec->isec_lock);
271 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700272
Steven Rostedt3dc91d42014-01-09 21:46:34 -0500273 /*
274 * The inode may still be referenced in a path walk and
275 * a call to selinux_inode_permission() can be made
276 * after inode_free_security() is called. Ideally, the VFS
277 * wouldn't do this, but fixing that is a much harder
278 * job. For now, simply free the i_security via RCU, and
279 * leave the current inode->i_security pointer intact.
280 * The inode will be freed after the RCU grace period too.
281 */
282 call_rcu(&isec->rcu, inode_free_rcu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283}
284
285static int file_alloc_security(struct file *file)
286{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287 struct file_security_struct *fsec;
David Howells275bb412008-11-14 10:39:19 +1100288 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700289
Stephen Smalley26d2a4b2006-02-01 03:05:55 -0800290 fsec = kzalloc(sizeof(struct file_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291 if (!fsec)
292 return -ENOMEM;
293
David Howells275bb412008-11-14 10:39:19 +1100294 fsec->sid = sid;
295 fsec->fown_sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700296 file->f_security = fsec;
297
298 return 0;
299}
300
301static void file_free_security(struct file *file)
302{
303 struct file_security_struct *fsec = file->f_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700304 file->f_security = NULL;
305 kfree(fsec);
306}
307
308static int superblock_alloc_security(struct super_block *sb)
309{
310 struct superblock_security_struct *sbsec;
311
James Morris89d155e2005-10-30 14:59:21 -0800312 sbsec = kzalloc(sizeof(struct superblock_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700313 if (!sbsec)
314 return -ENOMEM;
315
Eric Parisbc7e9822006-09-25 23:32:02 -0700316 mutex_init(&sbsec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700317 INIT_LIST_HEAD(&sbsec->isec_head);
318 spin_lock_init(&sbsec->isec_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700319 sbsec->sb = sb;
320 sbsec->sid = SECINITSID_UNLABELED;
321 sbsec->def_sid = SECINITSID_FILE;
Eric Parisc312feb2006-07-10 04:43:53 -0700322 sbsec->mntpoint_sid = SECINITSID_UNLABELED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700323 sb->s_security = sbsec;
324
325 return 0;
326}
327
328static void superblock_free_security(struct super_block *sb)
329{
330 struct superblock_security_struct *sbsec = sb->s_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700331 sb->s_security = NULL;
332 kfree(sbsec);
333}
334
Linus Torvalds1da177e2005-04-16 15:20:36 -0700335/* The file system's label must be initialized prior to use. */
336
David Quigleyeb9ae682013-05-22 12:50:37 -0400337static const char *labeling_behaviors[7] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700338 "uses xattr",
339 "uses transition SIDs",
340 "uses task SIDs",
341 "uses genfs_contexts",
342 "not configured for labeling",
343 "uses mountpoint labeling",
David Quigleyeb9ae682013-05-22 12:50:37 -0400344 "uses native labeling",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700345};
346
347static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry);
348
349static inline int inode_doinit(struct inode *inode)
350{
351 return inode_doinit_with_dentry(inode, NULL);
352}
353
354enum {
Eric Paris31e87932007-09-19 17:19:12 -0400355 Opt_error = -1,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700356 Opt_context = 1,
357 Opt_fscontext = 2,
Eric Parisc9180a52007-11-30 13:00:35 -0500358 Opt_defcontext = 3,
359 Opt_rootcontext = 4,
David P. Quigley11689d42009-01-16 09:22:03 -0500360 Opt_labelsupport = 5,
Eric Parisd355987f2012-08-24 15:58:53 -0400361 Opt_nextmntopt = 6,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700362};
363
Eric Parisd355987f2012-08-24 15:58:53 -0400364#define NUM_SEL_MNT_OPTS (Opt_nextmntopt - 1)
365
Steven Whitehousea447c092008-10-13 10:46:57 +0100366static const match_table_t tokens = {
Eric Paris832cbd92008-04-01 13:24:09 -0400367 {Opt_context, CONTEXT_STR "%s"},
368 {Opt_fscontext, FSCONTEXT_STR "%s"},
369 {Opt_defcontext, DEFCONTEXT_STR "%s"},
370 {Opt_rootcontext, ROOTCONTEXT_STR "%s"},
David P. Quigley11689d42009-01-16 09:22:03 -0500371 {Opt_labelsupport, LABELSUPP_STR},
Eric Paris31e87932007-09-19 17:19:12 -0400372 {Opt_error, NULL},
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373};
374
375#define SEL_MOUNT_FAIL_MSG "SELinux: duplicate or incompatible mount options\n"
376
Eric Parisc312feb2006-07-10 04:43:53 -0700377static int may_context_mount_sb_relabel(u32 sid,
378 struct superblock_security_struct *sbsec,
David Howells275bb412008-11-14 10:39:19 +1100379 const struct cred *cred)
Eric Parisc312feb2006-07-10 04:43:53 -0700380{
David Howells275bb412008-11-14 10:39:19 +1100381 const struct task_security_struct *tsec = cred->security;
Eric Parisc312feb2006-07-10 04:43:53 -0700382 int rc;
383
384 rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
385 FILESYSTEM__RELABELFROM, NULL);
386 if (rc)
387 return rc;
388
389 rc = avc_has_perm(tsec->sid, sid, SECCLASS_FILESYSTEM,
390 FILESYSTEM__RELABELTO, NULL);
391 return rc;
392}
393
Eric Paris08089252006-07-10 04:43:55 -0700394static int may_context_mount_inode_relabel(u32 sid,
395 struct superblock_security_struct *sbsec,
David Howells275bb412008-11-14 10:39:19 +1100396 const struct cred *cred)
Eric Paris08089252006-07-10 04:43:55 -0700397{
David Howells275bb412008-11-14 10:39:19 +1100398 const struct task_security_struct *tsec = cred->security;
Eric Paris08089252006-07-10 04:43:55 -0700399 int rc;
400 rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
401 FILESYSTEM__RELABELFROM, NULL);
402 if (rc)
403 return rc;
404
405 rc = avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM,
406 FILESYSTEM__ASSOCIATE, NULL);
407 return rc;
408}
409
Eric Parisb43e7252012-10-10 14:27:35 -0400410static int selinux_is_sblabel_mnt(struct super_block *sb)
411{
412 struct superblock_security_struct *sbsec = sb->s_security;
413
Mark Salyzynd5f3a5f2015-02-04 11:34:30 -0500414 return sbsec->behavior == SECURITY_FS_USE_XATTR ||
415 sbsec->behavior == SECURITY_FS_USE_TRANS ||
416 sbsec->behavior == SECURITY_FS_USE_TASK ||
J. Bruce Fields9fc2b4b2015-06-04 15:57:25 -0400417 sbsec->behavior == SECURITY_FS_USE_NATIVE ||
Mark Salyzynd5f3a5f2015-02-04 11:34:30 -0500418 /* Special handling. Genfs but also in-core setxattr handler */
419 !strcmp(sb->s_type->name, "sysfs") ||
420 !strcmp(sb->s_type->name, "pstore") ||
421 !strcmp(sb->s_type->name, "debugfs") ||
422 !strcmp(sb->s_type->name, "rootfs");
Eric Parisb43e7252012-10-10 14:27:35 -0400423}
424
Eric Parisc9180a52007-11-30 13:00:35 -0500425static int sb_finish_set_opts(struct super_block *sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700426{
427 struct superblock_security_struct *sbsec = sb->s_security;
428 struct dentry *root = sb->s_root;
David Howellsc6f493d2015-03-17 22:26:22 +0000429 struct inode *root_inode = d_backing_inode(root);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430 int rc = 0;
431
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432 if (sbsec->behavior == SECURITY_FS_USE_XATTR) {
433 /* Make sure that the xattr handler exists and that no
434 error other than -ENODATA is returned by getxattr on
435 the root directory. -ENODATA is ok, as this may be
436 the first boot of the SELinux kernel before we have
437 assigned xattr values to the filesystem. */
Eric Parisc9180a52007-11-30 13:00:35 -0500438 if (!root_inode->i_op->getxattr) {
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800439 printk(KERN_WARNING "SELinux: (dev %s, type %s) has no "
440 "xattr support\n", sb->s_id, sb->s_type->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441 rc = -EOPNOTSUPP;
442 goto out;
443 }
Eric Parisc9180a52007-11-30 13:00:35 -0500444 rc = root_inode->i_op->getxattr(root, XATTR_NAME_SELINUX, NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700445 if (rc < 0 && rc != -ENODATA) {
446 if (rc == -EOPNOTSUPP)
447 printk(KERN_WARNING "SELinux: (dev %s, type "
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800448 "%s) has no security xattr handler\n",
449 sb->s_id, sb->s_type->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700450 else
451 printk(KERN_WARNING "SELinux: (dev %s, type "
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800452 "%s) getxattr errno %d\n", sb->s_id,
453 sb->s_type->name, -rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454 goto out;
455 }
456 }
457
Eric Parisc9180a52007-11-30 13:00:35 -0500458 if (sbsec->behavior > ARRAY_SIZE(labeling_behaviors))
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800459 printk(KERN_ERR "SELinux: initialized (dev %s, type %s), unknown behavior\n",
460 sb->s_id, sb->s_type->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700461
Eric Pariseadcabc2012-08-24 15:59:14 -0400462 sbsec->flags |= SE_SBINITIALIZED;
Eric Parisb43e7252012-10-10 14:27:35 -0400463 if (selinux_is_sblabel_mnt(sb))
Eric Paris12f348b2012-10-09 10:56:25 -0400464 sbsec->flags |= SBLABEL_MNT;
David P. Quigleyddd29ec2009-09-09 14:25:37 -0400465
Linus Torvalds1da177e2005-04-16 15:20:36 -0700466 /* Initialize the root inode. */
Eric Parisc9180a52007-11-30 13:00:35 -0500467 rc = inode_doinit_with_dentry(root_inode, root);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700468
469 /* Initialize any other inodes associated with the superblock, e.g.
470 inodes created prior to initial policy load or inodes created
471 during get_sb by a pseudo filesystem that directly
472 populates itself. */
473 spin_lock(&sbsec->isec_lock);
474next_inode:
475 if (!list_empty(&sbsec->isec_head)) {
476 struct inode_security_struct *isec =
477 list_entry(sbsec->isec_head.next,
Eric Parisc9180a52007-11-30 13:00:35 -0500478 struct inode_security_struct, list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700479 struct inode *inode = isec->inode;
Stephen Smalley923190d2014-10-06 16:32:52 -0400480 list_del_init(&isec->list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481 spin_unlock(&sbsec->isec_lock);
482 inode = igrab(inode);
483 if (inode) {
Eric Parisc9180a52007-11-30 13:00:35 -0500484 if (!IS_PRIVATE(inode))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485 inode_doinit(inode);
486 iput(inode);
487 }
488 spin_lock(&sbsec->isec_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700489 goto next_inode;
490 }
491 spin_unlock(&sbsec->isec_lock);
492out:
Eric Parisc9180a52007-11-30 13:00:35 -0500493 return rc;
494}
495
496/*
497 * This function should allow an FS to ask what it's mount security
498 * options were so it can use those later for submounts, displaying
499 * mount options, or whatever.
500 */
501static int selinux_get_mnt_opts(const struct super_block *sb,
Eric Parise0007522008-03-05 10:31:54 -0500502 struct security_mnt_opts *opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500503{
504 int rc = 0, i;
505 struct superblock_security_struct *sbsec = sb->s_security;
506 char *context = NULL;
507 u32 len;
508 char tmp;
509
Eric Parise0007522008-03-05 10:31:54 -0500510 security_init_mnt_opts(opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500511
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500512 if (!(sbsec->flags & SE_SBINITIALIZED))
Eric Parisc9180a52007-11-30 13:00:35 -0500513 return -EINVAL;
514
515 if (!ss_initialized)
516 return -EINVAL;
517
Eric Parisaf8e50c2012-08-24 15:59:00 -0400518 /* make sure we always check enough bits to cover the mask */
519 BUILD_BUG_ON(SE_MNTMASK >= (1 << NUM_SEL_MNT_OPTS));
520
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500521 tmp = sbsec->flags & SE_MNTMASK;
Eric Parisc9180a52007-11-30 13:00:35 -0500522 /* count the number of mount options for this sb */
Eric Parisaf8e50c2012-08-24 15:59:00 -0400523 for (i = 0; i < NUM_SEL_MNT_OPTS; i++) {
Eric Parisc9180a52007-11-30 13:00:35 -0500524 if (tmp & 0x01)
Eric Parise0007522008-03-05 10:31:54 -0500525 opts->num_mnt_opts++;
Eric Parisc9180a52007-11-30 13:00:35 -0500526 tmp >>= 1;
527 }
David P. Quigley11689d42009-01-16 09:22:03 -0500528 /* Check if the Label support flag is set */
Eric Paris0b4bdb32013-08-28 13:32:42 -0400529 if (sbsec->flags & SBLABEL_MNT)
David P. Quigley11689d42009-01-16 09:22:03 -0500530 opts->num_mnt_opts++;
Eric Parisc9180a52007-11-30 13:00:35 -0500531
Eric Parise0007522008-03-05 10:31:54 -0500532 opts->mnt_opts = kcalloc(opts->num_mnt_opts, sizeof(char *), GFP_ATOMIC);
533 if (!opts->mnt_opts) {
Eric Parisc9180a52007-11-30 13:00:35 -0500534 rc = -ENOMEM;
535 goto out_free;
536 }
537
Eric Parise0007522008-03-05 10:31:54 -0500538 opts->mnt_opts_flags = kcalloc(opts->num_mnt_opts, sizeof(int), GFP_ATOMIC);
539 if (!opts->mnt_opts_flags) {
Eric Parisc9180a52007-11-30 13:00:35 -0500540 rc = -ENOMEM;
541 goto out_free;
542 }
543
544 i = 0;
545 if (sbsec->flags & FSCONTEXT_MNT) {
546 rc = security_sid_to_context(sbsec->sid, &context, &len);
547 if (rc)
548 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500549 opts->mnt_opts[i] = context;
550 opts->mnt_opts_flags[i++] = FSCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500551 }
552 if (sbsec->flags & CONTEXT_MNT) {
553 rc = security_sid_to_context(sbsec->mntpoint_sid, &context, &len);
554 if (rc)
555 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500556 opts->mnt_opts[i] = context;
557 opts->mnt_opts_flags[i++] = CONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500558 }
559 if (sbsec->flags & DEFCONTEXT_MNT) {
560 rc = security_sid_to_context(sbsec->def_sid, &context, &len);
561 if (rc)
562 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500563 opts->mnt_opts[i] = context;
564 opts->mnt_opts_flags[i++] = DEFCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500565 }
566 if (sbsec->flags & ROOTCONTEXT_MNT) {
David Howellsc6f493d2015-03-17 22:26:22 +0000567 struct inode *root = d_backing_inode(sbsec->sb->s_root);
Eric Parisc9180a52007-11-30 13:00:35 -0500568 struct inode_security_struct *isec = root->i_security;
569
570 rc = security_sid_to_context(isec->sid, &context, &len);
571 if (rc)
572 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500573 opts->mnt_opts[i] = context;
574 opts->mnt_opts_flags[i++] = ROOTCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500575 }
Eric Paris12f348b2012-10-09 10:56:25 -0400576 if (sbsec->flags & SBLABEL_MNT) {
David P. Quigley11689d42009-01-16 09:22:03 -0500577 opts->mnt_opts[i] = NULL;
Eric Paris12f348b2012-10-09 10:56:25 -0400578 opts->mnt_opts_flags[i++] = SBLABEL_MNT;
David P. Quigley11689d42009-01-16 09:22:03 -0500579 }
Eric Parisc9180a52007-11-30 13:00:35 -0500580
Eric Parise0007522008-03-05 10:31:54 -0500581 BUG_ON(i != opts->num_mnt_opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500582
583 return 0;
584
585out_free:
Eric Parise0007522008-03-05 10:31:54 -0500586 security_free_mnt_opts(opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500587 return rc;
588}
589
590static int bad_option(struct superblock_security_struct *sbsec, char flag,
591 u32 old_sid, u32 new_sid)
592{
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500593 char mnt_flags = sbsec->flags & SE_MNTMASK;
594
Eric Parisc9180a52007-11-30 13:00:35 -0500595 /* check if the old mount command had the same options */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500596 if (sbsec->flags & SE_SBINITIALIZED)
Eric Parisc9180a52007-11-30 13:00:35 -0500597 if (!(sbsec->flags & flag) ||
598 (old_sid != new_sid))
599 return 1;
600
601 /* check if we were passed the same options twice,
602 * aka someone passed context=a,context=b
603 */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500604 if (!(sbsec->flags & SE_SBINITIALIZED))
605 if (mnt_flags & flag)
Eric Parisc9180a52007-11-30 13:00:35 -0500606 return 1;
607 return 0;
608}
Eric Parise0007522008-03-05 10:31:54 -0500609
Eric Parisc9180a52007-11-30 13:00:35 -0500610/*
611 * Allow filesystems with binary mount data to explicitly set mount point
612 * labeling information.
613 */
Eric Parise0007522008-03-05 10:31:54 -0500614static int selinux_set_mnt_opts(struct super_block *sb,
David Quigley649f6e72013-05-22 12:50:36 -0400615 struct security_mnt_opts *opts,
616 unsigned long kern_flags,
617 unsigned long *set_kern_flags)
Eric Parisc9180a52007-11-30 13:00:35 -0500618{
David Howells275bb412008-11-14 10:39:19 +1100619 const struct cred *cred = current_cred();
Eric Parisc9180a52007-11-30 13:00:35 -0500620 int rc = 0, i;
Eric Parisc9180a52007-11-30 13:00:35 -0500621 struct superblock_security_struct *sbsec = sb->s_security;
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800622 const char *name = sb->s_type->name;
David Howellsc6f493d2015-03-17 22:26:22 +0000623 struct inode *inode = d_backing_inode(sbsec->sb->s_root);
James Morris089be432008-07-15 18:32:49 +1000624 struct inode_security_struct *root_isec = inode->i_security;
Eric Parisc9180a52007-11-30 13:00:35 -0500625 u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0;
626 u32 defcontext_sid = 0;
Eric Parise0007522008-03-05 10:31:54 -0500627 char **mount_options = opts->mnt_opts;
628 int *flags = opts->mnt_opts_flags;
629 int num_opts = opts->num_mnt_opts;
Eric Parisc9180a52007-11-30 13:00:35 -0500630
631 mutex_lock(&sbsec->lock);
632
633 if (!ss_initialized) {
634 if (!num_opts) {
635 /* Defer initialization until selinux_complete_init,
636 after the initial policy is loaded and the security
637 server is ready to handle calls. */
Eric Parisc9180a52007-11-30 13:00:35 -0500638 goto out;
639 }
640 rc = -EINVAL;
Eric Paris744ba352008-04-17 11:52:44 -0400641 printk(KERN_WARNING "SELinux: Unable to set superblock options "
642 "before the security server is initialized\n");
Eric Parisc9180a52007-11-30 13:00:35 -0500643 goto out;
644 }
David Quigley649f6e72013-05-22 12:50:36 -0400645 if (kern_flags && !set_kern_flags) {
646 /* Specifying internal flags without providing a place to
647 * place the results is not allowed */
648 rc = -EINVAL;
649 goto out;
650 }
Eric Parisc9180a52007-11-30 13:00:35 -0500651
652 /*
Eric Parise0007522008-03-05 10:31:54 -0500653 * Binary mount data FS will come through this function twice. Once
654 * from an explicit call and once from the generic calls from the vfs.
655 * Since the generic VFS calls will not contain any security mount data
656 * we need to skip the double mount verification.
657 *
658 * This does open a hole in which we will not notice if the first
659 * mount using this sb set explict options and a second mount using
660 * this sb does not set any security options. (The first options
661 * will be used for both mounts)
662 */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500663 if ((sbsec->flags & SE_SBINITIALIZED) && (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)
Eric Parise0007522008-03-05 10:31:54 -0500664 && (num_opts == 0))
Eric Parisf5269712008-05-14 11:27:45 -0400665 goto out;
Eric Parise0007522008-03-05 10:31:54 -0500666
667 /*
Eric Parisc9180a52007-11-30 13:00:35 -0500668 * parse the mount options, check if they are valid sids.
669 * also check if someone is trying to mount the same sb more
670 * than once with different security options.
671 */
672 for (i = 0; i < num_opts; i++) {
673 u32 sid;
David P. Quigley11689d42009-01-16 09:22:03 -0500674
Eric Paris12f348b2012-10-09 10:56:25 -0400675 if (flags[i] == SBLABEL_MNT)
David P. Quigley11689d42009-01-16 09:22:03 -0500676 continue;
Rasmus Villemoes44be2f62015-10-21 17:44:25 -0400677 rc = security_context_str_to_sid(mount_options[i], &sid, GFP_KERNEL);
Eric Parisc9180a52007-11-30 13:00:35 -0500678 if (rc) {
Rasmus Villemoes44be2f62015-10-21 17:44:25 -0400679 printk(KERN_WARNING "SELinux: security_context_str_to_sid"
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800680 "(%s) failed for (dev %s, type %s) errno=%d\n",
681 mount_options[i], sb->s_id, name, rc);
Eric Parisc9180a52007-11-30 13:00:35 -0500682 goto out;
683 }
684 switch (flags[i]) {
685 case FSCONTEXT_MNT:
686 fscontext_sid = sid;
687
688 if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid,
689 fscontext_sid))
690 goto out_double_mount;
691
692 sbsec->flags |= FSCONTEXT_MNT;
693 break;
694 case CONTEXT_MNT:
695 context_sid = sid;
696
697 if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid,
698 context_sid))
699 goto out_double_mount;
700
701 sbsec->flags |= CONTEXT_MNT;
702 break;
703 case ROOTCONTEXT_MNT:
704 rootcontext_sid = sid;
705
706 if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid,
707 rootcontext_sid))
708 goto out_double_mount;
709
710 sbsec->flags |= ROOTCONTEXT_MNT;
711
712 break;
713 case DEFCONTEXT_MNT:
714 defcontext_sid = sid;
715
716 if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid,
717 defcontext_sid))
718 goto out_double_mount;
719
720 sbsec->flags |= DEFCONTEXT_MNT;
721
722 break;
723 default:
724 rc = -EINVAL;
725 goto out;
726 }
727 }
728
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500729 if (sbsec->flags & SE_SBINITIALIZED) {
Eric Parisc9180a52007-11-30 13:00:35 -0500730 /* previously mounted with options, but not on this attempt? */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500731 if ((sbsec->flags & SE_MNTMASK) && !num_opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500732 goto out_double_mount;
733 rc = 0;
734 goto out;
735 }
736
James Morris089be432008-07-15 18:32:49 +1000737 if (strcmp(sb->s_type->name, "proc") == 0)
Stephen Smalley134509d2015-06-04 16:22:17 -0400738 sbsec->flags |= SE_SBPROC | SE_SBGENFS;
739
Stephen Smalley8e014722015-06-04 16:22:17 -0400740 if (!strcmp(sb->s_type->name, "debugfs") ||
741 !strcmp(sb->s_type->name, "sysfs") ||
742 !strcmp(sb->s_type->name, "pstore"))
Stephen Smalley134509d2015-06-04 16:22:17 -0400743 sbsec->flags |= SE_SBGENFS;
Eric Parisc9180a52007-11-30 13:00:35 -0500744
David Quigleyeb9ae682013-05-22 12:50:37 -0400745 if (!sbsec->behavior) {
746 /*
747 * Determine the labeling behavior to use for this
748 * filesystem type.
749 */
Paul Moore98f700f2013-09-18 13:52:20 -0400750 rc = security_fs_use(sb);
David Quigleyeb9ae682013-05-22 12:50:37 -0400751 if (rc) {
752 printk(KERN_WARNING
753 "%s: security_fs_use(%s) returned %d\n",
754 __func__, sb->s_type->name, rc);
755 goto out;
756 }
Eric Parisc9180a52007-11-30 13:00:35 -0500757 }
Eric Parisc9180a52007-11-30 13:00:35 -0500758 /* sets the context of the superblock for the fs being mounted. */
759 if (fscontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100760 rc = may_context_mount_sb_relabel(fscontext_sid, sbsec, cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500761 if (rc)
762 goto out;
763
764 sbsec->sid = fscontext_sid;
765 }
766
767 /*
768 * Switch to using mount point labeling behavior.
769 * sets the label used on all file below the mountpoint, and will set
770 * the superblock context if not already set.
771 */
David Quigleyeb9ae682013-05-22 12:50:37 -0400772 if (kern_flags & SECURITY_LSM_NATIVE_LABELS && !context_sid) {
773 sbsec->behavior = SECURITY_FS_USE_NATIVE;
774 *set_kern_flags |= SECURITY_LSM_NATIVE_LABELS;
775 }
776
Eric Parisc9180a52007-11-30 13:00:35 -0500777 if (context_sid) {
778 if (!fscontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100779 rc = may_context_mount_sb_relabel(context_sid, sbsec,
780 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500781 if (rc)
782 goto out;
783 sbsec->sid = context_sid;
784 } else {
David Howells275bb412008-11-14 10:39:19 +1100785 rc = may_context_mount_inode_relabel(context_sid, sbsec,
786 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500787 if (rc)
788 goto out;
789 }
790 if (!rootcontext_sid)
791 rootcontext_sid = context_sid;
792
793 sbsec->mntpoint_sid = context_sid;
794 sbsec->behavior = SECURITY_FS_USE_MNTPOINT;
795 }
796
797 if (rootcontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100798 rc = may_context_mount_inode_relabel(rootcontext_sid, sbsec,
799 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500800 if (rc)
801 goto out;
802
803 root_isec->sid = rootcontext_sid;
804 root_isec->initialized = 1;
805 }
806
807 if (defcontext_sid) {
David Quigleyeb9ae682013-05-22 12:50:37 -0400808 if (sbsec->behavior != SECURITY_FS_USE_XATTR &&
809 sbsec->behavior != SECURITY_FS_USE_NATIVE) {
Eric Parisc9180a52007-11-30 13:00:35 -0500810 rc = -EINVAL;
811 printk(KERN_WARNING "SELinux: defcontext option is "
812 "invalid for this filesystem type\n");
813 goto out;
814 }
815
816 if (defcontext_sid != sbsec->def_sid) {
817 rc = may_context_mount_inode_relabel(defcontext_sid,
David Howells275bb412008-11-14 10:39:19 +1100818 sbsec, cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500819 if (rc)
820 goto out;
821 }
822
823 sbsec->def_sid = defcontext_sid;
824 }
825
826 rc = sb_finish_set_opts(sb);
827out:
Eric Parisbc7e9822006-09-25 23:32:02 -0700828 mutex_unlock(&sbsec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700829 return rc;
Eric Parisc9180a52007-11-30 13:00:35 -0500830out_double_mount:
831 rc = -EINVAL;
832 printk(KERN_WARNING "SELinux: mount invalid. Same superblock, different "
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800833 "security settings for (dev %s, type %s)\n", sb->s_id, name);
Eric Parisc9180a52007-11-30 13:00:35 -0500834 goto out;
835}
836
Jeff Layton094f7b62013-04-01 08:14:24 -0400837static int selinux_cmp_sb_context(const struct super_block *oldsb,
838 const struct super_block *newsb)
839{
840 struct superblock_security_struct *old = oldsb->s_security;
841 struct superblock_security_struct *new = newsb->s_security;
842 char oldflags = old->flags & SE_MNTMASK;
843 char newflags = new->flags & SE_MNTMASK;
844
845 if (oldflags != newflags)
846 goto mismatch;
847 if ((oldflags & FSCONTEXT_MNT) && old->sid != new->sid)
848 goto mismatch;
849 if ((oldflags & CONTEXT_MNT) && old->mntpoint_sid != new->mntpoint_sid)
850 goto mismatch;
851 if ((oldflags & DEFCONTEXT_MNT) && old->def_sid != new->def_sid)
852 goto mismatch;
853 if (oldflags & ROOTCONTEXT_MNT) {
David Howellsc6f493d2015-03-17 22:26:22 +0000854 struct inode_security_struct *oldroot = d_backing_inode(oldsb->s_root)->i_security;
855 struct inode_security_struct *newroot = d_backing_inode(newsb->s_root)->i_security;
Jeff Layton094f7b62013-04-01 08:14:24 -0400856 if (oldroot->sid != newroot->sid)
857 goto mismatch;
858 }
859 return 0;
860mismatch:
861 printk(KERN_WARNING "SELinux: mount invalid. Same superblock, "
862 "different security settings for (dev %s, "
863 "type %s)\n", newsb->s_id, newsb->s_type->name);
864 return -EBUSY;
865}
866
867static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
Eric Parisc9180a52007-11-30 13:00:35 -0500868 struct super_block *newsb)
869{
870 const struct superblock_security_struct *oldsbsec = oldsb->s_security;
871 struct superblock_security_struct *newsbsec = newsb->s_security;
872
873 int set_fscontext = (oldsbsec->flags & FSCONTEXT_MNT);
874 int set_context = (oldsbsec->flags & CONTEXT_MNT);
875 int set_rootcontext = (oldsbsec->flags & ROOTCONTEXT_MNT);
876
Eric Paris0f5e6422008-04-21 16:24:11 -0400877 /*
878 * if the parent was able to be mounted it clearly had no special lsm
Al Viroe8c26252010-03-23 06:36:54 -0400879 * mount options. thus we can safely deal with this superblock later
Eric Paris0f5e6422008-04-21 16:24:11 -0400880 */
Al Viroe8c26252010-03-23 06:36:54 -0400881 if (!ss_initialized)
Jeff Layton094f7b62013-04-01 08:14:24 -0400882 return 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500883
Eric Parisc9180a52007-11-30 13:00:35 -0500884 /* how can we clone if the old one wasn't set up?? */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500885 BUG_ON(!(oldsbsec->flags & SE_SBINITIALIZED));
Eric Parisc9180a52007-11-30 13:00:35 -0500886
Jeff Layton094f7b62013-04-01 08:14:24 -0400887 /* if fs is reusing a sb, make sure that the contexts match */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500888 if (newsbsec->flags & SE_SBINITIALIZED)
Jeff Layton094f7b62013-04-01 08:14:24 -0400889 return selinux_cmp_sb_context(oldsb, newsb);
Eric Paris5a552612008-04-09 14:08:35 -0400890
Eric Parisc9180a52007-11-30 13:00:35 -0500891 mutex_lock(&newsbsec->lock);
892
893 newsbsec->flags = oldsbsec->flags;
894
895 newsbsec->sid = oldsbsec->sid;
896 newsbsec->def_sid = oldsbsec->def_sid;
897 newsbsec->behavior = oldsbsec->behavior;
898
899 if (set_context) {
900 u32 sid = oldsbsec->mntpoint_sid;
901
902 if (!set_fscontext)
903 newsbsec->sid = sid;
904 if (!set_rootcontext) {
David Howellsc6f493d2015-03-17 22:26:22 +0000905 struct inode *newinode = d_backing_inode(newsb->s_root);
Eric Parisc9180a52007-11-30 13:00:35 -0500906 struct inode_security_struct *newisec = newinode->i_security;
907 newisec->sid = sid;
908 }
909 newsbsec->mntpoint_sid = sid;
910 }
911 if (set_rootcontext) {
David Howellsc6f493d2015-03-17 22:26:22 +0000912 const struct inode *oldinode = d_backing_inode(oldsb->s_root);
Eric Parisc9180a52007-11-30 13:00:35 -0500913 const struct inode_security_struct *oldisec = oldinode->i_security;
David Howellsc6f493d2015-03-17 22:26:22 +0000914 struct inode *newinode = d_backing_inode(newsb->s_root);
Eric Parisc9180a52007-11-30 13:00:35 -0500915 struct inode_security_struct *newisec = newinode->i_security;
916
917 newisec->sid = oldisec->sid;
918 }
919
920 sb_finish_set_opts(newsb);
921 mutex_unlock(&newsbsec->lock);
Jeff Layton094f7b62013-04-01 08:14:24 -0400922 return 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500923}
924
Adrian Bunk2e1479d2008-03-17 22:29:23 +0200925static int selinux_parse_opts_str(char *options,
926 struct security_mnt_opts *opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500927{
Eric Parise0007522008-03-05 10:31:54 -0500928 char *p;
Eric Parisc9180a52007-11-30 13:00:35 -0500929 char *context = NULL, *defcontext = NULL;
930 char *fscontext = NULL, *rootcontext = NULL;
Eric Parise0007522008-03-05 10:31:54 -0500931 int rc, num_mnt_opts = 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500932
Eric Parise0007522008-03-05 10:31:54 -0500933 opts->num_mnt_opts = 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500934
935 /* Standard string-based options. */
936 while ((p = strsep(&options, "|")) != NULL) {
937 int token;
938 substring_t args[MAX_OPT_ARGS];
939
940 if (!*p)
941 continue;
942
943 token = match_token(p, tokens, args);
944
945 switch (token) {
946 case Opt_context:
947 if (context || defcontext) {
948 rc = -EINVAL;
949 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
950 goto out_err;
951 }
952 context = match_strdup(&args[0]);
953 if (!context) {
954 rc = -ENOMEM;
955 goto out_err;
956 }
957 break;
958
959 case Opt_fscontext:
960 if (fscontext) {
961 rc = -EINVAL;
962 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
963 goto out_err;
964 }
965 fscontext = match_strdup(&args[0]);
966 if (!fscontext) {
967 rc = -ENOMEM;
968 goto out_err;
969 }
970 break;
971
972 case Opt_rootcontext:
973 if (rootcontext) {
974 rc = -EINVAL;
975 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
976 goto out_err;
977 }
978 rootcontext = match_strdup(&args[0]);
979 if (!rootcontext) {
980 rc = -ENOMEM;
981 goto out_err;
982 }
983 break;
984
985 case Opt_defcontext:
986 if (context || defcontext) {
987 rc = -EINVAL;
988 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
989 goto out_err;
990 }
991 defcontext = match_strdup(&args[0]);
992 if (!defcontext) {
993 rc = -ENOMEM;
994 goto out_err;
995 }
996 break;
David P. Quigley11689d42009-01-16 09:22:03 -0500997 case Opt_labelsupport:
998 break;
Eric Parisc9180a52007-11-30 13:00:35 -0500999 default:
1000 rc = -EINVAL;
1001 printk(KERN_WARNING "SELinux: unknown mount option\n");
1002 goto out_err;
1003
1004 }
1005 }
1006
Eric Parise0007522008-03-05 10:31:54 -05001007 rc = -ENOMEM;
1008 opts->mnt_opts = kcalloc(NUM_SEL_MNT_OPTS, sizeof(char *), GFP_ATOMIC);
1009 if (!opts->mnt_opts)
1010 goto out_err;
1011
1012 opts->mnt_opts_flags = kcalloc(NUM_SEL_MNT_OPTS, sizeof(int), GFP_ATOMIC);
1013 if (!opts->mnt_opts_flags) {
1014 kfree(opts->mnt_opts);
1015 goto out_err;
Eric Parisc9180a52007-11-30 13:00:35 -05001016 }
1017
Eric Parise0007522008-03-05 10:31:54 -05001018 if (fscontext) {
1019 opts->mnt_opts[num_mnt_opts] = fscontext;
1020 opts->mnt_opts_flags[num_mnt_opts++] = FSCONTEXT_MNT;
1021 }
1022 if (context) {
1023 opts->mnt_opts[num_mnt_opts] = context;
1024 opts->mnt_opts_flags[num_mnt_opts++] = CONTEXT_MNT;
1025 }
1026 if (rootcontext) {
1027 opts->mnt_opts[num_mnt_opts] = rootcontext;
1028 opts->mnt_opts_flags[num_mnt_opts++] = ROOTCONTEXT_MNT;
1029 }
1030 if (defcontext) {
1031 opts->mnt_opts[num_mnt_opts] = defcontext;
1032 opts->mnt_opts_flags[num_mnt_opts++] = DEFCONTEXT_MNT;
1033 }
1034
1035 opts->num_mnt_opts = num_mnt_opts;
1036 return 0;
1037
Eric Parisc9180a52007-11-30 13:00:35 -05001038out_err:
1039 kfree(context);
1040 kfree(defcontext);
1041 kfree(fscontext);
1042 kfree(rootcontext);
1043 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001044}
Eric Parise0007522008-03-05 10:31:54 -05001045/*
1046 * string mount options parsing and call set the sbsec
1047 */
1048static int superblock_doinit(struct super_block *sb, void *data)
1049{
1050 int rc = 0;
1051 char *options = data;
1052 struct security_mnt_opts opts;
1053
1054 security_init_mnt_opts(&opts);
1055
1056 if (!data)
1057 goto out;
1058
1059 BUG_ON(sb->s_type->fs_flags & FS_BINARY_MOUNTDATA);
1060
1061 rc = selinux_parse_opts_str(options, &opts);
1062 if (rc)
1063 goto out_err;
1064
1065out:
David Quigley649f6e72013-05-22 12:50:36 -04001066 rc = selinux_set_mnt_opts(sb, &opts, 0, NULL);
Eric Parise0007522008-03-05 10:31:54 -05001067
1068out_err:
1069 security_free_mnt_opts(&opts);
1070 return rc;
1071}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001072
Adrian Bunk3583a712008-07-22 20:21:23 +03001073static void selinux_write_opts(struct seq_file *m,
1074 struct security_mnt_opts *opts)
Eric Paris2069f452008-07-04 09:47:13 +10001075{
1076 int i;
1077 char *prefix;
1078
1079 for (i = 0; i < opts->num_mnt_opts; i++) {
David P. Quigley11689d42009-01-16 09:22:03 -05001080 char *has_comma;
1081
1082 if (opts->mnt_opts[i])
1083 has_comma = strchr(opts->mnt_opts[i], ',');
1084 else
1085 has_comma = NULL;
Eric Paris2069f452008-07-04 09:47:13 +10001086
1087 switch (opts->mnt_opts_flags[i]) {
1088 case CONTEXT_MNT:
1089 prefix = CONTEXT_STR;
1090 break;
1091 case FSCONTEXT_MNT:
1092 prefix = FSCONTEXT_STR;
1093 break;
1094 case ROOTCONTEXT_MNT:
1095 prefix = ROOTCONTEXT_STR;
1096 break;
1097 case DEFCONTEXT_MNT:
1098 prefix = DEFCONTEXT_STR;
1099 break;
Eric Paris12f348b2012-10-09 10:56:25 -04001100 case SBLABEL_MNT:
David P. Quigley11689d42009-01-16 09:22:03 -05001101 seq_putc(m, ',');
1102 seq_puts(m, LABELSUPP_STR);
1103 continue;
Eric Paris2069f452008-07-04 09:47:13 +10001104 default:
1105 BUG();
Eric Parisa35c6c82011-04-20 10:21:28 -04001106 return;
Eric Paris2069f452008-07-04 09:47:13 +10001107 };
1108 /* we need a comma before each option */
1109 seq_putc(m, ',');
1110 seq_puts(m, prefix);
1111 if (has_comma)
1112 seq_putc(m, '\"');
Kees Cooka068acf2015-09-04 15:44:57 -07001113 seq_escape(m, opts->mnt_opts[i], "\"\n\\");
Eric Paris2069f452008-07-04 09:47:13 +10001114 if (has_comma)
1115 seq_putc(m, '\"');
1116 }
1117}
1118
1119static int selinux_sb_show_options(struct seq_file *m, struct super_block *sb)
1120{
1121 struct security_mnt_opts opts;
1122 int rc;
1123
1124 rc = selinux_get_mnt_opts(sb, &opts);
Eric Paris383795c2008-07-29 17:07:26 -04001125 if (rc) {
1126 /* before policy load we may get EINVAL, don't show anything */
1127 if (rc == -EINVAL)
1128 rc = 0;
Eric Paris2069f452008-07-04 09:47:13 +10001129 return rc;
Eric Paris383795c2008-07-29 17:07:26 -04001130 }
Eric Paris2069f452008-07-04 09:47:13 +10001131
1132 selinux_write_opts(m, &opts);
1133
1134 security_free_mnt_opts(&opts);
1135
1136 return rc;
1137}
1138
Linus Torvalds1da177e2005-04-16 15:20:36 -07001139static inline u16 inode_mode_to_security_class(umode_t mode)
1140{
1141 switch (mode & S_IFMT) {
1142 case S_IFSOCK:
1143 return SECCLASS_SOCK_FILE;
1144 case S_IFLNK:
1145 return SECCLASS_LNK_FILE;
1146 case S_IFREG:
1147 return SECCLASS_FILE;
1148 case S_IFBLK:
1149 return SECCLASS_BLK_FILE;
1150 case S_IFDIR:
1151 return SECCLASS_DIR;
1152 case S_IFCHR:
1153 return SECCLASS_CHR_FILE;
1154 case S_IFIFO:
1155 return SECCLASS_FIFO_FILE;
1156
1157 }
1158
1159 return SECCLASS_FILE;
1160}
1161
James Morris13402582005-09-30 14:24:34 -04001162static inline int default_protocol_stream(int protocol)
1163{
1164 return (protocol == IPPROTO_IP || protocol == IPPROTO_TCP);
1165}
1166
1167static inline int default_protocol_dgram(int protocol)
1168{
1169 return (protocol == IPPROTO_IP || protocol == IPPROTO_UDP);
1170}
1171
Linus Torvalds1da177e2005-04-16 15:20:36 -07001172static inline u16 socket_type_to_security_class(int family, int type, int protocol)
1173{
1174 switch (family) {
1175 case PF_UNIX:
1176 switch (type) {
1177 case SOCK_STREAM:
1178 case SOCK_SEQPACKET:
1179 return SECCLASS_UNIX_STREAM_SOCKET;
1180 case SOCK_DGRAM:
1181 return SECCLASS_UNIX_DGRAM_SOCKET;
1182 }
1183 break;
1184 case PF_INET:
1185 case PF_INET6:
1186 switch (type) {
1187 case SOCK_STREAM:
James Morris13402582005-09-30 14:24:34 -04001188 if (default_protocol_stream(protocol))
1189 return SECCLASS_TCP_SOCKET;
1190 else
1191 return SECCLASS_RAWIP_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001192 case SOCK_DGRAM:
James Morris13402582005-09-30 14:24:34 -04001193 if (default_protocol_dgram(protocol))
1194 return SECCLASS_UDP_SOCKET;
1195 else
1196 return SECCLASS_RAWIP_SOCKET;
James Morris2ee92d42006-11-13 16:09:01 -08001197 case SOCK_DCCP:
1198 return SECCLASS_DCCP_SOCKET;
James Morris13402582005-09-30 14:24:34 -04001199 default:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001200 return SECCLASS_RAWIP_SOCKET;
1201 }
1202 break;
1203 case PF_NETLINK:
1204 switch (protocol) {
1205 case NETLINK_ROUTE:
1206 return SECCLASS_NETLINK_ROUTE_SOCKET;
Pavel Emelyanov7f1fb602011-12-06 07:56:43 +00001207 case NETLINK_SOCK_DIAG:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208 return SECCLASS_NETLINK_TCPDIAG_SOCKET;
1209 case NETLINK_NFLOG:
1210 return SECCLASS_NETLINK_NFLOG_SOCKET;
1211 case NETLINK_XFRM:
1212 return SECCLASS_NETLINK_XFRM_SOCKET;
1213 case NETLINK_SELINUX:
1214 return SECCLASS_NETLINK_SELINUX_SOCKET;
Stephen Smalley6c6d2e92015-06-04 16:22:16 -04001215 case NETLINK_ISCSI:
1216 return SECCLASS_NETLINK_ISCSI_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001217 case NETLINK_AUDIT:
1218 return SECCLASS_NETLINK_AUDIT_SOCKET;
Stephen Smalley6c6d2e92015-06-04 16:22:16 -04001219 case NETLINK_FIB_LOOKUP:
1220 return SECCLASS_NETLINK_FIB_LOOKUP_SOCKET;
1221 case NETLINK_CONNECTOR:
1222 return SECCLASS_NETLINK_CONNECTOR_SOCKET;
1223 case NETLINK_NETFILTER:
1224 return SECCLASS_NETLINK_NETFILTER_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001225 case NETLINK_DNRTMSG:
1226 return SECCLASS_NETLINK_DNRT_SOCKET;
James Morris0c9b7942005-04-16 15:24:13 -07001227 case NETLINK_KOBJECT_UEVENT:
1228 return SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET;
Stephen Smalley6c6d2e92015-06-04 16:22:16 -04001229 case NETLINK_GENERIC:
1230 return SECCLASS_NETLINK_GENERIC_SOCKET;
1231 case NETLINK_SCSITRANSPORT:
1232 return SECCLASS_NETLINK_SCSITRANSPORT_SOCKET;
1233 case NETLINK_RDMA:
1234 return SECCLASS_NETLINK_RDMA_SOCKET;
1235 case NETLINK_CRYPTO:
1236 return SECCLASS_NETLINK_CRYPTO_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001237 default:
1238 return SECCLASS_NETLINK_SOCKET;
1239 }
1240 case PF_PACKET:
1241 return SECCLASS_PACKET_SOCKET;
1242 case PF_KEY:
1243 return SECCLASS_KEY_SOCKET;
Christopher J. PeBenito3e3ff152006-06-09 00:25:03 -07001244 case PF_APPLETALK:
1245 return SECCLASS_APPLETALK_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001246 }
1247
1248 return SECCLASS_SOCKET;
1249}
1250
Stephen Smalley134509d2015-06-04 16:22:17 -04001251static int selinux_genfs_get_sid(struct dentry *dentry,
1252 u16 tclass,
1253 u16 flags,
1254 u32 *sid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001255{
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001256 int rc;
Stephen Smalley134509d2015-06-04 16:22:17 -04001257 struct super_block *sb = dentry->d_inode->i_sb;
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001258 char *buffer, *path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001259
Eric Paris828dfe12008-04-17 13:17:49 -04001260 buffer = (char *)__get_free_page(GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001261 if (!buffer)
1262 return -ENOMEM;
1263
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001264 path = dentry_path_raw(dentry, buffer, PAGE_SIZE);
1265 if (IS_ERR(path))
1266 rc = PTR_ERR(path);
1267 else {
Stephen Smalley134509d2015-06-04 16:22:17 -04001268 if (flags & SE_SBPROC) {
1269 /* each process gets a /proc/PID/ entry. Strip off the
1270 * PID part to get a valid selinux labeling.
1271 * e.g. /proc/1/net/rpc/nfs -> /net/rpc/nfs */
1272 while (path[1] >= '0' && path[1] <= '9') {
1273 path[1] = '/';
1274 path++;
1275 }
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001276 }
Stephen Smalley134509d2015-06-04 16:22:17 -04001277 rc = security_genfs_sid(sb->s_type->name, path, tclass, sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001278 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001279 free_page((unsigned long)buffer);
1280 return rc;
1281}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001282
1283/* The inode's security attributes must be initialized before first use. */
1284static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry)
1285{
1286 struct superblock_security_struct *sbsec = NULL;
1287 struct inode_security_struct *isec = inode->i_security;
1288 u32 sid;
1289 struct dentry *dentry;
1290#define INITCONTEXTLEN 255
1291 char *context = NULL;
1292 unsigned len = 0;
1293 int rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001294
1295 if (isec->initialized)
1296 goto out;
1297
Eric Paris23970742006-09-25 23:32:01 -07001298 mutex_lock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001299 if (isec->initialized)
Eric Paris23970742006-09-25 23:32:01 -07001300 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001301
1302 sbsec = inode->i_sb->s_security;
David P. Quigley0d90a7e2009-01-16 09:22:02 -05001303 if (!(sbsec->flags & SE_SBINITIALIZED)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001304 /* Defer initialization until selinux_complete_init,
1305 after the initial policy is loaded and the security
1306 server is ready to handle calls. */
1307 spin_lock(&sbsec->isec_lock);
1308 if (list_empty(&isec->list))
1309 list_add(&isec->list, &sbsec->isec_head);
1310 spin_unlock(&sbsec->isec_lock);
Eric Paris23970742006-09-25 23:32:01 -07001311 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001312 }
1313
1314 switch (sbsec->behavior) {
David Quigleyeb9ae682013-05-22 12:50:37 -04001315 case SECURITY_FS_USE_NATIVE:
1316 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001317 case SECURITY_FS_USE_XATTR:
1318 if (!inode->i_op->getxattr) {
1319 isec->sid = sbsec->def_sid;
1320 break;
1321 }
1322
1323 /* Need a dentry, since the xattr API requires one.
1324 Life would be simpler if we could just pass the inode. */
1325 if (opt_dentry) {
1326 /* Called from d_instantiate or d_splice_alias. */
1327 dentry = dget(opt_dentry);
1328 } else {
1329 /* Called from selinux_complete_init, try to find a dentry. */
1330 dentry = d_find_alias(inode);
1331 }
1332 if (!dentry) {
Eric Parisdf7f54c2009-03-09 14:35:58 -04001333 /*
1334 * this is can be hit on boot when a file is accessed
1335 * before the policy is loaded. When we load policy we
1336 * may find inodes that have no dentry on the
1337 * sbsec->isec_head list. No reason to complain as these
1338 * will get fixed up the next time we go through
1339 * inode_doinit with a dentry, before these inodes could
1340 * be used again by userspace.
1341 */
Eric Paris23970742006-09-25 23:32:01 -07001342 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001343 }
1344
1345 len = INITCONTEXTLEN;
Eric Paris4cb912f2009-02-12 14:50:05 -05001346 context = kmalloc(len+1, GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001347 if (!context) {
1348 rc = -ENOMEM;
1349 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001350 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001351 }
Eric Paris4cb912f2009-02-12 14:50:05 -05001352 context[len] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001353 rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX,
1354 context, len);
1355 if (rc == -ERANGE) {
James Morris314dabb2009-08-10 22:00:13 +10001356 kfree(context);
1357
Linus Torvalds1da177e2005-04-16 15:20:36 -07001358 /* Need a larger buffer. Query for the right size. */
1359 rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX,
1360 NULL, 0);
1361 if (rc < 0) {
1362 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001363 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001364 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001365 len = rc;
Eric Paris4cb912f2009-02-12 14:50:05 -05001366 context = kmalloc(len+1, GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001367 if (!context) {
1368 rc = -ENOMEM;
1369 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001370 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001371 }
Eric Paris4cb912f2009-02-12 14:50:05 -05001372 context[len] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001373 rc = inode->i_op->getxattr(dentry,
1374 XATTR_NAME_SELINUX,
1375 context, len);
1376 }
1377 dput(dentry);
1378 if (rc < 0) {
1379 if (rc != -ENODATA) {
Eric Paris744ba352008-04-17 11:52:44 -04001380 printk(KERN_WARNING "SELinux: %s: getxattr returned "
Harvey Harrisondd6f9532008-03-06 10:03:59 +11001381 "%d for dev=%s ino=%ld\n", __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001382 -rc, inode->i_sb->s_id, inode->i_ino);
1383 kfree(context);
Eric Paris23970742006-09-25 23:32:01 -07001384 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001385 }
1386 /* Map ENODATA to the default file SID */
1387 sid = sbsec->def_sid;
1388 rc = 0;
1389 } else {
James Morrisf5c1d5b2005-07-28 01:07:37 -07001390 rc = security_context_to_sid_default(context, rc, &sid,
Stephen Smalley869ab512008-04-04 08:46:05 -04001391 sbsec->def_sid,
1392 GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001393 if (rc) {
Eric Paris4ba0a8a2009-02-12 15:01:10 -05001394 char *dev = inode->i_sb->s_id;
1395 unsigned long ino = inode->i_ino;
1396
1397 if (rc == -EINVAL) {
1398 if (printk_ratelimit())
1399 printk(KERN_NOTICE "SELinux: inode=%lu on dev=%s was found to have an invalid "
1400 "context=%s. This indicates you may need to relabel the inode or the "
1401 "filesystem in question.\n", ino, dev, context);
1402 } else {
1403 printk(KERN_WARNING "SELinux: %s: context_to_sid(%s) "
1404 "returned %d for dev=%s ino=%ld\n",
1405 __func__, context, -rc, dev, ino);
1406 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001407 kfree(context);
1408 /* Leave with the unlabeled SID */
1409 rc = 0;
1410 break;
1411 }
1412 }
1413 kfree(context);
1414 isec->sid = sid;
1415 break;
1416 case SECURITY_FS_USE_TASK:
1417 isec->sid = isec->task_sid;
1418 break;
1419 case SECURITY_FS_USE_TRANS:
1420 /* Default to the fs SID. */
1421 isec->sid = sbsec->sid;
1422
1423 /* Try to obtain a transition SID. */
1424 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Eric Paris652bb9b2011-02-01 11:05:40 -05001425 rc = security_transition_sid(isec->task_sid, sbsec->sid,
1426 isec->sclass, NULL, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001427 if (rc)
Eric Paris23970742006-09-25 23:32:01 -07001428 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001429 isec->sid = sid;
1430 break;
Eric Parisc312feb2006-07-10 04:43:53 -07001431 case SECURITY_FS_USE_MNTPOINT:
1432 isec->sid = sbsec->mntpoint_sid;
1433 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001434 default:
Eric Parisc312feb2006-07-10 04:43:53 -07001435 /* Default to the fs superblock SID. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001436 isec->sid = sbsec->sid;
1437
Stephen Smalley134509d2015-06-04 16:22:17 -04001438 if ((sbsec->flags & SE_SBGENFS) && !S_ISLNK(inode->i_mode)) {
Paul Mooref64410e2014-03-19 16:46:18 -04001439 /* We must have a dentry to determine the label on
1440 * procfs inodes */
1441 if (opt_dentry)
1442 /* Called from d_instantiate or
1443 * d_splice_alias. */
1444 dentry = dget(opt_dentry);
1445 else
1446 /* Called from selinux_complete_init, try to
1447 * find a dentry. */
1448 dentry = d_find_alias(inode);
1449 /*
1450 * This can be hit on boot when a file is accessed
1451 * before the policy is loaded. When we load policy we
1452 * may find inodes that have no dentry on the
1453 * sbsec->isec_head list. No reason to complain as
1454 * these will get fixed up the next time we go through
1455 * inode_doinit() with a dentry, before these inodes
1456 * could be used again by userspace.
1457 */
1458 if (!dentry)
1459 goto out_unlock;
1460 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Stephen Smalley134509d2015-06-04 16:22:17 -04001461 rc = selinux_genfs_get_sid(dentry, isec->sclass,
1462 sbsec->flags, &sid);
Paul Mooref64410e2014-03-19 16:46:18 -04001463 dput(dentry);
1464 if (rc)
1465 goto out_unlock;
1466 isec->sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001467 }
1468 break;
1469 }
1470
1471 isec->initialized = 1;
1472
Eric Paris23970742006-09-25 23:32:01 -07001473out_unlock:
1474 mutex_unlock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001475out:
1476 if (isec->sclass == SECCLASS_FILE)
1477 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001478 return rc;
1479}
1480
1481/* Convert a Linux signal to an access vector. */
1482static inline u32 signal_to_av(int sig)
1483{
1484 u32 perm = 0;
1485
1486 switch (sig) {
1487 case SIGCHLD:
1488 /* Commonly granted from child to parent. */
1489 perm = PROCESS__SIGCHLD;
1490 break;
1491 case SIGKILL:
1492 /* Cannot be caught or ignored */
1493 perm = PROCESS__SIGKILL;
1494 break;
1495 case SIGSTOP:
1496 /* Cannot be caught or ignored */
1497 perm = PROCESS__SIGSTOP;
1498 break;
1499 default:
1500 /* All other signals. */
1501 perm = PROCESS__SIGNAL;
1502 break;
1503 }
1504
1505 return perm;
1506}
1507
David Howells275bb412008-11-14 10:39:19 +11001508/*
David Howellsd84f4f92008-11-14 10:39:23 +11001509 * Check permission between a pair of credentials
1510 * fork check, ptrace check, etc.
1511 */
1512static int cred_has_perm(const struct cred *actor,
1513 const struct cred *target,
1514 u32 perms)
1515{
1516 u32 asid = cred_sid(actor), tsid = cred_sid(target);
1517
1518 return avc_has_perm(asid, tsid, SECCLASS_PROCESS, perms, NULL);
1519}
1520
1521/*
David Howells88e67f32008-11-14 10:39:21 +11001522 * Check permission between a pair of tasks, e.g. signal checks,
David Howells275bb412008-11-14 10:39:19 +11001523 * fork check, ptrace check, etc.
1524 * tsk1 is the actor and tsk2 is the target
David Howells3b11a1d2008-11-14 10:39:26 +11001525 * - this uses the default subjective creds of tsk1
David Howells275bb412008-11-14 10:39:19 +11001526 */
1527static int task_has_perm(const struct task_struct *tsk1,
1528 const struct task_struct *tsk2,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001529 u32 perms)
1530{
David Howells275bb412008-11-14 10:39:19 +11001531 const struct task_security_struct *__tsec1, *__tsec2;
1532 u32 sid1, sid2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001533
David Howells275bb412008-11-14 10:39:19 +11001534 rcu_read_lock();
1535 __tsec1 = __task_cred(tsk1)->security; sid1 = __tsec1->sid;
1536 __tsec2 = __task_cred(tsk2)->security; sid2 = __tsec2->sid;
1537 rcu_read_unlock();
1538 return avc_has_perm(sid1, sid2, SECCLASS_PROCESS, perms, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001539}
1540
David Howells3b11a1d2008-11-14 10:39:26 +11001541/*
1542 * Check permission between current and another task, e.g. signal checks,
1543 * fork check, ptrace check, etc.
1544 * current is the actor and tsk2 is the target
1545 * - this uses current's subjective creds
1546 */
1547static int current_has_perm(const struct task_struct *tsk,
1548 u32 perms)
1549{
1550 u32 sid, tsid;
1551
1552 sid = current_sid();
1553 tsid = task_sid(tsk);
1554 return avc_has_perm(sid, tsid, SECCLASS_PROCESS, perms, NULL);
1555}
1556
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001557#if CAP_LAST_CAP > 63
1558#error Fix SELinux to handle capabilities > 63.
1559#endif
1560
Linus Torvalds1da177e2005-04-16 15:20:36 -07001561/* Check whether a task is allowed to use a capability. */
Eric Paris6a9de492012-01-03 12:25:14 -05001562static int cred_has_capability(const struct cred *cred,
Eric Paris06112162008-11-11 22:02:50 +11001563 int cap, int audit)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001564{
Thomas Liu2bf49692009-07-14 12:14:09 -04001565 struct common_audit_data ad;
Eric Paris06112162008-11-11 22:02:50 +11001566 struct av_decision avd;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001567 u16 sclass;
David Howells3699c532009-01-06 22:27:01 +00001568 u32 sid = cred_sid(cred);
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001569 u32 av = CAP_TO_MASK(cap);
Eric Paris06112162008-11-11 22:02:50 +11001570 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001571
Eric Paris50c205f2012-04-04 15:01:43 -04001572 ad.type = LSM_AUDIT_DATA_CAP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001573 ad.u.cap = cap;
1574
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001575 switch (CAP_TO_INDEX(cap)) {
1576 case 0:
1577 sclass = SECCLASS_CAPABILITY;
1578 break;
1579 case 1:
1580 sclass = SECCLASS_CAPABILITY2;
1581 break;
1582 default:
1583 printk(KERN_ERR
1584 "SELinux: out of range capability %d\n", cap);
1585 BUG();
Eric Parisa35c6c82011-04-20 10:21:28 -04001586 return -EINVAL;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001587 }
Eric Paris06112162008-11-11 22:02:50 +11001588
David Howells275bb412008-11-14 10:39:19 +11001589 rc = avc_has_perm_noaudit(sid, sid, sclass, av, 0, &avd);
Eric Paris9ade0cf2011-04-25 16:26:29 -04001590 if (audit == SECURITY_CAP_AUDIT) {
NeilBrown7b20ea22015-03-23 13:37:39 +11001591 int rc2 = avc_audit(sid, sid, sclass, av, &avd, rc, &ad, 0);
Eric Paris9ade0cf2011-04-25 16:26:29 -04001592 if (rc2)
1593 return rc2;
1594 }
Eric Paris06112162008-11-11 22:02:50 +11001595 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001596}
1597
1598/* Check whether a task is allowed to use a system operation. */
1599static int task_has_system(struct task_struct *tsk,
1600 u32 perms)
1601{
David Howells275bb412008-11-14 10:39:19 +11001602 u32 sid = task_sid(tsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001603
David Howells275bb412008-11-14 10:39:19 +11001604 return avc_has_perm(sid, SECINITSID_KERNEL,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001605 SECCLASS_SYSTEM, perms, NULL);
1606}
1607
1608/* Check whether a task has a particular permission to an inode.
1609 The 'adp' parameter is optional and allows other audit
1610 data to be passed (e.g. the dentry). */
David Howells88e67f32008-11-14 10:39:21 +11001611static int inode_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001612 struct inode *inode,
1613 u32 perms,
Linus Torvalds19e49832013-10-04 12:54:11 -07001614 struct common_audit_data *adp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001615{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001616 struct inode_security_struct *isec;
David Howells275bb412008-11-14 10:39:19 +11001617 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001618
David Howellse0e81732009-09-02 09:13:40 +01001619 validate_creds(cred);
1620
Eric Paris828dfe12008-04-17 13:17:49 -04001621 if (unlikely(IS_PRIVATE(inode)))
Stephen Smalleybbaca6c2007-02-14 00:34:16 -08001622 return 0;
1623
David Howells88e67f32008-11-14 10:39:21 +11001624 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001625 isec = inode->i_security;
1626
Linus Torvalds19e49832013-10-04 12:54:11 -07001627 return avc_has_perm(sid, isec->sid, isec->sclass, perms, adp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001628}
1629
1630/* Same as inode_has_perm, but pass explicit audit data containing
1631 the dentry to help the auditing code to more easily generate the
1632 pathname if needed. */
David Howells88e67f32008-11-14 10:39:21 +11001633static inline int dentry_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001634 struct dentry *dentry,
1635 u32 av)
1636{
David Howellsc6f493d2015-03-17 22:26:22 +00001637 struct inode *inode = d_backing_inode(dentry);
Thomas Liu2bf49692009-07-14 12:14:09 -04001638 struct common_audit_data ad;
David Howells88e67f32008-11-14 10:39:21 +11001639
Eric Paris50c205f2012-04-04 15:01:43 -04001640 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Paris2875fa02011-04-28 16:04:24 -04001641 ad.u.dentry = dentry;
Linus Torvalds19e49832013-10-04 12:54:11 -07001642 return inode_has_perm(cred, inode, av, &ad);
Eric Paris2875fa02011-04-28 16:04:24 -04001643}
1644
1645/* Same as inode_has_perm, but pass explicit audit data containing
1646 the path to help the auditing code to more easily generate the
1647 pathname if needed. */
1648static inline int path_has_perm(const struct cred *cred,
Al Viro3f7036a2015-03-08 19:28:30 -04001649 const struct path *path,
Eric Paris2875fa02011-04-28 16:04:24 -04001650 u32 av)
1651{
David Howellsc6f493d2015-03-17 22:26:22 +00001652 struct inode *inode = d_backing_inode(path->dentry);
Eric Paris2875fa02011-04-28 16:04:24 -04001653 struct common_audit_data ad;
1654
Eric Paris50c205f2012-04-04 15:01:43 -04001655 ad.type = LSM_AUDIT_DATA_PATH;
Eric Paris2875fa02011-04-28 16:04:24 -04001656 ad.u.path = *path;
Linus Torvalds19e49832013-10-04 12:54:11 -07001657 return inode_has_perm(cred, inode, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001658}
1659
David Howells13f8e982013-06-13 23:37:55 +01001660/* Same as path_has_perm, but uses the inode from the file struct. */
1661static inline int file_path_has_perm(const struct cred *cred,
1662 struct file *file,
1663 u32 av)
1664{
1665 struct common_audit_data ad;
1666
1667 ad.type = LSM_AUDIT_DATA_PATH;
1668 ad.u.path = file->f_path;
Linus Torvalds19e49832013-10-04 12:54:11 -07001669 return inode_has_perm(cred, file_inode(file), av, &ad);
David Howells13f8e982013-06-13 23:37:55 +01001670}
1671
Linus Torvalds1da177e2005-04-16 15:20:36 -07001672/* Check whether a task can use an open file descriptor to
1673 access an inode in a given way. Check access to the
1674 descriptor itself, and then use dentry_has_perm to
1675 check a particular permission to the file.
1676 Access to the descriptor is implicitly granted if it
1677 has the same SID as the process. If av is zero, then
1678 access to the file is not checked, e.g. for cases
1679 where only the descriptor is affected like seek. */
David Howells88e67f32008-11-14 10:39:21 +11001680static int file_has_perm(const struct cred *cred,
1681 struct file *file,
1682 u32 av)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001683{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001684 struct file_security_struct *fsec = file->f_security;
Al Viro496ad9a2013-01-23 17:07:38 -05001685 struct inode *inode = file_inode(file);
Thomas Liu2bf49692009-07-14 12:14:09 -04001686 struct common_audit_data ad;
David Howells88e67f32008-11-14 10:39:21 +11001687 u32 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001688 int rc;
1689
Eric Paris50c205f2012-04-04 15:01:43 -04001690 ad.type = LSM_AUDIT_DATA_PATH;
Eric Parisf48b7392011-04-25 12:54:27 -04001691 ad.u.path = file->f_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001692
David Howells275bb412008-11-14 10:39:19 +11001693 if (sid != fsec->sid) {
1694 rc = avc_has_perm(sid, fsec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001695 SECCLASS_FD,
1696 FD__USE,
1697 &ad);
1698 if (rc)
David Howells88e67f32008-11-14 10:39:21 +11001699 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001700 }
1701
1702 /* av is zero if only checking access to the descriptor. */
David Howells88e67f32008-11-14 10:39:21 +11001703 rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001704 if (av)
Linus Torvalds19e49832013-10-04 12:54:11 -07001705 rc = inode_has_perm(cred, inode, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001706
David Howells88e67f32008-11-14 10:39:21 +11001707out:
1708 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001709}
1710
David Howellsc3c188b2015-07-10 17:19:58 -04001711/*
1712 * Determine the label for an inode that might be unioned.
1713 */
1714static int selinux_determine_inode_label(const struct inode *dir,
1715 const struct qstr *name,
1716 u16 tclass,
1717 u32 *_new_isid)
1718{
1719 const struct superblock_security_struct *sbsec = dir->i_sb->s_security;
1720 const struct inode_security_struct *dsec = dir->i_security;
1721 const struct task_security_struct *tsec = current_security();
1722
1723 if ((sbsec->flags & SE_SBINITIALIZED) &&
1724 (sbsec->behavior == SECURITY_FS_USE_MNTPOINT)) {
1725 *_new_isid = sbsec->mntpoint_sid;
1726 } else if ((sbsec->flags & SBLABEL_MNT) &&
1727 tsec->create_sid) {
1728 *_new_isid = tsec->create_sid;
1729 } else {
1730 return security_transition_sid(tsec->sid, dsec->sid, tclass,
1731 name, _new_isid);
1732 }
1733
1734 return 0;
1735}
1736
Linus Torvalds1da177e2005-04-16 15:20:36 -07001737/* Check whether a task can create a file. */
1738static int may_create(struct inode *dir,
1739 struct dentry *dentry,
1740 u16 tclass)
1741{
Paul Moore5fb49872010-04-22 14:46:19 -04001742 const struct task_security_struct *tsec = current_security();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001743 struct inode_security_struct *dsec;
1744 struct superblock_security_struct *sbsec;
David Howells275bb412008-11-14 10:39:19 +11001745 u32 sid, newsid;
Thomas Liu2bf49692009-07-14 12:14:09 -04001746 struct common_audit_data ad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001747 int rc;
1748
Linus Torvalds1da177e2005-04-16 15:20:36 -07001749 dsec = dir->i_security;
1750 sbsec = dir->i_sb->s_security;
1751
David Howells275bb412008-11-14 10:39:19 +11001752 sid = tsec->sid;
David Howells275bb412008-11-14 10:39:19 +11001753
Eric Paris50c205f2012-04-04 15:01:43 -04001754 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04001755 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001756
David Howells275bb412008-11-14 10:39:19 +11001757 rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001758 DIR__ADD_NAME | DIR__SEARCH,
1759 &ad);
1760 if (rc)
1761 return rc;
1762
David Howellsc3c188b2015-07-10 17:19:58 -04001763 rc = selinux_determine_inode_label(dir, &dentry->d_name, tclass,
1764 &newsid);
1765 if (rc)
1766 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001767
David Howells275bb412008-11-14 10:39:19 +11001768 rc = avc_has_perm(sid, newsid, tclass, FILE__CREATE, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001769 if (rc)
1770 return rc;
1771
1772 return avc_has_perm(newsid, sbsec->sid,
1773 SECCLASS_FILESYSTEM,
1774 FILESYSTEM__ASSOCIATE, &ad);
1775}
1776
Michael LeMay4eb582c2006-06-26 00:24:57 -07001777/* Check whether a task can create a key. */
1778static int may_create_key(u32 ksid,
1779 struct task_struct *ctx)
1780{
David Howells275bb412008-11-14 10:39:19 +11001781 u32 sid = task_sid(ctx);
Michael LeMay4eb582c2006-06-26 00:24:57 -07001782
David Howells275bb412008-11-14 10:39:19 +11001783 return avc_has_perm(sid, ksid, SECCLASS_KEY, KEY__CREATE, NULL);
Michael LeMay4eb582c2006-06-26 00:24:57 -07001784}
1785
Eric Paris828dfe12008-04-17 13:17:49 -04001786#define MAY_LINK 0
1787#define MAY_UNLINK 1
1788#define MAY_RMDIR 2
Linus Torvalds1da177e2005-04-16 15:20:36 -07001789
1790/* Check whether a task can link, unlink, or rmdir a file/directory. */
1791static int may_link(struct inode *dir,
1792 struct dentry *dentry,
1793 int kind)
1794
1795{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001796 struct inode_security_struct *dsec, *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04001797 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11001798 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001799 u32 av;
1800 int rc;
1801
Linus Torvalds1da177e2005-04-16 15:20:36 -07001802 dsec = dir->i_security;
David Howellsc6f493d2015-03-17 22:26:22 +00001803 isec = d_backing_inode(dentry)->i_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001804
Eric Paris50c205f2012-04-04 15:01:43 -04001805 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04001806 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001807
1808 av = DIR__SEARCH;
1809 av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME);
David Howells275bb412008-11-14 10:39:19 +11001810 rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001811 if (rc)
1812 return rc;
1813
1814 switch (kind) {
1815 case MAY_LINK:
1816 av = FILE__LINK;
1817 break;
1818 case MAY_UNLINK:
1819 av = FILE__UNLINK;
1820 break;
1821 case MAY_RMDIR:
1822 av = DIR__RMDIR;
1823 break;
1824 default:
Eric Paris744ba352008-04-17 11:52:44 -04001825 printk(KERN_WARNING "SELinux: %s: unrecognized kind %d\n",
1826 __func__, kind);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001827 return 0;
1828 }
1829
David Howells275bb412008-11-14 10:39:19 +11001830 rc = avc_has_perm(sid, isec->sid, isec->sclass, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001831 return rc;
1832}
1833
1834static inline int may_rename(struct inode *old_dir,
1835 struct dentry *old_dentry,
1836 struct inode *new_dir,
1837 struct dentry *new_dentry)
1838{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001839 struct inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04001840 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11001841 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001842 u32 av;
1843 int old_is_dir, new_is_dir;
1844 int rc;
1845
Linus Torvalds1da177e2005-04-16 15:20:36 -07001846 old_dsec = old_dir->i_security;
David Howellsc6f493d2015-03-17 22:26:22 +00001847 old_isec = d_backing_inode(old_dentry)->i_security;
David Howellse36cb0b2015-01-29 12:02:35 +00001848 old_is_dir = d_is_dir(old_dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001849 new_dsec = new_dir->i_security;
1850
Eric Paris50c205f2012-04-04 15:01:43 -04001851 ad.type = LSM_AUDIT_DATA_DENTRY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001852
Eric Parisa2694342011-04-25 13:10:27 -04001853 ad.u.dentry = old_dentry;
David Howells275bb412008-11-14 10:39:19 +11001854 rc = avc_has_perm(sid, old_dsec->sid, SECCLASS_DIR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001855 DIR__REMOVE_NAME | DIR__SEARCH, &ad);
1856 if (rc)
1857 return rc;
David Howells275bb412008-11-14 10:39:19 +11001858 rc = avc_has_perm(sid, old_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001859 old_isec->sclass, FILE__RENAME, &ad);
1860 if (rc)
1861 return rc;
1862 if (old_is_dir && new_dir != old_dir) {
David Howells275bb412008-11-14 10:39:19 +11001863 rc = avc_has_perm(sid, old_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001864 old_isec->sclass, DIR__REPARENT, &ad);
1865 if (rc)
1866 return rc;
1867 }
1868
Eric Parisa2694342011-04-25 13:10:27 -04001869 ad.u.dentry = new_dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001870 av = DIR__ADD_NAME | DIR__SEARCH;
David Howells2c616d42015-01-29 12:02:33 +00001871 if (d_is_positive(new_dentry))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001872 av |= DIR__REMOVE_NAME;
David Howells275bb412008-11-14 10:39:19 +11001873 rc = avc_has_perm(sid, new_dsec->sid, SECCLASS_DIR, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001874 if (rc)
1875 return rc;
David Howells2c616d42015-01-29 12:02:33 +00001876 if (d_is_positive(new_dentry)) {
David Howellsc6f493d2015-03-17 22:26:22 +00001877 new_isec = d_backing_inode(new_dentry)->i_security;
David Howellse36cb0b2015-01-29 12:02:35 +00001878 new_is_dir = d_is_dir(new_dentry);
David Howells275bb412008-11-14 10:39:19 +11001879 rc = avc_has_perm(sid, new_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001880 new_isec->sclass,
1881 (new_is_dir ? DIR__RMDIR : FILE__UNLINK), &ad);
1882 if (rc)
1883 return rc;
1884 }
1885
1886 return 0;
1887}
1888
1889/* Check whether a task can perform a filesystem operation. */
David Howells88e67f32008-11-14 10:39:21 +11001890static int superblock_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001891 struct super_block *sb,
1892 u32 perms,
Thomas Liu2bf49692009-07-14 12:14:09 -04001893 struct common_audit_data *ad)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001894{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001895 struct superblock_security_struct *sbsec;
David Howells88e67f32008-11-14 10:39:21 +11001896 u32 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001897
Linus Torvalds1da177e2005-04-16 15:20:36 -07001898 sbsec = sb->s_security;
David Howells275bb412008-11-14 10:39:19 +11001899 return avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM, perms, ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001900}
1901
1902/* Convert a Linux mode and permission mask to an access vector. */
1903static inline u32 file_mask_to_av(int mode, int mask)
1904{
1905 u32 av = 0;
1906
Al Virodba19c62011-07-25 20:49:29 -04001907 if (!S_ISDIR(mode)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001908 if (mask & MAY_EXEC)
1909 av |= FILE__EXECUTE;
1910 if (mask & MAY_READ)
1911 av |= FILE__READ;
1912
1913 if (mask & MAY_APPEND)
1914 av |= FILE__APPEND;
1915 else if (mask & MAY_WRITE)
1916 av |= FILE__WRITE;
1917
1918 } else {
1919 if (mask & MAY_EXEC)
1920 av |= DIR__SEARCH;
1921 if (mask & MAY_WRITE)
1922 av |= DIR__WRITE;
1923 if (mask & MAY_READ)
1924 av |= DIR__READ;
1925 }
1926
1927 return av;
1928}
1929
1930/* Convert a Linux file to an access vector. */
1931static inline u32 file_to_av(struct file *file)
1932{
1933 u32 av = 0;
1934
1935 if (file->f_mode & FMODE_READ)
1936 av |= FILE__READ;
1937 if (file->f_mode & FMODE_WRITE) {
1938 if (file->f_flags & O_APPEND)
1939 av |= FILE__APPEND;
1940 else
1941 av |= FILE__WRITE;
1942 }
Stephen Smalley0794c662008-03-17 08:55:18 -04001943 if (!av) {
1944 /*
1945 * Special file opened with flags 3 for ioctl-only use.
1946 */
1947 av = FILE__IOCTL;
1948 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001949
1950 return av;
1951}
1952
Eric Paris8b6a5a32008-10-29 17:06:46 -04001953/*
1954 * Convert a file to an access vector and include the correct open
1955 * open permission.
1956 */
1957static inline u32 open_file_to_av(struct file *file)
1958{
1959 u32 av = file_to_av(file);
1960
Eric Paris49b7b8d2010-07-23 11:44:09 -04001961 if (selinux_policycap_openperm)
1962 av |= FILE__OPEN;
1963
Eric Paris8b6a5a32008-10-29 17:06:46 -04001964 return av;
1965}
1966
Linus Torvalds1da177e2005-04-16 15:20:36 -07001967/* Hook functions begin here. */
1968
Stephen Smalley79af7302015-01-21 10:54:10 -05001969static int selinux_binder_set_context_mgr(struct task_struct *mgr)
1970{
1971 u32 mysid = current_sid();
1972 u32 mgrsid = task_sid(mgr);
1973
1974 return avc_has_perm(mysid, mgrsid, SECCLASS_BINDER,
1975 BINDER__SET_CONTEXT_MGR, NULL);
1976}
1977
1978static int selinux_binder_transaction(struct task_struct *from,
1979 struct task_struct *to)
1980{
1981 u32 mysid = current_sid();
1982 u32 fromsid = task_sid(from);
1983 u32 tosid = task_sid(to);
1984 int rc;
1985
1986 if (mysid != fromsid) {
1987 rc = avc_has_perm(mysid, fromsid, SECCLASS_BINDER,
1988 BINDER__IMPERSONATE, NULL);
1989 if (rc)
1990 return rc;
1991 }
1992
1993 return avc_has_perm(fromsid, tosid, SECCLASS_BINDER, BINDER__CALL,
1994 NULL);
1995}
1996
1997static int selinux_binder_transfer_binder(struct task_struct *from,
1998 struct task_struct *to)
1999{
2000 u32 fromsid = task_sid(from);
2001 u32 tosid = task_sid(to);
2002
2003 return avc_has_perm(fromsid, tosid, SECCLASS_BINDER, BINDER__TRANSFER,
2004 NULL);
2005}
2006
2007static int selinux_binder_transfer_file(struct task_struct *from,
2008 struct task_struct *to,
2009 struct file *file)
2010{
2011 u32 sid = task_sid(to);
2012 struct file_security_struct *fsec = file->f_security;
David Howellsc6f493d2015-03-17 22:26:22 +00002013 struct inode *inode = d_backing_inode(file->f_path.dentry);
Stephen Smalley79af7302015-01-21 10:54:10 -05002014 struct inode_security_struct *isec = inode->i_security;
2015 struct common_audit_data ad;
2016 int rc;
2017
2018 ad.type = LSM_AUDIT_DATA_PATH;
2019 ad.u.path = file->f_path;
2020
2021 if (sid != fsec->sid) {
2022 rc = avc_has_perm(sid, fsec->sid,
2023 SECCLASS_FD,
2024 FD__USE,
2025 &ad);
2026 if (rc)
2027 return rc;
2028 }
2029
2030 if (unlikely(IS_PRIVATE(inode)))
2031 return 0;
2032
2033 return avc_has_perm(sid, isec->sid, isec->sclass, file_to_av(file),
2034 &ad);
2035}
2036
Ingo Molnar9e488582009-05-07 19:26:19 +10002037static int selinux_ptrace_access_check(struct task_struct *child,
David Howells5cd9c582008-08-14 11:37:28 +01002038 unsigned int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002039{
Eric Paris69f594a2012-01-03 12:25:15 -05002040 if (mode & PTRACE_MODE_READ) {
David Howells275bb412008-11-14 10:39:19 +11002041 u32 sid = current_sid();
2042 u32 csid = task_sid(child);
2043 return avc_has_perm(sid, csid, SECCLASS_FILE, FILE__READ, NULL);
Stephen Smalley006ebb42008-05-19 08:32:49 -04002044 }
2045
David Howells3b11a1d2008-11-14 10:39:26 +11002046 return current_has_perm(child, PROCESS__PTRACE);
David Howells5cd9c582008-08-14 11:37:28 +01002047}
2048
2049static int selinux_ptrace_traceme(struct task_struct *parent)
2050{
David Howells5cd9c582008-08-14 11:37:28 +01002051 return task_has_perm(parent, current, PROCESS__PTRACE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002052}
2053
2054static int selinux_capget(struct task_struct *target, kernel_cap_t *effective,
Eric Paris828dfe12008-04-17 13:17:49 -04002055 kernel_cap_t *inheritable, kernel_cap_t *permitted)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002056{
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07002057 return current_has_perm(target, PROCESS__GETCAP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002058}
2059
David Howellsd84f4f92008-11-14 10:39:23 +11002060static int selinux_capset(struct cred *new, const struct cred *old,
2061 const kernel_cap_t *effective,
2062 const kernel_cap_t *inheritable,
2063 const kernel_cap_t *permitted)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002064{
David Howellsd84f4f92008-11-14 10:39:23 +11002065 return cred_has_perm(old, new, PROCESS__SETCAP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002066}
2067
James Morris5626d3e2009-01-30 10:05:06 +11002068/*
2069 * (This comment used to live with the selinux_task_setuid hook,
2070 * which was removed).
2071 *
2072 * Since setuid only affects the current process, and since the SELinux
2073 * controls are not based on the Linux identity attributes, SELinux does not
2074 * need to control this operation. However, SELinux does control the use of
2075 * the CAP_SETUID and CAP_SETGID capabilities using the capable hook.
2076 */
2077
Eric Paris6a9de492012-01-03 12:25:14 -05002078static int selinux_capable(const struct cred *cred, struct user_namespace *ns,
2079 int cap, int audit)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002080{
Eric Paris6a9de492012-01-03 12:25:14 -05002081 return cred_has_capability(cred, cap, audit);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002082}
2083
Linus Torvalds1da177e2005-04-16 15:20:36 -07002084static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb)
2085{
David Howells88e67f32008-11-14 10:39:21 +11002086 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002087 int rc = 0;
2088
2089 if (!sb)
2090 return 0;
2091
2092 switch (cmds) {
Eric Paris828dfe12008-04-17 13:17:49 -04002093 case Q_SYNC:
2094 case Q_QUOTAON:
2095 case Q_QUOTAOFF:
2096 case Q_SETINFO:
2097 case Q_SETQUOTA:
David Howells88e67f32008-11-14 10:39:21 +11002098 rc = superblock_has_perm(cred, sb, FILESYSTEM__QUOTAMOD, NULL);
Eric Paris828dfe12008-04-17 13:17:49 -04002099 break;
2100 case Q_GETFMT:
2101 case Q_GETINFO:
2102 case Q_GETQUOTA:
David Howells88e67f32008-11-14 10:39:21 +11002103 rc = superblock_has_perm(cred, sb, FILESYSTEM__QUOTAGET, NULL);
Eric Paris828dfe12008-04-17 13:17:49 -04002104 break;
2105 default:
2106 rc = 0; /* let the kernel handle invalid cmds */
2107 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002108 }
2109 return rc;
2110}
2111
2112static int selinux_quota_on(struct dentry *dentry)
2113{
David Howells88e67f32008-11-14 10:39:21 +11002114 const struct cred *cred = current_cred();
2115
Eric Paris2875fa02011-04-28 16:04:24 -04002116 return dentry_has_perm(cred, dentry, FILE__QUOTAON);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002117}
2118
Eric Paris12b30522010-11-15 18:36:29 -05002119static int selinux_syslog(int type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002120{
2121 int rc;
2122
Linus Torvalds1da177e2005-04-16 15:20:36 -07002123 switch (type) {
Kees Cookd78ca3c2010-02-03 15:37:13 -08002124 case SYSLOG_ACTION_READ_ALL: /* Read last kernel messages */
2125 case SYSLOG_ACTION_SIZE_BUFFER: /* Return size of the log buffer */
Eric Paris828dfe12008-04-17 13:17:49 -04002126 rc = task_has_system(current, SYSTEM__SYSLOG_READ);
2127 break;
Kees Cookd78ca3c2010-02-03 15:37:13 -08002128 case SYSLOG_ACTION_CONSOLE_OFF: /* Disable logging to console */
2129 case SYSLOG_ACTION_CONSOLE_ON: /* Enable logging to console */
2130 /* Set level of messages printed to console */
2131 case SYSLOG_ACTION_CONSOLE_LEVEL:
Eric Paris828dfe12008-04-17 13:17:49 -04002132 rc = task_has_system(current, SYSTEM__SYSLOG_CONSOLE);
2133 break;
Kees Cookd78ca3c2010-02-03 15:37:13 -08002134 case SYSLOG_ACTION_CLOSE: /* Close log */
2135 case SYSLOG_ACTION_OPEN: /* Open log */
2136 case SYSLOG_ACTION_READ: /* Read from log */
2137 case SYSLOG_ACTION_READ_CLEAR: /* Read/clear last kernel messages */
2138 case SYSLOG_ACTION_CLEAR: /* Clear ring buffer */
Eric Paris828dfe12008-04-17 13:17:49 -04002139 default:
2140 rc = task_has_system(current, SYSTEM__SYSLOG_MOD);
2141 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002142 }
2143 return rc;
2144}
2145
2146/*
2147 * Check that a process has enough memory to allocate a new virtual
2148 * mapping. 0 means there is enough memory for the allocation to
2149 * succeed and -ENOMEM implies there is not.
2150 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07002151 * Do not audit the selinux permission check, as this is applied to all
2152 * processes that allocate mappings.
2153 */
Alan Cox34b4e4a2007-08-22 14:01:28 -07002154static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002155{
2156 int rc, cap_sys_admin = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002157
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07002158 rc = cred_has_capability(current_cred(), CAP_SYS_ADMIN,
2159 SECURITY_CAP_NOAUDIT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002160 if (rc == 0)
2161 cap_sys_admin = 1;
2162
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07002163 return cap_sys_admin;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002164}
2165
2166/* binprm security operations */
2167
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002168static int check_nnp_nosuid(const struct linux_binprm *bprm,
2169 const struct task_security_struct *old_tsec,
2170 const struct task_security_struct *new_tsec)
2171{
2172 int nnp = (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS);
2173 int nosuid = (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID);
2174 int rc;
2175
2176 if (!nnp && !nosuid)
2177 return 0; /* neither NNP nor nosuid */
2178
2179 if (new_tsec->sid == old_tsec->sid)
2180 return 0; /* No change in credentials */
2181
2182 /*
2183 * The only transitions we permit under NNP or nosuid
2184 * are transitions to bounded SIDs, i.e. SIDs that are
2185 * guaranteed to only be allowed a subset of the permissions
2186 * of the current SID.
2187 */
2188 rc = security_bounded_transition(old_tsec->sid, new_tsec->sid);
2189 if (rc) {
2190 /*
2191 * On failure, preserve the errno values for NNP vs nosuid.
2192 * NNP: Operation not permitted for caller.
2193 * nosuid: Permission denied to file.
2194 */
2195 if (nnp)
2196 return -EPERM;
2197 else
2198 return -EACCES;
2199 }
2200 return 0;
2201}
2202
David Howellsa6f76f22008-11-14 10:39:24 +11002203static int selinux_bprm_set_creds(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002204{
David Howellsa6f76f22008-11-14 10:39:24 +11002205 const struct task_security_struct *old_tsec;
2206 struct task_security_struct *new_tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002207 struct inode_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04002208 struct common_audit_data ad;
Al Viro496ad9a2013-01-23 17:07:38 -05002209 struct inode *inode = file_inode(bprm->file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002210 int rc;
2211
David Howellsa6f76f22008-11-14 10:39:24 +11002212 /* SELinux context only depends on initial program or script and not
2213 * the script interpreter */
2214 if (bprm->cred_prepared)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002215 return 0;
2216
David Howellsa6f76f22008-11-14 10:39:24 +11002217 old_tsec = current_security();
2218 new_tsec = bprm->cred->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002219 isec = inode->i_security;
2220
2221 /* Default to the current task SID. */
David Howellsa6f76f22008-11-14 10:39:24 +11002222 new_tsec->sid = old_tsec->sid;
2223 new_tsec->osid = old_tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002224
Michael LeMay28eba5b2006-06-27 02:53:42 -07002225 /* Reset fs, key, and sock SIDs on execve. */
David Howellsa6f76f22008-11-14 10:39:24 +11002226 new_tsec->create_sid = 0;
2227 new_tsec->keycreate_sid = 0;
2228 new_tsec->sockcreate_sid = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002229
David Howellsa6f76f22008-11-14 10:39:24 +11002230 if (old_tsec->exec_sid) {
2231 new_tsec->sid = old_tsec->exec_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002232 /* Reset exec SID on execve. */
David Howellsa6f76f22008-11-14 10:39:24 +11002233 new_tsec->exec_sid = 0;
Andy Lutomirski259e5e62012-04-12 16:47:50 -05002234
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002235 /* Fail on NNP or nosuid if not an allowed transition. */
2236 rc = check_nnp_nosuid(bprm, old_tsec, new_tsec);
2237 if (rc)
2238 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002239 } else {
2240 /* Check for a default transition on this program. */
David Howellsa6f76f22008-11-14 10:39:24 +11002241 rc = security_transition_sid(old_tsec->sid, isec->sid,
Eric Paris652bb9b2011-02-01 11:05:40 -05002242 SECCLASS_PROCESS, NULL,
2243 &new_tsec->sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002244 if (rc)
2245 return rc;
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002246
2247 /*
2248 * Fallback to old SID on NNP or nosuid if not an allowed
2249 * transition.
2250 */
2251 rc = check_nnp_nosuid(bprm, old_tsec, new_tsec);
2252 if (rc)
2253 new_tsec->sid = old_tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002254 }
2255
Eric Paris50c205f2012-04-04 15:01:43 -04002256 ad.type = LSM_AUDIT_DATA_PATH;
Eric Parisf48b7392011-04-25 12:54:27 -04002257 ad.u.path = bprm->file->f_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002258
David Howellsa6f76f22008-11-14 10:39:24 +11002259 if (new_tsec->sid == old_tsec->sid) {
2260 rc = avc_has_perm(old_tsec->sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002261 SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, &ad);
2262 if (rc)
2263 return rc;
2264 } else {
2265 /* Check permissions for the transition. */
David Howellsa6f76f22008-11-14 10:39:24 +11002266 rc = avc_has_perm(old_tsec->sid, new_tsec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002267 SECCLASS_PROCESS, PROCESS__TRANSITION, &ad);
2268 if (rc)
2269 return rc;
2270
David Howellsa6f76f22008-11-14 10:39:24 +11002271 rc = avc_has_perm(new_tsec->sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002272 SECCLASS_FILE, FILE__ENTRYPOINT, &ad);
2273 if (rc)
2274 return rc;
2275
David Howellsa6f76f22008-11-14 10:39:24 +11002276 /* Check for shared state */
2277 if (bprm->unsafe & LSM_UNSAFE_SHARE) {
2278 rc = avc_has_perm(old_tsec->sid, new_tsec->sid,
2279 SECCLASS_PROCESS, PROCESS__SHARE,
2280 NULL);
2281 if (rc)
2282 return -EPERM;
2283 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002284
David Howellsa6f76f22008-11-14 10:39:24 +11002285 /* Make sure that anyone attempting to ptrace over a task that
2286 * changes its SID has the appropriate permit */
2287 if (bprm->unsafe &
2288 (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) {
2289 struct task_struct *tracer;
2290 struct task_security_struct *sec;
2291 u32 ptsid = 0;
2292
2293 rcu_read_lock();
Tejun Heo06d98472011-06-17 16:50:40 +02002294 tracer = ptrace_parent(current);
David Howellsa6f76f22008-11-14 10:39:24 +11002295 if (likely(tracer != NULL)) {
2296 sec = __task_cred(tracer)->security;
2297 ptsid = sec->sid;
2298 }
2299 rcu_read_unlock();
2300
2301 if (ptsid != 0) {
2302 rc = avc_has_perm(ptsid, new_tsec->sid,
2303 SECCLASS_PROCESS,
2304 PROCESS__PTRACE, NULL);
2305 if (rc)
2306 return -EPERM;
2307 }
2308 }
2309
2310 /* Clear any possibly unsafe personality bits on exec: */
2311 bprm->per_clear |= PER_CLEAR_ON_SETID;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002312 }
2313
Linus Torvalds1da177e2005-04-16 15:20:36 -07002314 return 0;
2315}
2316
Eric Paris828dfe12008-04-17 13:17:49 -04002317static int selinux_bprm_secureexec(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002318{
Paul Moore5fb49872010-04-22 14:46:19 -04002319 const struct task_security_struct *tsec = current_security();
David Howells275bb412008-11-14 10:39:19 +11002320 u32 sid, osid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002321 int atsecure = 0;
2322
David Howells275bb412008-11-14 10:39:19 +11002323 sid = tsec->sid;
2324 osid = tsec->osid;
2325
2326 if (osid != sid) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002327 /* Enable secure mode for SIDs transitions unless
2328 the noatsecure permission is granted between
2329 the two SIDs, i.e. ahp returns 0. */
David Howells275bb412008-11-14 10:39:19 +11002330 atsecure = avc_has_perm(osid, sid,
David Howellsa6f76f22008-11-14 10:39:24 +11002331 SECCLASS_PROCESS,
2332 PROCESS__NOATSECURE, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002333 }
2334
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07002335 return !!atsecure;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002336}
2337
Al Viroc3c073f2012-08-21 22:32:06 -04002338static int match_file(const void *p, struct file *file, unsigned fd)
2339{
2340 return file_has_perm(p, file, file_to_av(file)) ? fd + 1 : 0;
2341}
2342
Linus Torvalds1da177e2005-04-16 15:20:36 -07002343/* Derived from fs/exec.c:flush_old_files. */
David Howells745ca242008-11-14 10:39:22 +11002344static inline void flush_unauthorized_files(const struct cred *cred,
2345 struct files_struct *files)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002346{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002347 struct file *file, *devnull = NULL;
Stephen Smalleyb20c8122006-09-25 23:32:03 -07002348 struct tty_struct *tty;
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002349 int drop_tty = 0;
Al Viroc3c073f2012-08-21 22:32:06 -04002350 unsigned n;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002351
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002352 tty = get_current_tty();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002353 if (tty) {
Nick Pigginee2ffa02010-08-18 04:37:35 +10002354 spin_lock(&tty_files_lock);
Eric Paris37dd0bd2008-10-31 17:40:00 -04002355 if (!list_empty(&tty->tty_files)) {
Nick Piggind996b622010-08-18 04:37:36 +10002356 struct tty_file_private *file_priv;
Eric Paris37dd0bd2008-10-31 17:40:00 -04002357
Linus Torvalds1da177e2005-04-16 15:20:36 -07002358 /* Revalidate access to controlling tty.
David Howells13f8e982013-06-13 23:37:55 +01002359 Use file_path_has_perm on the tty path directly
2360 rather than using file_has_perm, as this particular
2361 open file may belong to another process and we are
2362 only interested in the inode-based check here. */
Nick Piggind996b622010-08-18 04:37:36 +10002363 file_priv = list_first_entry(&tty->tty_files,
2364 struct tty_file_private, list);
2365 file = file_priv->file;
David Howells13f8e982013-06-13 23:37:55 +01002366 if (file_path_has_perm(cred, file, FILE__READ | FILE__WRITE))
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002367 drop_tty = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002368 }
Nick Pigginee2ffa02010-08-18 04:37:35 +10002369 spin_unlock(&tty_files_lock);
Alan Cox452a00d2008-10-13 10:39:13 +01002370 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002371 }
Eric W. Biederman98a27ba2007-05-08 00:26:56 -07002372 /* Reset controlling tty. */
2373 if (drop_tty)
2374 no_tty();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002375
2376 /* Revalidate access to inherited open files. */
Al Viroc3c073f2012-08-21 22:32:06 -04002377 n = iterate_fd(files, 0, match_file, cred);
2378 if (!n) /* none found? */
2379 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002380
Al Viroc3c073f2012-08-21 22:32:06 -04002381 devnull = dentry_open(&selinux_null, O_RDWR, cred);
Al Viro45525b22012-10-16 13:30:07 -04002382 if (IS_ERR(devnull))
2383 devnull = NULL;
2384 /* replace all the matching ones with this */
2385 do {
2386 replace_fd(n - 1, devnull, 0);
2387 } while ((n = iterate_fd(files, n, match_file, cred)) != 0);
2388 if (devnull)
Al Viroc3c073f2012-08-21 22:32:06 -04002389 fput(devnull);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002390}
2391
Linus Torvalds1da177e2005-04-16 15:20:36 -07002392/*
David Howellsa6f76f22008-11-14 10:39:24 +11002393 * Prepare a process for imminent new credential changes due to exec
Linus Torvalds1da177e2005-04-16 15:20:36 -07002394 */
David Howellsa6f76f22008-11-14 10:39:24 +11002395static void selinux_bprm_committing_creds(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002396{
David Howellsa6f76f22008-11-14 10:39:24 +11002397 struct task_security_struct *new_tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002398 struct rlimit *rlim, *initrlim;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002399 int rc, i;
2400
David Howellsa6f76f22008-11-14 10:39:24 +11002401 new_tsec = bprm->cred->security;
2402 if (new_tsec->sid == new_tsec->osid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002403 return;
2404
2405 /* Close files for which the new task SID is not authorized. */
David Howellsa6f76f22008-11-14 10:39:24 +11002406 flush_unauthorized_files(bprm->cred, current->files);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002407
David Howellsa6f76f22008-11-14 10:39:24 +11002408 /* Always clear parent death signal on SID transitions. */
2409 current->pdeath_signal = 0;
2410
2411 /* Check whether the new SID can inherit resource limits from the old
2412 * SID. If not, reset all soft limits to the lower of the current
2413 * task's hard limit and the init task's soft limit.
2414 *
2415 * Note that the setting of hard limits (even to lower them) can be
2416 * controlled by the setrlimit check. The inclusion of the init task's
2417 * soft limit into the computation is to avoid resetting soft limits
2418 * higher than the default soft limit for cases where the default is
2419 * lower than the hard limit, e.g. RLIMIT_CORE or RLIMIT_STACK.
2420 */
2421 rc = avc_has_perm(new_tsec->osid, new_tsec->sid, SECCLASS_PROCESS,
2422 PROCESS__RLIMITINH, NULL);
2423 if (rc) {
Oleg Nesteroveb2d55a2010-06-23 22:43:32 +02002424 /* protect against do_prlimit() */
2425 task_lock(current);
David Howellsa6f76f22008-11-14 10:39:24 +11002426 for (i = 0; i < RLIM_NLIMITS; i++) {
2427 rlim = current->signal->rlim + i;
2428 initrlim = init_task.signal->rlim + i;
2429 rlim->rlim_cur = min(rlim->rlim_max, initrlim->rlim_cur);
2430 }
Oleg Nesteroveb2d55a2010-06-23 22:43:32 +02002431 task_unlock(current);
2432 update_rlimit_cpu(current, rlimit(RLIMIT_CPU));
David Howellsa6f76f22008-11-14 10:39:24 +11002433 }
2434}
2435
2436/*
2437 * Clean up the process immediately after the installation of new credentials
2438 * due to exec
2439 */
2440static void selinux_bprm_committed_creds(struct linux_binprm *bprm)
2441{
2442 const struct task_security_struct *tsec = current_security();
2443 struct itimerval itimer;
David Howellsa6f76f22008-11-14 10:39:24 +11002444 u32 osid, sid;
2445 int rc, i;
David Howellsa6f76f22008-11-14 10:39:24 +11002446
David Howellsa6f76f22008-11-14 10:39:24 +11002447 osid = tsec->osid;
2448 sid = tsec->sid;
2449
2450 if (sid == osid)
2451 return;
2452
2453 /* Check whether the new SID can inherit signal state from the old SID.
2454 * If not, clear itimers to avoid subsequent signal generation and
2455 * flush and unblock signals.
2456 *
2457 * This must occur _after_ the task SID has been updated so that any
2458 * kill done after the flush will be checked against the new SID.
2459 */
2460 rc = avc_has_perm(osid, sid, SECCLASS_PROCESS, PROCESS__SIGINH, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002461 if (rc) {
2462 memset(&itimer, 0, sizeof itimer);
2463 for (i = 0; i < 3; i++)
2464 do_setitimer(i, &itimer, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002465 spin_lock_irq(&current->sighand->siglock);
Oleg Nesterov9e7c8f82015-06-04 16:22:16 -04002466 if (!fatal_signal_pending(current)) {
2467 flush_sigqueue(&current->pending);
2468 flush_sigqueue(&current->signal->shared_pending);
David Howells3bcac022009-04-29 13:45:05 +01002469 flush_signal_handlers(current, 1);
2470 sigemptyset(&current->blocked);
Oleg Nesterov9e7c8f82015-06-04 16:22:16 -04002471 recalc_sigpending();
David Howells3bcac022009-04-29 13:45:05 +01002472 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002473 spin_unlock_irq(&current->sighand->siglock);
2474 }
2475
David Howellsa6f76f22008-11-14 10:39:24 +11002476 /* Wake up the parent if it is waiting so that it can recheck
2477 * wait permission to the new task SID. */
Oleg Nesterovecd6de32009-04-29 16:02:24 +02002478 read_lock(&tasklist_lock);
Oleg Nesterov0b7570e2009-09-23 15:56:46 -07002479 __wake_up_parent(current, current->real_parent);
Oleg Nesterovecd6de32009-04-29 16:02:24 +02002480 read_unlock(&tasklist_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002481}
2482
2483/* superblock security operations */
2484
2485static int selinux_sb_alloc_security(struct super_block *sb)
2486{
2487 return superblock_alloc_security(sb);
2488}
2489
2490static void selinux_sb_free_security(struct super_block *sb)
2491{
2492 superblock_free_security(sb);
2493}
2494
2495static inline int match_prefix(char *prefix, int plen, char *option, int olen)
2496{
2497 if (plen > olen)
2498 return 0;
2499
2500 return !memcmp(prefix, option, plen);
2501}
2502
2503static inline int selinux_option(char *option, int len)
2504{
Eric Paris832cbd92008-04-01 13:24:09 -04002505 return (match_prefix(CONTEXT_STR, sizeof(CONTEXT_STR)-1, option, len) ||
2506 match_prefix(FSCONTEXT_STR, sizeof(FSCONTEXT_STR)-1, option, len) ||
2507 match_prefix(DEFCONTEXT_STR, sizeof(DEFCONTEXT_STR)-1, option, len) ||
David P. Quigley11689d42009-01-16 09:22:03 -05002508 match_prefix(ROOTCONTEXT_STR, sizeof(ROOTCONTEXT_STR)-1, option, len) ||
2509 match_prefix(LABELSUPP_STR, sizeof(LABELSUPP_STR)-1, option, len));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002510}
2511
2512static inline void take_option(char **to, char *from, int *first, int len)
2513{
2514 if (!*first) {
2515 **to = ',';
2516 *to += 1;
Cory Olmo3528a952006-09-29 01:58:44 -07002517 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002518 *first = 0;
2519 memcpy(*to, from, len);
2520 *to += len;
2521}
2522
Eric Paris828dfe12008-04-17 13:17:49 -04002523static inline void take_selinux_option(char **to, char *from, int *first,
2524 int len)
Cory Olmo3528a952006-09-29 01:58:44 -07002525{
2526 int current_size = 0;
2527
2528 if (!*first) {
2529 **to = '|';
2530 *to += 1;
Eric Paris828dfe12008-04-17 13:17:49 -04002531 } else
Cory Olmo3528a952006-09-29 01:58:44 -07002532 *first = 0;
2533
2534 while (current_size < len) {
2535 if (*from != '"') {
2536 **to = *from;
2537 *to += 1;
2538 }
2539 from += 1;
2540 current_size += 1;
2541 }
2542}
2543
Eric Parise0007522008-03-05 10:31:54 -05002544static int selinux_sb_copy_data(char *orig, char *copy)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002545{
2546 int fnosec, fsec, rc = 0;
2547 char *in_save, *in_curr, *in_end;
2548 char *sec_curr, *nosec_save, *nosec;
Cory Olmo3528a952006-09-29 01:58:44 -07002549 int open_quote = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002550
2551 in_curr = orig;
2552 sec_curr = copy;
2553
Linus Torvalds1da177e2005-04-16 15:20:36 -07002554 nosec = (char *)get_zeroed_page(GFP_KERNEL);
2555 if (!nosec) {
2556 rc = -ENOMEM;
2557 goto out;
2558 }
2559
2560 nosec_save = nosec;
2561 fnosec = fsec = 1;
2562 in_save = in_end = orig;
2563
2564 do {
Cory Olmo3528a952006-09-29 01:58:44 -07002565 if (*in_end == '"')
2566 open_quote = !open_quote;
2567 if ((*in_end == ',' && open_quote == 0) ||
2568 *in_end == '\0') {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002569 int len = in_end - in_curr;
2570
2571 if (selinux_option(in_curr, len))
Cory Olmo3528a952006-09-29 01:58:44 -07002572 take_selinux_option(&sec_curr, in_curr, &fsec, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002573 else
2574 take_option(&nosec, in_curr, &fnosec, len);
2575
2576 in_curr = in_end + 1;
2577 }
2578 } while (*in_end++);
2579
Eric Paris6931dfc2005-06-30 02:58:51 -07002580 strcpy(in_save, nosec_save);
Gerald Schaeferda3caa22005-06-21 17:15:18 -07002581 free_page((unsigned long)nosec_save);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002582out:
2583 return rc;
2584}
2585
Eric Paris026eb162011-03-03 16:09:14 -05002586static int selinux_sb_remount(struct super_block *sb, void *data)
2587{
2588 int rc, i, *flags;
2589 struct security_mnt_opts opts;
2590 char *secdata, **mount_options;
2591 struct superblock_security_struct *sbsec = sb->s_security;
2592
2593 if (!(sbsec->flags & SE_SBINITIALIZED))
2594 return 0;
2595
2596 if (!data)
2597 return 0;
2598
2599 if (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)
2600 return 0;
2601
2602 security_init_mnt_opts(&opts);
2603 secdata = alloc_secdata();
2604 if (!secdata)
2605 return -ENOMEM;
2606 rc = selinux_sb_copy_data(data, secdata);
2607 if (rc)
2608 goto out_free_secdata;
2609
2610 rc = selinux_parse_opts_str(secdata, &opts);
2611 if (rc)
2612 goto out_free_secdata;
2613
2614 mount_options = opts.mnt_opts;
2615 flags = opts.mnt_opts_flags;
2616
2617 for (i = 0; i < opts.num_mnt_opts; i++) {
2618 u32 sid;
Eric Paris026eb162011-03-03 16:09:14 -05002619
Eric Paris12f348b2012-10-09 10:56:25 -04002620 if (flags[i] == SBLABEL_MNT)
Eric Paris026eb162011-03-03 16:09:14 -05002621 continue;
Rasmus Villemoes44be2f62015-10-21 17:44:25 -04002622 rc = security_context_str_to_sid(mount_options[i], &sid, GFP_KERNEL);
Eric Paris026eb162011-03-03 16:09:14 -05002623 if (rc) {
Rasmus Villemoes44be2f62015-10-21 17:44:25 -04002624 printk(KERN_WARNING "SELinux: security_context_str_to_sid"
Linus Torvalds29b1deb2013-12-15 11:17:45 -08002625 "(%s) failed for (dev %s, type %s) errno=%d\n",
2626 mount_options[i], sb->s_id, sb->s_type->name, rc);
Eric Paris026eb162011-03-03 16:09:14 -05002627 goto out_free_opts;
2628 }
2629 rc = -EINVAL;
2630 switch (flags[i]) {
2631 case FSCONTEXT_MNT:
2632 if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid, sid))
2633 goto out_bad_option;
2634 break;
2635 case CONTEXT_MNT:
2636 if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid, sid))
2637 goto out_bad_option;
2638 break;
2639 case ROOTCONTEXT_MNT: {
2640 struct inode_security_struct *root_isec;
David Howellsc6f493d2015-03-17 22:26:22 +00002641 root_isec = d_backing_inode(sb->s_root)->i_security;
Eric Paris026eb162011-03-03 16:09:14 -05002642
2643 if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid, sid))
2644 goto out_bad_option;
2645 break;
2646 }
2647 case DEFCONTEXT_MNT:
2648 if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid, sid))
2649 goto out_bad_option;
2650 break;
2651 default:
2652 goto out_free_opts;
2653 }
2654 }
2655
2656 rc = 0;
2657out_free_opts:
2658 security_free_mnt_opts(&opts);
2659out_free_secdata:
2660 free_secdata(secdata);
2661 return rc;
2662out_bad_option:
2663 printk(KERN_WARNING "SELinux: unable to change security options "
Linus Torvalds29b1deb2013-12-15 11:17:45 -08002664 "during remount (dev %s, type=%s)\n", sb->s_id,
2665 sb->s_type->name);
Eric Paris026eb162011-03-03 16:09:14 -05002666 goto out_free_opts;
2667}
2668
James Morris12204e22008-12-19 10:44:42 +11002669static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002670{
David Howells88e67f32008-11-14 10:39:21 +11002671 const struct cred *cred = current_cred();
Thomas Liu2bf49692009-07-14 12:14:09 -04002672 struct common_audit_data ad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002673 int rc;
2674
2675 rc = superblock_doinit(sb, data);
2676 if (rc)
2677 return rc;
2678
James Morris74192242008-12-19 11:41:10 +11002679 /* Allow all mounts performed by the kernel */
2680 if (flags & MS_KERNMOUNT)
2681 return 0;
2682
Eric Paris50c205f2012-04-04 15:01:43 -04002683 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04002684 ad.u.dentry = sb->s_root;
David Howells88e67f32008-11-14 10:39:21 +11002685 return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002686}
2687
David Howells726c3342006-06-23 02:02:58 -07002688static int selinux_sb_statfs(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002689{
David Howells88e67f32008-11-14 10:39:21 +11002690 const struct cred *cred = current_cred();
Thomas Liu2bf49692009-07-14 12:14:09 -04002691 struct common_audit_data ad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002692
Eric Paris50c205f2012-04-04 15:01:43 -04002693 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04002694 ad.u.dentry = dentry->d_sb->s_root;
David Howells88e67f32008-11-14 10:39:21 +11002695 return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002696}
2697
Al Viro808d4e32012-10-11 11:42:01 -04002698static int selinux_mount(const char *dev_name,
Al Virob5266eb2008-03-22 17:48:24 -04002699 struct path *path,
Al Viro808d4e32012-10-11 11:42:01 -04002700 const char *type,
Eric Paris828dfe12008-04-17 13:17:49 -04002701 unsigned long flags,
2702 void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002703{
David Howells88e67f32008-11-14 10:39:21 +11002704 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002705
2706 if (flags & MS_REMOUNT)
Al Virod8c95842011-12-07 18:16:57 -05002707 return superblock_has_perm(cred, path->dentry->d_sb,
Eric Paris828dfe12008-04-17 13:17:49 -04002708 FILESYSTEM__REMOUNT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002709 else
Eric Paris2875fa02011-04-28 16:04:24 -04002710 return path_has_perm(cred, path, FILE__MOUNTON);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002711}
2712
2713static int selinux_umount(struct vfsmount *mnt, int flags)
2714{
David Howells88e67f32008-11-14 10:39:21 +11002715 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002716
David Howells88e67f32008-11-14 10:39:21 +11002717 return superblock_has_perm(cred, mnt->mnt_sb,
Eric Paris828dfe12008-04-17 13:17:49 -04002718 FILESYSTEM__UNMOUNT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002719}
2720
2721/* inode security operations */
2722
2723static int selinux_inode_alloc_security(struct inode *inode)
2724{
2725 return inode_alloc_security(inode);
2726}
2727
2728static void selinux_inode_free_security(struct inode *inode)
2729{
2730 inode_free_security(inode);
2731}
2732
David Quigleyd47be3d2013-05-22 12:50:34 -04002733static int selinux_dentry_init_security(struct dentry *dentry, int mode,
2734 struct qstr *name, void **ctx,
2735 u32 *ctxlen)
2736{
David Quigleyd47be3d2013-05-22 12:50:34 -04002737 u32 newsid;
2738 int rc;
2739
David Howellsc3c188b2015-07-10 17:19:58 -04002740 rc = selinux_determine_inode_label(d_inode(dentry->d_parent), name,
2741 inode_mode_to_security_class(mode),
2742 &newsid);
2743 if (rc)
2744 return rc;
David Quigleyd47be3d2013-05-22 12:50:34 -04002745
2746 return security_sid_to_context(newsid, (char **)ctx, ctxlen);
2747}
2748
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002749static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
Tetsuo Handa95489062013-07-25 05:44:02 +09002750 const struct qstr *qstr,
2751 const char **name,
Eric Paris2a7dba32011-02-01 11:05:39 -05002752 void **value, size_t *len)
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002753{
Paul Moore5fb49872010-04-22 14:46:19 -04002754 const struct task_security_struct *tsec = current_security();
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002755 struct inode_security_struct *dsec;
2756 struct superblock_security_struct *sbsec;
David Howells275bb412008-11-14 10:39:19 +11002757 u32 sid, newsid, clen;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002758 int rc;
Tetsuo Handa95489062013-07-25 05:44:02 +09002759 char *context;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002760
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002761 dsec = dir->i_security;
2762 sbsec = dir->i_sb->s_security;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002763
David Howells275bb412008-11-14 10:39:19 +11002764 sid = tsec->sid;
2765 newsid = tsec->create_sid;
2766
David Howellsc3c188b2015-07-10 17:19:58 -04002767 rc = selinux_determine_inode_label(
2768 dir, qstr,
2769 inode_mode_to_security_class(inode->i_mode),
2770 &newsid);
2771 if (rc)
2772 return rc;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002773
Eric Paris296fddf2006-09-25 23:32:00 -07002774 /* Possibly defer initialization to selinux_complete_init. */
David P. Quigley0d90a7e2009-01-16 09:22:02 -05002775 if (sbsec->flags & SE_SBINITIALIZED) {
Eric Paris296fddf2006-09-25 23:32:00 -07002776 struct inode_security_struct *isec = inode->i_security;
2777 isec->sclass = inode_mode_to_security_class(inode->i_mode);
2778 isec->sid = newsid;
2779 isec->initialized = 1;
2780 }
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002781
Eric Paris12f348b2012-10-09 10:56:25 -04002782 if (!ss_initialized || !(sbsec->flags & SBLABEL_MNT))
Stephen Smalley25a74f32005-11-08 21:34:33 -08002783 return -EOPNOTSUPP;
2784
Tetsuo Handa95489062013-07-25 05:44:02 +09002785 if (name)
2786 *name = XATTR_SELINUX_SUFFIX;
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002787
2788 if (value && len) {
Stephen Smalley12b29f32008-05-07 13:03:20 -04002789 rc = security_sid_to_context_force(newsid, &context, &clen);
Tetsuo Handa95489062013-07-25 05:44:02 +09002790 if (rc)
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002791 return rc;
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002792 *value = context;
2793 *len = clen;
2794 }
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002795
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002796 return 0;
2797}
2798
Al Viro4acdaf22011-07-26 01:42:34 -04002799static int selinux_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002800{
2801 return may_create(dir, dentry, SECCLASS_FILE);
2802}
2803
Linus Torvalds1da177e2005-04-16 15:20:36 -07002804static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
2805{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002806 return may_link(dir, old_dentry, MAY_LINK);
2807}
2808
Linus Torvalds1da177e2005-04-16 15:20:36 -07002809static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry)
2810{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002811 return may_link(dir, dentry, MAY_UNLINK);
2812}
2813
2814static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry, const char *name)
2815{
2816 return may_create(dir, dentry, SECCLASS_LNK_FILE);
2817}
2818
Al Viro18bb1db2011-07-26 01:41:39 -04002819static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry, umode_t mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002820{
2821 return may_create(dir, dentry, SECCLASS_DIR);
2822}
2823
Linus Torvalds1da177e2005-04-16 15:20:36 -07002824static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry)
2825{
2826 return may_link(dir, dentry, MAY_RMDIR);
2827}
2828
Al Viro1a67aaf2011-07-26 01:52:52 -04002829static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002830{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002831 return may_create(dir, dentry, inode_mode_to_security_class(mode));
2832}
2833
Linus Torvalds1da177e2005-04-16 15:20:36 -07002834static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
Eric Paris828dfe12008-04-17 13:17:49 -04002835 struct inode *new_inode, struct dentry *new_dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002836{
2837 return may_rename(old_inode, old_dentry, new_inode, new_dentry);
2838}
2839
Linus Torvalds1da177e2005-04-16 15:20:36 -07002840static int selinux_inode_readlink(struct dentry *dentry)
2841{
David Howells88e67f32008-11-14 10:39:21 +11002842 const struct cred *cred = current_cred();
2843
Eric Paris2875fa02011-04-28 16:04:24 -04002844 return dentry_has_perm(cred, dentry, FILE__READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002845}
2846
NeilBrownbda0be72015-03-23 13:37:39 +11002847static int selinux_inode_follow_link(struct dentry *dentry, struct inode *inode,
2848 bool rcu)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002849{
David Howells88e67f32008-11-14 10:39:21 +11002850 const struct cred *cred = current_cred();
NeilBrownbda0be72015-03-23 13:37:39 +11002851 struct common_audit_data ad;
2852 struct inode_security_struct *isec;
2853 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002854
NeilBrownbda0be72015-03-23 13:37:39 +11002855 validate_creds(cred);
2856
2857 ad.type = LSM_AUDIT_DATA_DENTRY;
2858 ad.u.dentry = dentry;
2859 sid = cred_sid(cred);
2860 isec = inode->i_security;
2861
2862 return avc_has_perm_flags(sid, isec->sid, isec->sclass, FILE__READ, &ad,
2863 rcu ? MAY_NOT_BLOCK : 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002864}
2865
Eric Parisd4cf970d2012-04-04 15:01:42 -04002866static noinline int audit_inode_permission(struct inode *inode,
2867 u32 perms, u32 audited, u32 denied,
Stephen Smalley626b9742014-04-29 11:29:04 -07002868 int result,
Eric Parisd4cf970d2012-04-04 15:01:42 -04002869 unsigned flags)
2870{
2871 struct common_audit_data ad;
Eric Parisd4cf970d2012-04-04 15:01:42 -04002872 struct inode_security_struct *isec = inode->i_security;
2873 int rc;
2874
Eric Paris50c205f2012-04-04 15:01:43 -04002875 ad.type = LSM_AUDIT_DATA_INODE;
Eric Parisd4cf970d2012-04-04 15:01:42 -04002876 ad.u.inode = inode;
2877
2878 rc = slow_avc_audit(current_sid(), isec->sid, isec->sclass, perms,
Stephen Smalley626b9742014-04-29 11:29:04 -07002879 audited, denied, result, &ad, flags);
Eric Parisd4cf970d2012-04-04 15:01:42 -04002880 if (rc)
2881 return rc;
2882 return 0;
2883}
2884
Al Viroe74f71e2011-06-20 19:38:15 -04002885static int selinux_inode_permission(struct inode *inode, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002886{
David Howells88e67f32008-11-14 10:39:21 +11002887 const struct cred *cred = current_cred();
Eric Parisb782e0a2010-07-23 11:44:03 -04002888 u32 perms;
2889 bool from_access;
Al Virocf1dd1d2011-06-20 19:44:08 -04002890 unsigned flags = mask & MAY_NOT_BLOCK;
Eric Paris2e334052012-04-04 15:01:42 -04002891 struct inode_security_struct *isec;
2892 u32 sid;
2893 struct av_decision avd;
2894 int rc, rc2;
2895 u32 audited, denied;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002896
Eric Parisb782e0a2010-07-23 11:44:03 -04002897 from_access = mask & MAY_ACCESS;
Eric Parisd09ca732010-07-23 11:43:57 -04002898 mask &= (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND);
2899
Eric Parisb782e0a2010-07-23 11:44:03 -04002900 /* No permission to check. Existence test. */
2901 if (!mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002902 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002903
Eric Paris2e334052012-04-04 15:01:42 -04002904 validate_creds(cred);
Eric Parisb782e0a2010-07-23 11:44:03 -04002905
Eric Paris2e334052012-04-04 15:01:42 -04002906 if (unlikely(IS_PRIVATE(inode)))
2907 return 0;
Eric Parisb782e0a2010-07-23 11:44:03 -04002908
2909 perms = file_mask_to_av(inode->i_mode, mask);
2910
Eric Paris2e334052012-04-04 15:01:42 -04002911 sid = cred_sid(cred);
2912 isec = inode->i_security;
2913
2914 rc = avc_has_perm_noaudit(sid, isec->sid, isec->sclass, perms, 0, &avd);
2915 audited = avc_audit_required(perms, &avd, rc,
2916 from_access ? FILE__AUDIT_ACCESS : 0,
2917 &denied);
2918 if (likely(!audited))
2919 return rc;
2920
Stephen Smalley626b9742014-04-29 11:29:04 -07002921 rc2 = audit_inode_permission(inode, perms, audited, denied, rc, flags);
Eric Paris2e334052012-04-04 15:01:42 -04002922 if (rc2)
2923 return rc2;
2924 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002925}
2926
2927static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
2928{
David Howells88e67f32008-11-14 10:39:21 +11002929 const struct cred *cred = current_cred();
Amerigo Wangbc6a6002009-08-20 19:29:02 -07002930 unsigned int ia_valid = iattr->ia_valid;
Eric Paris95dbf732012-04-04 13:45:34 -04002931 __u32 av = FILE__WRITE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002932
Amerigo Wangbc6a6002009-08-20 19:29:02 -07002933 /* ATTR_FORCE is just used for ATTR_KILL_S[UG]ID. */
2934 if (ia_valid & ATTR_FORCE) {
2935 ia_valid &= ~(ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_MODE |
2936 ATTR_FORCE);
2937 if (!ia_valid)
2938 return 0;
2939 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002940
Amerigo Wangbc6a6002009-08-20 19:29:02 -07002941 if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID |
2942 ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_TIMES_SET))
Eric Paris2875fa02011-04-28 16:04:24 -04002943 return dentry_has_perm(cred, dentry, FILE__SETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002944
Jeff Vander Stoep44d37ad2015-10-21 17:44:25 -04002945 if (selinux_policycap_openperm && (ia_valid & ATTR_SIZE)
2946 && !(ia_valid & ATTR_FILE))
Eric Paris95dbf732012-04-04 13:45:34 -04002947 av |= FILE__OPEN;
2948
2949 return dentry_has_perm(cred, dentry, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002950}
2951
Al Viro3f7036a2015-03-08 19:28:30 -04002952static int selinux_inode_getattr(const struct path *path)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002953{
Al Viro3f7036a2015-03-08 19:28:30 -04002954 return path_has_perm(current_cred(), path, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002955}
2956
David Howells8f0cfa52008-04-29 00:59:41 -07002957static int selinux_inode_setotherxattr(struct dentry *dentry, const char *name)
Serge E. Hallynb5376772007-10-16 23:31:36 -07002958{
David Howells88e67f32008-11-14 10:39:21 +11002959 const struct cred *cred = current_cred();
2960
Serge E. Hallynb5376772007-10-16 23:31:36 -07002961 if (!strncmp(name, XATTR_SECURITY_PREFIX,
2962 sizeof XATTR_SECURITY_PREFIX - 1)) {
2963 if (!strcmp(name, XATTR_NAME_CAPS)) {
2964 if (!capable(CAP_SETFCAP))
2965 return -EPERM;
2966 } else if (!capable(CAP_SYS_ADMIN)) {
2967 /* A different attribute in the security namespace.
2968 Restrict to administrator. */
2969 return -EPERM;
2970 }
2971 }
2972
2973 /* Not an attribute we recognize, so just check the
2974 ordinary setattr permission. */
Eric Paris2875fa02011-04-28 16:04:24 -04002975 return dentry_has_perm(cred, dentry, FILE__SETATTR);
Serge E. Hallynb5376772007-10-16 23:31:36 -07002976}
2977
David Howells8f0cfa52008-04-29 00:59:41 -07002978static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
2979 const void *value, size_t size, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002980{
David Howellsc6f493d2015-03-17 22:26:22 +00002981 struct inode *inode = d_backing_inode(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002982 struct inode_security_struct *isec = inode->i_security;
2983 struct superblock_security_struct *sbsec;
Thomas Liu2bf49692009-07-14 12:14:09 -04002984 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11002985 u32 newsid, sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002986 int rc = 0;
2987
Serge E. Hallynb5376772007-10-16 23:31:36 -07002988 if (strcmp(name, XATTR_NAME_SELINUX))
2989 return selinux_inode_setotherxattr(dentry, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002990
2991 sbsec = inode->i_sb->s_security;
Eric Paris12f348b2012-10-09 10:56:25 -04002992 if (!(sbsec->flags & SBLABEL_MNT))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002993 return -EOPNOTSUPP;
2994
Serge E. Hallyn2e149672011-03-23 16:43:26 -07002995 if (!inode_owner_or_capable(inode))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002996 return -EPERM;
2997
Eric Paris50c205f2012-04-04 15:01:43 -04002998 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04002999 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003000
David Howells275bb412008-11-14 10:39:19 +11003001 rc = avc_has_perm(sid, isec->sid, isec->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003002 FILE__RELABELFROM, &ad);
3003 if (rc)
3004 return rc;
3005
Nikolay Aleksandrov52a4c642014-03-07 12:44:19 +01003006 rc = security_context_to_sid(value, size, &newsid, GFP_KERNEL);
Stephen Smalley12b29f32008-05-07 13:03:20 -04003007 if (rc == -EINVAL) {
Eric Parisd6ea83e2012-04-04 13:45:49 -04003008 if (!capable(CAP_MAC_ADMIN)) {
3009 struct audit_buffer *ab;
3010 size_t audit_size;
3011 const char *str;
3012
3013 /* We strip a nul only if it is at the end, otherwise the
3014 * context contains a nul and we should audit that */
Al Viroe3fea3f2012-06-09 08:15:16 +01003015 if (value) {
3016 str = value;
3017 if (str[size - 1] == '\0')
3018 audit_size = size - 1;
3019 else
3020 audit_size = size;
3021 } else {
3022 str = "";
3023 audit_size = 0;
3024 }
Eric Parisd6ea83e2012-04-04 13:45:49 -04003025 ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR);
3026 audit_log_format(ab, "op=setxattr invalid_context=");
3027 audit_log_n_untrustedstring(ab, value, audit_size);
3028 audit_log_end(ab);
3029
Stephen Smalley12b29f32008-05-07 13:03:20 -04003030 return rc;
Eric Parisd6ea83e2012-04-04 13:45:49 -04003031 }
Stephen Smalley12b29f32008-05-07 13:03:20 -04003032 rc = security_context_to_sid_force(value, size, &newsid);
3033 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003034 if (rc)
3035 return rc;
3036
David Howells275bb412008-11-14 10:39:19 +11003037 rc = avc_has_perm(sid, newsid, isec->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003038 FILE__RELABELTO, &ad);
3039 if (rc)
3040 return rc;
3041
David Howells275bb412008-11-14 10:39:19 +11003042 rc = security_validate_transition(isec->sid, newsid, sid,
Eric Paris828dfe12008-04-17 13:17:49 -04003043 isec->sclass);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003044 if (rc)
3045 return rc;
3046
3047 return avc_has_perm(newsid,
3048 sbsec->sid,
3049 SECCLASS_FILESYSTEM,
3050 FILESYSTEM__ASSOCIATE,
3051 &ad);
3052}
3053
David Howells8f0cfa52008-04-29 00:59:41 -07003054static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
Eric Parisf5269712008-05-14 11:27:45 -04003055 const void *value, size_t size,
David Howells8f0cfa52008-04-29 00:59:41 -07003056 int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003057{
David Howellsc6f493d2015-03-17 22:26:22 +00003058 struct inode *inode = d_backing_inode(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003059 struct inode_security_struct *isec = inode->i_security;
3060 u32 newsid;
3061 int rc;
3062
3063 if (strcmp(name, XATTR_NAME_SELINUX)) {
3064 /* Not an attribute we recognize, so nothing to do. */
3065 return;
3066 }
3067
Stephen Smalley12b29f32008-05-07 13:03:20 -04003068 rc = security_context_to_sid_force(value, size, &newsid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003069 if (rc) {
Stephen Smalley12b29f32008-05-07 13:03:20 -04003070 printk(KERN_ERR "SELinux: unable to map context to SID"
3071 "for (%s, %lu), rc=%d\n",
3072 inode->i_sb->s_id, inode->i_ino, -rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003073 return;
3074 }
3075
David Quigleyaa9c2662013-05-22 12:50:44 -04003076 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003077 isec->sid = newsid;
David Quigleyaa9c2662013-05-22 12:50:44 -04003078 isec->initialized = 1;
3079
Linus Torvalds1da177e2005-04-16 15:20:36 -07003080 return;
3081}
3082
David Howells8f0cfa52008-04-29 00:59:41 -07003083static int selinux_inode_getxattr(struct dentry *dentry, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003084{
David Howells88e67f32008-11-14 10:39:21 +11003085 const struct cred *cred = current_cred();
3086
Eric Paris2875fa02011-04-28 16:04:24 -04003087 return dentry_has_perm(cred, dentry, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003088}
3089
Eric Paris828dfe12008-04-17 13:17:49 -04003090static int selinux_inode_listxattr(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003091{
David Howells88e67f32008-11-14 10:39:21 +11003092 const struct cred *cred = current_cred();
3093
Eric Paris2875fa02011-04-28 16:04:24 -04003094 return dentry_has_perm(cred, dentry, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003095}
3096
David Howells8f0cfa52008-04-29 00:59:41 -07003097static int selinux_inode_removexattr(struct dentry *dentry, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003098{
Serge E. Hallynb5376772007-10-16 23:31:36 -07003099 if (strcmp(name, XATTR_NAME_SELINUX))
3100 return selinux_inode_setotherxattr(dentry, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003101
3102 /* No one is allowed to remove a SELinux security label.
3103 You can change the label, but all data must be labeled. */
3104 return -EACCES;
3105}
3106
James Morrisd381d8a2005-10-30 14:59:22 -08003107/*
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04003108 * Copy the inode security context value to the user.
James Morrisd381d8a2005-10-30 14:59:22 -08003109 *
3110 * Permission check is handled by selinux_inode_getxattr hook.
3111 */
David P. Quigley42492592008-02-04 22:29:39 -08003112static int selinux_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003113{
David P. Quigley42492592008-02-04 22:29:39 -08003114 u32 size;
3115 int error;
3116 char *context = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003117 struct inode_security_struct *isec = inode->i_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003118
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00003119 if (strcmp(name, XATTR_SELINUX_SUFFIX))
3120 return -EOPNOTSUPP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003121
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04003122 /*
3123 * If the caller has CAP_MAC_ADMIN, then get the raw context
3124 * value even if it is not defined by current policy; otherwise,
3125 * use the in-core value under current policy.
3126 * Use the non-auditing forms of the permission checks since
3127 * getxattr may be called by unprivileged processes commonly
3128 * and lack of permission just means that we fall back to the
3129 * in-core context value, not a denial.
3130 */
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07003131 error = cap_capable(current_cred(), &init_user_ns, CAP_MAC_ADMIN,
3132 SECURITY_CAP_NOAUDIT);
3133 if (!error)
3134 error = cred_has_capability(current_cred(), CAP_MAC_ADMIN,
3135 SECURITY_CAP_NOAUDIT);
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04003136 if (!error)
3137 error = security_sid_to_context_force(isec->sid, &context,
3138 &size);
3139 else
3140 error = security_sid_to_context(isec->sid, &context, &size);
David P. Quigley42492592008-02-04 22:29:39 -08003141 if (error)
3142 return error;
3143 error = size;
3144 if (alloc) {
3145 *buffer = context;
3146 goto out_nofree;
3147 }
3148 kfree(context);
3149out_nofree:
3150 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003151}
3152
3153static int selinux_inode_setsecurity(struct inode *inode, const char *name,
Eric Paris828dfe12008-04-17 13:17:49 -04003154 const void *value, size_t size, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003155{
3156 struct inode_security_struct *isec = inode->i_security;
3157 u32 newsid;
3158 int rc;
3159
3160 if (strcmp(name, XATTR_SELINUX_SUFFIX))
3161 return -EOPNOTSUPP;
3162
3163 if (!value || !size)
3164 return -EACCES;
3165
Rasmus Villemoes20ba96a2015-10-21 17:44:26 -04003166 rc = security_context_to_sid(value, size, &newsid, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003167 if (rc)
3168 return rc;
3169
David Quigleyaa9c2662013-05-22 12:50:44 -04003170 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003171 isec->sid = newsid;
David P. Quigleyddd29ec2009-09-09 14:25:37 -04003172 isec->initialized = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003173 return 0;
3174}
3175
3176static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size)
3177{
3178 const int len = sizeof(XATTR_NAME_SELINUX);
3179 if (buffer && len <= buffer_size)
3180 memcpy(buffer, XATTR_NAME_SELINUX, len);
3181 return len;
3182}
3183
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02003184static void selinux_inode_getsecid(const struct inode *inode, u32 *secid)
3185{
3186 struct inode_security_struct *isec = inode->i_security;
3187 *secid = isec->sid;
3188}
3189
Linus Torvalds1da177e2005-04-16 15:20:36 -07003190/* file security operations */
3191
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003192static int selinux_revalidate_file_permission(struct file *file, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003193{
David Howells88e67f32008-11-14 10:39:21 +11003194 const struct cred *cred = current_cred();
Al Viro496ad9a2013-01-23 17:07:38 -05003195 struct inode *inode = file_inode(file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003196
Linus Torvalds1da177e2005-04-16 15:20:36 -07003197 /* file_mask_to_av won't add FILE__WRITE if MAY_APPEND is set */
3198 if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE))
3199 mask |= MAY_APPEND;
3200
Paul Moore389fb8002009-03-27 17:10:34 -04003201 return file_has_perm(cred, file,
3202 file_mask_to_av(inode->i_mode, mask));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003203}
3204
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003205static int selinux_file_permission(struct file *file, int mask)
3206{
Al Viro496ad9a2013-01-23 17:07:38 -05003207 struct inode *inode = file_inode(file);
Stephen Smalley20dda182009-06-22 14:54:53 -04003208 struct file_security_struct *fsec = file->f_security;
3209 struct inode_security_struct *isec = inode->i_security;
3210 u32 sid = current_sid();
3211
Paul Moore389fb8002009-03-27 17:10:34 -04003212 if (!mask)
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003213 /* No permission to check. Existence test. */
3214 return 0;
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003215
Stephen Smalley20dda182009-06-22 14:54:53 -04003216 if (sid == fsec->sid && fsec->isid == isec->sid &&
3217 fsec->pseqno == avc_policy_seqno())
Eric Paris83d49852012-04-04 13:45:40 -04003218 /* No change since file_open check. */
Stephen Smalley20dda182009-06-22 14:54:53 -04003219 return 0;
3220
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003221 return selinux_revalidate_file_permission(file, mask);
3222}
3223
Linus Torvalds1da177e2005-04-16 15:20:36 -07003224static int selinux_file_alloc_security(struct file *file)
3225{
3226 return file_alloc_security(file);
3227}
3228
3229static void selinux_file_free_security(struct file *file)
3230{
3231 file_free_security(file);
3232}
3233
Jeff Vander Stoepfa1aa142015-07-10 17:19:56 -04003234/*
3235 * Check whether a task has the ioctl permission and cmd
3236 * operation to an inode.
3237 */
Geliang Tang1d2a1682015-10-21 17:44:27 -04003238static int ioctl_has_perm(const struct cred *cred, struct file *file,
Jeff Vander Stoepfa1aa142015-07-10 17:19:56 -04003239 u32 requested, u16 cmd)
3240{
3241 struct common_audit_data ad;
3242 struct file_security_struct *fsec = file->f_security;
3243 struct inode *inode = file_inode(file);
3244 struct inode_security_struct *isec = inode->i_security;
3245 struct lsm_ioctlop_audit ioctl;
3246 u32 ssid = cred_sid(cred);
3247 int rc;
3248 u8 driver = cmd >> 8;
3249 u8 xperm = cmd & 0xff;
3250
3251 ad.type = LSM_AUDIT_DATA_IOCTL_OP;
3252 ad.u.op = &ioctl;
3253 ad.u.op->cmd = cmd;
3254 ad.u.op->path = file->f_path;
3255
3256 if (ssid != fsec->sid) {
3257 rc = avc_has_perm(ssid, fsec->sid,
3258 SECCLASS_FD,
3259 FD__USE,
3260 &ad);
3261 if (rc)
3262 goto out;
3263 }
3264
3265 if (unlikely(IS_PRIVATE(inode)))
3266 return 0;
3267
3268 rc = avc_has_extended_perms(ssid, isec->sid, isec->sclass,
3269 requested, driver, xperm, &ad);
3270out:
3271 return rc;
3272}
3273
Linus Torvalds1da177e2005-04-16 15:20:36 -07003274static int selinux_file_ioctl(struct file *file, unsigned int cmd,
3275 unsigned long arg)
3276{
David Howells88e67f32008-11-14 10:39:21 +11003277 const struct cred *cred = current_cred();
Eric Paris0b24dcb2011-02-25 15:39:20 -05003278 int error = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003279
Eric Paris0b24dcb2011-02-25 15:39:20 -05003280 switch (cmd) {
3281 case FIONREAD:
3282 /* fall through */
3283 case FIBMAP:
3284 /* fall through */
3285 case FIGETBSZ:
3286 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003287 case FS_IOC_GETFLAGS:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003288 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003289 case FS_IOC_GETVERSION:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003290 error = file_has_perm(cred, file, FILE__GETATTR);
3291 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003292
Al Viro2f99c362012-03-23 16:04:05 -04003293 case FS_IOC_SETFLAGS:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003294 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003295 case FS_IOC_SETVERSION:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003296 error = file_has_perm(cred, file, FILE__SETATTR);
3297 break;
3298
3299 /* sys_ioctl() checks */
3300 case FIONBIO:
3301 /* fall through */
3302 case FIOASYNC:
3303 error = file_has_perm(cred, file, 0);
3304 break;
3305
3306 case KDSKBENT:
3307 case KDSKBSENT:
Eric Paris6a9de492012-01-03 12:25:14 -05003308 error = cred_has_capability(cred, CAP_SYS_TTY_CONFIG,
3309 SECURITY_CAP_AUDIT);
Eric Paris0b24dcb2011-02-25 15:39:20 -05003310 break;
3311
3312 /* default case assumes that the command will go
3313 * to the file's ioctl() function.
3314 */
3315 default:
Jeff Vander Stoepfa1aa142015-07-10 17:19:56 -04003316 error = ioctl_has_perm(cred, file, FILE__IOCTL, (u16) cmd);
Eric Paris0b24dcb2011-02-25 15:39:20 -05003317 }
3318 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003319}
3320
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003321static int default_noexec;
3322
Linus Torvalds1da177e2005-04-16 15:20:36 -07003323static int file_map_prot_check(struct file *file, unsigned long prot, int shared)
3324{
David Howells88e67f32008-11-14 10:39:21 +11003325 const struct cred *cred = current_cred();
David Howellsd84f4f92008-11-14 10:39:23 +11003326 int rc = 0;
David Howells88e67f32008-11-14 10:39:21 +11003327
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003328 if (default_noexec &&
Stephen Smalley892e8ca2015-07-10 09:40:59 -04003329 (prot & PROT_EXEC) && (!file || IS_PRIVATE(file_inode(file)) ||
3330 (!shared && (prot & PROT_WRITE)))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003331 /*
3332 * We are making executable an anonymous mapping or a
3333 * private file mapping that will also be writable.
3334 * This has an additional check.
3335 */
David Howellsd84f4f92008-11-14 10:39:23 +11003336 rc = cred_has_perm(cred, cred, PROCESS__EXECMEM);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003337 if (rc)
David Howellsd84f4f92008-11-14 10:39:23 +11003338 goto error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003339 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003340
3341 if (file) {
3342 /* read access is always possible with a mapping */
3343 u32 av = FILE__READ;
3344
3345 /* write access only matters if the mapping is shared */
3346 if (shared && (prot & PROT_WRITE))
3347 av |= FILE__WRITE;
3348
3349 if (prot & PROT_EXEC)
3350 av |= FILE__EXECUTE;
3351
David Howells88e67f32008-11-14 10:39:21 +11003352 return file_has_perm(cred, file, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003353 }
David Howellsd84f4f92008-11-14 10:39:23 +11003354
3355error:
3356 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003357}
3358
Al Viroe5467852012-05-30 13:30:51 -04003359static int selinux_mmap_addr(unsigned long addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003360{
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07003361 int rc = 0;
Paul Moore98883bf2014-03-19 16:46:11 -04003362
3363 if (addr < CONFIG_LSM_MMAP_MIN_ADDR) {
3364 u32 sid = current_sid();
3365 rc = avc_has_perm(sid, sid, SECCLASS_MEMPROTECT,
3366 MEMPROTECT__MMAP_ZERO, NULL);
3367 }
3368
3369 return rc;
Al Viroe5467852012-05-30 13:30:51 -04003370}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003371
Al Viroe5467852012-05-30 13:30:51 -04003372static int selinux_mmap_file(struct file *file, unsigned long reqprot,
3373 unsigned long prot, unsigned long flags)
3374{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003375 if (selinux_checkreqprot)
3376 prot = reqprot;
3377
3378 return file_map_prot_check(file, prot,
3379 (flags & MAP_TYPE) == MAP_SHARED);
3380}
3381
3382static int selinux_file_mprotect(struct vm_area_struct *vma,
3383 unsigned long reqprot,
3384 unsigned long prot)
3385{
David Howells88e67f32008-11-14 10:39:21 +11003386 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003387
3388 if (selinux_checkreqprot)
3389 prot = reqprot;
3390
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003391 if (default_noexec &&
3392 (prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) {
James Morrisd541bbe2009-01-29 12:19:51 +11003393 int rc = 0;
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003394 if (vma->vm_start >= vma->vm_mm->start_brk &&
3395 vma->vm_end <= vma->vm_mm->brk) {
David Howellsd84f4f92008-11-14 10:39:23 +11003396 rc = cred_has_perm(cred, cred, PROCESS__EXECHEAP);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003397 } else if (!vma->vm_file &&
3398 vma->vm_start <= vma->vm_mm->start_stack &&
3399 vma->vm_end >= vma->vm_mm->start_stack) {
David Howells3b11a1d2008-11-14 10:39:26 +11003400 rc = current_has_perm(current, PROCESS__EXECSTACK);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003401 } else if (vma->vm_file && vma->anon_vma) {
3402 /*
3403 * We are making executable a file mapping that has
3404 * had some COW done. Since pages might have been
3405 * written, check ability to execute the possibly
3406 * modified content. This typically should only
3407 * occur for text relocations.
3408 */
David Howellsd84f4f92008-11-14 10:39:23 +11003409 rc = file_has_perm(cred, vma->vm_file, FILE__EXECMOD);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003410 }
Lorenzo Hernandez García-Hierro6b992192005-06-25 14:54:34 -07003411 if (rc)
3412 return rc;
3413 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003414
3415 return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED);
3416}
3417
3418static int selinux_file_lock(struct file *file, unsigned int cmd)
3419{
David Howells88e67f32008-11-14 10:39:21 +11003420 const struct cred *cred = current_cred();
3421
3422 return file_has_perm(cred, file, FILE__LOCK);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003423}
3424
3425static int selinux_file_fcntl(struct file *file, unsigned int cmd,
3426 unsigned long arg)
3427{
David Howells88e67f32008-11-14 10:39:21 +11003428 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003429 int err = 0;
3430
3431 switch (cmd) {
Eric Paris828dfe12008-04-17 13:17:49 -04003432 case F_SETFL:
Eric Paris828dfe12008-04-17 13:17:49 -04003433 if ((file->f_flags & O_APPEND) && !(arg & O_APPEND)) {
David Howells88e67f32008-11-14 10:39:21 +11003434 err = file_has_perm(cred, file, FILE__WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003435 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003436 }
3437 /* fall through */
3438 case F_SETOWN:
3439 case F_SETSIG:
3440 case F_GETFL:
3441 case F_GETOWN:
3442 case F_GETSIG:
Cyrill Gorcunov1d151c32012-07-30 14:43:00 -07003443 case F_GETOWNER_UIDS:
Eric Paris828dfe12008-04-17 13:17:49 -04003444 /* Just check FD__USE permission */
David Howells88e67f32008-11-14 10:39:21 +11003445 err = file_has_perm(cred, file, 0);
Eric Paris828dfe12008-04-17 13:17:49 -04003446 break;
3447 case F_GETLK:
3448 case F_SETLK:
3449 case F_SETLKW:
Jeff Layton0d3f7a22014-04-22 08:23:58 -04003450 case F_OFD_GETLK:
3451 case F_OFD_SETLK:
3452 case F_OFD_SETLKW:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003453#if BITS_PER_LONG == 32
Eric Paris828dfe12008-04-17 13:17:49 -04003454 case F_GETLK64:
3455 case F_SETLK64:
3456 case F_SETLKW64:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003457#endif
David Howells88e67f32008-11-14 10:39:21 +11003458 err = file_has_perm(cred, file, FILE__LOCK);
Eric Paris828dfe12008-04-17 13:17:49 -04003459 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003460 }
3461
3462 return err;
3463}
3464
Jeff Laytone0b93ed2014-08-22 11:27:32 -04003465static void selinux_file_set_fowner(struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003466{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003467 struct file_security_struct *fsec;
3468
Linus Torvalds1da177e2005-04-16 15:20:36 -07003469 fsec = file->f_security;
David Howells275bb412008-11-14 10:39:19 +11003470 fsec->fown_sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003471}
3472
3473static int selinux_file_send_sigiotask(struct task_struct *tsk,
3474 struct fown_struct *fown, int signum)
3475{
Eric Paris828dfe12008-04-17 13:17:49 -04003476 struct file *file;
Stephen Smalley65c90bc2009-05-04 15:43:18 -04003477 u32 sid = task_sid(tsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003478 u32 perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003479 struct file_security_struct *fsec;
3480
3481 /* struct fown_struct is never outside the context of a struct file */
Eric Paris828dfe12008-04-17 13:17:49 -04003482 file = container_of(fown, struct file, f_owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003483
Linus Torvalds1da177e2005-04-16 15:20:36 -07003484 fsec = file->f_security;
3485
3486 if (!signum)
3487 perm = signal_to_av(SIGIO); /* as per send_sigio_to_task */
3488 else
3489 perm = signal_to_av(signum);
3490
David Howells275bb412008-11-14 10:39:19 +11003491 return avc_has_perm(fsec->fown_sid, sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003492 SECCLASS_PROCESS, perm, NULL);
3493}
3494
3495static int selinux_file_receive(struct file *file)
3496{
David Howells88e67f32008-11-14 10:39:21 +11003497 const struct cred *cred = current_cred();
3498
3499 return file_has_perm(cred, file, file_to_av(file));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003500}
3501
Eric Paris83d49852012-04-04 13:45:40 -04003502static int selinux_file_open(struct file *file, const struct cred *cred)
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003503{
3504 struct file_security_struct *fsec;
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003505 struct inode_security_struct *isec;
David Howellsd84f4f92008-11-14 10:39:23 +11003506
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003507 fsec = file->f_security;
Al Viro496ad9a2013-01-23 17:07:38 -05003508 isec = file_inode(file)->i_security;
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003509 /*
3510 * Save inode label and policy sequence number
3511 * at open-time so that selinux_file_permission
3512 * can determine whether revalidation is necessary.
3513 * Task label is already saved in the file security
3514 * struct as its SID.
3515 */
3516 fsec->isid = isec->sid;
3517 fsec->pseqno = avc_policy_seqno();
3518 /*
3519 * Since the inode label or policy seqno may have changed
3520 * between the selinux_inode_permission check and the saving
3521 * of state above, recheck that access is still permitted.
3522 * Otherwise, access might never be revalidated against the
3523 * new inode label or new policy.
3524 * This check is not redundant - do not remove.
3525 */
David Howells13f8e982013-06-13 23:37:55 +01003526 return file_path_has_perm(cred, file, open_file_to_av(file));
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003527}
3528
Linus Torvalds1da177e2005-04-16 15:20:36 -07003529/* task security operations */
3530
3531static int selinux_task_create(unsigned long clone_flags)
3532{
David Howells3b11a1d2008-11-14 10:39:26 +11003533 return current_has_perm(current, PROCESS__FORK);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003534}
3535
David Howellsf1752ee2008-11-14 10:39:17 +11003536/*
David Howellsee18d642009-09-02 09:14:21 +01003537 * allocate the SELinux part of blank credentials
3538 */
3539static int selinux_cred_alloc_blank(struct cred *cred, gfp_t gfp)
3540{
3541 struct task_security_struct *tsec;
3542
3543 tsec = kzalloc(sizeof(struct task_security_struct), gfp);
3544 if (!tsec)
3545 return -ENOMEM;
3546
3547 cred->security = tsec;
3548 return 0;
3549}
3550
3551/*
David Howellsf1752ee2008-11-14 10:39:17 +11003552 * detach and free the LSM part of a set of credentials
3553 */
3554static void selinux_cred_free(struct cred *cred)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003555{
David Howellsf1752ee2008-11-14 10:39:17 +11003556 struct task_security_struct *tsec = cred->security;
David Howellse0e81732009-09-02 09:13:40 +01003557
Tetsuo Handa2edeaa32011-02-07 13:36:10 +00003558 /*
3559 * cred->security == NULL if security_cred_alloc_blank() or
3560 * security_prepare_creds() returned an error.
3561 */
3562 BUG_ON(cred->security && (unsigned long) cred->security < PAGE_SIZE);
David Howellse0e81732009-09-02 09:13:40 +01003563 cred->security = (void *) 0x7UL;
David Howellsf1752ee2008-11-14 10:39:17 +11003564 kfree(tsec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003565}
3566
David Howellsd84f4f92008-11-14 10:39:23 +11003567/*
3568 * prepare a new set of credentials for modification
3569 */
3570static int selinux_cred_prepare(struct cred *new, const struct cred *old,
3571 gfp_t gfp)
3572{
3573 const struct task_security_struct *old_tsec;
3574 struct task_security_struct *tsec;
3575
3576 old_tsec = old->security;
3577
3578 tsec = kmemdup(old_tsec, sizeof(struct task_security_struct), gfp);
3579 if (!tsec)
3580 return -ENOMEM;
3581
3582 new->security = tsec;
3583 return 0;
3584}
3585
3586/*
David Howellsee18d642009-09-02 09:14:21 +01003587 * transfer the SELinux data to a blank set of creds
3588 */
3589static void selinux_cred_transfer(struct cred *new, const struct cred *old)
3590{
3591 const struct task_security_struct *old_tsec = old->security;
3592 struct task_security_struct *tsec = new->security;
3593
3594 *tsec = *old_tsec;
3595}
3596
3597/*
David Howells3a3b7ce2008-11-14 10:39:28 +11003598 * set the security data for a kernel service
3599 * - all the creation contexts are set to unlabelled
3600 */
3601static int selinux_kernel_act_as(struct cred *new, u32 secid)
3602{
3603 struct task_security_struct *tsec = new->security;
3604 u32 sid = current_sid();
3605 int ret;
3606
3607 ret = avc_has_perm(sid, secid,
3608 SECCLASS_KERNEL_SERVICE,
3609 KERNEL_SERVICE__USE_AS_OVERRIDE,
3610 NULL);
3611 if (ret == 0) {
3612 tsec->sid = secid;
3613 tsec->create_sid = 0;
3614 tsec->keycreate_sid = 0;
3615 tsec->sockcreate_sid = 0;
3616 }
3617 return ret;
3618}
3619
3620/*
3621 * set the file creation context in a security record to the same as the
3622 * objective context of the specified inode
3623 */
3624static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode)
3625{
3626 struct inode_security_struct *isec = inode->i_security;
3627 struct task_security_struct *tsec = new->security;
3628 u32 sid = current_sid();
3629 int ret;
3630
3631 ret = avc_has_perm(sid, isec->sid,
3632 SECCLASS_KERNEL_SERVICE,
3633 KERNEL_SERVICE__CREATE_FILES_AS,
3634 NULL);
3635
3636 if (ret == 0)
3637 tsec->create_sid = isec->sid;
David Howellsef574712010-02-26 01:56:16 +00003638 return ret;
David Howells3a3b7ce2008-11-14 10:39:28 +11003639}
3640
Eric Parisdd8dbf22009-11-03 16:35:32 +11003641static int selinux_kernel_module_request(char *kmod_name)
Eric Paris25354c42009-08-13 09:45:03 -04003642{
Eric Parisdd8dbf22009-11-03 16:35:32 +11003643 u32 sid;
3644 struct common_audit_data ad;
3645
3646 sid = task_sid(current);
3647
Eric Paris50c205f2012-04-04 15:01:43 -04003648 ad.type = LSM_AUDIT_DATA_KMOD;
Eric Parisdd8dbf22009-11-03 16:35:32 +11003649 ad.u.kmod_name = kmod_name;
3650
3651 return avc_has_perm(sid, SECINITSID_KERNEL, SECCLASS_SYSTEM,
3652 SYSTEM__MODULE_REQUEST, &ad);
Eric Paris25354c42009-08-13 09:45:03 -04003653}
3654
Linus Torvalds1da177e2005-04-16 15:20:36 -07003655static int selinux_task_setpgid(struct task_struct *p, pid_t pgid)
3656{
David Howells3b11a1d2008-11-14 10:39:26 +11003657 return current_has_perm(p, PROCESS__SETPGID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003658}
3659
3660static int selinux_task_getpgid(struct task_struct *p)
3661{
David Howells3b11a1d2008-11-14 10:39:26 +11003662 return current_has_perm(p, PROCESS__GETPGID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003663}
3664
3665static int selinux_task_getsid(struct task_struct *p)
3666{
David Howells3b11a1d2008-11-14 10:39:26 +11003667 return current_has_perm(p, PROCESS__GETSESSION);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003668}
3669
David Quigleyf9008e42006-06-30 01:55:46 -07003670static void selinux_task_getsecid(struct task_struct *p, u32 *secid)
3671{
David Howells275bb412008-11-14 10:39:19 +11003672 *secid = task_sid(p);
David Quigleyf9008e42006-06-30 01:55:46 -07003673}
3674
Linus Torvalds1da177e2005-04-16 15:20:36 -07003675static int selinux_task_setnice(struct task_struct *p, int nice)
3676{
David Howells3b11a1d2008-11-14 10:39:26 +11003677 return current_has_perm(p, PROCESS__SETSCHED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003678}
3679
James Morris03e68062006-06-23 02:03:58 -07003680static int selinux_task_setioprio(struct task_struct *p, int ioprio)
3681{
David Howells3b11a1d2008-11-14 10:39:26 +11003682 return current_has_perm(p, PROCESS__SETSCHED);
James Morris03e68062006-06-23 02:03:58 -07003683}
3684
David Quigleya1836a42006-06-30 01:55:49 -07003685static int selinux_task_getioprio(struct task_struct *p)
3686{
David Howells3b11a1d2008-11-14 10:39:26 +11003687 return current_has_perm(p, PROCESS__GETSCHED);
David Quigleya1836a42006-06-30 01:55:49 -07003688}
3689
Jiri Slaby8fd00b42009-08-26 18:41:16 +02003690static int selinux_task_setrlimit(struct task_struct *p, unsigned int resource,
3691 struct rlimit *new_rlim)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003692{
Jiri Slaby8fd00b42009-08-26 18:41:16 +02003693 struct rlimit *old_rlim = p->signal->rlim + resource;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003694
3695 /* Control the ability to change the hard limit (whether
3696 lowering or raising it), so that the hard limit can
3697 later be used as a safe reset point for the soft limit
David Howellsd84f4f92008-11-14 10:39:23 +11003698 upon context transitions. See selinux_bprm_committing_creds. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003699 if (old_rlim->rlim_max != new_rlim->rlim_max)
Jiri Slaby8fd00b42009-08-26 18:41:16 +02003700 return current_has_perm(p, PROCESS__SETRLIMIT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003701
3702 return 0;
3703}
3704
KOSAKI Motohirob0ae1982010-10-15 04:21:18 +09003705static int selinux_task_setscheduler(struct task_struct *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003706{
David Howells3b11a1d2008-11-14 10:39:26 +11003707 return current_has_perm(p, PROCESS__SETSCHED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003708}
3709
3710static int selinux_task_getscheduler(struct task_struct *p)
3711{
David Howells3b11a1d2008-11-14 10:39:26 +11003712 return current_has_perm(p, PROCESS__GETSCHED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003713}
3714
David Quigley35601542006-06-23 02:04:01 -07003715static int selinux_task_movememory(struct task_struct *p)
3716{
David Howells3b11a1d2008-11-14 10:39:26 +11003717 return current_has_perm(p, PROCESS__SETSCHED);
David Quigley35601542006-06-23 02:04:01 -07003718}
3719
David Quigleyf9008e42006-06-30 01:55:46 -07003720static int selinux_task_kill(struct task_struct *p, struct siginfo *info,
3721 int sig, u32 secid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003722{
3723 u32 perm;
3724 int rc;
3725
Linus Torvalds1da177e2005-04-16 15:20:36 -07003726 if (!sig)
3727 perm = PROCESS__SIGNULL; /* null signal; existence test */
3728 else
3729 perm = signal_to_av(sig);
David Quigleyf9008e42006-06-30 01:55:46 -07003730 if (secid)
David Howells275bb412008-11-14 10:39:19 +11003731 rc = avc_has_perm(secid, task_sid(p),
3732 SECCLASS_PROCESS, perm, NULL);
David Quigleyf9008e42006-06-30 01:55:46 -07003733 else
David Howells3b11a1d2008-11-14 10:39:26 +11003734 rc = current_has_perm(p, perm);
David Quigleyf9008e42006-06-30 01:55:46 -07003735 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003736}
3737
Linus Torvalds1da177e2005-04-16 15:20:36 -07003738static int selinux_task_wait(struct task_struct *p)
3739{
Eric Paris8a535142007-10-22 16:10:31 -04003740 return task_has_perm(p, current, PROCESS__SIGCHLD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003741}
3742
Linus Torvalds1da177e2005-04-16 15:20:36 -07003743static void selinux_task_to_inode(struct task_struct *p,
3744 struct inode *inode)
3745{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003746 struct inode_security_struct *isec = inode->i_security;
David Howells275bb412008-11-14 10:39:19 +11003747 u32 sid = task_sid(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003748
David Howells275bb412008-11-14 10:39:19 +11003749 isec->sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003750 isec->initialized = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003751}
3752
Linus Torvalds1da177e2005-04-16 15:20:36 -07003753/* Returns error only if unable to parse addresses */
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003754static int selinux_parse_skb_ipv4(struct sk_buff *skb,
Thomas Liu2bf49692009-07-14 12:14:09 -04003755 struct common_audit_data *ad, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003756{
3757 int offset, ihlen, ret = -EINVAL;
3758 struct iphdr _iph, *ih;
3759
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03003760 offset = skb_network_offset(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003761 ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph);
3762 if (ih == NULL)
3763 goto out;
3764
3765 ihlen = ih->ihl * 4;
3766 if (ihlen < sizeof(_iph))
3767 goto out;
3768
Eric Paris48c62af2012-04-02 13:15:44 -04003769 ad->u.net->v4info.saddr = ih->saddr;
3770 ad->u.net->v4info.daddr = ih->daddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003771 ret = 0;
3772
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003773 if (proto)
3774 *proto = ih->protocol;
3775
Linus Torvalds1da177e2005-04-16 15:20:36 -07003776 switch (ih->protocol) {
Eric Paris828dfe12008-04-17 13:17:49 -04003777 case IPPROTO_TCP: {
3778 struct tcphdr _tcph, *th;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003779
Eric Paris828dfe12008-04-17 13:17:49 -04003780 if (ntohs(ih->frag_off) & IP_OFFSET)
3781 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003782
3783 offset += ihlen;
3784 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
3785 if (th == NULL)
3786 break;
3787
Eric Paris48c62af2012-04-02 13:15:44 -04003788 ad->u.net->sport = th->source;
3789 ad->u.net->dport = th->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003790 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003791 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003792
Eric Paris828dfe12008-04-17 13:17:49 -04003793 case IPPROTO_UDP: {
3794 struct udphdr _udph, *uh;
3795
3796 if (ntohs(ih->frag_off) & IP_OFFSET)
3797 break;
3798
3799 offset += ihlen;
3800 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
3801 if (uh == NULL)
3802 break;
3803
Eric Paris48c62af2012-04-02 13:15:44 -04003804 ad->u.net->sport = uh->source;
3805 ad->u.net->dport = uh->dest;
Eric Paris828dfe12008-04-17 13:17:49 -04003806 break;
3807 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003808
James Morris2ee92d42006-11-13 16:09:01 -08003809 case IPPROTO_DCCP: {
3810 struct dccp_hdr _dccph, *dh;
3811
3812 if (ntohs(ih->frag_off) & IP_OFFSET)
3813 break;
3814
3815 offset += ihlen;
3816 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
3817 if (dh == NULL)
3818 break;
3819
Eric Paris48c62af2012-04-02 13:15:44 -04003820 ad->u.net->sport = dh->dccph_sport;
3821 ad->u.net->dport = dh->dccph_dport;
James Morris2ee92d42006-11-13 16:09:01 -08003822 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003823 }
James Morris2ee92d42006-11-13 16:09:01 -08003824
Eric Paris828dfe12008-04-17 13:17:49 -04003825 default:
3826 break;
3827 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003828out:
3829 return ret;
3830}
3831
3832#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
3833
3834/* Returns error only if unable to parse addresses */
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003835static int selinux_parse_skb_ipv6(struct sk_buff *skb,
Thomas Liu2bf49692009-07-14 12:14:09 -04003836 struct common_audit_data *ad, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003837{
3838 u8 nexthdr;
3839 int ret = -EINVAL, offset;
3840 struct ipv6hdr _ipv6h, *ip6;
Jesse Gross75f28112011-11-30 17:05:51 -08003841 __be16 frag_off;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003842
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03003843 offset = skb_network_offset(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003844 ip6 = skb_header_pointer(skb, offset, sizeof(_ipv6h), &_ipv6h);
3845 if (ip6 == NULL)
3846 goto out;
3847
Eric Paris48c62af2012-04-02 13:15:44 -04003848 ad->u.net->v6info.saddr = ip6->saddr;
3849 ad->u.net->v6info.daddr = ip6->daddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003850 ret = 0;
3851
3852 nexthdr = ip6->nexthdr;
3853 offset += sizeof(_ipv6h);
Jesse Gross75f28112011-11-30 17:05:51 -08003854 offset = ipv6_skip_exthdr(skb, offset, &nexthdr, &frag_off);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003855 if (offset < 0)
3856 goto out;
3857
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003858 if (proto)
3859 *proto = nexthdr;
3860
Linus Torvalds1da177e2005-04-16 15:20:36 -07003861 switch (nexthdr) {
3862 case IPPROTO_TCP: {
Eric Paris828dfe12008-04-17 13:17:49 -04003863 struct tcphdr _tcph, *th;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003864
3865 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
3866 if (th == NULL)
3867 break;
3868
Eric Paris48c62af2012-04-02 13:15:44 -04003869 ad->u.net->sport = th->source;
3870 ad->u.net->dport = th->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003871 break;
3872 }
3873
3874 case IPPROTO_UDP: {
3875 struct udphdr _udph, *uh;
3876
3877 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
3878 if (uh == NULL)
3879 break;
3880
Eric Paris48c62af2012-04-02 13:15:44 -04003881 ad->u.net->sport = uh->source;
3882 ad->u.net->dport = uh->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003883 break;
3884 }
3885
James Morris2ee92d42006-11-13 16:09:01 -08003886 case IPPROTO_DCCP: {
3887 struct dccp_hdr _dccph, *dh;
3888
3889 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
3890 if (dh == NULL)
3891 break;
3892
Eric Paris48c62af2012-04-02 13:15:44 -04003893 ad->u.net->sport = dh->dccph_sport;
3894 ad->u.net->dport = dh->dccph_dport;
James Morris2ee92d42006-11-13 16:09:01 -08003895 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003896 }
James Morris2ee92d42006-11-13 16:09:01 -08003897
Linus Torvalds1da177e2005-04-16 15:20:36 -07003898 /* includes fragments */
3899 default:
3900 break;
3901 }
3902out:
3903 return ret;
3904}
3905
3906#endif /* IPV6 */
3907
Thomas Liu2bf49692009-07-14 12:14:09 -04003908static int selinux_parse_skb(struct sk_buff *skb, struct common_audit_data *ad,
David Howellscf9481e2008-07-27 21:31:07 +10003909 char **_addrp, int src, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003910{
David Howellscf9481e2008-07-27 21:31:07 +10003911 char *addrp;
3912 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003913
Eric Paris48c62af2012-04-02 13:15:44 -04003914 switch (ad->u.net->family) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003915 case PF_INET:
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003916 ret = selinux_parse_skb_ipv4(skb, ad, proto);
David Howellscf9481e2008-07-27 21:31:07 +10003917 if (ret)
3918 goto parse_error;
Eric Paris48c62af2012-04-02 13:15:44 -04003919 addrp = (char *)(src ? &ad->u.net->v4info.saddr :
3920 &ad->u.net->v4info.daddr);
David Howellscf9481e2008-07-27 21:31:07 +10003921 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003922
3923#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
3924 case PF_INET6:
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003925 ret = selinux_parse_skb_ipv6(skb, ad, proto);
David Howellscf9481e2008-07-27 21:31:07 +10003926 if (ret)
3927 goto parse_error;
Eric Paris48c62af2012-04-02 13:15:44 -04003928 addrp = (char *)(src ? &ad->u.net->v6info.saddr :
3929 &ad->u.net->v6info.daddr);
David Howellscf9481e2008-07-27 21:31:07 +10003930 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003931#endif /* IPV6 */
3932 default:
David Howellscf9481e2008-07-27 21:31:07 +10003933 addrp = NULL;
3934 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003935 }
3936
David Howellscf9481e2008-07-27 21:31:07 +10003937parse_error:
3938 printk(KERN_WARNING
3939 "SELinux: failure in selinux_parse_skb(),"
3940 " unable to parse packet\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003941 return ret;
David Howellscf9481e2008-07-27 21:31:07 +10003942
3943okay:
3944 if (_addrp)
3945 *_addrp = addrp;
3946 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003947}
3948
Paul Moore4f6a9932007-03-01 14:35:22 -05003949/**
Paul Moore220deb92008-01-29 08:38:23 -05003950 * selinux_skb_peerlbl_sid - Determine the peer label of a packet
Paul Moore4f6a9932007-03-01 14:35:22 -05003951 * @skb: the packet
Paul Moore75e22912008-01-29 08:38:04 -05003952 * @family: protocol family
Paul Moore220deb92008-01-29 08:38:23 -05003953 * @sid: the packet's peer label SID
Paul Moore4f6a9932007-03-01 14:35:22 -05003954 *
3955 * Description:
Paul Moore220deb92008-01-29 08:38:23 -05003956 * Check the various different forms of network peer labeling and determine
3957 * the peer label/SID for the packet; most of the magic actually occurs in
3958 * the security server function security_net_peersid_cmp(). The function
3959 * returns zero if the value in @sid is valid (although it may be SECSID_NULL)
3960 * or -EACCES if @sid is invalid due to inconsistencies with the different
3961 * peer labels.
Paul Moore4f6a9932007-03-01 14:35:22 -05003962 *
3963 */
Paul Moore220deb92008-01-29 08:38:23 -05003964static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)
Paul Moore4f6a9932007-03-01 14:35:22 -05003965{
Paul Moore71f1cb02008-01-29 08:51:16 -05003966 int err;
Paul Moore4f6a9932007-03-01 14:35:22 -05003967 u32 xfrm_sid;
3968 u32 nlbl_sid;
Paul Moore220deb92008-01-29 08:38:23 -05003969 u32 nlbl_type;
Paul Moore4f6a9932007-03-01 14:35:22 -05003970
Paul Moore817eff72013-12-10 14:57:54 -05003971 err = selinux_xfrm_skb_sid(skb, &xfrm_sid);
Paul Moorebed4d7e2013-07-23 17:38:40 -04003972 if (unlikely(err))
3973 return -EACCES;
3974 err = selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid);
3975 if (unlikely(err))
3976 return -EACCES;
Paul Moore220deb92008-01-29 08:38:23 -05003977
Paul Moore71f1cb02008-01-29 08:51:16 -05003978 err = security_net_peersid_resolve(nlbl_sid, nlbl_type, xfrm_sid, sid);
3979 if (unlikely(err)) {
3980 printk(KERN_WARNING
3981 "SELinux: failure in selinux_skb_peerlbl_sid(),"
3982 " unable to determine packet's peer label\n");
Paul Moore220deb92008-01-29 08:38:23 -05003983 return -EACCES;
Paul Moore71f1cb02008-01-29 08:51:16 -05003984 }
Paul Moore220deb92008-01-29 08:38:23 -05003985
3986 return 0;
Paul Moore4f6a9932007-03-01 14:35:22 -05003987}
3988
Paul Moore446b8022013-12-04 16:10:51 -05003989/**
3990 * selinux_conn_sid - Determine the child socket label for a connection
3991 * @sk_sid: the parent socket's SID
3992 * @skb_sid: the packet's SID
3993 * @conn_sid: the resulting connection SID
3994 *
3995 * If @skb_sid is valid then the user:role:type information from @sk_sid is
3996 * combined with the MLS information from @skb_sid in order to create
3997 * @conn_sid. If @skb_sid is not valid then then @conn_sid is simply a copy
3998 * of @sk_sid. Returns zero on success, negative values on failure.
3999 *
4000 */
4001static int selinux_conn_sid(u32 sk_sid, u32 skb_sid, u32 *conn_sid)
4002{
4003 int err = 0;
4004
4005 if (skb_sid != SECSID_NULL)
4006 err = security_sid_mls_copy(sk_sid, skb_sid, conn_sid);
4007 else
4008 *conn_sid = sk_sid;
4009
4010 return err;
4011}
4012
Linus Torvalds1da177e2005-04-16 15:20:36 -07004013/* socket security operations */
Paul Moored4f2d972010-04-22 14:46:18 -04004014
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004015static int socket_sockcreate_sid(const struct task_security_struct *tsec,
4016 u16 secclass, u32 *socksid)
Paul Moored4f2d972010-04-22 14:46:18 -04004017{
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004018 if (tsec->sockcreate_sid > SECSID_NULL) {
4019 *socksid = tsec->sockcreate_sid;
4020 return 0;
4021 }
4022
4023 return security_transition_sid(tsec->sid, tsec->sid, secclass, NULL,
4024 socksid);
Paul Moored4f2d972010-04-22 14:46:18 -04004025}
4026
Paul Moore253bfae2010-04-22 14:46:19 -04004027static int sock_has_perm(struct task_struct *task, struct sock *sk, u32 perms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004028{
Paul Moore253bfae2010-04-22 14:46:19 -04004029 struct sk_security_struct *sksec = sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004030 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004031 struct lsm_network_audit net = {0,};
Paul Moore253bfae2010-04-22 14:46:19 -04004032 u32 tsid = task_sid(task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004033
Paul Moore253bfae2010-04-22 14:46:19 -04004034 if (sksec->sid == SECINITSID_KERNEL)
4035 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004036
Eric Paris50c205f2012-04-04 15:01:43 -04004037 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004038 ad.u.net = &net;
4039 ad.u.net->sk = sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004040
Paul Moore253bfae2010-04-22 14:46:19 -04004041 return avc_has_perm(tsid, sksec->sid, sksec->sclass, perms, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004042}
4043
4044static int selinux_socket_create(int family, int type,
4045 int protocol, int kern)
4046{
Paul Moore5fb49872010-04-22 14:46:19 -04004047 const struct task_security_struct *tsec = current_security();
Paul Moored4f2d972010-04-22 14:46:18 -04004048 u32 newsid;
David Howells275bb412008-11-14 10:39:19 +11004049 u16 secclass;
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004050 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004051
4052 if (kern)
Paul Moored4f2d972010-04-22 14:46:18 -04004053 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004054
David Howells275bb412008-11-14 10:39:19 +11004055 secclass = socket_type_to_security_class(family, type, protocol);
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004056 rc = socket_sockcreate_sid(tsec, secclass, &newsid);
4057 if (rc)
4058 return rc;
4059
Paul Moored4f2d972010-04-22 14:46:18 -04004060 return avc_has_perm(tsec->sid, newsid, secclass, SOCKET__CREATE, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004061}
4062
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07004063static int selinux_socket_post_create(struct socket *sock, int family,
4064 int type, int protocol, int kern)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004065{
Paul Moore5fb49872010-04-22 14:46:19 -04004066 const struct task_security_struct *tsec = current_security();
Paul Moored4f2d972010-04-22 14:46:18 -04004067 struct inode_security_struct *isec = SOCK_INODE(sock)->i_security;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004068 struct sk_security_struct *sksec;
David Howells275bb412008-11-14 10:39:19 +11004069 int err = 0;
4070
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004071 isec->sclass = socket_type_to_security_class(family, type, protocol);
4072
David Howells275bb412008-11-14 10:39:19 +11004073 if (kern)
4074 isec->sid = SECINITSID_KERNEL;
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004075 else {
4076 err = socket_sockcreate_sid(tsec, isec->sclass, &(isec->sid));
4077 if (err)
4078 return err;
4079 }
David Howells275bb412008-11-14 10:39:19 +11004080
Linus Torvalds1da177e2005-04-16 15:20:36 -07004081 isec->initialized = 1;
4082
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004083 if (sock->sk) {
4084 sksec = sock->sk->sk_security;
4085 sksec->sid = isec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05004086 sksec->sclass = isec->sclass;
Paul Moore389fb8002009-03-27 17:10:34 -04004087 err = selinux_netlbl_socket_post_create(sock->sk, family);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004088 }
4089
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07004090 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004091}
4092
4093/* Range of port numbers used to automatically bind.
4094 Need to determine whether we should perform a name_bind
4095 permission check between the socket and the port number. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004096
4097static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen)
4098{
Paul Moore253bfae2010-04-22 14:46:19 -04004099 struct sock *sk = sock->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004100 u16 family;
4101 int err;
4102
Paul Moore253bfae2010-04-22 14:46:19 -04004103 err = sock_has_perm(current, sk, SOCKET__BIND);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004104 if (err)
4105 goto out;
4106
4107 /*
4108 * If PF_INET or PF_INET6, check name_bind permission for the port.
James Morris13402582005-09-30 14:24:34 -04004109 * Multiple address binding for SCTP is not supported yet: we just
4110 * check the first address now.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004111 */
Paul Moore253bfae2010-04-22 14:46:19 -04004112 family = sk->sk_family;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004113 if (family == PF_INET || family == PF_INET6) {
4114 char *addrp;
Paul Moore253bfae2010-04-22 14:46:19 -04004115 struct sk_security_struct *sksec = sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004116 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004117 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004118 struct sockaddr_in *addr4 = NULL;
4119 struct sockaddr_in6 *addr6 = NULL;
4120 unsigned short snum;
James Morrise399f982008-06-12 01:39:58 +10004121 u32 sid, node_perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004122
Linus Torvalds1da177e2005-04-16 15:20:36 -07004123 if (family == PF_INET) {
4124 addr4 = (struct sockaddr_in *)address;
4125 snum = ntohs(addr4->sin_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004126 addrp = (char *)&addr4->sin_addr.s_addr;
4127 } else {
4128 addr6 = (struct sockaddr_in6 *)address;
4129 snum = ntohs(addr6->sin6_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004130 addrp = (char *)&addr6->sin6_addr.s6_addr;
4131 }
4132
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004133 if (snum) {
4134 int low, high;
4135
Eric W. Biederman0bbf87d2013-09-28 14:10:59 -07004136 inet_get_local_port_range(sock_net(sk), &low, &high);
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004137
4138 if (snum < max(PROT_SOCK, low) || snum > high) {
Paul Moore3e112172008-04-10 10:48:14 -04004139 err = sel_netport_sid(sk->sk_protocol,
4140 snum, &sid);
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004141 if (err)
4142 goto out;
Eric Paris50c205f2012-04-04 15:01:43 -04004143 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004144 ad.u.net = &net;
4145 ad.u.net->sport = htons(snum);
4146 ad.u.net->family = family;
Paul Moore253bfae2010-04-22 14:46:19 -04004147 err = avc_has_perm(sksec->sid, sid,
4148 sksec->sclass,
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004149 SOCKET__NAME_BIND, &ad);
4150 if (err)
4151 goto out;
4152 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004153 }
Eric Paris828dfe12008-04-17 13:17:49 -04004154
Paul Moore253bfae2010-04-22 14:46:19 -04004155 switch (sksec->sclass) {
James Morris13402582005-09-30 14:24:34 -04004156 case SECCLASS_TCP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004157 node_perm = TCP_SOCKET__NODE_BIND;
4158 break;
Eric Paris828dfe12008-04-17 13:17:49 -04004159
James Morris13402582005-09-30 14:24:34 -04004160 case SECCLASS_UDP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004161 node_perm = UDP_SOCKET__NODE_BIND;
4162 break;
James Morris2ee92d42006-11-13 16:09:01 -08004163
4164 case SECCLASS_DCCP_SOCKET:
4165 node_perm = DCCP_SOCKET__NODE_BIND;
4166 break;
4167
Linus Torvalds1da177e2005-04-16 15:20:36 -07004168 default:
4169 node_perm = RAWIP_SOCKET__NODE_BIND;
4170 break;
4171 }
Eric Paris828dfe12008-04-17 13:17:49 -04004172
Paul Moore224dfbd2008-01-29 08:38:13 -05004173 err = sel_netnode_sid(addrp, family, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004174 if (err)
4175 goto out;
Eric Paris828dfe12008-04-17 13:17:49 -04004176
Eric Paris50c205f2012-04-04 15:01:43 -04004177 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004178 ad.u.net = &net;
4179 ad.u.net->sport = htons(snum);
4180 ad.u.net->family = family;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004181
4182 if (family == PF_INET)
Eric Paris48c62af2012-04-02 13:15:44 -04004183 ad.u.net->v4info.saddr = addr4->sin_addr.s_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004184 else
Eric Paris48c62af2012-04-02 13:15:44 -04004185 ad.u.net->v6info.saddr = addr6->sin6_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004186
Paul Moore253bfae2010-04-22 14:46:19 -04004187 err = avc_has_perm(sksec->sid, sid,
4188 sksec->sclass, node_perm, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004189 if (err)
4190 goto out;
4191 }
4192out:
4193 return err;
4194}
4195
4196static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen)
4197{
Paul Moore014ab192008-10-10 10:16:33 -04004198 struct sock *sk = sock->sk;
Paul Moore253bfae2010-04-22 14:46:19 -04004199 struct sk_security_struct *sksec = sk->sk_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004200 int err;
4201
Paul Moore253bfae2010-04-22 14:46:19 -04004202 err = sock_has_perm(current, sk, SOCKET__CONNECT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004203 if (err)
4204 return err;
4205
4206 /*
James Morris2ee92d42006-11-13 16:09:01 -08004207 * If a TCP or DCCP socket, check name_connect permission for the port.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004208 */
Paul Moore253bfae2010-04-22 14:46:19 -04004209 if (sksec->sclass == SECCLASS_TCP_SOCKET ||
4210 sksec->sclass == SECCLASS_DCCP_SOCKET) {
Thomas Liu2bf49692009-07-14 12:14:09 -04004211 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004212 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004213 struct sockaddr_in *addr4 = NULL;
4214 struct sockaddr_in6 *addr6 = NULL;
4215 unsigned short snum;
James Morris2ee92d42006-11-13 16:09:01 -08004216 u32 sid, perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004217
4218 if (sk->sk_family == PF_INET) {
4219 addr4 = (struct sockaddr_in *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07004220 if (addrlen < sizeof(struct sockaddr_in))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004221 return -EINVAL;
4222 snum = ntohs(addr4->sin_port);
4223 } else {
4224 addr6 = (struct sockaddr_in6 *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07004225 if (addrlen < SIN6_LEN_RFC2133)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004226 return -EINVAL;
4227 snum = ntohs(addr6->sin6_port);
4228 }
4229
Paul Moore3e112172008-04-10 10:48:14 -04004230 err = sel_netport_sid(sk->sk_protocol, snum, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004231 if (err)
4232 goto out;
4233
Paul Moore253bfae2010-04-22 14:46:19 -04004234 perm = (sksec->sclass == SECCLASS_TCP_SOCKET) ?
James Morris2ee92d42006-11-13 16:09:01 -08004235 TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT;
4236
Eric Paris50c205f2012-04-04 15:01:43 -04004237 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004238 ad.u.net = &net;
4239 ad.u.net->dport = htons(snum);
4240 ad.u.net->family = sk->sk_family;
Paul Moore253bfae2010-04-22 14:46:19 -04004241 err = avc_has_perm(sksec->sid, sid, sksec->sclass, perm, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004242 if (err)
4243 goto out;
4244 }
4245
Paul Moore014ab192008-10-10 10:16:33 -04004246 err = selinux_netlbl_socket_connect(sk, address);
4247
Linus Torvalds1da177e2005-04-16 15:20:36 -07004248out:
4249 return err;
4250}
4251
4252static int selinux_socket_listen(struct socket *sock, int backlog)
4253{
Paul Moore253bfae2010-04-22 14:46:19 -04004254 return sock_has_perm(current, sock->sk, SOCKET__LISTEN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004255}
4256
4257static int selinux_socket_accept(struct socket *sock, struct socket *newsock)
4258{
4259 int err;
4260 struct inode_security_struct *isec;
4261 struct inode_security_struct *newisec;
4262
Paul Moore253bfae2010-04-22 14:46:19 -04004263 err = sock_has_perm(current, sock->sk, SOCKET__ACCEPT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004264 if (err)
4265 return err;
4266
4267 newisec = SOCK_INODE(newsock)->i_security;
4268
4269 isec = SOCK_INODE(sock)->i_security;
4270 newisec->sclass = isec->sclass;
4271 newisec->sid = isec->sid;
4272 newisec->initialized = 1;
4273
4274 return 0;
4275}
4276
4277static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg,
Eric Paris828dfe12008-04-17 13:17:49 -04004278 int size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004279{
Paul Moore253bfae2010-04-22 14:46:19 -04004280 return sock_has_perm(current, sock->sk, SOCKET__WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004281}
4282
4283static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg,
4284 int size, int flags)
4285{
Paul Moore253bfae2010-04-22 14:46:19 -04004286 return sock_has_perm(current, sock->sk, SOCKET__READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004287}
4288
4289static int selinux_socket_getsockname(struct socket *sock)
4290{
Paul Moore253bfae2010-04-22 14:46:19 -04004291 return sock_has_perm(current, sock->sk, SOCKET__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004292}
4293
4294static int selinux_socket_getpeername(struct socket *sock)
4295{
Paul Moore253bfae2010-04-22 14:46:19 -04004296 return sock_has_perm(current, sock->sk, SOCKET__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004297}
4298
Eric Paris828dfe12008-04-17 13:17:49 -04004299static int selinux_socket_setsockopt(struct socket *sock, int level, int optname)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004300{
Paul Mooref8687af2006-10-30 15:22:15 -08004301 int err;
4302
Paul Moore253bfae2010-04-22 14:46:19 -04004303 err = sock_has_perm(current, sock->sk, SOCKET__SETOPT);
Paul Mooref8687af2006-10-30 15:22:15 -08004304 if (err)
4305 return err;
4306
4307 return selinux_netlbl_socket_setsockopt(sock, level, optname);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004308}
4309
4310static int selinux_socket_getsockopt(struct socket *sock, int level,
4311 int optname)
4312{
Paul Moore253bfae2010-04-22 14:46:19 -04004313 return sock_has_perm(current, sock->sk, SOCKET__GETOPT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004314}
4315
4316static int selinux_socket_shutdown(struct socket *sock, int how)
4317{
Paul Moore253bfae2010-04-22 14:46:19 -04004318 return sock_has_perm(current, sock->sk, SOCKET__SHUTDOWN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004319}
4320
David S. Miller3610cda2011-01-05 15:38:53 -08004321static int selinux_socket_unix_stream_connect(struct sock *sock,
4322 struct sock *other,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004323 struct sock *newsk)
4324{
David S. Miller3610cda2011-01-05 15:38:53 -08004325 struct sk_security_struct *sksec_sock = sock->sk_security;
4326 struct sk_security_struct *sksec_other = other->sk_security;
Paul Moore4d1e2452010-04-22 14:46:18 -04004327 struct sk_security_struct *sksec_new = newsk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004328 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004329 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004330 int err;
4331
Eric Paris50c205f2012-04-04 15:01:43 -04004332 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004333 ad.u.net = &net;
4334 ad.u.net->sk = other;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004335
Paul Moore4d1e2452010-04-22 14:46:18 -04004336 err = avc_has_perm(sksec_sock->sid, sksec_other->sid,
4337 sksec_other->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004338 UNIX_STREAM_SOCKET__CONNECTTO, &ad);
4339 if (err)
4340 return err;
4341
Linus Torvalds1da177e2005-04-16 15:20:36 -07004342 /* server child socket */
Paul Moore4d1e2452010-04-22 14:46:18 -04004343 sksec_new->peer_sid = sksec_sock->sid;
4344 err = security_sid_mls_copy(sksec_other->sid, sksec_sock->sid,
4345 &sksec_new->sid);
4346 if (err)
4347 return err;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004348
Paul Moore4d1e2452010-04-22 14:46:18 -04004349 /* connecting socket */
4350 sksec_sock->peer_sid = sksec_new->sid;
4351
4352 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004353}
4354
4355static int selinux_socket_unix_may_send(struct socket *sock,
4356 struct socket *other)
4357{
Paul Moore253bfae2010-04-22 14:46:19 -04004358 struct sk_security_struct *ssec = sock->sk->sk_security;
4359 struct sk_security_struct *osec = other->sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004360 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004361 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004362
Eric Paris50c205f2012-04-04 15:01:43 -04004363 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004364 ad.u.net = &net;
4365 ad.u.net->sk = other->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004366
Paul Moore253bfae2010-04-22 14:46:19 -04004367 return avc_has_perm(ssec->sid, osec->sid, osec->sclass, SOCKET__SENDTO,
4368 &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004369}
4370
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004371static int selinux_inet_sys_rcv_skb(struct net *ns, int ifindex,
4372 char *addrp, u16 family, u32 peer_sid,
Thomas Liu2bf49692009-07-14 12:14:09 -04004373 struct common_audit_data *ad)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004374{
4375 int err;
4376 u32 if_sid;
4377 u32 node_sid;
4378
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004379 err = sel_netif_sid(ns, ifindex, &if_sid);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004380 if (err)
4381 return err;
4382 err = avc_has_perm(peer_sid, if_sid,
4383 SECCLASS_NETIF, NETIF__INGRESS, ad);
4384 if (err)
4385 return err;
4386
4387 err = sel_netnode_sid(addrp, family, &node_sid);
4388 if (err)
4389 return err;
4390 return avc_has_perm(peer_sid, node_sid,
4391 SECCLASS_NODE, NODE__RECVFROM, ad);
4392}
4393
Paul Moore220deb92008-01-29 08:38:23 -05004394static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
Paul Moored8395c82008-10-10 10:16:30 -04004395 u16 family)
Paul Moore220deb92008-01-29 08:38:23 -05004396{
Paul Moore277d3422008-12-31 12:54:11 -05004397 int err = 0;
Paul Moore220deb92008-01-29 08:38:23 -05004398 struct sk_security_struct *sksec = sk->sk_security;
Paul Moore220deb92008-01-29 08:38:23 -05004399 u32 sk_sid = sksec->sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04004400 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004401 struct lsm_network_audit net = {0,};
Paul Moored8395c82008-10-10 10:16:30 -04004402 char *addrp;
4403
Eric Paris50c205f2012-04-04 15:01:43 -04004404 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004405 ad.u.net = &net;
4406 ad.u.net->netif = skb->skb_iif;
4407 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04004408 err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
4409 if (err)
4410 return err;
Paul Moore220deb92008-01-29 08:38:23 -05004411
Paul Moore58bfbb52009-03-27 17:10:41 -04004412 if (selinux_secmark_enabled()) {
Paul Moore220deb92008-01-29 08:38:23 -05004413 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
Paul Moored8395c82008-10-10 10:16:30 -04004414 PACKET__RECV, &ad);
Paul Moore58bfbb52009-03-27 17:10:41 -04004415 if (err)
4416 return err;
4417 }
Paul Moore220deb92008-01-29 08:38:23 -05004418
Steffen Klassertb9679a72011-02-23 12:55:21 +01004419 err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, &ad);
4420 if (err)
4421 return err;
4422 err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, &ad);
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004423
James Morris4e5ab4c2006-06-09 00:33:33 -07004424 return err;
4425}
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004426
James Morris4e5ab4c2006-06-09 00:33:33 -07004427static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
4428{
Paul Moore220deb92008-01-29 08:38:23 -05004429 int err;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004430 struct sk_security_struct *sksec = sk->sk_security;
Paul Moore220deb92008-01-29 08:38:23 -05004431 u16 family = sk->sk_family;
4432 u32 sk_sid = sksec->sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04004433 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004434 struct lsm_network_audit net = {0,};
Paul Moore220deb92008-01-29 08:38:23 -05004435 char *addrp;
Paul Moored8395c82008-10-10 10:16:30 -04004436 u8 secmark_active;
4437 u8 peerlbl_active;
James Morris4e5ab4c2006-06-09 00:33:33 -07004438
James Morris4e5ab4c2006-06-09 00:33:33 -07004439 if (family != PF_INET && family != PF_INET6)
Paul Moore220deb92008-01-29 08:38:23 -05004440 return 0;
James Morris4e5ab4c2006-06-09 00:33:33 -07004441
4442 /* Handle mapped IPv4 packets arriving via IPv6 sockets */
Al Viro87fcd702006-12-04 22:00:55 +00004443 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
James Morris4e5ab4c2006-06-09 00:33:33 -07004444 family = PF_INET;
4445
Paul Moored8395c82008-10-10 10:16:30 -04004446 /* If any sort of compatibility mode is enabled then handoff processing
4447 * to the selinux_sock_rcv_skb_compat() function to deal with the
4448 * special handling. We do this in an attempt to keep this function
4449 * as fast and as clean as possible. */
Paul Moore58bfbb52009-03-27 17:10:41 -04004450 if (!selinux_policycap_netpeer)
Paul Moored8395c82008-10-10 10:16:30 -04004451 return selinux_sock_rcv_skb_compat(sk, skb, family);
4452
4453 secmark_active = selinux_secmark_enabled();
Chris PeBenito2be4d742013-05-03 09:05:39 -04004454 peerlbl_active = selinux_peerlbl_enabled();
Paul Moored8395c82008-10-10 10:16:30 -04004455 if (!secmark_active && !peerlbl_active)
4456 return 0;
4457
Eric Paris50c205f2012-04-04 15:01:43 -04004458 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004459 ad.u.net = &net;
4460 ad.u.net->netif = skb->skb_iif;
4461 ad.u.net->family = family;
Paul Moore224dfbd2008-01-29 08:38:13 -05004462 err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
James Morris4e5ab4c2006-06-09 00:33:33 -07004463 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05004464 return err;
James Morris4e5ab4c2006-06-09 00:33:33 -07004465
Paul Moored8395c82008-10-10 10:16:30 -04004466 if (peerlbl_active) {
Paul Moored621d352008-01-29 08:43:36 -05004467 u32 peer_sid;
4468
4469 err = selinux_skb_peerlbl_sid(skb, family, &peer_sid);
4470 if (err)
4471 return err;
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004472 err = selinux_inet_sys_rcv_skb(sock_net(sk), skb->skb_iif,
4473 addrp, family, peer_sid, &ad);
Paul Mooredfaebe92008-10-10 10:16:31 -04004474 if (err) {
4475 selinux_netlbl_err(skb, err, 0);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004476 return err;
Paul Mooredfaebe92008-10-10 10:16:31 -04004477 }
Paul Moored621d352008-01-29 08:43:36 -05004478 err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER,
4479 PEER__RECV, &ad);
Chad Hanson46d01d62013-12-23 17:45:01 -05004480 if (err) {
Paul Mooredfaebe92008-10-10 10:16:31 -04004481 selinux_netlbl_err(skb, err, 0);
Chad Hanson46d01d62013-12-23 17:45:01 -05004482 return err;
4483 }
Paul Moored621d352008-01-29 08:43:36 -05004484 }
4485
Paul Moored8395c82008-10-10 10:16:30 -04004486 if (secmark_active) {
Paul Mooreeffad8d2008-01-29 08:49:27 -05004487 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
4488 PACKET__RECV, &ad);
4489 if (err)
4490 return err;
4491 }
4492
Paul Moored621d352008-01-29 08:43:36 -05004493 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004494}
4495
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004496static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *optval,
4497 int __user *optlen, unsigned len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004498{
4499 int err = 0;
4500 char *scontext;
4501 u32 scontext_len;
Paul Moore253bfae2010-04-22 14:46:19 -04004502 struct sk_security_struct *sksec = sock->sk->sk_security;
Paul Moore3de4bab2006-11-17 17:38:54 -05004503 u32 peer_sid = SECSID_NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004504
Paul Moore253bfae2010-04-22 14:46:19 -04004505 if (sksec->sclass == SECCLASS_UNIX_STREAM_SOCKET ||
4506 sksec->sclass == SECCLASS_TCP_SOCKET)
Eric Parisdd3e7832010-04-07 15:08:46 -04004507 peer_sid = sksec->peer_sid;
Paul Moore253bfae2010-04-22 14:46:19 -04004508 if (peer_sid == SECSID_NULL)
4509 return -ENOPROTOOPT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004510
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004511 err = security_sid_to_context(peer_sid, &scontext, &scontext_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004512 if (err)
Paul Moore253bfae2010-04-22 14:46:19 -04004513 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004514
4515 if (scontext_len > len) {
4516 err = -ERANGE;
4517 goto out_len;
4518 }
4519
4520 if (copy_to_user(optval, scontext, scontext_len))
4521 err = -EFAULT;
4522
4523out_len:
4524 if (put_user(scontext_len, optlen))
4525 err = -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004526 kfree(scontext);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004527 return err;
4528}
4529
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004530static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid)
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004531{
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004532 u32 peer_secid = SECSID_NULL;
Paul Moore75e22912008-01-29 08:38:04 -05004533 u16 family;
Catherine Zhang877ce7c2006-06-29 12:27:47 -07004534
Paul Mooreaa862902008-10-10 10:16:29 -04004535 if (skb && skb->protocol == htons(ETH_P_IP))
4536 family = PF_INET;
4537 else if (skb && skb->protocol == htons(ETH_P_IPV6))
4538 family = PF_INET6;
4539 else if (sock)
Paul Moore75e22912008-01-29 08:38:04 -05004540 family = sock->sk->sk_family;
Paul Moore75e22912008-01-29 08:38:04 -05004541 else
4542 goto out;
4543
4544 if (sock && family == PF_UNIX)
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02004545 selinux_inode_getsecid(SOCK_INODE(sock), &peer_secid);
Paul Moore3de4bab2006-11-17 17:38:54 -05004546 else if (skb)
Paul Moore220deb92008-01-29 08:38:23 -05004547 selinux_skb_peerlbl_sid(skb, family, &peer_secid);
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004548
Paul Moore75e22912008-01-29 08:38:04 -05004549out:
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004550 *secid = peer_secid;
Paul Moore75e22912008-01-29 08:38:04 -05004551 if (peer_secid == SECSID_NULL)
4552 return -EINVAL;
4553 return 0;
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004554}
4555
Al Viro7d877f32005-10-21 03:20:43 -04004556static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004557{
Paul Moore84914b72010-04-22 14:46:18 -04004558 struct sk_security_struct *sksec;
4559
4560 sksec = kzalloc(sizeof(*sksec), priority);
4561 if (!sksec)
4562 return -ENOMEM;
4563
4564 sksec->peer_sid = SECINITSID_UNLABELED;
4565 sksec->sid = SECINITSID_UNLABELED;
Stephen Smalley5dee25d2015-07-10 17:19:57 -04004566 sksec->sclass = SECCLASS_SOCKET;
Paul Moore84914b72010-04-22 14:46:18 -04004567 selinux_netlbl_sk_security_reset(sksec);
4568 sk->sk_security = sksec;
4569
4570 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004571}
4572
4573static void selinux_sk_free_security(struct sock *sk)
4574{
Paul Moore84914b72010-04-22 14:46:18 -04004575 struct sk_security_struct *sksec = sk->sk_security;
4576
4577 sk->sk_security = NULL;
4578 selinux_netlbl_sk_security_free(sksec);
4579 kfree(sksec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004580}
4581
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004582static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk)
4583{
Eric Parisdd3e7832010-04-07 15:08:46 -04004584 struct sk_security_struct *sksec = sk->sk_security;
4585 struct sk_security_struct *newsksec = newsk->sk_security;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004586
Eric Parisdd3e7832010-04-07 15:08:46 -04004587 newsksec->sid = sksec->sid;
4588 newsksec->peer_sid = sksec->peer_sid;
4589 newsksec->sclass = sksec->sclass;
Paul Moore99f59ed2006-08-29 17:53:48 -07004590
Eric Parisdd3e7832010-04-07 15:08:46 -04004591 selinux_netlbl_sk_security_reset(newsksec);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004592}
4593
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004594static void selinux_sk_getsecid(struct sock *sk, u32 *secid)
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004595{
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004596 if (!sk)
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004597 *secid = SECINITSID_ANY_SOCKET;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004598 else {
4599 struct sk_security_struct *sksec = sk->sk_security;
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004600
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004601 *secid = sksec->sid;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004602 }
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004603}
4604
Eric Paris828dfe12008-04-17 13:17:49 -04004605static void selinux_sock_graft(struct sock *sk, struct socket *parent)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004606{
4607 struct inode_security_struct *isec = SOCK_INODE(parent)->i_security;
4608 struct sk_security_struct *sksec = sk->sk_security;
4609
Paul Moore2873ead2014-07-28 10:42:48 -04004610 if (sk->sk_family == PF_INET || sk->sk_family == PF_INET6 ||
4611 sk->sk_family == PF_UNIX)
David Woodhouse2148ccc2006-09-29 15:50:25 -07004612 isec->sid = sksec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05004613 sksec->sclass = isec->sclass;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004614}
4615
Adrian Bunk9a673e52006-08-15 00:03:53 -07004616static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
4617 struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004618{
4619 struct sk_security_struct *sksec = sk->sk_security;
4620 int err;
Paul Moore0b1f24e2013-12-03 11:39:13 -05004621 u16 family = req->rsk_ops->family;
Paul Moore446b8022013-12-04 16:10:51 -05004622 u32 connsid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004623 u32 peersid;
4624
Paul Mooreaa862902008-10-10 10:16:29 -04004625 err = selinux_skb_peerlbl_sid(skb, family, &peersid);
Paul Moore220deb92008-01-29 08:38:23 -05004626 if (err)
4627 return err;
Paul Moore446b8022013-12-04 16:10:51 -05004628 err = selinux_conn_sid(sksec->sid, peersid, &connsid);
4629 if (err)
4630 return err;
4631 req->secid = connsid;
4632 req->peer_secid = peersid;
Venkat Yekkiralaa51c64f2006-07-27 22:01:34 -07004633
Paul Moore389fb8002009-03-27 17:10:34 -04004634 return selinux_netlbl_inet_conn_request(req, family);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004635}
4636
Adrian Bunk9a673e52006-08-15 00:03:53 -07004637static void selinux_inet_csk_clone(struct sock *newsk,
4638 const struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004639{
4640 struct sk_security_struct *newsksec = newsk->sk_security;
4641
4642 newsksec->sid = req->secid;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004643 newsksec->peer_sid = req->peer_secid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004644 /* NOTE: Ideally, we should also get the isec->sid for the
4645 new socket in sync, but we don't have the isec available yet.
4646 So we will wait until sock_graft to do it, by which
4647 time it will have been created and available. */
Paul Moore99f59ed2006-08-29 17:53:48 -07004648
Paul Moore9f2ad662006-11-17 17:38:53 -05004649 /* We don't need to take any sort of lock here as we are the only
4650 * thread with access to newsksec */
Paul Moore389fb8002009-03-27 17:10:34 -04004651 selinux_netlbl_inet_csk_clone(newsk, req->rsk_ops->family);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004652}
4653
Paul Moore014ab192008-10-10 10:16:33 -04004654static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb)
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004655{
Paul Mooreaa862902008-10-10 10:16:29 -04004656 u16 family = sk->sk_family;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004657 struct sk_security_struct *sksec = sk->sk_security;
4658
Paul Mooreaa862902008-10-10 10:16:29 -04004659 /* handle mapped IPv4 packets arriving via IPv6 sockets */
4660 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
4661 family = PF_INET;
4662
4663 selinux_skb_peerlbl_sid(skb, family, &sksec->peer_sid);
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004664}
4665
Eric Paris2606fd12010-10-13 16:24:41 -04004666static int selinux_secmark_relabel_packet(u32 sid)
4667{
4668 const struct task_security_struct *__tsec;
4669 u32 tsid;
4670
4671 __tsec = current_security();
4672 tsid = __tsec->sid;
4673
4674 return avc_has_perm(tsid, sid, SECCLASS_PACKET, PACKET__RELABELTO, NULL);
4675}
4676
4677static void selinux_secmark_refcount_inc(void)
4678{
4679 atomic_inc(&selinux_secmark_refcount);
4680}
4681
4682static void selinux_secmark_refcount_dec(void)
4683{
4684 atomic_dec(&selinux_secmark_refcount);
4685}
4686
Adrian Bunk9a673e52006-08-15 00:03:53 -07004687static void selinux_req_classify_flow(const struct request_sock *req,
4688 struct flowi *fl)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004689{
David S. Miller1d28f422011-03-12 00:29:39 -05004690 fl->flowi_secid = req->secid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004691}
4692
Paul Moore5dbbaf22013-01-14 07:12:19 +00004693static int selinux_tun_dev_alloc_security(void **security)
4694{
4695 struct tun_security_struct *tunsec;
4696
4697 tunsec = kzalloc(sizeof(*tunsec), GFP_KERNEL);
4698 if (!tunsec)
4699 return -ENOMEM;
4700 tunsec->sid = current_sid();
4701
4702 *security = tunsec;
4703 return 0;
4704}
4705
4706static void selinux_tun_dev_free_security(void *security)
4707{
4708 kfree(security);
4709}
4710
Paul Mooreed6d76e2009-08-28 18:12:49 -04004711static int selinux_tun_dev_create(void)
4712{
4713 u32 sid = current_sid();
4714
4715 /* we aren't taking into account the "sockcreate" SID since the socket
4716 * that is being created here is not a socket in the traditional sense,
4717 * instead it is a private sock, accessible only to the kernel, and
4718 * representing a wide range of network traffic spanning multiple
4719 * connections unlike traditional sockets - check the TUN driver to
4720 * get a better understanding of why this socket is special */
4721
4722 return avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET, TUN_SOCKET__CREATE,
4723 NULL);
4724}
4725
Paul Moore5dbbaf22013-01-14 07:12:19 +00004726static int selinux_tun_dev_attach_queue(void *security)
Paul Mooreed6d76e2009-08-28 18:12:49 -04004727{
Paul Moore5dbbaf22013-01-14 07:12:19 +00004728 struct tun_security_struct *tunsec = security;
4729
4730 return avc_has_perm(current_sid(), tunsec->sid, SECCLASS_TUN_SOCKET,
4731 TUN_SOCKET__ATTACH_QUEUE, NULL);
4732}
4733
4734static int selinux_tun_dev_attach(struct sock *sk, void *security)
4735{
4736 struct tun_security_struct *tunsec = security;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004737 struct sk_security_struct *sksec = sk->sk_security;
4738
4739 /* we don't currently perform any NetLabel based labeling here and it
4740 * isn't clear that we would want to do so anyway; while we could apply
4741 * labeling without the support of the TUN user the resulting labeled
4742 * traffic from the other end of the connection would almost certainly
4743 * cause confusion to the TUN user that had no idea network labeling
4744 * protocols were being used */
4745
Paul Moore5dbbaf22013-01-14 07:12:19 +00004746 sksec->sid = tunsec->sid;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004747 sksec->sclass = SECCLASS_TUN_SOCKET;
Paul Moore5dbbaf22013-01-14 07:12:19 +00004748
4749 return 0;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004750}
4751
Paul Moore5dbbaf22013-01-14 07:12:19 +00004752static int selinux_tun_dev_open(void *security)
Paul Mooreed6d76e2009-08-28 18:12:49 -04004753{
Paul Moore5dbbaf22013-01-14 07:12:19 +00004754 struct tun_security_struct *tunsec = security;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004755 u32 sid = current_sid();
4756 int err;
4757
Paul Moore5dbbaf22013-01-14 07:12:19 +00004758 err = avc_has_perm(sid, tunsec->sid, SECCLASS_TUN_SOCKET,
Paul Mooreed6d76e2009-08-28 18:12:49 -04004759 TUN_SOCKET__RELABELFROM, NULL);
4760 if (err)
4761 return err;
4762 err = avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET,
4763 TUN_SOCKET__RELABELTO, NULL);
4764 if (err)
4765 return err;
Paul Moore5dbbaf22013-01-14 07:12:19 +00004766 tunsec->sid = sid;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004767
4768 return 0;
4769}
4770
Linus Torvalds1da177e2005-04-16 15:20:36 -07004771static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
4772{
4773 int err = 0;
4774 u32 perm;
4775 struct nlmsghdr *nlh;
Paul Moore253bfae2010-04-22 14:46:19 -04004776 struct sk_security_struct *sksec = sk->sk_security;
Eric Paris828dfe12008-04-17 13:17:49 -04004777
Hong zhi guo77954982013-03-27 06:49:35 +00004778 if (skb->len < NLMSG_HDRLEN) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004779 err = -EINVAL;
4780 goto out;
4781 }
Arnaldo Carvalho de Melob529ccf2007-04-25 19:08:35 -07004782 nlh = nlmsg_hdr(skb);
Eric Paris828dfe12008-04-17 13:17:49 -04004783
Paul Moore253bfae2010-04-22 14:46:19 -04004784 err = selinux_nlmsg_lookup(sksec->sclass, nlh->nlmsg_type, &perm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004785 if (err) {
4786 if (err == -EINVAL) {
Richard Guy Briggsd950f842014-11-12 14:01:34 -05004787 printk(KERN_WARNING
4788 "SELinux: unrecognized netlink message:"
Marek Milkoviccded3ff2015-06-04 16:22:16 -04004789 " protocol=%hu nlmsg_type=%hu sclass=%s\n",
4790 sk->sk_protocol, nlh->nlmsg_type,
4791 secclass_map[sksec->sclass - 1].name);
Eric Paris39c9aed2008-11-05 09:34:42 -05004792 if (!selinux_enforcing || security_get_allow_unknown())
Linus Torvalds1da177e2005-04-16 15:20:36 -07004793 err = 0;
4794 }
4795
4796 /* Ignore */
4797 if (err == -ENOENT)
4798 err = 0;
4799 goto out;
4800 }
4801
Paul Moore253bfae2010-04-22 14:46:19 -04004802 err = sock_has_perm(current, sk, perm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004803out:
4804 return err;
4805}
4806
4807#ifdef CONFIG_NETFILTER
4808
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004809static unsigned int selinux_ip_forward(struct sk_buff *skb,
4810 const struct net_device *indev,
Paul Mooreeffad8d2008-01-29 08:49:27 -05004811 u16 family)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004812{
Paul Mooredfaebe92008-10-10 10:16:31 -04004813 int err;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004814 char *addrp;
4815 u32 peer_sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04004816 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004817 struct lsm_network_audit net = {0,};
Paul Mooreeffad8d2008-01-29 08:49:27 -05004818 u8 secmark_active;
Paul Moore948bf852008-10-10 10:16:32 -04004819 u8 netlbl_active;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004820 u8 peerlbl_active;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004821
Paul Mooreeffad8d2008-01-29 08:49:27 -05004822 if (!selinux_policycap_netpeer)
4823 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004824
Paul Mooreeffad8d2008-01-29 08:49:27 -05004825 secmark_active = selinux_secmark_enabled();
Paul Moore948bf852008-10-10 10:16:32 -04004826 netlbl_active = netlbl_enabled();
Chris PeBenito2be4d742013-05-03 09:05:39 -04004827 peerlbl_active = selinux_peerlbl_enabled();
Paul Mooreeffad8d2008-01-29 08:49:27 -05004828 if (!secmark_active && !peerlbl_active)
4829 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004830
Paul Moored8395c82008-10-10 10:16:30 -04004831 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0)
4832 return NF_DROP;
4833
Eric Paris50c205f2012-04-04 15:01:43 -04004834 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004835 ad.u.net = &net;
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004836 ad.u.net->netif = indev->ifindex;
Eric Paris48c62af2012-04-02 13:15:44 -04004837 ad.u.net->family = family;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004838 if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0)
4839 return NF_DROP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004840
Paul Mooredfaebe92008-10-10 10:16:31 -04004841 if (peerlbl_active) {
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004842 err = selinux_inet_sys_rcv_skb(dev_net(indev), indev->ifindex,
4843 addrp, family, peer_sid, &ad);
Paul Mooredfaebe92008-10-10 10:16:31 -04004844 if (err) {
4845 selinux_netlbl_err(skb, err, 1);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004846 return NF_DROP;
Paul Mooredfaebe92008-10-10 10:16:31 -04004847 }
4848 }
Paul Mooreeffad8d2008-01-29 08:49:27 -05004849
4850 if (secmark_active)
4851 if (avc_has_perm(peer_sid, skb->secmark,
4852 SECCLASS_PACKET, PACKET__FORWARD_IN, &ad))
4853 return NF_DROP;
4854
Paul Moore948bf852008-10-10 10:16:32 -04004855 if (netlbl_active)
4856 /* we do this in the FORWARD path and not the POST_ROUTING
4857 * path because we want to make sure we apply the necessary
4858 * labeling before IPsec is applied so we can leverage AH
4859 * protection */
4860 if (selinux_netlbl_skbuff_setsid(skb, family, peer_sid) != 0)
4861 return NF_DROP;
4862
Paul Mooreeffad8d2008-01-29 08:49:27 -05004863 return NF_ACCEPT;
4864}
4865
Patrick McHardy795aa6e2013-10-10 09:21:55 +02004866static unsigned int selinux_ipv4_forward(const struct nf_hook_ops *ops,
Paul Mooreeffad8d2008-01-29 08:49:27 -05004867 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04004868 const struct nf_hook_state *state)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004869{
David S. Miller238e54c2015-04-03 20:32:56 -04004870 return selinux_ip_forward(skb, state->in, PF_INET);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004871}
4872
4873#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Patrick McHardy795aa6e2013-10-10 09:21:55 +02004874static unsigned int selinux_ipv6_forward(const struct nf_hook_ops *ops,
Paul Mooreeffad8d2008-01-29 08:49:27 -05004875 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04004876 const struct nf_hook_state *state)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004877{
David S. Miller238e54c2015-04-03 20:32:56 -04004878 return selinux_ip_forward(skb, state->in, PF_INET6);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004879}
4880#endif /* IPV6 */
4881
Paul Moore948bf852008-10-10 10:16:32 -04004882static unsigned int selinux_ip_output(struct sk_buff *skb,
4883 u16 family)
4884{
Paul Moore47180062013-12-04 16:10:45 -05004885 struct sock *sk;
Paul Moore948bf852008-10-10 10:16:32 -04004886 u32 sid;
4887
4888 if (!netlbl_enabled())
4889 return NF_ACCEPT;
4890
4891 /* we do this in the LOCAL_OUT path and not the POST_ROUTING path
4892 * because we want to make sure we apply the necessary labeling
4893 * before IPsec is applied so we can leverage AH protection */
Paul Moore47180062013-12-04 16:10:45 -05004894 sk = skb->sk;
4895 if (sk) {
4896 struct sk_security_struct *sksec;
4897
4898 if (sk->sk_state == TCP_LISTEN)
4899 /* if the socket is the listening state then this
4900 * packet is a SYN-ACK packet which means it needs to
4901 * be labeled based on the connection/request_sock and
4902 * not the parent socket. unfortunately, we can't
4903 * lookup the request_sock yet as it isn't queued on
4904 * the parent socket until after the SYN-ACK is sent.
4905 * the "solution" is to simply pass the packet as-is
4906 * as any IP option based labeling should be copied
4907 * from the initial connection request (in the IP
4908 * layer). it is far from ideal, but until we get a
4909 * security label in the packet itself this is the
4910 * best we can do. */
4911 return NF_ACCEPT;
4912
4913 /* standard practice, label using the parent socket */
4914 sksec = sk->sk_security;
Paul Moore948bf852008-10-10 10:16:32 -04004915 sid = sksec->sid;
4916 } else
4917 sid = SECINITSID_KERNEL;
4918 if (selinux_netlbl_skbuff_setsid(skb, family, sid) != 0)
4919 return NF_DROP;
4920
4921 return NF_ACCEPT;
4922}
4923
Patrick McHardy795aa6e2013-10-10 09:21:55 +02004924static unsigned int selinux_ipv4_output(const struct nf_hook_ops *ops,
Paul Moore948bf852008-10-10 10:16:32 -04004925 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04004926 const struct nf_hook_state *state)
Paul Moore948bf852008-10-10 10:16:32 -04004927{
4928 return selinux_ip_output(skb, PF_INET);
4929}
4930
Paul Mooreeffad8d2008-01-29 08:49:27 -05004931static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
4932 int ifindex,
Paul Moored8395c82008-10-10 10:16:30 -04004933 u16 family)
James Morris4e5ab4c2006-06-09 00:33:33 -07004934{
Paul Mooreeffad8d2008-01-29 08:49:27 -05004935 struct sock *sk = skb->sk;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004936 struct sk_security_struct *sksec;
Thomas Liu2bf49692009-07-14 12:14:09 -04004937 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004938 struct lsm_network_audit net = {0,};
Paul Moored8395c82008-10-10 10:16:30 -04004939 char *addrp;
4940 u8 proto;
James Morris4e5ab4c2006-06-09 00:33:33 -07004941
Paul Mooreeffad8d2008-01-29 08:49:27 -05004942 if (sk == NULL)
4943 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004944 sksec = sk->sk_security;
James Morris4e5ab4c2006-06-09 00:33:33 -07004945
Eric Paris50c205f2012-04-04 15:01:43 -04004946 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004947 ad.u.net = &net;
4948 ad.u.net->netif = ifindex;
4949 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04004950 if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto))
4951 return NF_DROP;
4952
Paul Moore58bfbb52009-03-27 17:10:41 -04004953 if (selinux_secmark_enabled())
Paul Mooreeffad8d2008-01-29 08:49:27 -05004954 if (avc_has_perm(sksec->sid, skb->secmark,
Paul Moored8395c82008-10-10 10:16:30 -04004955 SECCLASS_PACKET, PACKET__SEND, &ad))
Eric Paris2fe66ec2010-11-23 06:28:08 +00004956 return NF_DROP_ERR(-ECONNREFUSED);
James Morris4e5ab4c2006-06-09 00:33:33 -07004957
Steffen Klassertb9679a72011-02-23 12:55:21 +01004958 if (selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto))
4959 return NF_DROP_ERR(-ECONNREFUSED);
James Morris4e5ab4c2006-06-09 00:33:33 -07004960
Paul Mooreeffad8d2008-01-29 08:49:27 -05004961 return NF_ACCEPT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004962}
4963
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004964static unsigned int selinux_ip_postroute(struct sk_buff *skb,
4965 const struct net_device *outdev,
Paul Mooreeffad8d2008-01-29 08:49:27 -05004966 u16 family)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004967{
Paul Mooreeffad8d2008-01-29 08:49:27 -05004968 u32 secmark_perm;
4969 u32 peer_sid;
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004970 int ifindex = outdev->ifindex;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004971 struct sock *sk;
Thomas Liu2bf49692009-07-14 12:14:09 -04004972 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004973 struct lsm_network_audit net = {0,};
Paul Mooreeffad8d2008-01-29 08:49:27 -05004974 char *addrp;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004975 u8 secmark_active;
4976 u8 peerlbl_active;
4977
Paul Mooreeffad8d2008-01-29 08:49:27 -05004978 /* If any sort of compatibility mode is enabled then handoff processing
4979 * to the selinux_ip_postroute_compat() function to deal with the
4980 * special handling. We do this in an attempt to keep this function
4981 * as fast and as clean as possible. */
Paul Moore58bfbb52009-03-27 17:10:41 -04004982 if (!selinux_policycap_netpeer)
Paul Moored8395c82008-10-10 10:16:30 -04004983 return selinux_ip_postroute_compat(skb, ifindex, family);
Paul Moorec0828e52013-12-10 14:58:01 -05004984
Paul Mooreeffad8d2008-01-29 08:49:27 -05004985 secmark_active = selinux_secmark_enabled();
Chris PeBenito2be4d742013-05-03 09:05:39 -04004986 peerlbl_active = selinux_peerlbl_enabled();
Paul Mooreeffad8d2008-01-29 08:49:27 -05004987 if (!secmark_active && !peerlbl_active)
4988 return NF_ACCEPT;
4989
Paul Mooreeffad8d2008-01-29 08:49:27 -05004990 sk = skb->sk;
Paul Moorec0828e52013-12-10 14:58:01 -05004991
Paul Mooreeffad8d2008-01-29 08:49:27 -05004992#ifdef CONFIG_XFRM
4993 /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec
4994 * packet transformation so allow the packet to pass without any checks
4995 * since we'll have another chance to perform access control checks
4996 * when the packet is on it's final way out.
4997 * NOTE: there appear to be some IPv6 multicast cases where skb->dst
Paul Moorec0828e52013-12-10 14:58:01 -05004998 * is NULL, in this case go ahead and apply access control.
4999 * NOTE: if this is a local socket (skb->sk != NULL) that is in the
5000 * TCP listening state we cannot wait until the XFRM processing
5001 * is done as we will miss out on the SA label if we do;
5002 * unfortunately, this means more work, but it is only once per
5003 * connection. */
5004 if (skb_dst(skb) != NULL && skb_dst(skb)->xfrm != NULL &&
5005 !(sk != NULL && sk->sk_state == TCP_LISTEN))
Paul Mooreeffad8d2008-01-29 08:49:27 -05005006 return NF_ACCEPT;
5007#endif
Paul Mooreeffad8d2008-01-29 08:49:27 -05005008
Paul Moored8395c82008-10-10 10:16:30 -04005009 if (sk == NULL) {
Paul Moore446b8022013-12-04 16:10:51 -05005010 /* Without an associated socket the packet is either coming
5011 * from the kernel or it is being forwarded; check the packet
5012 * to determine which and if the packet is being forwarded
5013 * query the packet directly to determine the security label. */
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01005014 if (skb->skb_iif) {
5015 secmark_perm = PACKET__FORWARD_OUT;
Paul Moored8395c82008-10-10 10:16:30 -04005016 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00005017 return NF_DROP;
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01005018 } else {
5019 secmark_perm = PACKET__SEND;
Paul Moored8395c82008-10-10 10:16:30 -04005020 peer_sid = SECINITSID_KERNEL;
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01005021 }
Paul Moore446b8022013-12-04 16:10:51 -05005022 } else if (sk->sk_state == TCP_LISTEN) {
5023 /* Locally generated packet but the associated socket is in the
5024 * listening state which means this is a SYN-ACK packet. In
5025 * this particular case the correct security label is assigned
5026 * to the connection/request_sock but unfortunately we can't
5027 * query the request_sock as it isn't queued on the parent
5028 * socket until after the SYN-ACK packet is sent; the only
5029 * viable choice is to regenerate the label like we do in
5030 * selinux_inet_conn_request(). See also selinux_ip_output()
5031 * for similar problems. */
5032 u32 skb_sid;
5033 struct sk_security_struct *sksec = sk->sk_security;
5034 if (selinux_skb_peerlbl_sid(skb, family, &skb_sid))
5035 return NF_DROP;
Paul Moorec0828e52013-12-10 14:58:01 -05005036 /* At this point, if the returned skb peerlbl is SECSID_NULL
5037 * and the packet has been through at least one XFRM
5038 * transformation then we must be dealing with the "final"
5039 * form of labeled IPsec packet; since we've already applied
5040 * all of our access controls on this packet we can safely
5041 * pass the packet. */
5042 if (skb_sid == SECSID_NULL) {
5043 switch (family) {
5044 case PF_INET:
5045 if (IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED)
5046 return NF_ACCEPT;
5047 break;
5048 case PF_INET6:
5049 if (IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED)
5050 return NF_ACCEPT;
Paul Moorea7a91a12014-09-03 10:51:59 -04005051 break;
Paul Moorec0828e52013-12-10 14:58:01 -05005052 default:
5053 return NF_DROP_ERR(-ECONNREFUSED);
5054 }
5055 }
Paul Moore446b8022013-12-04 16:10:51 -05005056 if (selinux_conn_sid(sksec->sid, skb_sid, &peer_sid))
5057 return NF_DROP;
5058 secmark_perm = PACKET__SEND;
Paul Moored8395c82008-10-10 10:16:30 -04005059 } else {
Paul Moore446b8022013-12-04 16:10:51 -05005060 /* Locally generated packet, fetch the security label from the
5061 * associated socket. */
Paul Mooreeffad8d2008-01-29 08:49:27 -05005062 struct sk_security_struct *sksec = sk->sk_security;
5063 peer_sid = sksec->sid;
5064 secmark_perm = PACKET__SEND;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005065 }
5066
Eric Paris50c205f2012-04-04 15:01:43 -04005067 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04005068 ad.u.net = &net;
5069 ad.u.net->netif = ifindex;
5070 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04005071 if (selinux_parse_skb(skb, &ad, &addrp, 0, NULL))
Eric Paris04f6d702010-11-23 06:28:02 +00005072 return NF_DROP;
Paul Moored8395c82008-10-10 10:16:30 -04005073
Paul Mooreeffad8d2008-01-29 08:49:27 -05005074 if (secmark_active)
5075 if (avc_has_perm(peer_sid, skb->secmark,
5076 SECCLASS_PACKET, secmark_perm, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00005077 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005078
5079 if (peerlbl_active) {
5080 u32 if_sid;
5081 u32 node_sid;
5082
Paul Moorecbe0d6e2014-09-10 17:09:57 -04005083 if (sel_netif_sid(dev_net(outdev), ifindex, &if_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00005084 return NF_DROP;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005085 if (avc_has_perm(peer_sid, if_sid,
5086 SECCLASS_NETIF, NETIF__EGRESS, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00005087 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005088
5089 if (sel_netnode_sid(addrp, family, &node_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00005090 return NF_DROP;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005091 if (avc_has_perm(peer_sid, node_sid,
5092 SECCLASS_NODE, NODE__SENDTO, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00005093 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005094 }
5095
5096 return NF_ACCEPT;
5097}
5098
Patrick McHardy795aa6e2013-10-10 09:21:55 +02005099static unsigned int selinux_ipv4_postroute(const struct nf_hook_ops *ops,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005100 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04005101 const struct nf_hook_state *state)
Paul Mooreeffad8d2008-01-29 08:49:27 -05005102{
David S. Miller238e54c2015-04-03 20:32:56 -04005103 return selinux_ip_postroute(skb, state->out, PF_INET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005104}
5105
5106#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Patrick McHardy795aa6e2013-10-10 09:21:55 +02005107static unsigned int selinux_ipv6_postroute(const struct nf_hook_ops *ops,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005108 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04005109 const struct nf_hook_state *state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005110{
David S. Miller238e54c2015-04-03 20:32:56 -04005111 return selinux_ip_postroute(skb, state->out, PF_INET6);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005112}
Linus Torvalds1da177e2005-04-16 15:20:36 -07005113#endif /* IPV6 */
5114
5115#endif /* CONFIG_NETFILTER */
5116
Linus Torvalds1da177e2005-04-16 15:20:36 -07005117static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb)
5118{
Stephen Smalley941fc5b2009-10-01 14:48:23 -04005119 return selinux_nlmsg_perm(sk, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005120}
5121
Linus Torvalds1da177e2005-04-16 15:20:36 -07005122static int ipc_alloc_security(struct task_struct *task,
5123 struct kern_ipc_perm *perm,
5124 u16 sclass)
5125{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005126 struct ipc_security_struct *isec;
David Howells275bb412008-11-14 10:39:19 +11005127 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005128
James Morris89d155e2005-10-30 14:59:21 -08005129 isec = kzalloc(sizeof(struct ipc_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005130 if (!isec)
5131 return -ENOMEM;
5132
David Howells275bb412008-11-14 10:39:19 +11005133 sid = task_sid(task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005134 isec->sclass = sclass;
David Howells275bb412008-11-14 10:39:19 +11005135 isec->sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005136 perm->security = isec;
5137
5138 return 0;
5139}
5140
5141static void ipc_free_security(struct kern_ipc_perm *perm)
5142{
5143 struct ipc_security_struct *isec = perm->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005144 perm->security = NULL;
5145 kfree(isec);
5146}
5147
5148static int msg_msg_alloc_security(struct msg_msg *msg)
5149{
5150 struct msg_security_struct *msec;
5151
James Morris89d155e2005-10-30 14:59:21 -08005152 msec = kzalloc(sizeof(struct msg_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005153 if (!msec)
5154 return -ENOMEM;
5155
Linus Torvalds1da177e2005-04-16 15:20:36 -07005156 msec->sid = SECINITSID_UNLABELED;
5157 msg->security = msec;
5158
5159 return 0;
5160}
5161
5162static void msg_msg_free_security(struct msg_msg *msg)
5163{
5164 struct msg_security_struct *msec = msg->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005165
5166 msg->security = NULL;
5167 kfree(msec);
5168}
5169
5170static int ipc_has_perm(struct kern_ipc_perm *ipc_perms,
Stephen Smalley6af963f2005-05-01 08:58:39 -07005171 u32 perms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005172{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005173 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005174 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005175 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005176
Linus Torvalds1da177e2005-04-16 15:20:36 -07005177 isec = ipc_perms->security;
5178
Eric Paris50c205f2012-04-04 15:01:43 -04005179 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005180 ad.u.ipc_id = ipc_perms->key;
5181
David Howells275bb412008-11-14 10:39:19 +11005182 return avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005183}
5184
5185static int selinux_msg_msg_alloc_security(struct msg_msg *msg)
5186{
5187 return msg_msg_alloc_security(msg);
5188}
5189
5190static void selinux_msg_msg_free_security(struct msg_msg *msg)
5191{
5192 msg_msg_free_security(msg);
5193}
5194
5195/* message queue security operations */
5196static int selinux_msg_queue_alloc_security(struct msg_queue *msq)
5197{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005198 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005199 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005200 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005201 int rc;
5202
5203 rc = ipc_alloc_security(current, &msq->q_perm, SECCLASS_MSGQ);
5204 if (rc)
5205 return rc;
5206
Linus Torvalds1da177e2005-04-16 15:20:36 -07005207 isec = msq->q_perm.security;
5208
Eric Paris50c205f2012-04-04 15:01:43 -04005209 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04005210 ad.u.ipc_id = msq->q_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005211
David Howells275bb412008-11-14 10:39:19 +11005212 rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005213 MSGQ__CREATE, &ad);
5214 if (rc) {
5215 ipc_free_security(&msq->q_perm);
5216 return rc;
5217 }
5218 return 0;
5219}
5220
5221static void selinux_msg_queue_free_security(struct msg_queue *msq)
5222{
5223 ipc_free_security(&msq->q_perm);
5224}
5225
5226static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg)
5227{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005228 struct ipc_security_struct *isec;
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
Linus Torvalds1da177e2005-04-16 15:20:36 -07005232 isec = msq->q_perm.security;
5233
Eric Paris50c205f2012-04-04 15:01:43 -04005234 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005235 ad.u.ipc_id = msq->q_perm.key;
5236
David Howells275bb412008-11-14 10:39:19 +11005237 return avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005238 MSGQ__ASSOCIATE, &ad);
5239}
5240
5241static int selinux_msg_queue_msgctl(struct msg_queue *msq, int cmd)
5242{
5243 int err;
5244 int perms;
5245
Eric Paris828dfe12008-04-17 13:17:49 -04005246 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005247 case IPC_INFO:
5248 case MSG_INFO:
5249 /* No specific object, just general system-wide information. */
5250 return task_has_system(current, SYSTEM__IPC_INFO);
5251 case IPC_STAT:
5252 case MSG_STAT:
5253 perms = MSGQ__GETATTR | MSGQ__ASSOCIATE;
5254 break;
5255 case IPC_SET:
5256 perms = MSGQ__SETATTR;
5257 break;
5258 case IPC_RMID:
5259 perms = MSGQ__DESTROY;
5260 break;
5261 default:
5262 return 0;
5263 }
5264
Stephen Smalley6af963f2005-05-01 08:58:39 -07005265 err = ipc_has_perm(&msq->q_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005266 return err;
5267}
5268
5269static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, int msqflg)
5270{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005271 struct ipc_security_struct *isec;
5272 struct msg_security_struct *msec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005273 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005274 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005275 int rc;
5276
Linus Torvalds1da177e2005-04-16 15:20:36 -07005277 isec = msq->q_perm.security;
5278 msec = msg->security;
5279
5280 /*
5281 * First time through, need to assign label to the message
5282 */
5283 if (msec->sid == SECINITSID_UNLABELED) {
5284 /*
5285 * Compute new sid based on current process and
5286 * message queue this message will be stored in
5287 */
David Howells275bb412008-11-14 10:39:19 +11005288 rc = security_transition_sid(sid, isec->sid, SECCLASS_MSG,
Eric Paris652bb9b2011-02-01 11:05:40 -05005289 NULL, &msec->sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005290 if (rc)
5291 return rc;
5292 }
5293
Eric Paris50c205f2012-04-04 15:01:43 -04005294 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005295 ad.u.ipc_id = msq->q_perm.key;
5296
5297 /* Can this process write to the queue? */
David Howells275bb412008-11-14 10:39:19 +11005298 rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005299 MSGQ__WRITE, &ad);
5300 if (!rc)
5301 /* Can this process send the message */
David Howells275bb412008-11-14 10:39:19 +11005302 rc = avc_has_perm(sid, msec->sid, SECCLASS_MSG,
5303 MSG__SEND, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005304 if (!rc)
5305 /* Can the message be put in the queue? */
David Howells275bb412008-11-14 10:39:19 +11005306 rc = avc_has_perm(msec->sid, isec->sid, SECCLASS_MSGQ,
5307 MSGQ__ENQUEUE, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005308
5309 return rc;
5310}
5311
5312static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
5313 struct task_struct *target,
5314 long type, int mode)
5315{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005316 struct ipc_security_struct *isec;
5317 struct msg_security_struct *msec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005318 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005319 u32 sid = task_sid(target);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005320 int rc;
5321
Linus Torvalds1da177e2005-04-16 15:20:36 -07005322 isec = msq->q_perm.security;
5323 msec = msg->security;
5324
Eric Paris50c205f2012-04-04 15:01:43 -04005325 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04005326 ad.u.ipc_id = msq->q_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005327
David Howells275bb412008-11-14 10:39:19 +11005328 rc = avc_has_perm(sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005329 SECCLASS_MSGQ, MSGQ__READ, &ad);
5330 if (!rc)
David Howells275bb412008-11-14 10:39:19 +11005331 rc = avc_has_perm(sid, msec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005332 SECCLASS_MSG, MSG__RECEIVE, &ad);
5333 return rc;
5334}
5335
5336/* Shared Memory security operations */
5337static int selinux_shm_alloc_security(struct shmid_kernel *shp)
5338{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005339 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005340 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005341 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005342 int rc;
5343
5344 rc = ipc_alloc_security(current, &shp->shm_perm, SECCLASS_SHM);
5345 if (rc)
5346 return rc;
5347
Linus Torvalds1da177e2005-04-16 15:20:36 -07005348 isec = shp->shm_perm.security;
5349
Eric Paris50c205f2012-04-04 15:01:43 -04005350 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04005351 ad.u.ipc_id = shp->shm_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005352
David Howells275bb412008-11-14 10:39:19 +11005353 rc = avc_has_perm(sid, isec->sid, SECCLASS_SHM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005354 SHM__CREATE, &ad);
5355 if (rc) {
5356 ipc_free_security(&shp->shm_perm);
5357 return rc;
5358 }
5359 return 0;
5360}
5361
5362static void selinux_shm_free_security(struct shmid_kernel *shp)
5363{
5364 ipc_free_security(&shp->shm_perm);
5365}
5366
5367static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg)
5368{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005369 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005370 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005371 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005372
Linus Torvalds1da177e2005-04-16 15:20:36 -07005373 isec = shp->shm_perm.security;
5374
Eric Paris50c205f2012-04-04 15:01:43 -04005375 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005376 ad.u.ipc_id = shp->shm_perm.key;
5377
David Howells275bb412008-11-14 10:39:19 +11005378 return avc_has_perm(sid, isec->sid, SECCLASS_SHM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005379 SHM__ASSOCIATE, &ad);
5380}
5381
5382/* Note, at this point, shp is locked down */
5383static int selinux_shm_shmctl(struct shmid_kernel *shp, int cmd)
5384{
5385 int perms;
5386 int err;
5387
Eric Paris828dfe12008-04-17 13:17:49 -04005388 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005389 case IPC_INFO:
5390 case SHM_INFO:
5391 /* No specific object, just general system-wide information. */
5392 return task_has_system(current, SYSTEM__IPC_INFO);
5393 case IPC_STAT:
5394 case SHM_STAT:
5395 perms = SHM__GETATTR | SHM__ASSOCIATE;
5396 break;
5397 case IPC_SET:
5398 perms = SHM__SETATTR;
5399 break;
5400 case SHM_LOCK:
5401 case SHM_UNLOCK:
5402 perms = SHM__LOCK;
5403 break;
5404 case IPC_RMID:
5405 perms = SHM__DESTROY;
5406 break;
5407 default:
5408 return 0;
5409 }
5410
Stephen Smalley6af963f2005-05-01 08:58:39 -07005411 err = ipc_has_perm(&shp->shm_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005412 return err;
5413}
5414
5415static int selinux_shm_shmat(struct shmid_kernel *shp,
5416 char __user *shmaddr, int shmflg)
5417{
5418 u32 perms;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005419
5420 if (shmflg & SHM_RDONLY)
5421 perms = SHM__READ;
5422 else
5423 perms = SHM__READ | SHM__WRITE;
5424
Stephen Smalley6af963f2005-05-01 08:58:39 -07005425 return ipc_has_perm(&shp->shm_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005426}
5427
5428/* Semaphore security operations */
5429static int selinux_sem_alloc_security(struct sem_array *sma)
5430{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005431 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005432 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005433 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005434 int rc;
5435
5436 rc = ipc_alloc_security(current, &sma->sem_perm, SECCLASS_SEM);
5437 if (rc)
5438 return rc;
5439
Linus Torvalds1da177e2005-04-16 15:20:36 -07005440 isec = sma->sem_perm.security;
5441
Eric Paris50c205f2012-04-04 15:01:43 -04005442 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04005443 ad.u.ipc_id = sma->sem_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005444
David Howells275bb412008-11-14 10:39:19 +11005445 rc = avc_has_perm(sid, isec->sid, SECCLASS_SEM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005446 SEM__CREATE, &ad);
5447 if (rc) {
5448 ipc_free_security(&sma->sem_perm);
5449 return rc;
5450 }
5451 return 0;
5452}
5453
5454static void selinux_sem_free_security(struct sem_array *sma)
5455{
5456 ipc_free_security(&sma->sem_perm);
5457}
5458
5459static int selinux_sem_associate(struct sem_array *sma, int semflg)
5460{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005461 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005462 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005463 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005464
Linus Torvalds1da177e2005-04-16 15:20:36 -07005465 isec = sma->sem_perm.security;
5466
Eric Paris50c205f2012-04-04 15:01:43 -04005467 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005468 ad.u.ipc_id = sma->sem_perm.key;
5469
David Howells275bb412008-11-14 10:39:19 +11005470 return avc_has_perm(sid, isec->sid, SECCLASS_SEM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005471 SEM__ASSOCIATE, &ad);
5472}
5473
5474/* Note, at this point, sma is locked down */
5475static int selinux_sem_semctl(struct sem_array *sma, int cmd)
5476{
5477 int err;
5478 u32 perms;
5479
Eric Paris828dfe12008-04-17 13:17:49 -04005480 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005481 case IPC_INFO:
5482 case SEM_INFO:
5483 /* No specific object, just general system-wide information. */
5484 return task_has_system(current, SYSTEM__IPC_INFO);
5485 case GETPID:
5486 case GETNCNT:
5487 case GETZCNT:
5488 perms = SEM__GETATTR;
5489 break;
5490 case GETVAL:
5491 case GETALL:
5492 perms = SEM__READ;
5493 break;
5494 case SETVAL:
5495 case SETALL:
5496 perms = SEM__WRITE;
5497 break;
5498 case IPC_RMID:
5499 perms = SEM__DESTROY;
5500 break;
5501 case IPC_SET:
5502 perms = SEM__SETATTR;
5503 break;
5504 case IPC_STAT:
5505 case SEM_STAT:
5506 perms = SEM__GETATTR | SEM__ASSOCIATE;
5507 break;
5508 default:
5509 return 0;
5510 }
5511
Stephen Smalley6af963f2005-05-01 08:58:39 -07005512 err = ipc_has_perm(&sma->sem_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005513 return err;
5514}
5515
5516static int selinux_sem_semop(struct sem_array *sma,
5517 struct sembuf *sops, unsigned nsops, int alter)
5518{
5519 u32 perms;
5520
5521 if (alter)
5522 perms = SEM__READ | SEM__WRITE;
5523 else
5524 perms = SEM__READ;
5525
Stephen Smalley6af963f2005-05-01 08:58:39 -07005526 return ipc_has_perm(&sma->sem_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005527}
5528
5529static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
5530{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005531 u32 av = 0;
5532
Linus Torvalds1da177e2005-04-16 15:20:36 -07005533 av = 0;
5534 if (flag & S_IRUGO)
5535 av |= IPC__UNIX_READ;
5536 if (flag & S_IWUGO)
5537 av |= IPC__UNIX_WRITE;
5538
5539 if (av == 0)
5540 return 0;
5541
Stephen Smalley6af963f2005-05-01 08:58:39 -07005542 return ipc_has_perm(ipcp, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005543}
5544
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02005545static void selinux_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
5546{
5547 struct ipc_security_struct *isec = ipcp->security;
5548 *secid = isec->sid;
5549}
5550
Eric Paris828dfe12008-04-17 13:17:49 -04005551static void selinux_d_instantiate(struct dentry *dentry, struct inode *inode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005552{
5553 if (inode)
5554 inode_doinit_with_dentry(inode, dentry);
5555}
5556
5557static int selinux_getprocattr(struct task_struct *p,
Al Viro04ff9702007-03-12 16:17:58 +00005558 char *name, char **value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005559{
David Howells275bb412008-11-14 10:39:19 +11005560 const struct task_security_struct *__tsec;
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00005561 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005562 int error;
Al Viro04ff9702007-03-12 16:17:58 +00005563 unsigned len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005564
5565 if (current != p) {
David Howells3b11a1d2008-11-14 10:39:26 +11005566 error = current_has_perm(p, PROCESS__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005567 if (error)
5568 return error;
5569 }
5570
David Howells275bb412008-11-14 10:39:19 +11005571 rcu_read_lock();
5572 __tsec = __task_cred(p)->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005573
5574 if (!strcmp(name, "current"))
David Howells275bb412008-11-14 10:39:19 +11005575 sid = __tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005576 else if (!strcmp(name, "prev"))
David Howells275bb412008-11-14 10:39:19 +11005577 sid = __tsec->osid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005578 else if (!strcmp(name, "exec"))
David Howells275bb412008-11-14 10:39:19 +11005579 sid = __tsec->exec_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005580 else if (!strcmp(name, "fscreate"))
David Howells275bb412008-11-14 10:39:19 +11005581 sid = __tsec->create_sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005582 else if (!strcmp(name, "keycreate"))
David Howells275bb412008-11-14 10:39:19 +11005583 sid = __tsec->keycreate_sid;
Eric Paris42c3e032006-06-26 00:26:03 -07005584 else if (!strcmp(name, "sockcreate"))
David Howells275bb412008-11-14 10:39:19 +11005585 sid = __tsec->sockcreate_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005586 else
David Howells275bb412008-11-14 10:39:19 +11005587 goto invalid;
5588 rcu_read_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005589
5590 if (!sid)
5591 return 0;
5592
Al Viro04ff9702007-03-12 16:17:58 +00005593 error = security_sid_to_context(sid, value, &len);
5594 if (error)
5595 return error;
5596 return len;
David Howells275bb412008-11-14 10:39:19 +11005597
5598invalid:
5599 rcu_read_unlock();
5600 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005601}
5602
5603static int selinux_setprocattr(struct task_struct *p,
5604 char *name, void *value, size_t size)
5605{
5606 struct task_security_struct *tsec;
Roland McGrath03563572008-03-26 15:46:39 -07005607 struct task_struct *tracer;
David Howellsd84f4f92008-11-14 10:39:23 +11005608 struct cred *new;
5609 u32 sid = 0, ptsid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005610 int error;
5611 char *str = value;
5612
5613 if (current != p) {
5614 /* SELinux only allows a process to change its own
5615 security attributes. */
5616 return -EACCES;
5617 }
5618
5619 /*
5620 * Basic control over ability to set these attributes at all.
5621 * current == p, but we'll pass them separately in case the
5622 * above restriction is ever removed.
5623 */
5624 if (!strcmp(name, "exec"))
David Howells3b11a1d2008-11-14 10:39:26 +11005625 error = current_has_perm(p, PROCESS__SETEXEC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005626 else if (!strcmp(name, "fscreate"))
David Howells3b11a1d2008-11-14 10:39:26 +11005627 error = current_has_perm(p, PROCESS__SETFSCREATE);
Michael LeMay4eb582c2006-06-26 00:24:57 -07005628 else if (!strcmp(name, "keycreate"))
David Howells3b11a1d2008-11-14 10:39:26 +11005629 error = current_has_perm(p, PROCESS__SETKEYCREATE);
Eric Paris42c3e032006-06-26 00:26:03 -07005630 else if (!strcmp(name, "sockcreate"))
David Howells3b11a1d2008-11-14 10:39:26 +11005631 error = current_has_perm(p, PROCESS__SETSOCKCREATE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005632 else if (!strcmp(name, "current"))
David Howells3b11a1d2008-11-14 10:39:26 +11005633 error = current_has_perm(p, PROCESS__SETCURRENT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005634 else
5635 error = -EINVAL;
5636 if (error)
5637 return error;
5638
5639 /* Obtain a SID for the context, if one was specified. */
5640 if (size && str[1] && str[1] != '\n') {
5641 if (str[size-1] == '\n') {
5642 str[size-1] = 0;
5643 size--;
5644 }
Nikolay Aleksandrov52a4c642014-03-07 12:44:19 +01005645 error = security_context_to_sid(value, size, &sid, GFP_KERNEL);
Stephen Smalley12b29f32008-05-07 13:03:20 -04005646 if (error == -EINVAL && !strcmp(name, "fscreate")) {
Eric Parisd6ea83e2012-04-04 13:45:49 -04005647 if (!capable(CAP_MAC_ADMIN)) {
5648 struct audit_buffer *ab;
5649 size_t audit_size;
5650
5651 /* We strip a nul only if it is at the end, otherwise the
5652 * context contains a nul and we should audit that */
5653 if (str[size - 1] == '\0')
5654 audit_size = size - 1;
5655 else
5656 audit_size = size;
5657 ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR);
5658 audit_log_format(ab, "op=fscreate invalid_context=");
5659 audit_log_n_untrustedstring(ab, value, audit_size);
5660 audit_log_end(ab);
5661
Stephen Smalley12b29f32008-05-07 13:03:20 -04005662 return error;
Eric Parisd6ea83e2012-04-04 13:45:49 -04005663 }
Stephen Smalley12b29f32008-05-07 13:03:20 -04005664 error = security_context_to_sid_force(value, size,
5665 &sid);
5666 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005667 if (error)
5668 return error;
5669 }
5670
David Howellsd84f4f92008-11-14 10:39:23 +11005671 new = prepare_creds();
5672 if (!new)
5673 return -ENOMEM;
5674
Linus Torvalds1da177e2005-04-16 15:20:36 -07005675 /* Permission checking based on the specified context is
5676 performed during the actual operation (execve,
5677 open/mkdir/...), when we know the full context of the
David Howellsd84f4f92008-11-14 10:39:23 +11005678 operation. See selinux_bprm_set_creds for the execve
Linus Torvalds1da177e2005-04-16 15:20:36 -07005679 checks and may_create for the file creation checks. The
5680 operation will then fail if the context is not permitted. */
David Howellsd84f4f92008-11-14 10:39:23 +11005681 tsec = new->security;
5682 if (!strcmp(name, "exec")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005683 tsec->exec_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005684 } else if (!strcmp(name, "fscreate")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005685 tsec->create_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005686 } else if (!strcmp(name, "keycreate")) {
Michael LeMay4eb582c2006-06-26 00:24:57 -07005687 error = may_create_key(sid, p);
5688 if (error)
David Howellsd84f4f92008-11-14 10:39:23 +11005689 goto abort_change;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005690 tsec->keycreate_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005691 } else if (!strcmp(name, "sockcreate")) {
Eric Paris42c3e032006-06-26 00:26:03 -07005692 tsec->sockcreate_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005693 } else if (!strcmp(name, "current")) {
5694 error = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005695 if (sid == 0)
David Howellsd84f4f92008-11-14 10:39:23 +11005696 goto abort_change;
KaiGai Koheid9250de2008-08-28 16:35:57 +09005697
David Howellsd84f4f92008-11-14 10:39:23 +11005698 /* Only allow single threaded processes to change context */
5699 error = -EPERM;
Oleg Nesterov5bb459b2009-07-10 03:48:23 +02005700 if (!current_is_single_threaded()) {
David Howellsd84f4f92008-11-14 10:39:23 +11005701 error = security_bounded_transition(tsec->sid, sid);
5702 if (error)
5703 goto abort_change;
Eric Paris828dfe12008-04-17 13:17:49 -04005704 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005705
5706 /* Check permissions for the transition. */
5707 error = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS,
Eric Paris828dfe12008-04-17 13:17:49 -04005708 PROCESS__DYNTRANSITION, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005709 if (error)
David Howellsd84f4f92008-11-14 10:39:23 +11005710 goto abort_change;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005711
5712 /* Check for ptracing, and update the task SID if ok.
5713 Otherwise, leave SID unchanged and fail. */
David Howellsd84f4f92008-11-14 10:39:23 +11005714 ptsid = 0;
Oleg Nesterovc0c14392013-12-23 17:45:01 -05005715 rcu_read_lock();
Tejun Heo06d98472011-06-17 16:50:40 +02005716 tracer = ptrace_parent(p);
David Howellsd84f4f92008-11-14 10:39:23 +11005717 if (tracer)
5718 ptsid = task_sid(tracer);
Oleg Nesterovc0c14392013-12-23 17:45:01 -05005719 rcu_read_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005720
David Howellsd84f4f92008-11-14 10:39:23 +11005721 if (tracer) {
5722 error = avc_has_perm(ptsid, sid, SECCLASS_PROCESS,
5723 PROCESS__PTRACE, NULL);
5724 if (error)
5725 goto abort_change;
5726 }
5727
5728 tsec->sid = sid;
5729 } else {
5730 error = -EINVAL;
5731 goto abort_change;
5732 }
5733
5734 commit_creds(new);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005735 return size;
David Howellsd84f4f92008-11-14 10:39:23 +11005736
5737abort_change:
5738 abort_creds(new);
5739 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005740}
5741
David Quigley746df9b2013-05-22 12:50:35 -04005742static int selinux_ismaclabel(const char *name)
5743{
5744 return (strcmp(name, XATTR_SELINUX_SUFFIX) == 0);
5745}
5746
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005747static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
5748{
5749 return security_sid_to_context(secid, secdata, seclen);
5750}
5751
David Howells7bf570d2008-04-29 20:52:51 +01005752static int selinux_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
David Howells63cb3442008-01-15 23:47:35 +00005753{
Nikolay Aleksandrov52a4c642014-03-07 12:44:19 +01005754 return security_context_to_sid(secdata, seclen, secid, GFP_KERNEL);
David Howells63cb3442008-01-15 23:47:35 +00005755}
5756
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005757static void selinux_release_secctx(char *secdata, u32 seclen)
5758{
Paul Moore088999e2007-08-01 11:12:58 -04005759 kfree(secdata);
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005760}
5761
David P. Quigley1ee65e32009-09-03 14:25:57 -04005762/*
5763 * called with inode->i_mutex locked
5764 */
5765static int selinux_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen)
5766{
5767 return selinux_inode_setsecurity(inode, XATTR_SELINUX_SUFFIX, ctx, ctxlen, 0);
5768}
5769
5770/*
5771 * called with inode->i_mutex locked
5772 */
5773static int selinux_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen)
5774{
5775 return __vfs_setxattr_noperm(dentry, XATTR_NAME_SELINUX, ctx, ctxlen, 0);
5776}
5777
5778static int selinux_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen)
5779{
5780 int len = 0;
5781 len = selinux_inode_getsecurity(inode, XATTR_SELINUX_SUFFIX,
5782 ctx, true);
5783 if (len < 0)
5784 return len;
5785 *ctxlen = len;
5786 return 0;
5787}
Michael LeMayd7200242006-06-22 14:47:17 -07005788#ifdef CONFIG_KEYS
5789
David Howellsd84f4f92008-11-14 10:39:23 +11005790static int selinux_key_alloc(struct key *k, const struct cred *cred,
David Howells7e047ef2006-06-26 00:24:50 -07005791 unsigned long flags)
Michael LeMayd7200242006-06-22 14:47:17 -07005792{
David Howellsd84f4f92008-11-14 10:39:23 +11005793 const struct task_security_struct *tsec;
Michael LeMayd7200242006-06-22 14:47:17 -07005794 struct key_security_struct *ksec;
5795
5796 ksec = kzalloc(sizeof(struct key_security_struct), GFP_KERNEL);
5797 if (!ksec)
5798 return -ENOMEM;
5799
David Howellsd84f4f92008-11-14 10:39:23 +11005800 tsec = cred->security;
5801 if (tsec->keycreate_sid)
5802 ksec->sid = tsec->keycreate_sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005803 else
David Howellsd84f4f92008-11-14 10:39:23 +11005804 ksec->sid = tsec->sid;
Michael LeMayd7200242006-06-22 14:47:17 -07005805
David Howells275bb412008-11-14 10:39:19 +11005806 k->security = ksec;
Michael LeMayd7200242006-06-22 14:47:17 -07005807 return 0;
5808}
5809
5810static void selinux_key_free(struct key *k)
5811{
5812 struct key_security_struct *ksec = k->security;
5813
5814 k->security = NULL;
5815 kfree(ksec);
5816}
5817
5818static int selinux_key_permission(key_ref_t key_ref,
David Howellsd84f4f92008-11-14 10:39:23 +11005819 const struct cred *cred,
David Howellsf5895942014-03-14 17:44:49 +00005820 unsigned perm)
Michael LeMayd7200242006-06-22 14:47:17 -07005821{
5822 struct key *key;
Michael LeMayd7200242006-06-22 14:47:17 -07005823 struct key_security_struct *ksec;
David Howells275bb412008-11-14 10:39:19 +11005824 u32 sid;
Michael LeMayd7200242006-06-22 14:47:17 -07005825
5826 /* if no specific permissions are requested, we skip the
5827 permission check. No serious, additional covert channels
5828 appear to be created. */
5829 if (perm == 0)
5830 return 0;
5831
David Howellsd84f4f92008-11-14 10:39:23 +11005832 sid = cred_sid(cred);
David Howells275bb412008-11-14 10:39:19 +11005833
5834 key = key_ref_to_ptr(key_ref);
5835 ksec = key->security;
5836
5837 return avc_has_perm(sid, ksec->sid, SECCLASS_KEY, perm, NULL);
Michael LeMayd7200242006-06-22 14:47:17 -07005838}
5839
David Howells70a5bb72008-04-29 01:01:26 -07005840static int selinux_key_getsecurity(struct key *key, char **_buffer)
5841{
5842 struct key_security_struct *ksec = key->security;
5843 char *context = NULL;
5844 unsigned len;
5845 int rc;
5846
5847 rc = security_sid_to_context(ksec->sid, &context, &len);
5848 if (!rc)
5849 rc = len;
5850 *_buffer = context;
5851 return rc;
5852}
5853
Michael LeMayd7200242006-06-22 14:47:17 -07005854#endif
5855
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07005856static struct security_hook_list selinux_hooks[] = {
Casey Schauflere20b0432015-05-02 15:11:36 -07005857 LSM_HOOK_INIT(binder_set_context_mgr, selinux_binder_set_context_mgr),
5858 LSM_HOOK_INIT(binder_transaction, selinux_binder_transaction),
5859 LSM_HOOK_INIT(binder_transfer_binder, selinux_binder_transfer_binder),
5860 LSM_HOOK_INIT(binder_transfer_file, selinux_binder_transfer_file),
Ahmed S. Darwish076c54c2008-03-06 18:09:10 +02005861
Casey Schauflere20b0432015-05-02 15:11:36 -07005862 LSM_HOOK_INIT(ptrace_access_check, selinux_ptrace_access_check),
5863 LSM_HOOK_INIT(ptrace_traceme, selinux_ptrace_traceme),
5864 LSM_HOOK_INIT(capget, selinux_capget),
5865 LSM_HOOK_INIT(capset, selinux_capset),
5866 LSM_HOOK_INIT(capable, selinux_capable),
5867 LSM_HOOK_INIT(quotactl, selinux_quotactl),
5868 LSM_HOOK_INIT(quota_on, selinux_quota_on),
5869 LSM_HOOK_INIT(syslog, selinux_syslog),
5870 LSM_HOOK_INIT(vm_enough_memory, selinux_vm_enough_memory),
Stephen Smalley79af7302015-01-21 10:54:10 -05005871
Casey Schauflere20b0432015-05-02 15:11:36 -07005872 LSM_HOOK_INIT(netlink_send, selinux_netlink_send),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005873
Casey Schauflere20b0432015-05-02 15:11:36 -07005874 LSM_HOOK_INIT(bprm_set_creds, selinux_bprm_set_creds),
5875 LSM_HOOK_INIT(bprm_committing_creds, selinux_bprm_committing_creds),
5876 LSM_HOOK_INIT(bprm_committed_creds, selinux_bprm_committed_creds),
5877 LSM_HOOK_INIT(bprm_secureexec, selinux_bprm_secureexec),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005878
Casey Schauflere20b0432015-05-02 15:11:36 -07005879 LSM_HOOK_INIT(sb_alloc_security, selinux_sb_alloc_security),
5880 LSM_HOOK_INIT(sb_free_security, selinux_sb_free_security),
5881 LSM_HOOK_INIT(sb_copy_data, selinux_sb_copy_data),
5882 LSM_HOOK_INIT(sb_remount, selinux_sb_remount),
5883 LSM_HOOK_INIT(sb_kern_mount, selinux_sb_kern_mount),
5884 LSM_HOOK_INIT(sb_show_options, selinux_sb_show_options),
5885 LSM_HOOK_INIT(sb_statfs, selinux_sb_statfs),
5886 LSM_HOOK_INIT(sb_mount, selinux_mount),
5887 LSM_HOOK_INIT(sb_umount, selinux_umount),
5888 LSM_HOOK_INIT(sb_set_mnt_opts, selinux_set_mnt_opts),
5889 LSM_HOOK_INIT(sb_clone_mnt_opts, selinux_sb_clone_mnt_opts),
5890 LSM_HOOK_INIT(sb_parse_opts_str, selinux_parse_opts_str),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005891
Casey Schauflere20b0432015-05-02 15:11:36 -07005892 LSM_HOOK_INIT(dentry_init_security, selinux_dentry_init_security),
Eric Parise0007522008-03-05 10:31:54 -05005893
Casey Schauflere20b0432015-05-02 15:11:36 -07005894 LSM_HOOK_INIT(inode_alloc_security, selinux_inode_alloc_security),
5895 LSM_HOOK_INIT(inode_free_security, selinux_inode_free_security),
5896 LSM_HOOK_INIT(inode_init_security, selinux_inode_init_security),
5897 LSM_HOOK_INIT(inode_create, selinux_inode_create),
5898 LSM_HOOK_INIT(inode_link, selinux_inode_link),
5899 LSM_HOOK_INIT(inode_unlink, selinux_inode_unlink),
5900 LSM_HOOK_INIT(inode_symlink, selinux_inode_symlink),
5901 LSM_HOOK_INIT(inode_mkdir, selinux_inode_mkdir),
5902 LSM_HOOK_INIT(inode_rmdir, selinux_inode_rmdir),
5903 LSM_HOOK_INIT(inode_mknod, selinux_inode_mknod),
5904 LSM_HOOK_INIT(inode_rename, selinux_inode_rename),
5905 LSM_HOOK_INIT(inode_readlink, selinux_inode_readlink),
5906 LSM_HOOK_INIT(inode_follow_link, selinux_inode_follow_link),
5907 LSM_HOOK_INIT(inode_permission, selinux_inode_permission),
5908 LSM_HOOK_INIT(inode_setattr, selinux_inode_setattr),
5909 LSM_HOOK_INIT(inode_getattr, selinux_inode_getattr),
5910 LSM_HOOK_INIT(inode_setxattr, selinux_inode_setxattr),
5911 LSM_HOOK_INIT(inode_post_setxattr, selinux_inode_post_setxattr),
5912 LSM_HOOK_INIT(inode_getxattr, selinux_inode_getxattr),
5913 LSM_HOOK_INIT(inode_listxattr, selinux_inode_listxattr),
5914 LSM_HOOK_INIT(inode_removexattr, selinux_inode_removexattr),
5915 LSM_HOOK_INIT(inode_getsecurity, selinux_inode_getsecurity),
5916 LSM_HOOK_INIT(inode_setsecurity, selinux_inode_setsecurity),
5917 LSM_HOOK_INIT(inode_listsecurity, selinux_inode_listsecurity),
5918 LSM_HOOK_INIT(inode_getsecid, selinux_inode_getsecid),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005919
Casey Schauflere20b0432015-05-02 15:11:36 -07005920 LSM_HOOK_INIT(file_permission, selinux_file_permission),
5921 LSM_HOOK_INIT(file_alloc_security, selinux_file_alloc_security),
5922 LSM_HOOK_INIT(file_free_security, selinux_file_free_security),
5923 LSM_HOOK_INIT(file_ioctl, selinux_file_ioctl),
5924 LSM_HOOK_INIT(mmap_file, selinux_mmap_file),
5925 LSM_HOOK_INIT(mmap_addr, selinux_mmap_addr),
5926 LSM_HOOK_INIT(file_mprotect, selinux_file_mprotect),
5927 LSM_HOOK_INIT(file_lock, selinux_file_lock),
5928 LSM_HOOK_INIT(file_fcntl, selinux_file_fcntl),
5929 LSM_HOOK_INIT(file_set_fowner, selinux_file_set_fowner),
5930 LSM_HOOK_INIT(file_send_sigiotask, selinux_file_send_sigiotask),
5931 LSM_HOOK_INIT(file_receive, selinux_file_receive),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005932
Casey Schauflere20b0432015-05-02 15:11:36 -07005933 LSM_HOOK_INIT(file_open, selinux_file_open),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005934
Casey Schauflere20b0432015-05-02 15:11:36 -07005935 LSM_HOOK_INIT(task_create, selinux_task_create),
5936 LSM_HOOK_INIT(cred_alloc_blank, selinux_cred_alloc_blank),
5937 LSM_HOOK_INIT(cred_free, selinux_cred_free),
5938 LSM_HOOK_INIT(cred_prepare, selinux_cred_prepare),
5939 LSM_HOOK_INIT(cred_transfer, selinux_cred_transfer),
5940 LSM_HOOK_INIT(kernel_act_as, selinux_kernel_act_as),
5941 LSM_HOOK_INIT(kernel_create_files_as, selinux_kernel_create_files_as),
5942 LSM_HOOK_INIT(kernel_module_request, selinux_kernel_module_request),
5943 LSM_HOOK_INIT(task_setpgid, selinux_task_setpgid),
5944 LSM_HOOK_INIT(task_getpgid, selinux_task_getpgid),
5945 LSM_HOOK_INIT(task_getsid, selinux_task_getsid),
5946 LSM_HOOK_INIT(task_getsecid, selinux_task_getsecid),
5947 LSM_HOOK_INIT(task_setnice, selinux_task_setnice),
5948 LSM_HOOK_INIT(task_setioprio, selinux_task_setioprio),
5949 LSM_HOOK_INIT(task_getioprio, selinux_task_getioprio),
5950 LSM_HOOK_INIT(task_setrlimit, selinux_task_setrlimit),
5951 LSM_HOOK_INIT(task_setscheduler, selinux_task_setscheduler),
5952 LSM_HOOK_INIT(task_getscheduler, selinux_task_getscheduler),
5953 LSM_HOOK_INIT(task_movememory, selinux_task_movememory),
5954 LSM_HOOK_INIT(task_kill, selinux_task_kill),
5955 LSM_HOOK_INIT(task_wait, selinux_task_wait),
5956 LSM_HOOK_INIT(task_to_inode, selinux_task_to_inode),
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09005957
Casey Schauflere20b0432015-05-02 15:11:36 -07005958 LSM_HOOK_INIT(ipc_permission, selinux_ipc_permission),
5959 LSM_HOOK_INIT(ipc_getsecid, selinux_ipc_getsecid),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005960
Casey Schauflere20b0432015-05-02 15:11:36 -07005961 LSM_HOOK_INIT(msg_msg_alloc_security, selinux_msg_msg_alloc_security),
5962 LSM_HOOK_INIT(msg_msg_free_security, selinux_msg_msg_free_security),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005963
Casey Schauflere20b0432015-05-02 15:11:36 -07005964 LSM_HOOK_INIT(msg_queue_alloc_security,
5965 selinux_msg_queue_alloc_security),
5966 LSM_HOOK_INIT(msg_queue_free_security, selinux_msg_queue_free_security),
5967 LSM_HOOK_INIT(msg_queue_associate, selinux_msg_queue_associate),
5968 LSM_HOOK_INIT(msg_queue_msgctl, selinux_msg_queue_msgctl),
5969 LSM_HOOK_INIT(msg_queue_msgsnd, selinux_msg_queue_msgsnd),
5970 LSM_HOOK_INIT(msg_queue_msgrcv, selinux_msg_queue_msgrcv),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005971
Casey Schauflere20b0432015-05-02 15:11:36 -07005972 LSM_HOOK_INIT(shm_alloc_security, selinux_shm_alloc_security),
5973 LSM_HOOK_INIT(shm_free_security, selinux_shm_free_security),
5974 LSM_HOOK_INIT(shm_associate, selinux_shm_associate),
5975 LSM_HOOK_INIT(shm_shmctl, selinux_shm_shmctl),
5976 LSM_HOOK_INIT(shm_shmat, selinux_shm_shmat),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005977
Casey Schauflere20b0432015-05-02 15:11:36 -07005978 LSM_HOOK_INIT(sem_alloc_security, selinux_sem_alloc_security),
5979 LSM_HOOK_INIT(sem_free_security, selinux_sem_free_security),
5980 LSM_HOOK_INIT(sem_associate, selinux_sem_associate),
5981 LSM_HOOK_INIT(sem_semctl, selinux_sem_semctl),
5982 LSM_HOOK_INIT(sem_semop, selinux_sem_semop),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005983
Casey Schauflere20b0432015-05-02 15:11:36 -07005984 LSM_HOOK_INIT(d_instantiate, selinux_d_instantiate),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005985
Casey Schauflere20b0432015-05-02 15:11:36 -07005986 LSM_HOOK_INIT(getprocattr, selinux_getprocattr),
5987 LSM_HOOK_INIT(setprocattr, selinux_setprocattr),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005988
Casey Schauflere20b0432015-05-02 15:11:36 -07005989 LSM_HOOK_INIT(ismaclabel, selinux_ismaclabel),
5990 LSM_HOOK_INIT(secid_to_secctx, selinux_secid_to_secctx),
5991 LSM_HOOK_INIT(secctx_to_secid, selinux_secctx_to_secid),
5992 LSM_HOOK_INIT(release_secctx, selinux_release_secctx),
5993 LSM_HOOK_INIT(inode_notifysecctx, selinux_inode_notifysecctx),
5994 LSM_HOOK_INIT(inode_setsecctx, selinux_inode_setsecctx),
5995 LSM_HOOK_INIT(inode_getsecctx, selinux_inode_getsecctx),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005996
Casey Schauflere20b0432015-05-02 15:11:36 -07005997 LSM_HOOK_INIT(unix_stream_connect, selinux_socket_unix_stream_connect),
5998 LSM_HOOK_INIT(unix_may_send, selinux_socket_unix_may_send),
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005999
Casey Schauflere20b0432015-05-02 15:11:36 -07006000 LSM_HOOK_INIT(socket_create, selinux_socket_create),
6001 LSM_HOOK_INIT(socket_post_create, selinux_socket_post_create),
6002 LSM_HOOK_INIT(socket_bind, selinux_socket_bind),
6003 LSM_HOOK_INIT(socket_connect, selinux_socket_connect),
6004 LSM_HOOK_INIT(socket_listen, selinux_socket_listen),
6005 LSM_HOOK_INIT(socket_accept, selinux_socket_accept),
6006 LSM_HOOK_INIT(socket_sendmsg, selinux_socket_sendmsg),
6007 LSM_HOOK_INIT(socket_recvmsg, selinux_socket_recvmsg),
6008 LSM_HOOK_INIT(socket_getsockname, selinux_socket_getsockname),
6009 LSM_HOOK_INIT(socket_getpeername, selinux_socket_getpeername),
6010 LSM_HOOK_INIT(socket_getsockopt, selinux_socket_getsockopt),
6011 LSM_HOOK_INIT(socket_setsockopt, selinux_socket_setsockopt),
6012 LSM_HOOK_INIT(socket_shutdown, selinux_socket_shutdown),
6013 LSM_HOOK_INIT(socket_sock_rcv_skb, selinux_socket_sock_rcv_skb),
6014 LSM_HOOK_INIT(socket_getpeersec_stream,
6015 selinux_socket_getpeersec_stream),
6016 LSM_HOOK_INIT(socket_getpeersec_dgram, selinux_socket_getpeersec_dgram),
6017 LSM_HOOK_INIT(sk_alloc_security, selinux_sk_alloc_security),
6018 LSM_HOOK_INIT(sk_free_security, selinux_sk_free_security),
6019 LSM_HOOK_INIT(sk_clone_security, selinux_sk_clone_security),
6020 LSM_HOOK_INIT(sk_getsecid, selinux_sk_getsecid),
6021 LSM_HOOK_INIT(sock_graft, selinux_sock_graft),
6022 LSM_HOOK_INIT(inet_conn_request, selinux_inet_conn_request),
6023 LSM_HOOK_INIT(inet_csk_clone, selinux_inet_csk_clone),
6024 LSM_HOOK_INIT(inet_conn_established, selinux_inet_conn_established),
6025 LSM_HOOK_INIT(secmark_relabel_packet, selinux_secmark_relabel_packet),
6026 LSM_HOOK_INIT(secmark_refcount_inc, selinux_secmark_refcount_inc),
6027 LSM_HOOK_INIT(secmark_refcount_dec, selinux_secmark_refcount_dec),
6028 LSM_HOOK_INIT(req_classify_flow, selinux_req_classify_flow),
6029 LSM_HOOK_INIT(tun_dev_alloc_security, selinux_tun_dev_alloc_security),
6030 LSM_HOOK_INIT(tun_dev_free_security, selinux_tun_dev_free_security),
6031 LSM_HOOK_INIT(tun_dev_create, selinux_tun_dev_create),
6032 LSM_HOOK_INIT(tun_dev_attach_queue, selinux_tun_dev_attach_queue),
6033 LSM_HOOK_INIT(tun_dev_attach, selinux_tun_dev_attach),
6034 LSM_HOOK_INIT(tun_dev_open, selinux_tun_dev_open),
Trent Jaegerd28d1e02005-12-13 23:12:40 -08006035
6036#ifdef CONFIG_SECURITY_NETWORK_XFRM
Casey Schauflere20b0432015-05-02 15:11:36 -07006037 LSM_HOOK_INIT(xfrm_policy_alloc_security, selinux_xfrm_policy_alloc),
6038 LSM_HOOK_INIT(xfrm_policy_clone_security, selinux_xfrm_policy_clone),
6039 LSM_HOOK_INIT(xfrm_policy_free_security, selinux_xfrm_policy_free),
6040 LSM_HOOK_INIT(xfrm_policy_delete_security, selinux_xfrm_policy_delete),
6041 LSM_HOOK_INIT(xfrm_state_alloc, selinux_xfrm_state_alloc),
6042 LSM_HOOK_INIT(xfrm_state_alloc_acquire,
6043 selinux_xfrm_state_alloc_acquire),
6044 LSM_HOOK_INIT(xfrm_state_free_security, selinux_xfrm_state_free),
6045 LSM_HOOK_INIT(xfrm_state_delete_security, selinux_xfrm_state_delete),
6046 LSM_HOOK_INIT(xfrm_policy_lookup, selinux_xfrm_policy_lookup),
6047 LSM_HOOK_INIT(xfrm_state_pol_flow_match,
6048 selinux_xfrm_state_pol_flow_match),
6049 LSM_HOOK_INIT(xfrm_decode_session, selinux_xfrm_decode_session),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006050#endif
Michael LeMayd7200242006-06-22 14:47:17 -07006051
6052#ifdef CONFIG_KEYS
Casey Schauflere20b0432015-05-02 15:11:36 -07006053 LSM_HOOK_INIT(key_alloc, selinux_key_alloc),
6054 LSM_HOOK_INIT(key_free, selinux_key_free),
6055 LSM_HOOK_INIT(key_permission, selinux_key_permission),
6056 LSM_HOOK_INIT(key_getsecurity, selinux_key_getsecurity),
Michael LeMayd7200242006-06-22 14:47:17 -07006057#endif
Ahmed S. Darwish9d57a7f2008-03-01 22:03:14 +02006058
6059#ifdef CONFIG_AUDIT
Casey Schauflere20b0432015-05-02 15:11:36 -07006060 LSM_HOOK_INIT(audit_rule_init, selinux_audit_rule_init),
6061 LSM_HOOK_INIT(audit_rule_known, selinux_audit_rule_known),
6062 LSM_HOOK_INIT(audit_rule_match, selinux_audit_rule_match),
6063 LSM_HOOK_INIT(audit_rule_free, selinux_audit_rule_free),
Ahmed S. Darwish9d57a7f2008-03-01 22:03:14 +02006064#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07006065};
6066
6067static __init int selinux_init(void)
6068{
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07006069 if (!security_module_enable("selinux")) {
Ahmed S. Darwish076c54c2008-03-06 18:09:10 +02006070 selinux_enabled = 0;
6071 return 0;
6072 }
6073
Linus Torvalds1da177e2005-04-16 15:20:36 -07006074 if (!selinux_enabled) {
6075 printk(KERN_INFO "SELinux: Disabled at boot.\n");
6076 return 0;
6077 }
6078
6079 printk(KERN_INFO "SELinux: Initializing.\n");
6080
6081 /* Set the security state for the initial task. */
David Howellsd84f4f92008-11-14 10:39:23 +11006082 cred_init_security();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006083
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04006084 default_noexec = !(VM_DATA_DEFAULT_FLAGS & VM_EXEC);
6085
James Morris7cae7e22006-03-22 00:09:22 -08006086 sel_inode_cache = kmem_cache_create("selinux_inode_security",
6087 sizeof(struct inode_security_struct),
Paul Mundt20c2df82007-07-20 10:11:58 +09006088 0, SLAB_PANIC, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006089 avc_init();
6090
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07006091 security_add_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006092
Paul Moore615e51f2014-06-26 14:33:56 -04006093 if (avc_add_callback(selinux_netcache_avc_callback, AVC_CALLBACK_RESET))
6094 panic("SELinux: Unable to register AVC netcache callback\n");
6095
Eric Paris828dfe12008-04-17 13:17:49 -04006096 if (selinux_enforcing)
Eric Parisfadcdb42007-02-22 18:11:31 -05006097 printk(KERN_DEBUG "SELinux: Starting in enforcing mode\n");
Eric Paris828dfe12008-04-17 13:17:49 -04006098 else
Eric Parisfadcdb42007-02-22 18:11:31 -05006099 printk(KERN_DEBUG "SELinux: Starting in permissive mode\n");
Michael LeMayd7200242006-06-22 14:47:17 -07006100
Linus Torvalds1da177e2005-04-16 15:20:36 -07006101 return 0;
6102}
6103
Al Viroe8c26252010-03-23 06:36:54 -04006104static void delayed_superblock_init(struct super_block *sb, void *unused)
6105{
6106 superblock_doinit(sb, NULL);
6107}
6108
Linus Torvalds1da177e2005-04-16 15:20:36 -07006109void selinux_complete_init(void)
6110{
Eric Parisfadcdb42007-02-22 18:11:31 -05006111 printk(KERN_DEBUG "SELinux: Completing initialization.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07006112
6113 /* Set up any superblocks initialized prior to the policy load. */
Eric Parisfadcdb42007-02-22 18:11:31 -05006114 printk(KERN_DEBUG "SELinux: Setting up existing superblocks.\n");
Al Viroe8c26252010-03-23 06:36:54 -04006115 iterate_supers(delayed_superblock_init, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006116}
6117
6118/* SELinux requires early initialization in order to label
6119 all processes and objects when they are created. */
6120security_initcall(selinux_init);
6121
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08006122#if defined(CONFIG_NETFILTER)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006123
Jiri Pirko25db6be2014-09-03 17:42:13 +02006124static struct nf_hook_ops selinux_nf_ops[] = {
Paul Mooreeffad8d2008-01-29 08:49:27 -05006125 {
6126 .hook = selinux_ipv4_postroute,
6127 .owner = THIS_MODULE,
Alban Crequy2597a832012-05-14 03:56:39 +00006128 .pf = NFPROTO_IPV4,
Paul Mooreeffad8d2008-01-29 08:49:27 -05006129 .hooknum = NF_INET_POST_ROUTING,
6130 .priority = NF_IP_PRI_SELINUX_LAST,
6131 },
6132 {
6133 .hook = selinux_ipv4_forward,
6134 .owner = THIS_MODULE,
Alban Crequy2597a832012-05-14 03:56:39 +00006135 .pf = NFPROTO_IPV4,
Paul Mooreeffad8d2008-01-29 08:49:27 -05006136 .hooknum = NF_INET_FORWARD,
6137 .priority = NF_IP_PRI_SELINUX_FIRST,
Paul Moore948bf852008-10-10 10:16:32 -04006138 },
6139 {
6140 .hook = selinux_ipv4_output,
6141 .owner = THIS_MODULE,
Alban Crequy2597a832012-05-14 03:56:39 +00006142 .pf = NFPROTO_IPV4,
Paul Moore948bf852008-10-10 10:16:32 -04006143 .hooknum = NF_INET_LOCAL_OUT,
6144 .priority = NF_IP_PRI_SELINUX_FIRST,
Jiri Pirko25db6be2014-09-03 17:42:13 +02006145 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07006146#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Paul Mooreeffad8d2008-01-29 08:49:27 -05006147 {
6148 .hook = selinux_ipv6_postroute,
6149 .owner = THIS_MODULE,
Alban Crequy2597a832012-05-14 03:56:39 +00006150 .pf = NFPROTO_IPV6,
Paul Mooreeffad8d2008-01-29 08:49:27 -05006151 .hooknum = NF_INET_POST_ROUTING,
6152 .priority = NF_IP6_PRI_SELINUX_LAST,
6153 },
6154 {
6155 .hook = selinux_ipv6_forward,
6156 .owner = THIS_MODULE,
Alban Crequy2597a832012-05-14 03:56:39 +00006157 .pf = NFPROTO_IPV6,
Paul Mooreeffad8d2008-01-29 08:49:27 -05006158 .hooknum = NF_INET_FORWARD,
6159 .priority = NF_IP6_PRI_SELINUX_FIRST,
Jiri Pirko25db6be2014-09-03 17:42:13 +02006160 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07006161#endif /* IPV6 */
Jiri Pirko25db6be2014-09-03 17:42:13 +02006162};
Linus Torvalds1da177e2005-04-16 15:20:36 -07006163
6164static int __init selinux_nf_ip_init(void)
6165{
Jiri Pirko25db6be2014-09-03 17:42:13 +02006166 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006167
6168 if (!selinux_enabled)
Jiri Pirko25db6be2014-09-03 17:42:13 +02006169 return 0;
Eric Parisfadcdb42007-02-22 18:11:31 -05006170
6171 printk(KERN_DEBUG "SELinux: Registering netfilter hooks\n");
6172
Jiri Pirko25db6be2014-09-03 17:42:13 +02006173 err = nf_register_hooks(selinux_nf_ops, ARRAY_SIZE(selinux_nf_ops));
Alexey Dobriyan6c5a9d22008-07-26 17:48:15 -07006174 if (err)
Jiri Pirko25db6be2014-09-03 17:42:13 +02006175 panic("SELinux: nf_register_hooks: error %d\n", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006176
Jiri Pirko25db6be2014-09-03 17:42:13 +02006177 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006178}
6179
6180__initcall(selinux_nf_ip_init);
6181
6182#ifdef CONFIG_SECURITY_SELINUX_DISABLE
6183static void selinux_nf_ip_exit(void)
6184{
Eric Parisfadcdb42007-02-22 18:11:31 -05006185 printk(KERN_DEBUG "SELinux: Unregistering netfilter hooks\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07006186
Jiri Pirko25db6be2014-09-03 17:42:13 +02006187 nf_unregister_hooks(selinux_nf_ops, ARRAY_SIZE(selinux_nf_ops));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006188}
6189#endif
6190
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08006191#else /* CONFIG_NETFILTER */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006192
6193#ifdef CONFIG_SECURITY_SELINUX_DISABLE
6194#define selinux_nf_ip_exit()
6195#endif
6196
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08006197#endif /* CONFIG_NETFILTER */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006198
6199#ifdef CONFIG_SECURITY_SELINUX_DISABLE
Eric Paris828dfe12008-04-17 13:17:49 -04006200static int selinux_disabled;
6201
Linus Torvalds1da177e2005-04-16 15:20:36 -07006202int selinux_disable(void)
6203{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006204 if (ss_initialized) {
6205 /* Not permitted after initial policy load. */
6206 return -EINVAL;
6207 }
6208
6209 if (selinux_disabled) {
6210 /* Only do this once. */
6211 return -EINVAL;
6212 }
6213
6214 printk(KERN_INFO "SELinux: Disabled at runtime.\n");
6215
6216 selinux_disabled = 1;
Stephen Smalley30d55282006-05-03 10:52:36 -04006217 selinux_enabled = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006218
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07006219 security_delete_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006220
Eric Parisaf8ff042009-09-20 21:23:01 -04006221 /* Try to destroy the avc node cache */
6222 avc_disable();
6223
Linus Torvalds1da177e2005-04-16 15:20:36 -07006224 /* Unregister netfilter hooks. */
6225 selinux_nf_ip_exit();
6226
6227 /* Unregister selinuxfs. */
6228 exit_sel_fs();
6229
6230 return 0;
6231}
6232#endif