blob: d0cfaa9f19d08034a3c3600d8381ed166a369388 [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;
Sangwoo63205652015-10-21 17:44:30 -0400129static struct kmem_cache *file_security_cache;
James Morris7cae7e22006-03-22 00:09:22 -0800130
Paul Moored621d352008-01-29 08:43:36 -0500131/**
132 * selinux_secmark_enabled - Check to see if SECMARK is currently enabled
133 *
134 * Description:
135 * This function checks the SECMARK reference counter to see if any SECMARK
136 * targets are currently configured, if the reference counter is greater than
137 * zero SECMARK is considered to be enabled. Returns true (1) if SECMARK is
Chris PeBenito2be4d742013-05-03 09:05:39 -0400138 * enabled, false (0) if SECMARK is disabled. If the always_check_network
139 * policy capability is enabled, SECMARK is always considered enabled.
Paul Moored621d352008-01-29 08:43:36 -0500140 *
141 */
142static int selinux_secmark_enabled(void)
143{
Chris PeBenito2be4d742013-05-03 09:05:39 -0400144 return (selinux_policycap_alwaysnetwork || atomic_read(&selinux_secmark_refcount));
145}
146
147/**
148 * selinux_peerlbl_enabled - Check to see if peer labeling is currently enabled
149 *
150 * Description:
151 * This function checks if NetLabel or labeled IPSEC is enabled. Returns true
152 * (1) if any are enabled or false (0) if neither are enabled. If the
153 * always_check_network policy capability is enabled, peer labeling
154 * is always considered enabled.
155 *
156 */
157static int selinux_peerlbl_enabled(void)
158{
159 return (selinux_policycap_alwaysnetwork || netlbl_enabled() || selinux_xfrm_enabled());
Paul Moored621d352008-01-29 08:43:36 -0500160}
161
Paul Moore615e51f2014-06-26 14:33:56 -0400162static int selinux_netcache_avc_callback(u32 event)
163{
164 if (event == AVC_CALLBACK_RESET) {
165 sel_netif_flush();
166 sel_netnode_flush();
167 sel_netport_flush();
168 synchronize_net();
169 }
170 return 0;
171}
172
David Howellsd84f4f92008-11-14 10:39:23 +1100173/*
174 * initialise the security for the init task
175 */
176static void cred_init_security(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700177{
David Howells3b11a1d2008-11-14 10:39:26 +1100178 struct cred *cred = (struct cred *) current->real_cred;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700179 struct task_security_struct *tsec;
180
James Morris89d155e2005-10-30 14:59:21 -0800181 tsec = kzalloc(sizeof(struct task_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700182 if (!tsec)
David Howellsd84f4f92008-11-14 10:39:23 +1100183 panic("SELinux: Failed to initialize initial task.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700184
David Howellsd84f4f92008-11-14 10:39:23 +1100185 tsec->osid = tsec->sid = SECINITSID_KERNEL;
David Howellsf1752ee2008-11-14 10:39:17 +1100186 cred->security = tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700187}
188
David Howells275bb412008-11-14 10:39:19 +1100189/*
David Howells88e67f32008-11-14 10:39:21 +1100190 * get the security ID of a set of credentials
191 */
192static inline u32 cred_sid(const struct cred *cred)
193{
194 const struct task_security_struct *tsec;
195
196 tsec = cred->security;
197 return tsec->sid;
198}
199
200/*
David Howells3b11a1d2008-11-14 10:39:26 +1100201 * get the objective security ID of a task
David Howells275bb412008-11-14 10:39:19 +1100202 */
203static inline u32 task_sid(const struct task_struct *task)
204{
David Howells275bb412008-11-14 10:39:19 +1100205 u32 sid;
206
207 rcu_read_lock();
David Howells88e67f32008-11-14 10:39:21 +1100208 sid = cred_sid(__task_cred(task));
David Howells275bb412008-11-14 10:39:19 +1100209 rcu_read_unlock();
210 return sid;
211}
212
213/*
David Howells3b11a1d2008-11-14 10:39:26 +1100214 * get the subjective security ID of the current task
David Howells275bb412008-11-14 10:39:19 +1100215 */
216static inline u32 current_sid(void)
217{
Paul Moore5fb49872010-04-22 14:46:19 -0400218 const struct task_security_struct *tsec = current_security();
David Howells275bb412008-11-14 10:39:19 +1100219
220 return tsec->sid;
221}
222
David Howells88e67f32008-11-14 10:39:21 +1100223/* Allocate and free functions for each kind of security blob. */
224
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225static int inode_alloc_security(struct inode *inode)
226{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700227 struct inode_security_struct *isec;
David Howells275bb412008-11-14 10:39:19 +1100228 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700229
Josef Bacika02fe132008-04-04 09:35:05 +1100230 isec = kmem_cache_zalloc(sel_inode_cache, GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700231 if (!isec)
232 return -ENOMEM;
233
Eric Paris23970742006-09-25 23:32:01 -0700234 mutex_init(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700235 INIT_LIST_HEAD(&isec->list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700236 isec->inode = inode;
237 isec->sid = SECINITSID_UNLABELED;
238 isec->sclass = SECCLASS_FILE;
David Howells275bb412008-11-14 10:39:19 +1100239 isec->task_sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700240 inode->i_security = isec;
241
242 return 0;
243}
244
Steven Rostedt3dc91d42014-01-09 21:46:34 -0500245static void inode_free_rcu(struct rcu_head *head)
246{
247 struct inode_security_struct *isec;
248
249 isec = container_of(head, struct inode_security_struct, rcu);
250 kmem_cache_free(sel_inode_cache, isec);
251}
252
Linus Torvalds1da177e2005-04-16 15:20:36 -0700253static void inode_free_security(struct inode *inode)
254{
255 struct inode_security_struct *isec = inode->i_security;
256 struct superblock_security_struct *sbsec = inode->i_sb->s_security;
257
Waiman Long9629d042015-07-10 17:19:56 -0400258 /*
259 * As not all inode security structures are in a list, we check for
260 * empty list outside of the lock to make sure that we won't waste
261 * time taking a lock doing nothing.
262 *
263 * The list_del_init() function can be safely called more than once.
264 * It should not be possible for this function to be called with
265 * concurrent list_add(), but for better safety against future changes
266 * in the code, we use list_empty_careful() here.
267 */
268 if (!list_empty_careful(&isec->list)) {
269 spin_lock(&sbsec->isec_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700270 list_del_init(&isec->list);
Waiman Long9629d042015-07-10 17:19:56 -0400271 spin_unlock(&sbsec->isec_lock);
272 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273
Steven Rostedt3dc91d42014-01-09 21:46:34 -0500274 /*
275 * The inode may still be referenced in a path walk and
276 * a call to selinux_inode_permission() can be made
277 * after inode_free_security() is called. Ideally, the VFS
278 * wouldn't do this, but fixing that is a much harder
279 * job. For now, simply free the i_security via RCU, and
280 * leave the current inode->i_security pointer intact.
281 * The inode will be freed after the RCU grace period too.
282 */
283 call_rcu(&isec->rcu, inode_free_rcu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284}
285
286static int file_alloc_security(struct file *file)
287{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288 struct file_security_struct *fsec;
David Howells275bb412008-11-14 10:39:19 +1100289 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700290
Sangwoo63205652015-10-21 17:44:30 -0400291 fsec = kmem_cache_zalloc(file_security_cache, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700292 if (!fsec)
293 return -ENOMEM;
294
David Howells275bb412008-11-14 10:39:19 +1100295 fsec->sid = sid;
296 fsec->fown_sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700297 file->f_security = fsec;
298
299 return 0;
300}
301
302static void file_free_security(struct file *file)
303{
304 struct file_security_struct *fsec = file->f_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700305 file->f_security = NULL;
Sangwoo63205652015-10-21 17:44:30 -0400306 kmem_cache_free(file_security_cache, fsec);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307}
308
309static int superblock_alloc_security(struct super_block *sb)
310{
311 struct superblock_security_struct *sbsec;
312
James Morris89d155e2005-10-30 14:59:21 -0800313 sbsec = kzalloc(sizeof(struct superblock_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700314 if (!sbsec)
315 return -ENOMEM;
316
Eric Parisbc7e9822006-09-25 23:32:02 -0700317 mutex_init(&sbsec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700318 INIT_LIST_HEAD(&sbsec->isec_head);
319 spin_lock_init(&sbsec->isec_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320 sbsec->sb = sb;
321 sbsec->sid = SECINITSID_UNLABELED;
322 sbsec->def_sid = SECINITSID_FILE;
Eric Parisc312feb2006-07-10 04:43:53 -0700323 sbsec->mntpoint_sid = SECINITSID_UNLABELED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324 sb->s_security = sbsec;
325
326 return 0;
327}
328
329static void superblock_free_security(struct super_block *sb)
330{
331 struct superblock_security_struct *sbsec = sb->s_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700332 sb->s_security = NULL;
333 kfree(sbsec);
334}
335
Linus Torvalds1da177e2005-04-16 15:20:36 -0700336/* The file system's label must be initialized prior to use. */
337
David Quigleyeb9ae682013-05-22 12:50:37 -0400338static const char *labeling_behaviors[7] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700339 "uses xattr",
340 "uses transition SIDs",
341 "uses task SIDs",
342 "uses genfs_contexts",
343 "not configured for labeling",
344 "uses mountpoint labeling",
David Quigleyeb9ae682013-05-22 12:50:37 -0400345 "uses native labeling",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700346};
347
348static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry);
349
350static inline int inode_doinit(struct inode *inode)
351{
352 return inode_doinit_with_dentry(inode, NULL);
353}
354
355enum {
Eric Paris31e87932007-09-19 17:19:12 -0400356 Opt_error = -1,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357 Opt_context = 1,
358 Opt_fscontext = 2,
Eric Parisc9180a52007-11-30 13:00:35 -0500359 Opt_defcontext = 3,
360 Opt_rootcontext = 4,
David P. Quigley11689d42009-01-16 09:22:03 -0500361 Opt_labelsupport = 5,
Eric Parisd355987f2012-08-24 15:58:53 -0400362 Opt_nextmntopt = 6,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700363};
364
Eric Parisd355987f2012-08-24 15:58:53 -0400365#define NUM_SEL_MNT_OPTS (Opt_nextmntopt - 1)
366
Steven Whitehousea447c092008-10-13 10:46:57 +0100367static const match_table_t tokens = {
Eric Paris832cbd92008-04-01 13:24:09 -0400368 {Opt_context, CONTEXT_STR "%s"},
369 {Opt_fscontext, FSCONTEXT_STR "%s"},
370 {Opt_defcontext, DEFCONTEXT_STR "%s"},
371 {Opt_rootcontext, ROOTCONTEXT_STR "%s"},
David P. Quigley11689d42009-01-16 09:22:03 -0500372 {Opt_labelsupport, LABELSUPP_STR},
Eric Paris31e87932007-09-19 17:19:12 -0400373 {Opt_error, NULL},
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374};
375
376#define SEL_MOUNT_FAIL_MSG "SELinux: duplicate or incompatible mount options\n"
377
Eric Parisc312feb2006-07-10 04:43:53 -0700378static int may_context_mount_sb_relabel(u32 sid,
379 struct superblock_security_struct *sbsec,
David Howells275bb412008-11-14 10:39:19 +1100380 const struct cred *cred)
Eric Parisc312feb2006-07-10 04:43:53 -0700381{
David Howells275bb412008-11-14 10:39:19 +1100382 const struct task_security_struct *tsec = cred->security;
Eric Parisc312feb2006-07-10 04:43:53 -0700383 int rc;
384
385 rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
386 FILESYSTEM__RELABELFROM, NULL);
387 if (rc)
388 return rc;
389
390 rc = avc_has_perm(tsec->sid, sid, SECCLASS_FILESYSTEM,
391 FILESYSTEM__RELABELTO, NULL);
392 return rc;
393}
394
Eric Paris08089252006-07-10 04:43:55 -0700395static int may_context_mount_inode_relabel(u32 sid,
396 struct superblock_security_struct *sbsec,
David Howells275bb412008-11-14 10:39:19 +1100397 const struct cred *cred)
Eric Paris08089252006-07-10 04:43:55 -0700398{
David Howells275bb412008-11-14 10:39:19 +1100399 const struct task_security_struct *tsec = cred->security;
Eric Paris08089252006-07-10 04:43:55 -0700400 int rc;
401 rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
402 FILESYSTEM__RELABELFROM, NULL);
403 if (rc)
404 return rc;
405
406 rc = avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM,
407 FILESYSTEM__ASSOCIATE, NULL);
408 return rc;
409}
410
Eric Parisb43e7252012-10-10 14:27:35 -0400411static int selinux_is_sblabel_mnt(struct super_block *sb)
412{
413 struct superblock_security_struct *sbsec = sb->s_security;
414
Mark Salyzynd5f3a5f2015-02-04 11:34:30 -0500415 return sbsec->behavior == SECURITY_FS_USE_XATTR ||
416 sbsec->behavior == SECURITY_FS_USE_TRANS ||
417 sbsec->behavior == SECURITY_FS_USE_TASK ||
J. Bruce Fields9fc2b4b2015-06-04 15:57:25 -0400418 sbsec->behavior == SECURITY_FS_USE_NATIVE ||
Mark Salyzynd5f3a5f2015-02-04 11:34:30 -0500419 /* Special handling. Genfs but also in-core setxattr handler */
420 !strcmp(sb->s_type->name, "sysfs") ||
421 !strcmp(sb->s_type->name, "pstore") ||
422 !strcmp(sb->s_type->name, "debugfs") ||
423 !strcmp(sb->s_type->name, "rootfs");
Eric Parisb43e7252012-10-10 14:27:35 -0400424}
425
Eric Parisc9180a52007-11-30 13:00:35 -0500426static int sb_finish_set_opts(struct super_block *sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700427{
428 struct superblock_security_struct *sbsec = sb->s_security;
429 struct dentry *root = sb->s_root;
David Howellsc6f493d2015-03-17 22:26:22 +0000430 struct inode *root_inode = d_backing_inode(root);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431 int rc = 0;
432
Linus Torvalds1da177e2005-04-16 15:20:36 -0700433 if (sbsec->behavior == SECURITY_FS_USE_XATTR) {
434 /* Make sure that the xattr handler exists and that no
435 error other than -ENODATA is returned by getxattr on
436 the root directory. -ENODATA is ok, as this may be
437 the first boot of the SELinux kernel before we have
438 assigned xattr values to the filesystem. */
Eric Parisc9180a52007-11-30 13:00:35 -0500439 if (!root_inode->i_op->getxattr) {
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800440 printk(KERN_WARNING "SELinux: (dev %s, type %s) has no "
441 "xattr support\n", sb->s_id, sb->s_type->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442 rc = -EOPNOTSUPP;
443 goto out;
444 }
Eric Parisc9180a52007-11-30 13:00:35 -0500445 rc = root_inode->i_op->getxattr(root, XATTR_NAME_SELINUX, NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700446 if (rc < 0 && rc != -ENODATA) {
447 if (rc == -EOPNOTSUPP)
448 printk(KERN_WARNING "SELinux: (dev %s, type "
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800449 "%s) has no security xattr handler\n",
450 sb->s_id, sb->s_type->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451 else
452 printk(KERN_WARNING "SELinux: (dev %s, type "
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800453 "%s) getxattr errno %d\n", sb->s_id,
454 sb->s_type->name, -rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700455 goto out;
456 }
457 }
458
Eric Parisc9180a52007-11-30 13:00:35 -0500459 if (sbsec->behavior > ARRAY_SIZE(labeling_behaviors))
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800460 printk(KERN_ERR "SELinux: initialized (dev %s, type %s), unknown behavior\n",
461 sb->s_id, sb->s_type->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462
Eric Pariseadcabc2012-08-24 15:59:14 -0400463 sbsec->flags |= SE_SBINITIALIZED;
Eric Parisb43e7252012-10-10 14:27:35 -0400464 if (selinux_is_sblabel_mnt(sb))
Eric Paris12f348b2012-10-09 10:56:25 -0400465 sbsec->flags |= SBLABEL_MNT;
David P. Quigleyddd29ec2009-09-09 14:25:37 -0400466
Linus Torvalds1da177e2005-04-16 15:20:36 -0700467 /* Initialize the root inode. */
Eric Parisc9180a52007-11-30 13:00:35 -0500468 rc = inode_doinit_with_dentry(root_inode, root);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469
470 /* Initialize any other inodes associated with the superblock, e.g.
471 inodes created prior to initial policy load or inodes created
472 during get_sb by a pseudo filesystem that directly
473 populates itself. */
474 spin_lock(&sbsec->isec_lock);
475next_inode:
476 if (!list_empty(&sbsec->isec_head)) {
477 struct inode_security_struct *isec =
478 list_entry(sbsec->isec_head.next,
Eric Parisc9180a52007-11-30 13:00:35 -0500479 struct inode_security_struct, list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700480 struct inode *inode = isec->inode;
Stephen Smalley923190d2014-10-06 16:32:52 -0400481 list_del_init(&isec->list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482 spin_unlock(&sbsec->isec_lock);
483 inode = igrab(inode);
484 if (inode) {
Eric Parisc9180a52007-11-30 13:00:35 -0500485 if (!IS_PRIVATE(inode))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700486 inode_doinit(inode);
487 iput(inode);
488 }
489 spin_lock(&sbsec->isec_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490 goto next_inode;
491 }
492 spin_unlock(&sbsec->isec_lock);
493out:
Eric Parisc9180a52007-11-30 13:00:35 -0500494 return rc;
495}
496
497/*
498 * This function should allow an FS to ask what it's mount security
499 * options were so it can use those later for submounts, displaying
500 * mount options, or whatever.
501 */
502static int selinux_get_mnt_opts(const struct super_block *sb,
Eric Parise0007522008-03-05 10:31:54 -0500503 struct security_mnt_opts *opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500504{
505 int rc = 0, i;
506 struct superblock_security_struct *sbsec = sb->s_security;
507 char *context = NULL;
508 u32 len;
509 char tmp;
510
Eric Parise0007522008-03-05 10:31:54 -0500511 security_init_mnt_opts(opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500512
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500513 if (!(sbsec->flags & SE_SBINITIALIZED))
Eric Parisc9180a52007-11-30 13:00:35 -0500514 return -EINVAL;
515
516 if (!ss_initialized)
517 return -EINVAL;
518
Eric Parisaf8e50c2012-08-24 15:59:00 -0400519 /* make sure we always check enough bits to cover the mask */
520 BUILD_BUG_ON(SE_MNTMASK >= (1 << NUM_SEL_MNT_OPTS));
521
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500522 tmp = sbsec->flags & SE_MNTMASK;
Eric Parisc9180a52007-11-30 13:00:35 -0500523 /* count the number of mount options for this sb */
Eric Parisaf8e50c2012-08-24 15:59:00 -0400524 for (i = 0; i < NUM_SEL_MNT_OPTS; i++) {
Eric Parisc9180a52007-11-30 13:00:35 -0500525 if (tmp & 0x01)
Eric Parise0007522008-03-05 10:31:54 -0500526 opts->num_mnt_opts++;
Eric Parisc9180a52007-11-30 13:00:35 -0500527 tmp >>= 1;
528 }
David P. Quigley11689d42009-01-16 09:22:03 -0500529 /* Check if the Label support flag is set */
Eric Paris0b4bdb32013-08-28 13:32:42 -0400530 if (sbsec->flags & SBLABEL_MNT)
David P. Quigley11689d42009-01-16 09:22:03 -0500531 opts->num_mnt_opts++;
Eric Parisc9180a52007-11-30 13:00:35 -0500532
Eric Parise0007522008-03-05 10:31:54 -0500533 opts->mnt_opts = kcalloc(opts->num_mnt_opts, sizeof(char *), GFP_ATOMIC);
534 if (!opts->mnt_opts) {
Eric Parisc9180a52007-11-30 13:00:35 -0500535 rc = -ENOMEM;
536 goto out_free;
537 }
538
Eric Parise0007522008-03-05 10:31:54 -0500539 opts->mnt_opts_flags = kcalloc(opts->num_mnt_opts, sizeof(int), GFP_ATOMIC);
540 if (!opts->mnt_opts_flags) {
Eric Parisc9180a52007-11-30 13:00:35 -0500541 rc = -ENOMEM;
542 goto out_free;
543 }
544
545 i = 0;
546 if (sbsec->flags & FSCONTEXT_MNT) {
547 rc = security_sid_to_context(sbsec->sid, &context, &len);
548 if (rc)
549 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500550 opts->mnt_opts[i] = context;
551 opts->mnt_opts_flags[i++] = FSCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500552 }
553 if (sbsec->flags & CONTEXT_MNT) {
554 rc = security_sid_to_context(sbsec->mntpoint_sid, &context, &len);
555 if (rc)
556 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500557 opts->mnt_opts[i] = context;
558 opts->mnt_opts_flags[i++] = CONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500559 }
560 if (sbsec->flags & DEFCONTEXT_MNT) {
561 rc = security_sid_to_context(sbsec->def_sid, &context, &len);
562 if (rc)
563 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500564 opts->mnt_opts[i] = context;
565 opts->mnt_opts_flags[i++] = DEFCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500566 }
567 if (sbsec->flags & ROOTCONTEXT_MNT) {
David Howellsc6f493d2015-03-17 22:26:22 +0000568 struct inode *root = d_backing_inode(sbsec->sb->s_root);
Eric Parisc9180a52007-11-30 13:00:35 -0500569 struct inode_security_struct *isec = root->i_security;
570
571 rc = security_sid_to_context(isec->sid, &context, &len);
572 if (rc)
573 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500574 opts->mnt_opts[i] = context;
575 opts->mnt_opts_flags[i++] = ROOTCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500576 }
Eric Paris12f348b2012-10-09 10:56:25 -0400577 if (sbsec->flags & SBLABEL_MNT) {
David P. Quigley11689d42009-01-16 09:22:03 -0500578 opts->mnt_opts[i] = NULL;
Eric Paris12f348b2012-10-09 10:56:25 -0400579 opts->mnt_opts_flags[i++] = SBLABEL_MNT;
David P. Quigley11689d42009-01-16 09:22:03 -0500580 }
Eric Parisc9180a52007-11-30 13:00:35 -0500581
Eric Parise0007522008-03-05 10:31:54 -0500582 BUG_ON(i != opts->num_mnt_opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500583
584 return 0;
585
586out_free:
Eric Parise0007522008-03-05 10:31:54 -0500587 security_free_mnt_opts(opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500588 return rc;
589}
590
591static int bad_option(struct superblock_security_struct *sbsec, char flag,
592 u32 old_sid, u32 new_sid)
593{
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500594 char mnt_flags = sbsec->flags & SE_MNTMASK;
595
Eric Parisc9180a52007-11-30 13:00:35 -0500596 /* check if the old mount command had the same options */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500597 if (sbsec->flags & SE_SBINITIALIZED)
Eric Parisc9180a52007-11-30 13:00:35 -0500598 if (!(sbsec->flags & flag) ||
599 (old_sid != new_sid))
600 return 1;
601
602 /* check if we were passed the same options twice,
603 * aka someone passed context=a,context=b
604 */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500605 if (!(sbsec->flags & SE_SBINITIALIZED))
606 if (mnt_flags & flag)
Eric Parisc9180a52007-11-30 13:00:35 -0500607 return 1;
608 return 0;
609}
Eric Parise0007522008-03-05 10:31:54 -0500610
Eric Parisc9180a52007-11-30 13:00:35 -0500611/*
612 * Allow filesystems with binary mount data to explicitly set mount point
613 * labeling information.
614 */
Eric Parise0007522008-03-05 10:31:54 -0500615static int selinux_set_mnt_opts(struct super_block *sb,
David Quigley649f6e72013-05-22 12:50:36 -0400616 struct security_mnt_opts *opts,
617 unsigned long kern_flags,
618 unsigned long *set_kern_flags)
Eric Parisc9180a52007-11-30 13:00:35 -0500619{
David Howells275bb412008-11-14 10:39:19 +1100620 const struct cred *cred = current_cred();
Eric Parisc9180a52007-11-30 13:00:35 -0500621 int rc = 0, i;
Eric Parisc9180a52007-11-30 13:00:35 -0500622 struct superblock_security_struct *sbsec = sb->s_security;
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800623 const char *name = sb->s_type->name;
David Howellsc6f493d2015-03-17 22:26:22 +0000624 struct inode *inode = d_backing_inode(sbsec->sb->s_root);
James Morris089be432008-07-15 18:32:49 +1000625 struct inode_security_struct *root_isec = inode->i_security;
Eric Parisc9180a52007-11-30 13:00:35 -0500626 u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0;
627 u32 defcontext_sid = 0;
Eric Parise0007522008-03-05 10:31:54 -0500628 char **mount_options = opts->mnt_opts;
629 int *flags = opts->mnt_opts_flags;
630 int num_opts = opts->num_mnt_opts;
Eric Parisc9180a52007-11-30 13:00:35 -0500631
632 mutex_lock(&sbsec->lock);
633
634 if (!ss_initialized) {
635 if (!num_opts) {
636 /* Defer initialization until selinux_complete_init,
637 after the initial policy is loaded and the security
638 server is ready to handle calls. */
Eric Parisc9180a52007-11-30 13:00:35 -0500639 goto out;
640 }
641 rc = -EINVAL;
Eric Paris744ba352008-04-17 11:52:44 -0400642 printk(KERN_WARNING "SELinux: Unable to set superblock options "
643 "before the security server is initialized\n");
Eric Parisc9180a52007-11-30 13:00:35 -0500644 goto out;
645 }
David Quigley649f6e72013-05-22 12:50:36 -0400646 if (kern_flags && !set_kern_flags) {
647 /* Specifying internal flags without providing a place to
648 * place the results is not allowed */
649 rc = -EINVAL;
650 goto out;
651 }
Eric Parisc9180a52007-11-30 13:00:35 -0500652
653 /*
Eric Parise0007522008-03-05 10:31:54 -0500654 * Binary mount data FS will come through this function twice. Once
655 * from an explicit call and once from the generic calls from the vfs.
656 * Since the generic VFS calls will not contain any security mount data
657 * we need to skip the double mount verification.
658 *
659 * This does open a hole in which we will not notice if the first
660 * mount using this sb set explict options and a second mount using
661 * this sb does not set any security options. (The first options
662 * will be used for both mounts)
663 */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500664 if ((sbsec->flags & SE_SBINITIALIZED) && (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)
Eric Parise0007522008-03-05 10:31:54 -0500665 && (num_opts == 0))
Eric Parisf5269712008-05-14 11:27:45 -0400666 goto out;
Eric Parise0007522008-03-05 10:31:54 -0500667
668 /*
Eric Parisc9180a52007-11-30 13:00:35 -0500669 * parse the mount options, check if they are valid sids.
670 * also check if someone is trying to mount the same sb more
671 * than once with different security options.
672 */
673 for (i = 0; i < num_opts; i++) {
674 u32 sid;
David P. Quigley11689d42009-01-16 09:22:03 -0500675
Eric Paris12f348b2012-10-09 10:56:25 -0400676 if (flags[i] == SBLABEL_MNT)
David P. Quigley11689d42009-01-16 09:22:03 -0500677 continue;
Rasmus Villemoes44be2f62015-10-21 17:44:25 -0400678 rc = security_context_str_to_sid(mount_options[i], &sid, GFP_KERNEL);
Eric Parisc9180a52007-11-30 13:00:35 -0500679 if (rc) {
Rasmus Villemoes44be2f62015-10-21 17:44:25 -0400680 printk(KERN_WARNING "SELinux: security_context_str_to_sid"
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800681 "(%s) failed for (dev %s, type %s) errno=%d\n",
682 mount_options[i], sb->s_id, name, rc);
Eric Parisc9180a52007-11-30 13:00:35 -0500683 goto out;
684 }
685 switch (flags[i]) {
686 case FSCONTEXT_MNT:
687 fscontext_sid = sid;
688
689 if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid,
690 fscontext_sid))
691 goto out_double_mount;
692
693 sbsec->flags |= FSCONTEXT_MNT;
694 break;
695 case CONTEXT_MNT:
696 context_sid = sid;
697
698 if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid,
699 context_sid))
700 goto out_double_mount;
701
702 sbsec->flags |= CONTEXT_MNT;
703 break;
704 case ROOTCONTEXT_MNT:
705 rootcontext_sid = sid;
706
707 if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid,
708 rootcontext_sid))
709 goto out_double_mount;
710
711 sbsec->flags |= ROOTCONTEXT_MNT;
712
713 break;
714 case DEFCONTEXT_MNT:
715 defcontext_sid = sid;
716
717 if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid,
718 defcontext_sid))
719 goto out_double_mount;
720
721 sbsec->flags |= DEFCONTEXT_MNT;
722
723 break;
724 default:
725 rc = -EINVAL;
726 goto out;
727 }
728 }
729
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500730 if (sbsec->flags & SE_SBINITIALIZED) {
Eric Parisc9180a52007-11-30 13:00:35 -0500731 /* previously mounted with options, but not on this attempt? */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500732 if ((sbsec->flags & SE_MNTMASK) && !num_opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500733 goto out_double_mount;
734 rc = 0;
735 goto out;
736 }
737
James Morris089be432008-07-15 18:32:49 +1000738 if (strcmp(sb->s_type->name, "proc") == 0)
Stephen Smalley134509d2015-06-04 16:22:17 -0400739 sbsec->flags |= SE_SBPROC | SE_SBGENFS;
740
Stephen Smalley8e014722015-06-04 16:22:17 -0400741 if (!strcmp(sb->s_type->name, "debugfs") ||
742 !strcmp(sb->s_type->name, "sysfs") ||
743 !strcmp(sb->s_type->name, "pstore"))
Stephen Smalley134509d2015-06-04 16:22:17 -0400744 sbsec->flags |= SE_SBGENFS;
Eric Parisc9180a52007-11-30 13:00:35 -0500745
David Quigleyeb9ae682013-05-22 12:50:37 -0400746 if (!sbsec->behavior) {
747 /*
748 * Determine the labeling behavior to use for this
749 * filesystem type.
750 */
Paul Moore98f700f2013-09-18 13:52:20 -0400751 rc = security_fs_use(sb);
David Quigleyeb9ae682013-05-22 12:50:37 -0400752 if (rc) {
753 printk(KERN_WARNING
754 "%s: security_fs_use(%s) returned %d\n",
755 __func__, sb->s_type->name, rc);
756 goto out;
757 }
Eric Parisc9180a52007-11-30 13:00:35 -0500758 }
Eric Parisc9180a52007-11-30 13:00:35 -0500759 /* sets the context of the superblock for the fs being mounted. */
760 if (fscontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100761 rc = may_context_mount_sb_relabel(fscontext_sid, sbsec, cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500762 if (rc)
763 goto out;
764
765 sbsec->sid = fscontext_sid;
766 }
767
768 /*
769 * Switch to using mount point labeling behavior.
770 * sets the label used on all file below the mountpoint, and will set
771 * the superblock context if not already set.
772 */
David Quigleyeb9ae682013-05-22 12:50:37 -0400773 if (kern_flags & SECURITY_LSM_NATIVE_LABELS && !context_sid) {
774 sbsec->behavior = SECURITY_FS_USE_NATIVE;
775 *set_kern_flags |= SECURITY_LSM_NATIVE_LABELS;
776 }
777
Eric Parisc9180a52007-11-30 13:00:35 -0500778 if (context_sid) {
779 if (!fscontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100780 rc = may_context_mount_sb_relabel(context_sid, sbsec,
781 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500782 if (rc)
783 goto out;
784 sbsec->sid = context_sid;
785 } else {
David Howells275bb412008-11-14 10:39:19 +1100786 rc = may_context_mount_inode_relabel(context_sid, sbsec,
787 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500788 if (rc)
789 goto out;
790 }
791 if (!rootcontext_sid)
792 rootcontext_sid = context_sid;
793
794 sbsec->mntpoint_sid = context_sid;
795 sbsec->behavior = SECURITY_FS_USE_MNTPOINT;
796 }
797
798 if (rootcontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100799 rc = may_context_mount_inode_relabel(rootcontext_sid, sbsec,
800 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500801 if (rc)
802 goto out;
803
804 root_isec->sid = rootcontext_sid;
805 root_isec->initialized = 1;
806 }
807
808 if (defcontext_sid) {
David Quigleyeb9ae682013-05-22 12:50:37 -0400809 if (sbsec->behavior != SECURITY_FS_USE_XATTR &&
810 sbsec->behavior != SECURITY_FS_USE_NATIVE) {
Eric Parisc9180a52007-11-30 13:00:35 -0500811 rc = -EINVAL;
812 printk(KERN_WARNING "SELinux: defcontext option is "
813 "invalid for this filesystem type\n");
814 goto out;
815 }
816
817 if (defcontext_sid != sbsec->def_sid) {
818 rc = may_context_mount_inode_relabel(defcontext_sid,
David Howells275bb412008-11-14 10:39:19 +1100819 sbsec, cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500820 if (rc)
821 goto out;
822 }
823
824 sbsec->def_sid = defcontext_sid;
825 }
826
827 rc = sb_finish_set_opts(sb);
828out:
Eric Parisbc7e9822006-09-25 23:32:02 -0700829 mutex_unlock(&sbsec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700830 return rc;
Eric Parisc9180a52007-11-30 13:00:35 -0500831out_double_mount:
832 rc = -EINVAL;
833 printk(KERN_WARNING "SELinux: mount invalid. Same superblock, different "
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800834 "security settings for (dev %s, type %s)\n", sb->s_id, name);
Eric Parisc9180a52007-11-30 13:00:35 -0500835 goto out;
836}
837
Jeff Layton094f7b62013-04-01 08:14:24 -0400838static int selinux_cmp_sb_context(const struct super_block *oldsb,
839 const struct super_block *newsb)
840{
841 struct superblock_security_struct *old = oldsb->s_security;
842 struct superblock_security_struct *new = newsb->s_security;
843 char oldflags = old->flags & SE_MNTMASK;
844 char newflags = new->flags & SE_MNTMASK;
845
846 if (oldflags != newflags)
847 goto mismatch;
848 if ((oldflags & FSCONTEXT_MNT) && old->sid != new->sid)
849 goto mismatch;
850 if ((oldflags & CONTEXT_MNT) && old->mntpoint_sid != new->mntpoint_sid)
851 goto mismatch;
852 if ((oldflags & DEFCONTEXT_MNT) && old->def_sid != new->def_sid)
853 goto mismatch;
854 if (oldflags & ROOTCONTEXT_MNT) {
David Howellsc6f493d2015-03-17 22:26:22 +0000855 struct inode_security_struct *oldroot = d_backing_inode(oldsb->s_root)->i_security;
856 struct inode_security_struct *newroot = d_backing_inode(newsb->s_root)->i_security;
Jeff Layton094f7b62013-04-01 08:14:24 -0400857 if (oldroot->sid != newroot->sid)
858 goto mismatch;
859 }
860 return 0;
861mismatch:
862 printk(KERN_WARNING "SELinux: mount invalid. Same superblock, "
863 "different security settings for (dev %s, "
864 "type %s)\n", newsb->s_id, newsb->s_type->name);
865 return -EBUSY;
866}
867
868static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
Eric Parisc9180a52007-11-30 13:00:35 -0500869 struct super_block *newsb)
870{
871 const struct superblock_security_struct *oldsbsec = oldsb->s_security;
872 struct superblock_security_struct *newsbsec = newsb->s_security;
873
874 int set_fscontext = (oldsbsec->flags & FSCONTEXT_MNT);
875 int set_context = (oldsbsec->flags & CONTEXT_MNT);
876 int set_rootcontext = (oldsbsec->flags & ROOTCONTEXT_MNT);
877
Eric Paris0f5e6422008-04-21 16:24:11 -0400878 /*
879 * if the parent was able to be mounted it clearly had no special lsm
Al Viroe8c26252010-03-23 06:36:54 -0400880 * mount options. thus we can safely deal with this superblock later
Eric Paris0f5e6422008-04-21 16:24:11 -0400881 */
Al Viroe8c26252010-03-23 06:36:54 -0400882 if (!ss_initialized)
Jeff Layton094f7b62013-04-01 08:14:24 -0400883 return 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500884
Eric Parisc9180a52007-11-30 13:00:35 -0500885 /* how can we clone if the old one wasn't set up?? */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500886 BUG_ON(!(oldsbsec->flags & SE_SBINITIALIZED));
Eric Parisc9180a52007-11-30 13:00:35 -0500887
Jeff Layton094f7b62013-04-01 08:14:24 -0400888 /* if fs is reusing a sb, make sure that the contexts match */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500889 if (newsbsec->flags & SE_SBINITIALIZED)
Jeff Layton094f7b62013-04-01 08:14:24 -0400890 return selinux_cmp_sb_context(oldsb, newsb);
Eric Paris5a552612008-04-09 14:08:35 -0400891
Eric Parisc9180a52007-11-30 13:00:35 -0500892 mutex_lock(&newsbsec->lock);
893
894 newsbsec->flags = oldsbsec->flags;
895
896 newsbsec->sid = oldsbsec->sid;
897 newsbsec->def_sid = oldsbsec->def_sid;
898 newsbsec->behavior = oldsbsec->behavior;
899
900 if (set_context) {
901 u32 sid = oldsbsec->mntpoint_sid;
902
903 if (!set_fscontext)
904 newsbsec->sid = sid;
905 if (!set_rootcontext) {
David Howellsc6f493d2015-03-17 22:26:22 +0000906 struct inode *newinode = d_backing_inode(newsb->s_root);
Eric Parisc9180a52007-11-30 13:00:35 -0500907 struct inode_security_struct *newisec = newinode->i_security;
908 newisec->sid = sid;
909 }
910 newsbsec->mntpoint_sid = sid;
911 }
912 if (set_rootcontext) {
David Howellsc6f493d2015-03-17 22:26:22 +0000913 const struct inode *oldinode = d_backing_inode(oldsb->s_root);
Eric Parisc9180a52007-11-30 13:00:35 -0500914 const struct inode_security_struct *oldisec = oldinode->i_security;
David Howellsc6f493d2015-03-17 22:26:22 +0000915 struct inode *newinode = d_backing_inode(newsb->s_root);
Eric Parisc9180a52007-11-30 13:00:35 -0500916 struct inode_security_struct *newisec = newinode->i_security;
917
918 newisec->sid = oldisec->sid;
919 }
920
921 sb_finish_set_opts(newsb);
922 mutex_unlock(&newsbsec->lock);
Jeff Layton094f7b62013-04-01 08:14:24 -0400923 return 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500924}
925
Adrian Bunk2e1479d2008-03-17 22:29:23 +0200926static int selinux_parse_opts_str(char *options,
927 struct security_mnt_opts *opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500928{
Eric Parise0007522008-03-05 10:31:54 -0500929 char *p;
Eric Parisc9180a52007-11-30 13:00:35 -0500930 char *context = NULL, *defcontext = NULL;
931 char *fscontext = NULL, *rootcontext = NULL;
Eric Parise0007522008-03-05 10:31:54 -0500932 int rc, num_mnt_opts = 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500933
Eric Parise0007522008-03-05 10:31:54 -0500934 opts->num_mnt_opts = 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500935
936 /* Standard string-based options. */
937 while ((p = strsep(&options, "|")) != NULL) {
938 int token;
939 substring_t args[MAX_OPT_ARGS];
940
941 if (!*p)
942 continue;
943
944 token = match_token(p, tokens, args);
945
946 switch (token) {
947 case Opt_context:
948 if (context || defcontext) {
949 rc = -EINVAL;
950 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
951 goto out_err;
952 }
953 context = match_strdup(&args[0]);
954 if (!context) {
955 rc = -ENOMEM;
956 goto out_err;
957 }
958 break;
959
960 case Opt_fscontext:
961 if (fscontext) {
962 rc = -EINVAL;
963 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
964 goto out_err;
965 }
966 fscontext = match_strdup(&args[0]);
967 if (!fscontext) {
968 rc = -ENOMEM;
969 goto out_err;
970 }
971 break;
972
973 case Opt_rootcontext:
974 if (rootcontext) {
975 rc = -EINVAL;
976 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
977 goto out_err;
978 }
979 rootcontext = match_strdup(&args[0]);
980 if (!rootcontext) {
981 rc = -ENOMEM;
982 goto out_err;
983 }
984 break;
985
986 case Opt_defcontext:
987 if (context || defcontext) {
988 rc = -EINVAL;
989 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
990 goto out_err;
991 }
992 defcontext = match_strdup(&args[0]);
993 if (!defcontext) {
994 rc = -ENOMEM;
995 goto out_err;
996 }
997 break;
David P. Quigley11689d42009-01-16 09:22:03 -0500998 case Opt_labelsupport:
999 break;
Eric Parisc9180a52007-11-30 13:00:35 -05001000 default:
1001 rc = -EINVAL;
1002 printk(KERN_WARNING "SELinux: unknown mount option\n");
1003 goto out_err;
1004
1005 }
1006 }
1007
Eric Parise0007522008-03-05 10:31:54 -05001008 rc = -ENOMEM;
1009 opts->mnt_opts = kcalloc(NUM_SEL_MNT_OPTS, sizeof(char *), GFP_ATOMIC);
1010 if (!opts->mnt_opts)
1011 goto out_err;
1012
1013 opts->mnt_opts_flags = kcalloc(NUM_SEL_MNT_OPTS, sizeof(int), GFP_ATOMIC);
1014 if (!opts->mnt_opts_flags) {
1015 kfree(opts->mnt_opts);
1016 goto out_err;
Eric Parisc9180a52007-11-30 13:00:35 -05001017 }
1018
Eric Parise0007522008-03-05 10:31:54 -05001019 if (fscontext) {
1020 opts->mnt_opts[num_mnt_opts] = fscontext;
1021 opts->mnt_opts_flags[num_mnt_opts++] = FSCONTEXT_MNT;
1022 }
1023 if (context) {
1024 opts->mnt_opts[num_mnt_opts] = context;
1025 opts->mnt_opts_flags[num_mnt_opts++] = CONTEXT_MNT;
1026 }
1027 if (rootcontext) {
1028 opts->mnt_opts[num_mnt_opts] = rootcontext;
1029 opts->mnt_opts_flags[num_mnt_opts++] = ROOTCONTEXT_MNT;
1030 }
1031 if (defcontext) {
1032 opts->mnt_opts[num_mnt_opts] = defcontext;
1033 opts->mnt_opts_flags[num_mnt_opts++] = DEFCONTEXT_MNT;
1034 }
1035
1036 opts->num_mnt_opts = num_mnt_opts;
1037 return 0;
1038
Eric Parisc9180a52007-11-30 13:00:35 -05001039out_err:
1040 kfree(context);
1041 kfree(defcontext);
1042 kfree(fscontext);
1043 kfree(rootcontext);
1044 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001045}
Eric Parise0007522008-03-05 10:31:54 -05001046/*
1047 * string mount options parsing and call set the sbsec
1048 */
1049static int superblock_doinit(struct super_block *sb, void *data)
1050{
1051 int rc = 0;
1052 char *options = data;
1053 struct security_mnt_opts opts;
1054
1055 security_init_mnt_opts(&opts);
1056
1057 if (!data)
1058 goto out;
1059
1060 BUG_ON(sb->s_type->fs_flags & FS_BINARY_MOUNTDATA);
1061
1062 rc = selinux_parse_opts_str(options, &opts);
1063 if (rc)
1064 goto out_err;
1065
1066out:
David Quigley649f6e72013-05-22 12:50:36 -04001067 rc = selinux_set_mnt_opts(sb, &opts, 0, NULL);
Eric Parise0007522008-03-05 10:31:54 -05001068
1069out_err:
1070 security_free_mnt_opts(&opts);
1071 return rc;
1072}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001073
Adrian Bunk3583a712008-07-22 20:21:23 +03001074static void selinux_write_opts(struct seq_file *m,
1075 struct security_mnt_opts *opts)
Eric Paris2069f452008-07-04 09:47:13 +10001076{
1077 int i;
1078 char *prefix;
1079
1080 for (i = 0; i < opts->num_mnt_opts; i++) {
David P. Quigley11689d42009-01-16 09:22:03 -05001081 char *has_comma;
1082
1083 if (opts->mnt_opts[i])
1084 has_comma = strchr(opts->mnt_opts[i], ',');
1085 else
1086 has_comma = NULL;
Eric Paris2069f452008-07-04 09:47:13 +10001087
1088 switch (opts->mnt_opts_flags[i]) {
1089 case CONTEXT_MNT:
1090 prefix = CONTEXT_STR;
1091 break;
1092 case FSCONTEXT_MNT:
1093 prefix = FSCONTEXT_STR;
1094 break;
1095 case ROOTCONTEXT_MNT:
1096 prefix = ROOTCONTEXT_STR;
1097 break;
1098 case DEFCONTEXT_MNT:
1099 prefix = DEFCONTEXT_STR;
1100 break;
Eric Paris12f348b2012-10-09 10:56:25 -04001101 case SBLABEL_MNT:
David P. Quigley11689d42009-01-16 09:22:03 -05001102 seq_putc(m, ',');
1103 seq_puts(m, LABELSUPP_STR);
1104 continue;
Eric Paris2069f452008-07-04 09:47:13 +10001105 default:
1106 BUG();
Eric Parisa35c6c82011-04-20 10:21:28 -04001107 return;
Eric Paris2069f452008-07-04 09:47:13 +10001108 };
1109 /* we need a comma before each option */
1110 seq_putc(m, ',');
1111 seq_puts(m, prefix);
1112 if (has_comma)
1113 seq_putc(m, '\"');
Kees Cooka068acf2015-09-04 15:44:57 -07001114 seq_escape(m, opts->mnt_opts[i], "\"\n\\");
Eric Paris2069f452008-07-04 09:47:13 +10001115 if (has_comma)
1116 seq_putc(m, '\"');
1117 }
1118}
1119
1120static int selinux_sb_show_options(struct seq_file *m, struct super_block *sb)
1121{
1122 struct security_mnt_opts opts;
1123 int rc;
1124
1125 rc = selinux_get_mnt_opts(sb, &opts);
Eric Paris383795c2008-07-29 17:07:26 -04001126 if (rc) {
1127 /* before policy load we may get EINVAL, don't show anything */
1128 if (rc == -EINVAL)
1129 rc = 0;
Eric Paris2069f452008-07-04 09:47:13 +10001130 return rc;
Eric Paris383795c2008-07-29 17:07:26 -04001131 }
Eric Paris2069f452008-07-04 09:47:13 +10001132
1133 selinux_write_opts(m, &opts);
1134
1135 security_free_mnt_opts(&opts);
1136
1137 return rc;
1138}
1139
Linus Torvalds1da177e2005-04-16 15:20:36 -07001140static inline u16 inode_mode_to_security_class(umode_t mode)
1141{
1142 switch (mode & S_IFMT) {
1143 case S_IFSOCK:
1144 return SECCLASS_SOCK_FILE;
1145 case S_IFLNK:
1146 return SECCLASS_LNK_FILE;
1147 case S_IFREG:
1148 return SECCLASS_FILE;
1149 case S_IFBLK:
1150 return SECCLASS_BLK_FILE;
1151 case S_IFDIR:
1152 return SECCLASS_DIR;
1153 case S_IFCHR:
1154 return SECCLASS_CHR_FILE;
1155 case S_IFIFO:
1156 return SECCLASS_FIFO_FILE;
1157
1158 }
1159
1160 return SECCLASS_FILE;
1161}
1162
James Morris13402582005-09-30 14:24:34 -04001163static inline int default_protocol_stream(int protocol)
1164{
1165 return (protocol == IPPROTO_IP || protocol == IPPROTO_TCP);
1166}
1167
1168static inline int default_protocol_dgram(int protocol)
1169{
1170 return (protocol == IPPROTO_IP || protocol == IPPROTO_UDP);
1171}
1172
Linus Torvalds1da177e2005-04-16 15:20:36 -07001173static inline u16 socket_type_to_security_class(int family, int type, int protocol)
1174{
1175 switch (family) {
1176 case PF_UNIX:
1177 switch (type) {
1178 case SOCK_STREAM:
1179 case SOCK_SEQPACKET:
1180 return SECCLASS_UNIX_STREAM_SOCKET;
1181 case SOCK_DGRAM:
1182 return SECCLASS_UNIX_DGRAM_SOCKET;
1183 }
1184 break;
1185 case PF_INET:
1186 case PF_INET6:
1187 switch (type) {
1188 case SOCK_STREAM:
James Morris13402582005-09-30 14:24:34 -04001189 if (default_protocol_stream(protocol))
1190 return SECCLASS_TCP_SOCKET;
1191 else
1192 return SECCLASS_RAWIP_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001193 case SOCK_DGRAM:
James Morris13402582005-09-30 14:24:34 -04001194 if (default_protocol_dgram(protocol))
1195 return SECCLASS_UDP_SOCKET;
1196 else
1197 return SECCLASS_RAWIP_SOCKET;
James Morris2ee92d42006-11-13 16:09:01 -08001198 case SOCK_DCCP:
1199 return SECCLASS_DCCP_SOCKET;
James Morris13402582005-09-30 14:24:34 -04001200 default:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001201 return SECCLASS_RAWIP_SOCKET;
1202 }
1203 break;
1204 case PF_NETLINK:
1205 switch (protocol) {
1206 case NETLINK_ROUTE:
1207 return SECCLASS_NETLINK_ROUTE_SOCKET;
Pavel Emelyanov7f1fb602011-12-06 07:56:43 +00001208 case NETLINK_SOCK_DIAG:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001209 return SECCLASS_NETLINK_TCPDIAG_SOCKET;
1210 case NETLINK_NFLOG:
1211 return SECCLASS_NETLINK_NFLOG_SOCKET;
1212 case NETLINK_XFRM:
1213 return SECCLASS_NETLINK_XFRM_SOCKET;
1214 case NETLINK_SELINUX:
1215 return SECCLASS_NETLINK_SELINUX_SOCKET;
Stephen Smalley6c6d2e92015-06-04 16:22:16 -04001216 case NETLINK_ISCSI:
1217 return SECCLASS_NETLINK_ISCSI_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001218 case NETLINK_AUDIT:
1219 return SECCLASS_NETLINK_AUDIT_SOCKET;
Stephen Smalley6c6d2e92015-06-04 16:22:16 -04001220 case NETLINK_FIB_LOOKUP:
1221 return SECCLASS_NETLINK_FIB_LOOKUP_SOCKET;
1222 case NETLINK_CONNECTOR:
1223 return SECCLASS_NETLINK_CONNECTOR_SOCKET;
1224 case NETLINK_NETFILTER:
1225 return SECCLASS_NETLINK_NETFILTER_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001226 case NETLINK_DNRTMSG:
1227 return SECCLASS_NETLINK_DNRT_SOCKET;
James Morris0c9b7942005-04-16 15:24:13 -07001228 case NETLINK_KOBJECT_UEVENT:
1229 return SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET;
Stephen Smalley6c6d2e92015-06-04 16:22:16 -04001230 case NETLINK_GENERIC:
1231 return SECCLASS_NETLINK_GENERIC_SOCKET;
1232 case NETLINK_SCSITRANSPORT:
1233 return SECCLASS_NETLINK_SCSITRANSPORT_SOCKET;
1234 case NETLINK_RDMA:
1235 return SECCLASS_NETLINK_RDMA_SOCKET;
1236 case NETLINK_CRYPTO:
1237 return SECCLASS_NETLINK_CRYPTO_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001238 default:
1239 return SECCLASS_NETLINK_SOCKET;
1240 }
1241 case PF_PACKET:
1242 return SECCLASS_PACKET_SOCKET;
1243 case PF_KEY:
1244 return SECCLASS_KEY_SOCKET;
Christopher J. PeBenito3e3ff152006-06-09 00:25:03 -07001245 case PF_APPLETALK:
1246 return SECCLASS_APPLETALK_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001247 }
1248
1249 return SECCLASS_SOCKET;
1250}
1251
Stephen Smalley134509d2015-06-04 16:22:17 -04001252static int selinux_genfs_get_sid(struct dentry *dentry,
1253 u16 tclass,
1254 u16 flags,
1255 u32 *sid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001256{
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001257 int rc;
Stephen Smalley134509d2015-06-04 16:22:17 -04001258 struct super_block *sb = dentry->d_inode->i_sb;
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001259 char *buffer, *path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001260
Eric Paris828dfe12008-04-17 13:17:49 -04001261 buffer = (char *)__get_free_page(GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001262 if (!buffer)
1263 return -ENOMEM;
1264
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001265 path = dentry_path_raw(dentry, buffer, PAGE_SIZE);
1266 if (IS_ERR(path))
1267 rc = PTR_ERR(path);
1268 else {
Stephen Smalley134509d2015-06-04 16:22:17 -04001269 if (flags & SE_SBPROC) {
1270 /* each process gets a /proc/PID/ entry. Strip off the
1271 * PID part to get a valid selinux labeling.
1272 * e.g. /proc/1/net/rpc/nfs -> /net/rpc/nfs */
1273 while (path[1] >= '0' && path[1] <= '9') {
1274 path[1] = '/';
1275 path++;
1276 }
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001277 }
Stephen Smalley134509d2015-06-04 16:22:17 -04001278 rc = security_genfs_sid(sb->s_type->name, path, tclass, sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001279 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001280 free_page((unsigned long)buffer);
1281 return rc;
1282}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001283
1284/* The inode's security attributes must be initialized before first use. */
1285static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry)
1286{
1287 struct superblock_security_struct *sbsec = NULL;
1288 struct inode_security_struct *isec = inode->i_security;
1289 u32 sid;
1290 struct dentry *dentry;
1291#define INITCONTEXTLEN 255
1292 char *context = NULL;
1293 unsigned len = 0;
1294 int rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001295
1296 if (isec->initialized)
1297 goto out;
1298
Eric Paris23970742006-09-25 23:32:01 -07001299 mutex_lock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001300 if (isec->initialized)
Eric Paris23970742006-09-25 23:32:01 -07001301 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001302
1303 sbsec = inode->i_sb->s_security;
David P. Quigley0d90a7e2009-01-16 09:22:02 -05001304 if (!(sbsec->flags & SE_SBINITIALIZED)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001305 /* Defer initialization until selinux_complete_init,
1306 after the initial policy is loaded and the security
1307 server is ready to handle calls. */
1308 spin_lock(&sbsec->isec_lock);
1309 if (list_empty(&isec->list))
1310 list_add(&isec->list, &sbsec->isec_head);
1311 spin_unlock(&sbsec->isec_lock);
Eric Paris23970742006-09-25 23:32:01 -07001312 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001313 }
1314
1315 switch (sbsec->behavior) {
David Quigleyeb9ae682013-05-22 12:50:37 -04001316 case SECURITY_FS_USE_NATIVE:
1317 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001318 case SECURITY_FS_USE_XATTR:
1319 if (!inode->i_op->getxattr) {
1320 isec->sid = sbsec->def_sid;
1321 break;
1322 }
1323
1324 /* Need a dentry, since the xattr API requires one.
1325 Life would be simpler if we could just pass the inode. */
1326 if (opt_dentry) {
1327 /* Called from d_instantiate or d_splice_alias. */
1328 dentry = dget(opt_dentry);
1329 } else {
1330 /* Called from selinux_complete_init, try to find a dentry. */
1331 dentry = d_find_alias(inode);
1332 }
1333 if (!dentry) {
Eric Parisdf7f54c2009-03-09 14:35:58 -04001334 /*
1335 * this is can be hit on boot when a file is accessed
1336 * before the policy is loaded. When we load policy we
1337 * may find inodes that have no dentry on the
1338 * sbsec->isec_head list. No reason to complain as these
1339 * will get fixed up the next time we go through
1340 * inode_doinit with a dentry, before these inodes could
1341 * be used again by userspace.
1342 */
Eric Paris23970742006-09-25 23:32:01 -07001343 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001344 }
1345
1346 len = INITCONTEXTLEN;
Eric Paris4cb912f2009-02-12 14:50:05 -05001347 context = kmalloc(len+1, GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001348 if (!context) {
1349 rc = -ENOMEM;
1350 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001351 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001352 }
Eric Paris4cb912f2009-02-12 14:50:05 -05001353 context[len] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001354 rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX,
1355 context, len);
1356 if (rc == -ERANGE) {
James Morris314dabb2009-08-10 22:00:13 +10001357 kfree(context);
1358
Linus Torvalds1da177e2005-04-16 15:20:36 -07001359 /* Need a larger buffer. Query for the right size. */
1360 rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX,
1361 NULL, 0);
1362 if (rc < 0) {
1363 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001364 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001365 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001366 len = rc;
Eric Paris4cb912f2009-02-12 14:50:05 -05001367 context = kmalloc(len+1, GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001368 if (!context) {
1369 rc = -ENOMEM;
1370 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001371 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001372 }
Eric Paris4cb912f2009-02-12 14:50:05 -05001373 context[len] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001374 rc = inode->i_op->getxattr(dentry,
1375 XATTR_NAME_SELINUX,
1376 context, len);
1377 }
1378 dput(dentry);
1379 if (rc < 0) {
1380 if (rc != -ENODATA) {
Eric Paris744ba352008-04-17 11:52:44 -04001381 printk(KERN_WARNING "SELinux: %s: getxattr returned "
Harvey Harrisondd6f9532008-03-06 10:03:59 +11001382 "%d for dev=%s ino=%ld\n", __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001383 -rc, inode->i_sb->s_id, inode->i_ino);
1384 kfree(context);
Eric Paris23970742006-09-25 23:32:01 -07001385 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001386 }
1387 /* Map ENODATA to the default file SID */
1388 sid = sbsec->def_sid;
1389 rc = 0;
1390 } else {
James Morrisf5c1d5b2005-07-28 01:07:37 -07001391 rc = security_context_to_sid_default(context, rc, &sid,
Stephen Smalley869ab512008-04-04 08:46:05 -04001392 sbsec->def_sid,
1393 GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001394 if (rc) {
Eric Paris4ba0a8a2009-02-12 15:01:10 -05001395 char *dev = inode->i_sb->s_id;
1396 unsigned long ino = inode->i_ino;
1397
1398 if (rc == -EINVAL) {
1399 if (printk_ratelimit())
1400 printk(KERN_NOTICE "SELinux: inode=%lu on dev=%s was found to have an invalid "
1401 "context=%s. This indicates you may need to relabel the inode or the "
1402 "filesystem in question.\n", ino, dev, context);
1403 } else {
1404 printk(KERN_WARNING "SELinux: %s: context_to_sid(%s) "
1405 "returned %d for dev=%s ino=%ld\n",
1406 __func__, context, -rc, dev, ino);
1407 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001408 kfree(context);
1409 /* Leave with the unlabeled SID */
1410 rc = 0;
1411 break;
1412 }
1413 }
1414 kfree(context);
1415 isec->sid = sid;
1416 break;
1417 case SECURITY_FS_USE_TASK:
1418 isec->sid = isec->task_sid;
1419 break;
1420 case SECURITY_FS_USE_TRANS:
1421 /* Default to the fs SID. */
1422 isec->sid = sbsec->sid;
1423
1424 /* Try to obtain a transition SID. */
1425 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Eric Paris652bb9b2011-02-01 11:05:40 -05001426 rc = security_transition_sid(isec->task_sid, sbsec->sid,
1427 isec->sclass, NULL, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001428 if (rc)
Eric Paris23970742006-09-25 23:32:01 -07001429 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001430 isec->sid = sid;
1431 break;
Eric Parisc312feb2006-07-10 04:43:53 -07001432 case SECURITY_FS_USE_MNTPOINT:
1433 isec->sid = sbsec->mntpoint_sid;
1434 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001435 default:
Eric Parisc312feb2006-07-10 04:43:53 -07001436 /* Default to the fs superblock SID. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001437 isec->sid = sbsec->sid;
1438
Stephen Smalley134509d2015-06-04 16:22:17 -04001439 if ((sbsec->flags & SE_SBGENFS) && !S_ISLNK(inode->i_mode)) {
Paul Mooref64410e2014-03-19 16:46:18 -04001440 /* We must have a dentry to determine the label on
1441 * procfs inodes */
1442 if (opt_dentry)
1443 /* Called from d_instantiate or
1444 * d_splice_alias. */
1445 dentry = dget(opt_dentry);
1446 else
1447 /* Called from selinux_complete_init, try to
1448 * find a dentry. */
1449 dentry = d_find_alias(inode);
1450 /*
1451 * This can be hit on boot when a file is accessed
1452 * before the policy is loaded. When we load policy we
1453 * may find inodes that have no dentry on the
1454 * sbsec->isec_head list. No reason to complain as
1455 * these will get fixed up the next time we go through
1456 * inode_doinit() with a dentry, before these inodes
1457 * could be used again by userspace.
1458 */
1459 if (!dentry)
1460 goto out_unlock;
1461 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Stephen Smalley134509d2015-06-04 16:22:17 -04001462 rc = selinux_genfs_get_sid(dentry, isec->sclass,
1463 sbsec->flags, &sid);
Paul Mooref64410e2014-03-19 16:46:18 -04001464 dput(dentry);
1465 if (rc)
1466 goto out_unlock;
1467 isec->sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468 }
1469 break;
1470 }
1471
1472 isec->initialized = 1;
1473
Eric Paris23970742006-09-25 23:32:01 -07001474out_unlock:
1475 mutex_unlock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001476out:
1477 if (isec->sclass == SECCLASS_FILE)
1478 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001479 return rc;
1480}
1481
1482/* Convert a Linux signal to an access vector. */
1483static inline u32 signal_to_av(int sig)
1484{
1485 u32 perm = 0;
1486
1487 switch (sig) {
1488 case SIGCHLD:
1489 /* Commonly granted from child to parent. */
1490 perm = PROCESS__SIGCHLD;
1491 break;
1492 case SIGKILL:
1493 /* Cannot be caught or ignored */
1494 perm = PROCESS__SIGKILL;
1495 break;
1496 case SIGSTOP:
1497 /* Cannot be caught or ignored */
1498 perm = PROCESS__SIGSTOP;
1499 break;
1500 default:
1501 /* All other signals. */
1502 perm = PROCESS__SIGNAL;
1503 break;
1504 }
1505
1506 return perm;
1507}
1508
David Howells275bb412008-11-14 10:39:19 +11001509/*
David Howellsd84f4f92008-11-14 10:39:23 +11001510 * Check permission between a pair of credentials
1511 * fork check, ptrace check, etc.
1512 */
1513static int cred_has_perm(const struct cred *actor,
1514 const struct cred *target,
1515 u32 perms)
1516{
1517 u32 asid = cred_sid(actor), tsid = cred_sid(target);
1518
1519 return avc_has_perm(asid, tsid, SECCLASS_PROCESS, perms, NULL);
1520}
1521
1522/*
David Howells88e67f32008-11-14 10:39:21 +11001523 * Check permission between a pair of tasks, e.g. signal checks,
David Howells275bb412008-11-14 10:39:19 +11001524 * fork check, ptrace check, etc.
1525 * tsk1 is the actor and tsk2 is the target
David Howells3b11a1d2008-11-14 10:39:26 +11001526 * - this uses the default subjective creds of tsk1
David Howells275bb412008-11-14 10:39:19 +11001527 */
1528static int task_has_perm(const struct task_struct *tsk1,
1529 const struct task_struct *tsk2,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001530 u32 perms)
1531{
David Howells275bb412008-11-14 10:39:19 +11001532 const struct task_security_struct *__tsec1, *__tsec2;
1533 u32 sid1, sid2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001534
David Howells275bb412008-11-14 10:39:19 +11001535 rcu_read_lock();
1536 __tsec1 = __task_cred(tsk1)->security; sid1 = __tsec1->sid;
1537 __tsec2 = __task_cred(tsk2)->security; sid2 = __tsec2->sid;
1538 rcu_read_unlock();
1539 return avc_has_perm(sid1, sid2, SECCLASS_PROCESS, perms, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001540}
1541
David Howells3b11a1d2008-11-14 10:39:26 +11001542/*
1543 * Check permission between current and another task, e.g. signal checks,
1544 * fork check, ptrace check, etc.
1545 * current is the actor and tsk2 is the target
1546 * - this uses current's subjective creds
1547 */
1548static int current_has_perm(const struct task_struct *tsk,
1549 u32 perms)
1550{
1551 u32 sid, tsid;
1552
1553 sid = current_sid();
1554 tsid = task_sid(tsk);
1555 return avc_has_perm(sid, tsid, SECCLASS_PROCESS, perms, NULL);
1556}
1557
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001558#if CAP_LAST_CAP > 63
1559#error Fix SELinux to handle capabilities > 63.
1560#endif
1561
Linus Torvalds1da177e2005-04-16 15:20:36 -07001562/* Check whether a task is allowed to use a capability. */
Eric Paris6a9de492012-01-03 12:25:14 -05001563static int cred_has_capability(const struct cred *cred,
Eric Paris06112162008-11-11 22:02:50 +11001564 int cap, int audit)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001565{
Thomas Liu2bf49692009-07-14 12:14:09 -04001566 struct common_audit_data ad;
Eric Paris06112162008-11-11 22:02:50 +11001567 struct av_decision avd;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001568 u16 sclass;
David Howells3699c532009-01-06 22:27:01 +00001569 u32 sid = cred_sid(cred);
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001570 u32 av = CAP_TO_MASK(cap);
Eric Paris06112162008-11-11 22:02:50 +11001571 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001572
Eric Paris50c205f2012-04-04 15:01:43 -04001573 ad.type = LSM_AUDIT_DATA_CAP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001574 ad.u.cap = cap;
1575
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001576 switch (CAP_TO_INDEX(cap)) {
1577 case 0:
1578 sclass = SECCLASS_CAPABILITY;
1579 break;
1580 case 1:
1581 sclass = SECCLASS_CAPABILITY2;
1582 break;
1583 default:
1584 printk(KERN_ERR
1585 "SELinux: out of range capability %d\n", cap);
1586 BUG();
Eric Parisa35c6c82011-04-20 10:21:28 -04001587 return -EINVAL;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001588 }
Eric Paris06112162008-11-11 22:02:50 +11001589
David Howells275bb412008-11-14 10:39:19 +11001590 rc = avc_has_perm_noaudit(sid, sid, sclass, av, 0, &avd);
Eric Paris9ade0cf2011-04-25 16:26:29 -04001591 if (audit == SECURITY_CAP_AUDIT) {
NeilBrown7b20ea22015-03-23 13:37:39 +11001592 int rc2 = avc_audit(sid, sid, sclass, av, &avd, rc, &ad, 0);
Eric Paris9ade0cf2011-04-25 16:26:29 -04001593 if (rc2)
1594 return rc2;
1595 }
Eric Paris06112162008-11-11 22:02:50 +11001596 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001597}
1598
1599/* Check whether a task is allowed to use a system operation. */
1600static int task_has_system(struct task_struct *tsk,
1601 u32 perms)
1602{
David Howells275bb412008-11-14 10:39:19 +11001603 u32 sid = task_sid(tsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001604
David Howells275bb412008-11-14 10:39:19 +11001605 return avc_has_perm(sid, SECINITSID_KERNEL,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001606 SECCLASS_SYSTEM, perms, NULL);
1607}
1608
1609/* Check whether a task has a particular permission to an inode.
1610 The 'adp' parameter is optional and allows other audit
1611 data to be passed (e.g. the dentry). */
David Howells88e67f32008-11-14 10:39:21 +11001612static int inode_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001613 struct inode *inode,
1614 u32 perms,
Linus Torvalds19e49832013-10-04 12:54:11 -07001615 struct common_audit_data *adp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001616{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001617 struct inode_security_struct *isec;
David Howells275bb412008-11-14 10:39:19 +11001618 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001619
David Howellse0e81732009-09-02 09:13:40 +01001620 validate_creds(cred);
1621
Eric Paris828dfe12008-04-17 13:17:49 -04001622 if (unlikely(IS_PRIVATE(inode)))
Stephen Smalleybbaca6c2007-02-14 00:34:16 -08001623 return 0;
1624
David Howells88e67f32008-11-14 10:39:21 +11001625 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001626 isec = inode->i_security;
1627
Linus Torvalds19e49832013-10-04 12:54:11 -07001628 return avc_has_perm(sid, isec->sid, isec->sclass, perms, adp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001629}
1630
1631/* Same as inode_has_perm, but pass explicit audit data containing
1632 the dentry to help the auditing code to more easily generate the
1633 pathname if needed. */
David Howells88e67f32008-11-14 10:39:21 +11001634static inline int dentry_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001635 struct dentry *dentry,
1636 u32 av)
1637{
David Howellsc6f493d2015-03-17 22:26:22 +00001638 struct inode *inode = d_backing_inode(dentry);
Thomas Liu2bf49692009-07-14 12:14:09 -04001639 struct common_audit_data ad;
David Howells88e67f32008-11-14 10:39:21 +11001640
Eric Paris50c205f2012-04-04 15:01:43 -04001641 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Paris2875fa02011-04-28 16:04:24 -04001642 ad.u.dentry = dentry;
Linus Torvalds19e49832013-10-04 12:54:11 -07001643 return inode_has_perm(cred, inode, av, &ad);
Eric Paris2875fa02011-04-28 16:04:24 -04001644}
1645
1646/* Same as inode_has_perm, but pass explicit audit data containing
1647 the path to help the auditing code to more easily generate the
1648 pathname if needed. */
1649static inline int path_has_perm(const struct cred *cred,
Al Viro3f7036a2015-03-08 19:28:30 -04001650 const struct path *path,
Eric Paris2875fa02011-04-28 16:04:24 -04001651 u32 av)
1652{
David Howellsc6f493d2015-03-17 22:26:22 +00001653 struct inode *inode = d_backing_inode(path->dentry);
Eric Paris2875fa02011-04-28 16:04:24 -04001654 struct common_audit_data ad;
1655
Eric Paris50c205f2012-04-04 15:01:43 -04001656 ad.type = LSM_AUDIT_DATA_PATH;
Eric Paris2875fa02011-04-28 16:04:24 -04001657 ad.u.path = *path;
Linus Torvalds19e49832013-10-04 12:54:11 -07001658 return inode_has_perm(cred, inode, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001659}
1660
David Howells13f8e982013-06-13 23:37:55 +01001661/* Same as path_has_perm, but uses the inode from the file struct. */
1662static inline int file_path_has_perm(const struct cred *cred,
1663 struct file *file,
1664 u32 av)
1665{
1666 struct common_audit_data ad;
1667
1668 ad.type = LSM_AUDIT_DATA_PATH;
1669 ad.u.path = file->f_path;
Linus Torvalds19e49832013-10-04 12:54:11 -07001670 return inode_has_perm(cred, file_inode(file), av, &ad);
David Howells13f8e982013-06-13 23:37:55 +01001671}
1672
Linus Torvalds1da177e2005-04-16 15:20:36 -07001673/* Check whether a task can use an open file descriptor to
1674 access an inode in a given way. Check access to the
1675 descriptor itself, and then use dentry_has_perm to
1676 check a particular permission to the file.
1677 Access to the descriptor is implicitly granted if it
1678 has the same SID as the process. If av is zero, then
1679 access to the file is not checked, e.g. for cases
1680 where only the descriptor is affected like seek. */
David Howells88e67f32008-11-14 10:39:21 +11001681static int file_has_perm(const struct cred *cred,
1682 struct file *file,
1683 u32 av)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001684{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001685 struct file_security_struct *fsec = file->f_security;
Al Viro496ad9a2013-01-23 17:07:38 -05001686 struct inode *inode = file_inode(file);
Thomas Liu2bf49692009-07-14 12:14:09 -04001687 struct common_audit_data ad;
David Howells88e67f32008-11-14 10:39:21 +11001688 u32 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001689 int rc;
1690
Eric Paris50c205f2012-04-04 15:01:43 -04001691 ad.type = LSM_AUDIT_DATA_PATH;
Eric Parisf48b7392011-04-25 12:54:27 -04001692 ad.u.path = file->f_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001693
David Howells275bb412008-11-14 10:39:19 +11001694 if (sid != fsec->sid) {
1695 rc = avc_has_perm(sid, fsec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001696 SECCLASS_FD,
1697 FD__USE,
1698 &ad);
1699 if (rc)
David Howells88e67f32008-11-14 10:39:21 +11001700 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001701 }
1702
1703 /* av is zero if only checking access to the descriptor. */
David Howells88e67f32008-11-14 10:39:21 +11001704 rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001705 if (av)
Linus Torvalds19e49832013-10-04 12:54:11 -07001706 rc = inode_has_perm(cred, inode, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001707
David Howells88e67f32008-11-14 10:39:21 +11001708out:
1709 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001710}
1711
David Howellsc3c188b2015-07-10 17:19:58 -04001712/*
1713 * Determine the label for an inode that might be unioned.
1714 */
1715static int selinux_determine_inode_label(const struct inode *dir,
1716 const struct qstr *name,
1717 u16 tclass,
1718 u32 *_new_isid)
1719{
1720 const struct superblock_security_struct *sbsec = dir->i_sb->s_security;
1721 const struct inode_security_struct *dsec = dir->i_security;
1722 const struct task_security_struct *tsec = current_security();
1723
1724 if ((sbsec->flags & SE_SBINITIALIZED) &&
1725 (sbsec->behavior == SECURITY_FS_USE_MNTPOINT)) {
1726 *_new_isid = sbsec->mntpoint_sid;
1727 } else if ((sbsec->flags & SBLABEL_MNT) &&
1728 tsec->create_sid) {
1729 *_new_isid = tsec->create_sid;
1730 } else {
1731 return security_transition_sid(tsec->sid, dsec->sid, tclass,
1732 name, _new_isid);
1733 }
1734
1735 return 0;
1736}
1737
Linus Torvalds1da177e2005-04-16 15:20:36 -07001738/* Check whether a task can create a file. */
1739static int may_create(struct inode *dir,
1740 struct dentry *dentry,
1741 u16 tclass)
1742{
Paul Moore5fb49872010-04-22 14:46:19 -04001743 const struct task_security_struct *tsec = current_security();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001744 struct inode_security_struct *dsec;
1745 struct superblock_security_struct *sbsec;
David Howells275bb412008-11-14 10:39:19 +11001746 u32 sid, newsid;
Thomas Liu2bf49692009-07-14 12:14:09 -04001747 struct common_audit_data ad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001748 int rc;
1749
Linus Torvalds1da177e2005-04-16 15:20:36 -07001750 dsec = dir->i_security;
1751 sbsec = dir->i_sb->s_security;
1752
David Howells275bb412008-11-14 10:39:19 +11001753 sid = tsec->sid;
David Howells275bb412008-11-14 10:39:19 +11001754
Eric Paris50c205f2012-04-04 15:01:43 -04001755 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04001756 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001757
David Howells275bb412008-11-14 10:39:19 +11001758 rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001759 DIR__ADD_NAME | DIR__SEARCH,
1760 &ad);
1761 if (rc)
1762 return rc;
1763
David Howellsc3c188b2015-07-10 17:19:58 -04001764 rc = selinux_determine_inode_label(dir, &dentry->d_name, tclass,
1765 &newsid);
1766 if (rc)
1767 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001768
David Howells275bb412008-11-14 10:39:19 +11001769 rc = avc_has_perm(sid, newsid, tclass, FILE__CREATE, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001770 if (rc)
1771 return rc;
1772
1773 return avc_has_perm(newsid, sbsec->sid,
1774 SECCLASS_FILESYSTEM,
1775 FILESYSTEM__ASSOCIATE, &ad);
1776}
1777
Michael LeMay4eb582c2006-06-26 00:24:57 -07001778/* Check whether a task can create a key. */
1779static int may_create_key(u32 ksid,
1780 struct task_struct *ctx)
1781{
David Howells275bb412008-11-14 10:39:19 +11001782 u32 sid = task_sid(ctx);
Michael LeMay4eb582c2006-06-26 00:24:57 -07001783
David Howells275bb412008-11-14 10:39:19 +11001784 return avc_has_perm(sid, ksid, SECCLASS_KEY, KEY__CREATE, NULL);
Michael LeMay4eb582c2006-06-26 00:24:57 -07001785}
1786
Eric Paris828dfe12008-04-17 13:17:49 -04001787#define MAY_LINK 0
1788#define MAY_UNLINK 1
1789#define MAY_RMDIR 2
Linus Torvalds1da177e2005-04-16 15:20:36 -07001790
1791/* Check whether a task can link, unlink, or rmdir a file/directory. */
1792static int may_link(struct inode *dir,
1793 struct dentry *dentry,
1794 int kind)
1795
1796{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001797 struct inode_security_struct *dsec, *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04001798 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11001799 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001800 u32 av;
1801 int rc;
1802
Linus Torvalds1da177e2005-04-16 15:20:36 -07001803 dsec = dir->i_security;
David Howellsc6f493d2015-03-17 22:26:22 +00001804 isec = d_backing_inode(dentry)->i_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001805
Eric Paris50c205f2012-04-04 15:01:43 -04001806 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04001807 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001808
1809 av = DIR__SEARCH;
1810 av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME);
David Howells275bb412008-11-14 10:39:19 +11001811 rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001812 if (rc)
1813 return rc;
1814
1815 switch (kind) {
1816 case MAY_LINK:
1817 av = FILE__LINK;
1818 break;
1819 case MAY_UNLINK:
1820 av = FILE__UNLINK;
1821 break;
1822 case MAY_RMDIR:
1823 av = DIR__RMDIR;
1824 break;
1825 default:
Eric Paris744ba352008-04-17 11:52:44 -04001826 printk(KERN_WARNING "SELinux: %s: unrecognized kind %d\n",
1827 __func__, kind);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001828 return 0;
1829 }
1830
David Howells275bb412008-11-14 10:39:19 +11001831 rc = avc_has_perm(sid, isec->sid, isec->sclass, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001832 return rc;
1833}
1834
1835static inline int may_rename(struct inode *old_dir,
1836 struct dentry *old_dentry,
1837 struct inode *new_dir,
1838 struct dentry *new_dentry)
1839{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001840 struct inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04001841 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11001842 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001843 u32 av;
1844 int old_is_dir, new_is_dir;
1845 int rc;
1846
Linus Torvalds1da177e2005-04-16 15:20:36 -07001847 old_dsec = old_dir->i_security;
David Howellsc6f493d2015-03-17 22:26:22 +00001848 old_isec = d_backing_inode(old_dentry)->i_security;
David Howellse36cb0b2015-01-29 12:02:35 +00001849 old_is_dir = d_is_dir(old_dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001850 new_dsec = new_dir->i_security;
1851
Eric Paris50c205f2012-04-04 15:01:43 -04001852 ad.type = LSM_AUDIT_DATA_DENTRY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001853
Eric Parisa2694342011-04-25 13:10:27 -04001854 ad.u.dentry = old_dentry;
David Howells275bb412008-11-14 10:39:19 +11001855 rc = avc_has_perm(sid, old_dsec->sid, SECCLASS_DIR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001856 DIR__REMOVE_NAME | DIR__SEARCH, &ad);
1857 if (rc)
1858 return rc;
David Howells275bb412008-11-14 10:39:19 +11001859 rc = avc_has_perm(sid, old_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001860 old_isec->sclass, FILE__RENAME, &ad);
1861 if (rc)
1862 return rc;
1863 if (old_is_dir && new_dir != old_dir) {
David Howells275bb412008-11-14 10:39:19 +11001864 rc = avc_has_perm(sid, old_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001865 old_isec->sclass, DIR__REPARENT, &ad);
1866 if (rc)
1867 return rc;
1868 }
1869
Eric Parisa2694342011-04-25 13:10:27 -04001870 ad.u.dentry = new_dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001871 av = DIR__ADD_NAME | DIR__SEARCH;
David Howells2c616d42015-01-29 12:02:33 +00001872 if (d_is_positive(new_dentry))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001873 av |= DIR__REMOVE_NAME;
David Howells275bb412008-11-14 10:39:19 +11001874 rc = avc_has_perm(sid, new_dsec->sid, SECCLASS_DIR, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001875 if (rc)
1876 return rc;
David Howells2c616d42015-01-29 12:02:33 +00001877 if (d_is_positive(new_dentry)) {
David Howellsc6f493d2015-03-17 22:26:22 +00001878 new_isec = d_backing_inode(new_dentry)->i_security;
David Howellse36cb0b2015-01-29 12:02:35 +00001879 new_is_dir = d_is_dir(new_dentry);
David Howells275bb412008-11-14 10:39:19 +11001880 rc = avc_has_perm(sid, new_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001881 new_isec->sclass,
1882 (new_is_dir ? DIR__RMDIR : FILE__UNLINK), &ad);
1883 if (rc)
1884 return rc;
1885 }
1886
1887 return 0;
1888}
1889
1890/* Check whether a task can perform a filesystem operation. */
David Howells88e67f32008-11-14 10:39:21 +11001891static int superblock_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001892 struct super_block *sb,
1893 u32 perms,
Thomas Liu2bf49692009-07-14 12:14:09 -04001894 struct common_audit_data *ad)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001895{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001896 struct superblock_security_struct *sbsec;
David Howells88e67f32008-11-14 10:39:21 +11001897 u32 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001898
Linus Torvalds1da177e2005-04-16 15:20:36 -07001899 sbsec = sb->s_security;
David Howells275bb412008-11-14 10:39:19 +11001900 return avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM, perms, ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001901}
1902
1903/* Convert a Linux mode and permission mask to an access vector. */
1904static inline u32 file_mask_to_av(int mode, int mask)
1905{
1906 u32 av = 0;
1907
Al Virodba19c62011-07-25 20:49:29 -04001908 if (!S_ISDIR(mode)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001909 if (mask & MAY_EXEC)
1910 av |= FILE__EXECUTE;
1911 if (mask & MAY_READ)
1912 av |= FILE__READ;
1913
1914 if (mask & MAY_APPEND)
1915 av |= FILE__APPEND;
1916 else if (mask & MAY_WRITE)
1917 av |= FILE__WRITE;
1918
1919 } else {
1920 if (mask & MAY_EXEC)
1921 av |= DIR__SEARCH;
1922 if (mask & MAY_WRITE)
1923 av |= DIR__WRITE;
1924 if (mask & MAY_READ)
1925 av |= DIR__READ;
1926 }
1927
1928 return av;
1929}
1930
1931/* Convert a Linux file to an access vector. */
1932static inline u32 file_to_av(struct file *file)
1933{
1934 u32 av = 0;
1935
1936 if (file->f_mode & FMODE_READ)
1937 av |= FILE__READ;
1938 if (file->f_mode & FMODE_WRITE) {
1939 if (file->f_flags & O_APPEND)
1940 av |= FILE__APPEND;
1941 else
1942 av |= FILE__WRITE;
1943 }
Stephen Smalley0794c662008-03-17 08:55:18 -04001944 if (!av) {
1945 /*
1946 * Special file opened with flags 3 for ioctl-only use.
1947 */
1948 av = FILE__IOCTL;
1949 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001950
1951 return av;
1952}
1953
Eric Paris8b6a5a32008-10-29 17:06:46 -04001954/*
1955 * Convert a file to an access vector and include the correct open
1956 * open permission.
1957 */
1958static inline u32 open_file_to_av(struct file *file)
1959{
1960 u32 av = file_to_av(file);
1961
Eric Paris49b7b8d2010-07-23 11:44:09 -04001962 if (selinux_policycap_openperm)
1963 av |= FILE__OPEN;
1964
Eric Paris8b6a5a32008-10-29 17:06:46 -04001965 return av;
1966}
1967
Linus Torvalds1da177e2005-04-16 15:20:36 -07001968/* Hook functions begin here. */
1969
Stephen Smalley79af7302015-01-21 10:54:10 -05001970static int selinux_binder_set_context_mgr(struct task_struct *mgr)
1971{
1972 u32 mysid = current_sid();
1973 u32 mgrsid = task_sid(mgr);
1974
1975 return avc_has_perm(mysid, mgrsid, SECCLASS_BINDER,
1976 BINDER__SET_CONTEXT_MGR, NULL);
1977}
1978
1979static int selinux_binder_transaction(struct task_struct *from,
1980 struct task_struct *to)
1981{
1982 u32 mysid = current_sid();
1983 u32 fromsid = task_sid(from);
1984 u32 tosid = task_sid(to);
1985 int rc;
1986
1987 if (mysid != fromsid) {
1988 rc = avc_has_perm(mysid, fromsid, SECCLASS_BINDER,
1989 BINDER__IMPERSONATE, NULL);
1990 if (rc)
1991 return rc;
1992 }
1993
1994 return avc_has_perm(fromsid, tosid, SECCLASS_BINDER, BINDER__CALL,
1995 NULL);
1996}
1997
1998static int selinux_binder_transfer_binder(struct task_struct *from,
1999 struct task_struct *to)
2000{
2001 u32 fromsid = task_sid(from);
2002 u32 tosid = task_sid(to);
2003
2004 return avc_has_perm(fromsid, tosid, SECCLASS_BINDER, BINDER__TRANSFER,
2005 NULL);
2006}
2007
2008static int selinux_binder_transfer_file(struct task_struct *from,
2009 struct task_struct *to,
2010 struct file *file)
2011{
2012 u32 sid = task_sid(to);
2013 struct file_security_struct *fsec = file->f_security;
David Howellsc6f493d2015-03-17 22:26:22 +00002014 struct inode *inode = d_backing_inode(file->f_path.dentry);
Stephen Smalley79af7302015-01-21 10:54:10 -05002015 struct inode_security_struct *isec = inode->i_security;
2016 struct common_audit_data ad;
2017 int rc;
2018
2019 ad.type = LSM_AUDIT_DATA_PATH;
2020 ad.u.path = file->f_path;
2021
2022 if (sid != fsec->sid) {
2023 rc = avc_has_perm(sid, fsec->sid,
2024 SECCLASS_FD,
2025 FD__USE,
2026 &ad);
2027 if (rc)
2028 return rc;
2029 }
2030
2031 if (unlikely(IS_PRIVATE(inode)))
2032 return 0;
2033
2034 return avc_has_perm(sid, isec->sid, isec->sclass, file_to_av(file),
2035 &ad);
2036}
2037
Ingo Molnar9e488582009-05-07 19:26:19 +10002038static int selinux_ptrace_access_check(struct task_struct *child,
David Howells5cd9c582008-08-14 11:37:28 +01002039 unsigned int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002040{
Eric Paris69f594a2012-01-03 12:25:15 -05002041 if (mode & PTRACE_MODE_READ) {
David Howells275bb412008-11-14 10:39:19 +11002042 u32 sid = current_sid();
2043 u32 csid = task_sid(child);
2044 return avc_has_perm(sid, csid, SECCLASS_FILE, FILE__READ, NULL);
Stephen Smalley006ebb42008-05-19 08:32:49 -04002045 }
2046
David Howells3b11a1d2008-11-14 10:39:26 +11002047 return current_has_perm(child, PROCESS__PTRACE);
David Howells5cd9c582008-08-14 11:37:28 +01002048}
2049
2050static int selinux_ptrace_traceme(struct task_struct *parent)
2051{
David Howells5cd9c582008-08-14 11:37:28 +01002052 return task_has_perm(parent, current, PROCESS__PTRACE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002053}
2054
2055static int selinux_capget(struct task_struct *target, kernel_cap_t *effective,
Eric Paris828dfe12008-04-17 13:17:49 -04002056 kernel_cap_t *inheritable, kernel_cap_t *permitted)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002057{
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07002058 return current_has_perm(target, PROCESS__GETCAP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002059}
2060
David Howellsd84f4f92008-11-14 10:39:23 +11002061static int selinux_capset(struct cred *new, const struct cred *old,
2062 const kernel_cap_t *effective,
2063 const kernel_cap_t *inheritable,
2064 const kernel_cap_t *permitted)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002065{
David Howellsd84f4f92008-11-14 10:39:23 +11002066 return cred_has_perm(old, new, PROCESS__SETCAP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002067}
2068
James Morris5626d3e2009-01-30 10:05:06 +11002069/*
2070 * (This comment used to live with the selinux_task_setuid hook,
2071 * which was removed).
2072 *
2073 * Since setuid only affects the current process, and since the SELinux
2074 * controls are not based on the Linux identity attributes, SELinux does not
2075 * need to control this operation. However, SELinux does control the use of
2076 * the CAP_SETUID and CAP_SETGID capabilities using the capable hook.
2077 */
2078
Eric Paris6a9de492012-01-03 12:25:14 -05002079static int selinux_capable(const struct cred *cred, struct user_namespace *ns,
2080 int cap, int audit)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002081{
Eric Paris6a9de492012-01-03 12:25:14 -05002082 return cred_has_capability(cred, cap, audit);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002083}
2084
Linus Torvalds1da177e2005-04-16 15:20:36 -07002085static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb)
2086{
David Howells88e67f32008-11-14 10:39:21 +11002087 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002088 int rc = 0;
2089
2090 if (!sb)
2091 return 0;
2092
2093 switch (cmds) {
Eric Paris828dfe12008-04-17 13:17:49 -04002094 case Q_SYNC:
2095 case Q_QUOTAON:
2096 case Q_QUOTAOFF:
2097 case Q_SETINFO:
2098 case Q_SETQUOTA:
David Howells88e67f32008-11-14 10:39:21 +11002099 rc = superblock_has_perm(cred, sb, FILESYSTEM__QUOTAMOD, NULL);
Eric Paris828dfe12008-04-17 13:17:49 -04002100 break;
2101 case Q_GETFMT:
2102 case Q_GETINFO:
2103 case Q_GETQUOTA:
David Howells88e67f32008-11-14 10:39:21 +11002104 rc = superblock_has_perm(cred, sb, FILESYSTEM__QUOTAGET, NULL);
Eric Paris828dfe12008-04-17 13:17:49 -04002105 break;
2106 default:
2107 rc = 0; /* let the kernel handle invalid cmds */
2108 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002109 }
2110 return rc;
2111}
2112
2113static int selinux_quota_on(struct dentry *dentry)
2114{
David Howells88e67f32008-11-14 10:39:21 +11002115 const struct cred *cred = current_cred();
2116
Eric Paris2875fa02011-04-28 16:04:24 -04002117 return dentry_has_perm(cred, dentry, FILE__QUOTAON);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002118}
2119
Eric Paris12b30522010-11-15 18:36:29 -05002120static int selinux_syslog(int type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002121{
2122 int rc;
2123
Linus Torvalds1da177e2005-04-16 15:20:36 -07002124 switch (type) {
Kees Cookd78ca3c2010-02-03 15:37:13 -08002125 case SYSLOG_ACTION_READ_ALL: /* Read last kernel messages */
2126 case SYSLOG_ACTION_SIZE_BUFFER: /* Return size of the log buffer */
Eric Paris828dfe12008-04-17 13:17:49 -04002127 rc = task_has_system(current, SYSTEM__SYSLOG_READ);
2128 break;
Kees Cookd78ca3c2010-02-03 15:37:13 -08002129 case SYSLOG_ACTION_CONSOLE_OFF: /* Disable logging to console */
2130 case SYSLOG_ACTION_CONSOLE_ON: /* Enable logging to console */
2131 /* Set level of messages printed to console */
2132 case SYSLOG_ACTION_CONSOLE_LEVEL:
Eric Paris828dfe12008-04-17 13:17:49 -04002133 rc = task_has_system(current, SYSTEM__SYSLOG_CONSOLE);
2134 break;
Kees Cookd78ca3c2010-02-03 15:37:13 -08002135 case SYSLOG_ACTION_CLOSE: /* Close log */
2136 case SYSLOG_ACTION_OPEN: /* Open log */
2137 case SYSLOG_ACTION_READ: /* Read from log */
2138 case SYSLOG_ACTION_READ_CLEAR: /* Read/clear last kernel messages */
2139 case SYSLOG_ACTION_CLEAR: /* Clear ring buffer */
Eric Paris828dfe12008-04-17 13:17:49 -04002140 default:
2141 rc = task_has_system(current, SYSTEM__SYSLOG_MOD);
2142 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002143 }
2144 return rc;
2145}
2146
2147/*
2148 * Check that a process has enough memory to allocate a new virtual
2149 * mapping. 0 means there is enough memory for the allocation to
2150 * succeed and -ENOMEM implies there is not.
2151 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07002152 * Do not audit the selinux permission check, as this is applied to all
2153 * processes that allocate mappings.
2154 */
Alan Cox34b4e4a2007-08-22 14:01:28 -07002155static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002156{
2157 int rc, cap_sys_admin = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002158
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07002159 rc = cred_has_capability(current_cred(), CAP_SYS_ADMIN,
2160 SECURITY_CAP_NOAUDIT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002161 if (rc == 0)
2162 cap_sys_admin = 1;
2163
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07002164 return cap_sys_admin;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002165}
2166
2167/* binprm security operations */
2168
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002169static int check_nnp_nosuid(const struct linux_binprm *bprm,
2170 const struct task_security_struct *old_tsec,
2171 const struct task_security_struct *new_tsec)
2172{
2173 int nnp = (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS);
2174 int nosuid = (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID);
2175 int rc;
2176
2177 if (!nnp && !nosuid)
2178 return 0; /* neither NNP nor nosuid */
2179
2180 if (new_tsec->sid == old_tsec->sid)
2181 return 0; /* No change in credentials */
2182
2183 /*
2184 * The only transitions we permit under NNP or nosuid
2185 * are transitions to bounded SIDs, i.e. SIDs that are
2186 * guaranteed to only be allowed a subset of the permissions
2187 * of the current SID.
2188 */
2189 rc = security_bounded_transition(old_tsec->sid, new_tsec->sid);
2190 if (rc) {
2191 /*
2192 * On failure, preserve the errno values for NNP vs nosuid.
2193 * NNP: Operation not permitted for caller.
2194 * nosuid: Permission denied to file.
2195 */
2196 if (nnp)
2197 return -EPERM;
2198 else
2199 return -EACCES;
2200 }
2201 return 0;
2202}
2203
David Howellsa6f76f22008-11-14 10:39:24 +11002204static int selinux_bprm_set_creds(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002205{
David Howellsa6f76f22008-11-14 10:39:24 +11002206 const struct task_security_struct *old_tsec;
2207 struct task_security_struct *new_tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002208 struct inode_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04002209 struct common_audit_data ad;
Al Viro496ad9a2013-01-23 17:07:38 -05002210 struct inode *inode = file_inode(bprm->file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002211 int rc;
2212
David Howellsa6f76f22008-11-14 10:39:24 +11002213 /* SELinux context only depends on initial program or script and not
2214 * the script interpreter */
2215 if (bprm->cred_prepared)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002216 return 0;
2217
David Howellsa6f76f22008-11-14 10:39:24 +11002218 old_tsec = current_security();
2219 new_tsec = bprm->cred->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002220 isec = inode->i_security;
2221
2222 /* Default to the current task SID. */
David Howellsa6f76f22008-11-14 10:39:24 +11002223 new_tsec->sid = old_tsec->sid;
2224 new_tsec->osid = old_tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002225
Michael LeMay28eba5b2006-06-27 02:53:42 -07002226 /* Reset fs, key, and sock SIDs on execve. */
David Howellsa6f76f22008-11-14 10:39:24 +11002227 new_tsec->create_sid = 0;
2228 new_tsec->keycreate_sid = 0;
2229 new_tsec->sockcreate_sid = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002230
David Howellsa6f76f22008-11-14 10:39:24 +11002231 if (old_tsec->exec_sid) {
2232 new_tsec->sid = old_tsec->exec_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002233 /* Reset exec SID on execve. */
David Howellsa6f76f22008-11-14 10:39:24 +11002234 new_tsec->exec_sid = 0;
Andy Lutomirski259e5e62012-04-12 16:47:50 -05002235
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002236 /* Fail on NNP or nosuid if not an allowed transition. */
2237 rc = check_nnp_nosuid(bprm, old_tsec, new_tsec);
2238 if (rc)
2239 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002240 } else {
2241 /* Check for a default transition on this program. */
David Howellsa6f76f22008-11-14 10:39:24 +11002242 rc = security_transition_sid(old_tsec->sid, isec->sid,
Eric Paris652bb9b2011-02-01 11:05:40 -05002243 SECCLASS_PROCESS, NULL,
2244 &new_tsec->sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002245 if (rc)
2246 return rc;
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002247
2248 /*
2249 * Fallback to old SID on NNP or nosuid if not an allowed
2250 * transition.
2251 */
2252 rc = check_nnp_nosuid(bprm, old_tsec, new_tsec);
2253 if (rc)
2254 new_tsec->sid = old_tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002255 }
2256
Eric Paris50c205f2012-04-04 15:01:43 -04002257 ad.type = LSM_AUDIT_DATA_PATH;
Eric Parisf48b7392011-04-25 12:54:27 -04002258 ad.u.path = bprm->file->f_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002259
David Howellsa6f76f22008-11-14 10:39:24 +11002260 if (new_tsec->sid == old_tsec->sid) {
2261 rc = avc_has_perm(old_tsec->sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002262 SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, &ad);
2263 if (rc)
2264 return rc;
2265 } else {
2266 /* Check permissions for the transition. */
David Howellsa6f76f22008-11-14 10:39:24 +11002267 rc = avc_has_perm(old_tsec->sid, new_tsec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002268 SECCLASS_PROCESS, PROCESS__TRANSITION, &ad);
2269 if (rc)
2270 return rc;
2271
David Howellsa6f76f22008-11-14 10:39:24 +11002272 rc = avc_has_perm(new_tsec->sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002273 SECCLASS_FILE, FILE__ENTRYPOINT, &ad);
2274 if (rc)
2275 return rc;
2276
David Howellsa6f76f22008-11-14 10:39:24 +11002277 /* Check for shared state */
2278 if (bprm->unsafe & LSM_UNSAFE_SHARE) {
2279 rc = avc_has_perm(old_tsec->sid, new_tsec->sid,
2280 SECCLASS_PROCESS, PROCESS__SHARE,
2281 NULL);
2282 if (rc)
2283 return -EPERM;
2284 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002285
David Howellsa6f76f22008-11-14 10:39:24 +11002286 /* Make sure that anyone attempting to ptrace over a task that
2287 * changes its SID has the appropriate permit */
2288 if (bprm->unsafe &
2289 (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) {
2290 struct task_struct *tracer;
2291 struct task_security_struct *sec;
2292 u32 ptsid = 0;
2293
2294 rcu_read_lock();
Tejun Heo06d98472011-06-17 16:50:40 +02002295 tracer = ptrace_parent(current);
David Howellsa6f76f22008-11-14 10:39:24 +11002296 if (likely(tracer != NULL)) {
2297 sec = __task_cred(tracer)->security;
2298 ptsid = sec->sid;
2299 }
2300 rcu_read_unlock();
2301
2302 if (ptsid != 0) {
2303 rc = avc_has_perm(ptsid, new_tsec->sid,
2304 SECCLASS_PROCESS,
2305 PROCESS__PTRACE, NULL);
2306 if (rc)
2307 return -EPERM;
2308 }
2309 }
2310
2311 /* Clear any possibly unsafe personality bits on exec: */
2312 bprm->per_clear |= PER_CLEAR_ON_SETID;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002313 }
2314
Linus Torvalds1da177e2005-04-16 15:20:36 -07002315 return 0;
2316}
2317
Eric Paris828dfe12008-04-17 13:17:49 -04002318static int selinux_bprm_secureexec(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002319{
Paul Moore5fb49872010-04-22 14:46:19 -04002320 const struct task_security_struct *tsec = current_security();
David Howells275bb412008-11-14 10:39:19 +11002321 u32 sid, osid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002322 int atsecure = 0;
2323
David Howells275bb412008-11-14 10:39:19 +11002324 sid = tsec->sid;
2325 osid = tsec->osid;
2326
2327 if (osid != sid) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002328 /* Enable secure mode for SIDs transitions unless
2329 the noatsecure permission is granted between
2330 the two SIDs, i.e. ahp returns 0. */
David Howells275bb412008-11-14 10:39:19 +11002331 atsecure = avc_has_perm(osid, sid,
David Howellsa6f76f22008-11-14 10:39:24 +11002332 SECCLASS_PROCESS,
2333 PROCESS__NOATSECURE, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002334 }
2335
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07002336 return !!atsecure;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002337}
2338
Al Viroc3c073f2012-08-21 22:32:06 -04002339static int match_file(const void *p, struct file *file, unsigned fd)
2340{
2341 return file_has_perm(p, file, file_to_av(file)) ? fd + 1 : 0;
2342}
2343
Linus Torvalds1da177e2005-04-16 15:20:36 -07002344/* Derived from fs/exec.c:flush_old_files. */
David Howells745ca242008-11-14 10:39:22 +11002345static inline void flush_unauthorized_files(const struct cred *cred,
2346 struct files_struct *files)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002347{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002348 struct file *file, *devnull = NULL;
Stephen Smalleyb20c8122006-09-25 23:32:03 -07002349 struct tty_struct *tty;
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002350 int drop_tty = 0;
Al Viroc3c073f2012-08-21 22:32:06 -04002351 unsigned n;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002352
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002353 tty = get_current_tty();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002354 if (tty) {
Nick Pigginee2ffa02010-08-18 04:37:35 +10002355 spin_lock(&tty_files_lock);
Eric Paris37dd0bd2008-10-31 17:40:00 -04002356 if (!list_empty(&tty->tty_files)) {
Nick Piggind996b622010-08-18 04:37:36 +10002357 struct tty_file_private *file_priv;
Eric Paris37dd0bd2008-10-31 17:40:00 -04002358
Linus Torvalds1da177e2005-04-16 15:20:36 -07002359 /* Revalidate access to controlling tty.
David Howells13f8e982013-06-13 23:37:55 +01002360 Use file_path_has_perm on the tty path directly
2361 rather than using file_has_perm, as this particular
2362 open file may belong to another process and we are
2363 only interested in the inode-based check here. */
Nick Piggind996b622010-08-18 04:37:36 +10002364 file_priv = list_first_entry(&tty->tty_files,
2365 struct tty_file_private, list);
2366 file = file_priv->file;
David Howells13f8e982013-06-13 23:37:55 +01002367 if (file_path_has_perm(cred, file, FILE__READ | FILE__WRITE))
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002368 drop_tty = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002369 }
Nick Pigginee2ffa02010-08-18 04:37:35 +10002370 spin_unlock(&tty_files_lock);
Alan Cox452a00d2008-10-13 10:39:13 +01002371 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002372 }
Eric W. Biederman98a27ba2007-05-08 00:26:56 -07002373 /* Reset controlling tty. */
2374 if (drop_tty)
2375 no_tty();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002376
2377 /* Revalidate access to inherited open files. */
Al Viroc3c073f2012-08-21 22:32:06 -04002378 n = iterate_fd(files, 0, match_file, cred);
2379 if (!n) /* none found? */
2380 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002381
Al Viroc3c073f2012-08-21 22:32:06 -04002382 devnull = dentry_open(&selinux_null, O_RDWR, cred);
Al Viro45525b22012-10-16 13:30:07 -04002383 if (IS_ERR(devnull))
2384 devnull = NULL;
2385 /* replace all the matching ones with this */
2386 do {
2387 replace_fd(n - 1, devnull, 0);
2388 } while ((n = iterate_fd(files, n, match_file, cred)) != 0);
2389 if (devnull)
Al Viroc3c073f2012-08-21 22:32:06 -04002390 fput(devnull);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002391}
2392
Linus Torvalds1da177e2005-04-16 15:20:36 -07002393/*
David Howellsa6f76f22008-11-14 10:39:24 +11002394 * Prepare a process for imminent new credential changes due to exec
Linus Torvalds1da177e2005-04-16 15:20:36 -07002395 */
David Howellsa6f76f22008-11-14 10:39:24 +11002396static void selinux_bprm_committing_creds(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002397{
David Howellsa6f76f22008-11-14 10:39:24 +11002398 struct task_security_struct *new_tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002399 struct rlimit *rlim, *initrlim;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002400 int rc, i;
2401
David Howellsa6f76f22008-11-14 10:39:24 +11002402 new_tsec = bprm->cred->security;
2403 if (new_tsec->sid == new_tsec->osid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002404 return;
2405
2406 /* Close files for which the new task SID is not authorized. */
David Howellsa6f76f22008-11-14 10:39:24 +11002407 flush_unauthorized_files(bprm->cred, current->files);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002408
David Howellsa6f76f22008-11-14 10:39:24 +11002409 /* Always clear parent death signal on SID transitions. */
2410 current->pdeath_signal = 0;
2411
2412 /* Check whether the new SID can inherit resource limits from the old
2413 * SID. If not, reset all soft limits to the lower of the current
2414 * task's hard limit and the init task's soft limit.
2415 *
2416 * Note that the setting of hard limits (even to lower them) can be
2417 * controlled by the setrlimit check. The inclusion of the init task's
2418 * soft limit into the computation is to avoid resetting soft limits
2419 * higher than the default soft limit for cases where the default is
2420 * lower than the hard limit, e.g. RLIMIT_CORE or RLIMIT_STACK.
2421 */
2422 rc = avc_has_perm(new_tsec->osid, new_tsec->sid, SECCLASS_PROCESS,
2423 PROCESS__RLIMITINH, NULL);
2424 if (rc) {
Oleg Nesteroveb2d55a2010-06-23 22:43:32 +02002425 /* protect against do_prlimit() */
2426 task_lock(current);
David Howellsa6f76f22008-11-14 10:39:24 +11002427 for (i = 0; i < RLIM_NLIMITS; i++) {
2428 rlim = current->signal->rlim + i;
2429 initrlim = init_task.signal->rlim + i;
2430 rlim->rlim_cur = min(rlim->rlim_max, initrlim->rlim_cur);
2431 }
Oleg Nesteroveb2d55a2010-06-23 22:43:32 +02002432 task_unlock(current);
2433 update_rlimit_cpu(current, rlimit(RLIMIT_CPU));
David Howellsa6f76f22008-11-14 10:39:24 +11002434 }
2435}
2436
2437/*
2438 * Clean up the process immediately after the installation of new credentials
2439 * due to exec
2440 */
2441static void selinux_bprm_committed_creds(struct linux_binprm *bprm)
2442{
2443 const struct task_security_struct *tsec = current_security();
2444 struct itimerval itimer;
David Howellsa6f76f22008-11-14 10:39:24 +11002445 u32 osid, sid;
2446 int rc, i;
David Howellsa6f76f22008-11-14 10:39:24 +11002447
David Howellsa6f76f22008-11-14 10:39:24 +11002448 osid = tsec->osid;
2449 sid = tsec->sid;
2450
2451 if (sid == osid)
2452 return;
2453
2454 /* Check whether the new SID can inherit signal state from the old SID.
2455 * If not, clear itimers to avoid subsequent signal generation and
2456 * flush and unblock signals.
2457 *
2458 * This must occur _after_ the task SID has been updated so that any
2459 * kill done after the flush will be checked against the new SID.
2460 */
2461 rc = avc_has_perm(osid, sid, SECCLASS_PROCESS, PROCESS__SIGINH, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002462 if (rc) {
2463 memset(&itimer, 0, sizeof itimer);
2464 for (i = 0; i < 3; i++)
2465 do_setitimer(i, &itimer, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002466 spin_lock_irq(&current->sighand->siglock);
Oleg Nesterov9e7c8f82015-06-04 16:22:16 -04002467 if (!fatal_signal_pending(current)) {
2468 flush_sigqueue(&current->pending);
2469 flush_sigqueue(&current->signal->shared_pending);
David Howells3bcac022009-04-29 13:45:05 +01002470 flush_signal_handlers(current, 1);
2471 sigemptyset(&current->blocked);
Oleg Nesterov9e7c8f82015-06-04 16:22:16 -04002472 recalc_sigpending();
David Howells3bcac022009-04-29 13:45:05 +01002473 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002474 spin_unlock_irq(&current->sighand->siglock);
2475 }
2476
David Howellsa6f76f22008-11-14 10:39:24 +11002477 /* Wake up the parent if it is waiting so that it can recheck
2478 * wait permission to the new task SID. */
Oleg Nesterovecd6de32009-04-29 16:02:24 +02002479 read_lock(&tasklist_lock);
Oleg Nesterov0b7570e2009-09-23 15:56:46 -07002480 __wake_up_parent(current, current->real_parent);
Oleg Nesterovecd6de32009-04-29 16:02:24 +02002481 read_unlock(&tasklist_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002482}
2483
2484/* superblock security operations */
2485
2486static int selinux_sb_alloc_security(struct super_block *sb)
2487{
2488 return superblock_alloc_security(sb);
2489}
2490
2491static void selinux_sb_free_security(struct super_block *sb)
2492{
2493 superblock_free_security(sb);
2494}
2495
2496static inline int match_prefix(char *prefix, int plen, char *option, int olen)
2497{
2498 if (plen > olen)
2499 return 0;
2500
2501 return !memcmp(prefix, option, plen);
2502}
2503
2504static inline int selinux_option(char *option, int len)
2505{
Eric Paris832cbd92008-04-01 13:24:09 -04002506 return (match_prefix(CONTEXT_STR, sizeof(CONTEXT_STR)-1, option, len) ||
2507 match_prefix(FSCONTEXT_STR, sizeof(FSCONTEXT_STR)-1, option, len) ||
2508 match_prefix(DEFCONTEXT_STR, sizeof(DEFCONTEXT_STR)-1, option, len) ||
David P. Quigley11689d42009-01-16 09:22:03 -05002509 match_prefix(ROOTCONTEXT_STR, sizeof(ROOTCONTEXT_STR)-1, option, len) ||
2510 match_prefix(LABELSUPP_STR, sizeof(LABELSUPP_STR)-1, option, len));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002511}
2512
2513static inline void take_option(char **to, char *from, int *first, int len)
2514{
2515 if (!*first) {
2516 **to = ',';
2517 *to += 1;
Cory Olmo3528a952006-09-29 01:58:44 -07002518 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002519 *first = 0;
2520 memcpy(*to, from, len);
2521 *to += len;
2522}
2523
Eric Paris828dfe12008-04-17 13:17:49 -04002524static inline void take_selinux_option(char **to, char *from, int *first,
2525 int len)
Cory Olmo3528a952006-09-29 01:58:44 -07002526{
2527 int current_size = 0;
2528
2529 if (!*first) {
2530 **to = '|';
2531 *to += 1;
Eric Paris828dfe12008-04-17 13:17:49 -04002532 } else
Cory Olmo3528a952006-09-29 01:58:44 -07002533 *first = 0;
2534
2535 while (current_size < len) {
2536 if (*from != '"') {
2537 **to = *from;
2538 *to += 1;
2539 }
2540 from += 1;
2541 current_size += 1;
2542 }
2543}
2544
Eric Parise0007522008-03-05 10:31:54 -05002545static int selinux_sb_copy_data(char *orig, char *copy)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002546{
2547 int fnosec, fsec, rc = 0;
2548 char *in_save, *in_curr, *in_end;
2549 char *sec_curr, *nosec_save, *nosec;
Cory Olmo3528a952006-09-29 01:58:44 -07002550 int open_quote = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002551
2552 in_curr = orig;
2553 sec_curr = copy;
2554
Linus Torvalds1da177e2005-04-16 15:20:36 -07002555 nosec = (char *)get_zeroed_page(GFP_KERNEL);
2556 if (!nosec) {
2557 rc = -ENOMEM;
2558 goto out;
2559 }
2560
2561 nosec_save = nosec;
2562 fnosec = fsec = 1;
2563 in_save = in_end = orig;
2564
2565 do {
Cory Olmo3528a952006-09-29 01:58:44 -07002566 if (*in_end == '"')
2567 open_quote = !open_quote;
2568 if ((*in_end == ',' && open_quote == 0) ||
2569 *in_end == '\0') {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002570 int len = in_end - in_curr;
2571
2572 if (selinux_option(in_curr, len))
Cory Olmo3528a952006-09-29 01:58:44 -07002573 take_selinux_option(&sec_curr, in_curr, &fsec, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002574 else
2575 take_option(&nosec, in_curr, &fnosec, len);
2576
2577 in_curr = in_end + 1;
2578 }
2579 } while (*in_end++);
2580
Eric Paris6931dfc2005-06-30 02:58:51 -07002581 strcpy(in_save, nosec_save);
Gerald Schaeferda3caa22005-06-21 17:15:18 -07002582 free_page((unsigned long)nosec_save);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002583out:
2584 return rc;
2585}
2586
Eric Paris026eb162011-03-03 16:09:14 -05002587static int selinux_sb_remount(struct super_block *sb, void *data)
2588{
2589 int rc, i, *flags;
2590 struct security_mnt_opts opts;
2591 char *secdata, **mount_options;
2592 struct superblock_security_struct *sbsec = sb->s_security;
2593
2594 if (!(sbsec->flags & SE_SBINITIALIZED))
2595 return 0;
2596
2597 if (!data)
2598 return 0;
2599
2600 if (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)
2601 return 0;
2602
2603 security_init_mnt_opts(&opts);
2604 secdata = alloc_secdata();
2605 if (!secdata)
2606 return -ENOMEM;
2607 rc = selinux_sb_copy_data(data, secdata);
2608 if (rc)
2609 goto out_free_secdata;
2610
2611 rc = selinux_parse_opts_str(secdata, &opts);
2612 if (rc)
2613 goto out_free_secdata;
2614
2615 mount_options = opts.mnt_opts;
2616 flags = opts.mnt_opts_flags;
2617
2618 for (i = 0; i < opts.num_mnt_opts; i++) {
2619 u32 sid;
Eric Paris026eb162011-03-03 16:09:14 -05002620
Eric Paris12f348b2012-10-09 10:56:25 -04002621 if (flags[i] == SBLABEL_MNT)
Eric Paris026eb162011-03-03 16:09:14 -05002622 continue;
Rasmus Villemoes44be2f62015-10-21 17:44:25 -04002623 rc = security_context_str_to_sid(mount_options[i], &sid, GFP_KERNEL);
Eric Paris026eb162011-03-03 16:09:14 -05002624 if (rc) {
Rasmus Villemoes44be2f62015-10-21 17:44:25 -04002625 printk(KERN_WARNING "SELinux: security_context_str_to_sid"
Linus Torvalds29b1deb2013-12-15 11:17:45 -08002626 "(%s) failed for (dev %s, type %s) errno=%d\n",
2627 mount_options[i], sb->s_id, sb->s_type->name, rc);
Eric Paris026eb162011-03-03 16:09:14 -05002628 goto out_free_opts;
2629 }
2630 rc = -EINVAL;
2631 switch (flags[i]) {
2632 case FSCONTEXT_MNT:
2633 if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid, sid))
2634 goto out_bad_option;
2635 break;
2636 case CONTEXT_MNT:
2637 if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid, sid))
2638 goto out_bad_option;
2639 break;
2640 case ROOTCONTEXT_MNT: {
2641 struct inode_security_struct *root_isec;
David Howellsc6f493d2015-03-17 22:26:22 +00002642 root_isec = d_backing_inode(sb->s_root)->i_security;
Eric Paris026eb162011-03-03 16:09:14 -05002643
2644 if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid, sid))
2645 goto out_bad_option;
2646 break;
2647 }
2648 case DEFCONTEXT_MNT:
2649 if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid, sid))
2650 goto out_bad_option;
2651 break;
2652 default:
2653 goto out_free_opts;
2654 }
2655 }
2656
2657 rc = 0;
2658out_free_opts:
2659 security_free_mnt_opts(&opts);
2660out_free_secdata:
2661 free_secdata(secdata);
2662 return rc;
2663out_bad_option:
2664 printk(KERN_WARNING "SELinux: unable to change security options "
Linus Torvalds29b1deb2013-12-15 11:17:45 -08002665 "during remount (dev %s, type=%s)\n", sb->s_id,
2666 sb->s_type->name);
Eric Paris026eb162011-03-03 16:09:14 -05002667 goto out_free_opts;
2668}
2669
James Morris12204e22008-12-19 10:44:42 +11002670static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002671{
David Howells88e67f32008-11-14 10:39:21 +11002672 const struct cred *cred = current_cred();
Thomas Liu2bf49692009-07-14 12:14:09 -04002673 struct common_audit_data ad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002674 int rc;
2675
2676 rc = superblock_doinit(sb, data);
2677 if (rc)
2678 return rc;
2679
James Morris74192242008-12-19 11:41:10 +11002680 /* Allow all mounts performed by the kernel */
2681 if (flags & MS_KERNMOUNT)
2682 return 0;
2683
Eric Paris50c205f2012-04-04 15:01:43 -04002684 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04002685 ad.u.dentry = sb->s_root;
David Howells88e67f32008-11-14 10:39:21 +11002686 return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002687}
2688
David Howells726c3342006-06-23 02:02:58 -07002689static int selinux_sb_statfs(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002690{
David Howells88e67f32008-11-14 10:39:21 +11002691 const struct cred *cred = current_cred();
Thomas Liu2bf49692009-07-14 12:14:09 -04002692 struct common_audit_data ad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002693
Eric Paris50c205f2012-04-04 15:01:43 -04002694 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04002695 ad.u.dentry = dentry->d_sb->s_root;
David Howells88e67f32008-11-14 10:39:21 +11002696 return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002697}
2698
Al Viro808d4e32012-10-11 11:42:01 -04002699static int selinux_mount(const char *dev_name,
Al Virob5266eb2008-03-22 17:48:24 -04002700 struct path *path,
Al Viro808d4e32012-10-11 11:42:01 -04002701 const char *type,
Eric Paris828dfe12008-04-17 13:17:49 -04002702 unsigned long flags,
2703 void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002704{
David Howells88e67f32008-11-14 10:39:21 +11002705 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002706
2707 if (flags & MS_REMOUNT)
Al Virod8c95842011-12-07 18:16:57 -05002708 return superblock_has_perm(cred, path->dentry->d_sb,
Eric Paris828dfe12008-04-17 13:17:49 -04002709 FILESYSTEM__REMOUNT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002710 else
Eric Paris2875fa02011-04-28 16:04:24 -04002711 return path_has_perm(cred, path, FILE__MOUNTON);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002712}
2713
2714static int selinux_umount(struct vfsmount *mnt, int flags)
2715{
David Howells88e67f32008-11-14 10:39:21 +11002716 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002717
David Howells88e67f32008-11-14 10:39:21 +11002718 return superblock_has_perm(cred, mnt->mnt_sb,
Eric Paris828dfe12008-04-17 13:17:49 -04002719 FILESYSTEM__UNMOUNT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002720}
2721
2722/* inode security operations */
2723
2724static int selinux_inode_alloc_security(struct inode *inode)
2725{
2726 return inode_alloc_security(inode);
2727}
2728
2729static void selinux_inode_free_security(struct inode *inode)
2730{
2731 inode_free_security(inode);
2732}
2733
David Quigleyd47be3d2013-05-22 12:50:34 -04002734static int selinux_dentry_init_security(struct dentry *dentry, int mode,
2735 struct qstr *name, void **ctx,
2736 u32 *ctxlen)
2737{
David Quigleyd47be3d2013-05-22 12:50:34 -04002738 u32 newsid;
2739 int rc;
2740
David Howellsc3c188b2015-07-10 17:19:58 -04002741 rc = selinux_determine_inode_label(d_inode(dentry->d_parent), name,
2742 inode_mode_to_security_class(mode),
2743 &newsid);
2744 if (rc)
2745 return rc;
David Quigleyd47be3d2013-05-22 12:50:34 -04002746
2747 return security_sid_to_context(newsid, (char **)ctx, ctxlen);
2748}
2749
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002750static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
Tetsuo Handa95489062013-07-25 05:44:02 +09002751 const struct qstr *qstr,
2752 const char **name,
Eric Paris2a7dba32011-02-01 11:05:39 -05002753 void **value, size_t *len)
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002754{
Paul Moore5fb49872010-04-22 14:46:19 -04002755 const struct task_security_struct *tsec = current_security();
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002756 struct inode_security_struct *dsec;
2757 struct superblock_security_struct *sbsec;
David Howells275bb412008-11-14 10:39:19 +11002758 u32 sid, newsid, clen;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002759 int rc;
Tetsuo Handa95489062013-07-25 05:44:02 +09002760 char *context;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002761
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002762 dsec = dir->i_security;
2763 sbsec = dir->i_sb->s_security;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002764
David Howells275bb412008-11-14 10:39:19 +11002765 sid = tsec->sid;
2766 newsid = tsec->create_sid;
2767
David Howellsc3c188b2015-07-10 17:19:58 -04002768 rc = selinux_determine_inode_label(
2769 dir, qstr,
2770 inode_mode_to_security_class(inode->i_mode),
2771 &newsid);
2772 if (rc)
2773 return rc;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002774
Eric Paris296fddf2006-09-25 23:32:00 -07002775 /* Possibly defer initialization to selinux_complete_init. */
David P. Quigley0d90a7e2009-01-16 09:22:02 -05002776 if (sbsec->flags & SE_SBINITIALIZED) {
Eric Paris296fddf2006-09-25 23:32:00 -07002777 struct inode_security_struct *isec = inode->i_security;
2778 isec->sclass = inode_mode_to_security_class(inode->i_mode);
2779 isec->sid = newsid;
2780 isec->initialized = 1;
2781 }
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002782
Eric Paris12f348b2012-10-09 10:56:25 -04002783 if (!ss_initialized || !(sbsec->flags & SBLABEL_MNT))
Stephen Smalley25a74f32005-11-08 21:34:33 -08002784 return -EOPNOTSUPP;
2785
Tetsuo Handa95489062013-07-25 05:44:02 +09002786 if (name)
2787 *name = XATTR_SELINUX_SUFFIX;
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002788
2789 if (value && len) {
Stephen Smalley12b29f32008-05-07 13:03:20 -04002790 rc = security_sid_to_context_force(newsid, &context, &clen);
Tetsuo Handa95489062013-07-25 05:44:02 +09002791 if (rc)
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002792 return rc;
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002793 *value = context;
2794 *len = clen;
2795 }
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002796
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002797 return 0;
2798}
2799
Al Viro4acdaf22011-07-26 01:42:34 -04002800static int selinux_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002801{
2802 return may_create(dir, dentry, SECCLASS_FILE);
2803}
2804
Linus Torvalds1da177e2005-04-16 15:20:36 -07002805static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
2806{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002807 return may_link(dir, old_dentry, MAY_LINK);
2808}
2809
Linus Torvalds1da177e2005-04-16 15:20:36 -07002810static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry)
2811{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002812 return may_link(dir, dentry, MAY_UNLINK);
2813}
2814
2815static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry, const char *name)
2816{
2817 return may_create(dir, dentry, SECCLASS_LNK_FILE);
2818}
2819
Al Viro18bb1db2011-07-26 01:41:39 -04002820static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry, umode_t mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002821{
2822 return may_create(dir, dentry, SECCLASS_DIR);
2823}
2824
Linus Torvalds1da177e2005-04-16 15:20:36 -07002825static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry)
2826{
2827 return may_link(dir, dentry, MAY_RMDIR);
2828}
2829
Al Viro1a67aaf2011-07-26 01:52:52 -04002830static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002831{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002832 return may_create(dir, dentry, inode_mode_to_security_class(mode));
2833}
2834
Linus Torvalds1da177e2005-04-16 15:20:36 -07002835static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
Eric Paris828dfe12008-04-17 13:17:49 -04002836 struct inode *new_inode, struct dentry *new_dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002837{
2838 return may_rename(old_inode, old_dentry, new_inode, new_dentry);
2839}
2840
Linus Torvalds1da177e2005-04-16 15:20:36 -07002841static int selinux_inode_readlink(struct dentry *dentry)
2842{
David Howells88e67f32008-11-14 10:39:21 +11002843 const struct cred *cred = current_cred();
2844
Eric Paris2875fa02011-04-28 16:04:24 -04002845 return dentry_has_perm(cred, dentry, FILE__READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002846}
2847
NeilBrownbda0be72015-03-23 13:37:39 +11002848static int selinux_inode_follow_link(struct dentry *dentry, struct inode *inode,
2849 bool rcu)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002850{
David Howells88e67f32008-11-14 10:39:21 +11002851 const struct cred *cred = current_cred();
NeilBrownbda0be72015-03-23 13:37:39 +11002852 struct common_audit_data ad;
2853 struct inode_security_struct *isec;
2854 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002855
NeilBrownbda0be72015-03-23 13:37:39 +11002856 validate_creds(cred);
2857
2858 ad.type = LSM_AUDIT_DATA_DENTRY;
2859 ad.u.dentry = dentry;
2860 sid = cred_sid(cred);
2861 isec = inode->i_security;
2862
2863 return avc_has_perm_flags(sid, isec->sid, isec->sclass, FILE__READ, &ad,
2864 rcu ? MAY_NOT_BLOCK : 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002865}
2866
Eric Parisd4cf970d2012-04-04 15:01:42 -04002867static noinline int audit_inode_permission(struct inode *inode,
2868 u32 perms, u32 audited, u32 denied,
Stephen Smalley626b9742014-04-29 11:29:04 -07002869 int result,
Eric Parisd4cf970d2012-04-04 15:01:42 -04002870 unsigned flags)
2871{
2872 struct common_audit_data ad;
Eric Parisd4cf970d2012-04-04 15:01:42 -04002873 struct inode_security_struct *isec = inode->i_security;
2874 int rc;
2875
Eric Paris50c205f2012-04-04 15:01:43 -04002876 ad.type = LSM_AUDIT_DATA_INODE;
Eric Parisd4cf970d2012-04-04 15:01:42 -04002877 ad.u.inode = inode;
2878
2879 rc = slow_avc_audit(current_sid(), isec->sid, isec->sclass, perms,
Stephen Smalley626b9742014-04-29 11:29:04 -07002880 audited, denied, result, &ad, flags);
Eric Parisd4cf970d2012-04-04 15:01:42 -04002881 if (rc)
2882 return rc;
2883 return 0;
2884}
2885
Al Viroe74f71e2011-06-20 19:38:15 -04002886static int selinux_inode_permission(struct inode *inode, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002887{
David Howells88e67f32008-11-14 10:39:21 +11002888 const struct cred *cred = current_cred();
Eric Parisb782e0a2010-07-23 11:44:03 -04002889 u32 perms;
2890 bool from_access;
Al Virocf1dd1d2011-06-20 19:44:08 -04002891 unsigned flags = mask & MAY_NOT_BLOCK;
Eric Paris2e334052012-04-04 15:01:42 -04002892 struct inode_security_struct *isec;
2893 u32 sid;
2894 struct av_decision avd;
2895 int rc, rc2;
2896 u32 audited, denied;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002897
Eric Parisb782e0a2010-07-23 11:44:03 -04002898 from_access = mask & MAY_ACCESS;
Eric Parisd09ca732010-07-23 11:43:57 -04002899 mask &= (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND);
2900
Eric Parisb782e0a2010-07-23 11:44:03 -04002901 /* No permission to check. Existence test. */
2902 if (!mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002903 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002904
Eric Paris2e334052012-04-04 15:01:42 -04002905 validate_creds(cred);
Eric Parisb782e0a2010-07-23 11:44:03 -04002906
Eric Paris2e334052012-04-04 15:01:42 -04002907 if (unlikely(IS_PRIVATE(inode)))
2908 return 0;
Eric Parisb782e0a2010-07-23 11:44:03 -04002909
2910 perms = file_mask_to_av(inode->i_mode, mask);
2911
Eric Paris2e334052012-04-04 15:01:42 -04002912 sid = cred_sid(cred);
2913 isec = inode->i_security;
2914
2915 rc = avc_has_perm_noaudit(sid, isec->sid, isec->sclass, perms, 0, &avd);
2916 audited = avc_audit_required(perms, &avd, rc,
2917 from_access ? FILE__AUDIT_ACCESS : 0,
2918 &denied);
2919 if (likely(!audited))
2920 return rc;
2921
Stephen Smalley626b9742014-04-29 11:29:04 -07002922 rc2 = audit_inode_permission(inode, perms, audited, denied, rc, flags);
Eric Paris2e334052012-04-04 15:01:42 -04002923 if (rc2)
2924 return rc2;
2925 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002926}
2927
2928static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
2929{
David Howells88e67f32008-11-14 10:39:21 +11002930 const struct cred *cred = current_cred();
Amerigo Wangbc6a6002009-08-20 19:29:02 -07002931 unsigned int ia_valid = iattr->ia_valid;
Eric Paris95dbf732012-04-04 13:45:34 -04002932 __u32 av = FILE__WRITE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002933
Amerigo Wangbc6a6002009-08-20 19:29:02 -07002934 /* ATTR_FORCE is just used for ATTR_KILL_S[UG]ID. */
2935 if (ia_valid & ATTR_FORCE) {
2936 ia_valid &= ~(ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_MODE |
2937 ATTR_FORCE);
2938 if (!ia_valid)
2939 return 0;
2940 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002941
Amerigo Wangbc6a6002009-08-20 19:29:02 -07002942 if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID |
2943 ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_TIMES_SET))
Eric Paris2875fa02011-04-28 16:04:24 -04002944 return dentry_has_perm(cred, dentry, FILE__SETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002945
Jeff Vander Stoep44d37ad2015-10-21 17:44:25 -04002946 if (selinux_policycap_openperm && (ia_valid & ATTR_SIZE)
2947 && !(ia_valid & ATTR_FILE))
Eric Paris95dbf732012-04-04 13:45:34 -04002948 av |= FILE__OPEN;
2949
2950 return dentry_has_perm(cred, dentry, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002951}
2952
Al Viro3f7036a2015-03-08 19:28:30 -04002953static int selinux_inode_getattr(const struct path *path)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002954{
Al Viro3f7036a2015-03-08 19:28:30 -04002955 return path_has_perm(current_cred(), path, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002956}
2957
David Howells8f0cfa52008-04-29 00:59:41 -07002958static int selinux_inode_setotherxattr(struct dentry *dentry, const char *name)
Serge E. Hallynb5376772007-10-16 23:31:36 -07002959{
David Howells88e67f32008-11-14 10:39:21 +11002960 const struct cred *cred = current_cred();
2961
Serge E. Hallynb5376772007-10-16 23:31:36 -07002962 if (!strncmp(name, XATTR_SECURITY_PREFIX,
2963 sizeof XATTR_SECURITY_PREFIX - 1)) {
2964 if (!strcmp(name, XATTR_NAME_CAPS)) {
2965 if (!capable(CAP_SETFCAP))
2966 return -EPERM;
2967 } else if (!capable(CAP_SYS_ADMIN)) {
2968 /* A different attribute in the security namespace.
2969 Restrict to administrator. */
2970 return -EPERM;
2971 }
2972 }
2973
2974 /* Not an attribute we recognize, so just check the
2975 ordinary setattr permission. */
Eric Paris2875fa02011-04-28 16:04:24 -04002976 return dentry_has_perm(cred, dentry, FILE__SETATTR);
Serge E. Hallynb5376772007-10-16 23:31:36 -07002977}
2978
David Howells8f0cfa52008-04-29 00:59:41 -07002979static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
2980 const void *value, size_t size, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002981{
David Howellsc6f493d2015-03-17 22:26:22 +00002982 struct inode *inode = d_backing_inode(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002983 struct inode_security_struct *isec = inode->i_security;
2984 struct superblock_security_struct *sbsec;
Thomas Liu2bf49692009-07-14 12:14:09 -04002985 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11002986 u32 newsid, sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002987 int rc = 0;
2988
Serge E. Hallynb5376772007-10-16 23:31:36 -07002989 if (strcmp(name, XATTR_NAME_SELINUX))
2990 return selinux_inode_setotherxattr(dentry, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002991
2992 sbsec = inode->i_sb->s_security;
Eric Paris12f348b2012-10-09 10:56:25 -04002993 if (!(sbsec->flags & SBLABEL_MNT))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002994 return -EOPNOTSUPP;
2995
Serge E. Hallyn2e149672011-03-23 16:43:26 -07002996 if (!inode_owner_or_capable(inode))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002997 return -EPERM;
2998
Eric Paris50c205f2012-04-04 15:01:43 -04002999 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04003000 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003001
David Howells275bb412008-11-14 10:39:19 +11003002 rc = avc_has_perm(sid, isec->sid, isec->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003003 FILE__RELABELFROM, &ad);
3004 if (rc)
3005 return rc;
3006
Nikolay Aleksandrov52a4c642014-03-07 12:44:19 +01003007 rc = security_context_to_sid(value, size, &newsid, GFP_KERNEL);
Stephen Smalley12b29f32008-05-07 13:03:20 -04003008 if (rc == -EINVAL) {
Eric Parisd6ea83e2012-04-04 13:45:49 -04003009 if (!capable(CAP_MAC_ADMIN)) {
3010 struct audit_buffer *ab;
3011 size_t audit_size;
3012 const char *str;
3013
3014 /* We strip a nul only if it is at the end, otherwise the
3015 * context contains a nul and we should audit that */
Al Viroe3fea3f2012-06-09 08:15:16 +01003016 if (value) {
3017 str = value;
3018 if (str[size - 1] == '\0')
3019 audit_size = size - 1;
3020 else
3021 audit_size = size;
3022 } else {
3023 str = "";
3024 audit_size = 0;
3025 }
Eric Parisd6ea83e2012-04-04 13:45:49 -04003026 ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR);
3027 audit_log_format(ab, "op=setxattr invalid_context=");
3028 audit_log_n_untrustedstring(ab, value, audit_size);
3029 audit_log_end(ab);
3030
Stephen Smalley12b29f32008-05-07 13:03:20 -04003031 return rc;
Eric Parisd6ea83e2012-04-04 13:45:49 -04003032 }
Stephen Smalley12b29f32008-05-07 13:03:20 -04003033 rc = security_context_to_sid_force(value, size, &newsid);
3034 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003035 if (rc)
3036 return rc;
3037
David Howells275bb412008-11-14 10:39:19 +11003038 rc = avc_has_perm(sid, newsid, isec->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003039 FILE__RELABELTO, &ad);
3040 if (rc)
3041 return rc;
3042
David Howells275bb412008-11-14 10:39:19 +11003043 rc = security_validate_transition(isec->sid, newsid, sid,
Eric Paris828dfe12008-04-17 13:17:49 -04003044 isec->sclass);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003045 if (rc)
3046 return rc;
3047
3048 return avc_has_perm(newsid,
3049 sbsec->sid,
3050 SECCLASS_FILESYSTEM,
3051 FILESYSTEM__ASSOCIATE,
3052 &ad);
3053}
3054
David Howells8f0cfa52008-04-29 00:59:41 -07003055static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
Eric Parisf5269712008-05-14 11:27:45 -04003056 const void *value, size_t size,
David Howells8f0cfa52008-04-29 00:59:41 -07003057 int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003058{
David Howellsc6f493d2015-03-17 22:26:22 +00003059 struct inode *inode = d_backing_inode(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003060 struct inode_security_struct *isec = inode->i_security;
3061 u32 newsid;
3062 int rc;
3063
3064 if (strcmp(name, XATTR_NAME_SELINUX)) {
3065 /* Not an attribute we recognize, so nothing to do. */
3066 return;
3067 }
3068
Stephen Smalley12b29f32008-05-07 13:03:20 -04003069 rc = security_context_to_sid_force(value, size, &newsid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003070 if (rc) {
Stephen Smalley12b29f32008-05-07 13:03:20 -04003071 printk(KERN_ERR "SELinux: unable to map context to SID"
3072 "for (%s, %lu), rc=%d\n",
3073 inode->i_sb->s_id, inode->i_ino, -rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003074 return;
3075 }
3076
David Quigleyaa9c2662013-05-22 12:50:44 -04003077 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003078 isec->sid = newsid;
David Quigleyaa9c2662013-05-22 12:50:44 -04003079 isec->initialized = 1;
3080
Linus Torvalds1da177e2005-04-16 15:20:36 -07003081 return;
3082}
3083
David Howells8f0cfa52008-04-29 00:59:41 -07003084static int selinux_inode_getxattr(struct dentry *dentry, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003085{
David Howells88e67f32008-11-14 10:39:21 +11003086 const struct cred *cred = current_cred();
3087
Eric Paris2875fa02011-04-28 16:04:24 -04003088 return dentry_has_perm(cred, dentry, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003089}
3090
Eric Paris828dfe12008-04-17 13:17:49 -04003091static int selinux_inode_listxattr(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003092{
David Howells88e67f32008-11-14 10:39:21 +11003093 const struct cred *cred = current_cred();
3094
Eric Paris2875fa02011-04-28 16:04:24 -04003095 return dentry_has_perm(cred, dentry, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003096}
3097
David Howells8f0cfa52008-04-29 00:59:41 -07003098static int selinux_inode_removexattr(struct dentry *dentry, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003099{
Serge E. Hallynb5376772007-10-16 23:31:36 -07003100 if (strcmp(name, XATTR_NAME_SELINUX))
3101 return selinux_inode_setotherxattr(dentry, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003102
3103 /* No one is allowed to remove a SELinux security label.
3104 You can change the label, but all data must be labeled. */
3105 return -EACCES;
3106}
3107
James Morrisd381d8a2005-10-30 14:59:22 -08003108/*
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04003109 * Copy the inode security context value to the user.
James Morrisd381d8a2005-10-30 14:59:22 -08003110 *
3111 * Permission check is handled by selinux_inode_getxattr hook.
3112 */
David P. Quigley42492592008-02-04 22:29:39 -08003113static int selinux_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003114{
David P. Quigley42492592008-02-04 22:29:39 -08003115 u32 size;
3116 int error;
3117 char *context = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003118 struct inode_security_struct *isec = inode->i_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003119
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00003120 if (strcmp(name, XATTR_SELINUX_SUFFIX))
3121 return -EOPNOTSUPP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003122
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04003123 /*
3124 * If the caller has CAP_MAC_ADMIN, then get the raw context
3125 * value even if it is not defined by current policy; otherwise,
3126 * use the in-core value under current policy.
3127 * Use the non-auditing forms of the permission checks since
3128 * getxattr may be called by unprivileged processes commonly
3129 * and lack of permission just means that we fall back to the
3130 * in-core context value, not a denial.
3131 */
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07003132 error = cap_capable(current_cred(), &init_user_ns, CAP_MAC_ADMIN,
3133 SECURITY_CAP_NOAUDIT);
3134 if (!error)
3135 error = cred_has_capability(current_cred(), CAP_MAC_ADMIN,
3136 SECURITY_CAP_NOAUDIT);
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04003137 if (!error)
3138 error = security_sid_to_context_force(isec->sid, &context,
3139 &size);
3140 else
3141 error = security_sid_to_context(isec->sid, &context, &size);
David P. Quigley42492592008-02-04 22:29:39 -08003142 if (error)
3143 return error;
3144 error = size;
3145 if (alloc) {
3146 *buffer = context;
3147 goto out_nofree;
3148 }
3149 kfree(context);
3150out_nofree:
3151 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003152}
3153
3154static int selinux_inode_setsecurity(struct inode *inode, const char *name,
Eric Paris828dfe12008-04-17 13:17:49 -04003155 const void *value, size_t size, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003156{
3157 struct inode_security_struct *isec = inode->i_security;
3158 u32 newsid;
3159 int rc;
3160
3161 if (strcmp(name, XATTR_SELINUX_SUFFIX))
3162 return -EOPNOTSUPP;
3163
3164 if (!value || !size)
3165 return -EACCES;
3166
Rasmus Villemoes20ba96a2015-10-21 17:44:26 -04003167 rc = security_context_to_sid(value, size, &newsid, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003168 if (rc)
3169 return rc;
3170
David Quigleyaa9c2662013-05-22 12:50:44 -04003171 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003172 isec->sid = newsid;
David P. Quigleyddd29ec2009-09-09 14:25:37 -04003173 isec->initialized = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003174 return 0;
3175}
3176
3177static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size)
3178{
3179 const int len = sizeof(XATTR_NAME_SELINUX);
3180 if (buffer && len <= buffer_size)
3181 memcpy(buffer, XATTR_NAME_SELINUX, len);
3182 return len;
3183}
3184
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02003185static void selinux_inode_getsecid(const struct inode *inode, u32 *secid)
3186{
3187 struct inode_security_struct *isec = inode->i_security;
3188 *secid = isec->sid;
3189}
3190
Linus Torvalds1da177e2005-04-16 15:20:36 -07003191/* file security operations */
3192
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003193static int selinux_revalidate_file_permission(struct file *file, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003194{
David Howells88e67f32008-11-14 10:39:21 +11003195 const struct cred *cred = current_cred();
Al Viro496ad9a2013-01-23 17:07:38 -05003196 struct inode *inode = file_inode(file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003197
Linus Torvalds1da177e2005-04-16 15:20:36 -07003198 /* file_mask_to_av won't add FILE__WRITE if MAY_APPEND is set */
3199 if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE))
3200 mask |= MAY_APPEND;
3201
Paul Moore389fb8002009-03-27 17:10:34 -04003202 return file_has_perm(cred, file,
3203 file_mask_to_av(inode->i_mode, mask));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003204}
3205
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003206static int selinux_file_permission(struct file *file, int mask)
3207{
Al Viro496ad9a2013-01-23 17:07:38 -05003208 struct inode *inode = file_inode(file);
Stephen Smalley20dda182009-06-22 14:54:53 -04003209 struct file_security_struct *fsec = file->f_security;
3210 struct inode_security_struct *isec = inode->i_security;
3211 u32 sid = current_sid();
3212
Paul Moore389fb8002009-03-27 17:10:34 -04003213 if (!mask)
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003214 /* No permission to check. Existence test. */
3215 return 0;
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003216
Stephen Smalley20dda182009-06-22 14:54:53 -04003217 if (sid == fsec->sid && fsec->isid == isec->sid &&
3218 fsec->pseqno == avc_policy_seqno())
Eric Paris83d49852012-04-04 13:45:40 -04003219 /* No change since file_open check. */
Stephen Smalley20dda182009-06-22 14:54:53 -04003220 return 0;
3221
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003222 return selinux_revalidate_file_permission(file, mask);
3223}
3224
Linus Torvalds1da177e2005-04-16 15:20:36 -07003225static int selinux_file_alloc_security(struct file *file)
3226{
3227 return file_alloc_security(file);
3228}
3229
3230static void selinux_file_free_security(struct file *file)
3231{
3232 file_free_security(file);
3233}
3234
Jeff Vander Stoepfa1aa142015-07-10 17:19:56 -04003235/*
3236 * Check whether a task has the ioctl permission and cmd
3237 * operation to an inode.
3238 */
Geliang Tang1d2a1682015-10-21 17:44:27 -04003239static int ioctl_has_perm(const struct cred *cred, struct file *file,
Jeff Vander Stoepfa1aa142015-07-10 17:19:56 -04003240 u32 requested, u16 cmd)
3241{
3242 struct common_audit_data ad;
3243 struct file_security_struct *fsec = file->f_security;
3244 struct inode *inode = file_inode(file);
3245 struct inode_security_struct *isec = inode->i_security;
3246 struct lsm_ioctlop_audit ioctl;
3247 u32 ssid = cred_sid(cred);
3248 int rc;
3249 u8 driver = cmd >> 8;
3250 u8 xperm = cmd & 0xff;
3251
3252 ad.type = LSM_AUDIT_DATA_IOCTL_OP;
3253 ad.u.op = &ioctl;
3254 ad.u.op->cmd = cmd;
3255 ad.u.op->path = file->f_path;
3256
3257 if (ssid != fsec->sid) {
3258 rc = avc_has_perm(ssid, fsec->sid,
3259 SECCLASS_FD,
3260 FD__USE,
3261 &ad);
3262 if (rc)
3263 goto out;
3264 }
3265
3266 if (unlikely(IS_PRIVATE(inode)))
3267 return 0;
3268
3269 rc = avc_has_extended_perms(ssid, isec->sid, isec->sclass,
3270 requested, driver, xperm, &ad);
3271out:
3272 return rc;
3273}
3274
Linus Torvalds1da177e2005-04-16 15:20:36 -07003275static int selinux_file_ioctl(struct file *file, unsigned int cmd,
3276 unsigned long arg)
3277{
David Howells88e67f32008-11-14 10:39:21 +11003278 const struct cred *cred = current_cred();
Eric Paris0b24dcb2011-02-25 15:39:20 -05003279 int error = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003280
Eric Paris0b24dcb2011-02-25 15:39:20 -05003281 switch (cmd) {
3282 case FIONREAD:
3283 /* fall through */
3284 case FIBMAP:
3285 /* fall through */
3286 case FIGETBSZ:
3287 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003288 case FS_IOC_GETFLAGS:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003289 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003290 case FS_IOC_GETVERSION:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003291 error = file_has_perm(cred, file, FILE__GETATTR);
3292 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003293
Al Viro2f99c362012-03-23 16:04:05 -04003294 case FS_IOC_SETFLAGS:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003295 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003296 case FS_IOC_SETVERSION:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003297 error = file_has_perm(cred, file, FILE__SETATTR);
3298 break;
3299
3300 /* sys_ioctl() checks */
3301 case FIONBIO:
3302 /* fall through */
3303 case FIOASYNC:
3304 error = file_has_perm(cred, file, 0);
3305 break;
3306
3307 case KDSKBENT:
3308 case KDSKBSENT:
Eric Paris6a9de492012-01-03 12:25:14 -05003309 error = cred_has_capability(cred, CAP_SYS_TTY_CONFIG,
3310 SECURITY_CAP_AUDIT);
Eric Paris0b24dcb2011-02-25 15:39:20 -05003311 break;
3312
3313 /* default case assumes that the command will go
3314 * to the file's ioctl() function.
3315 */
3316 default:
Jeff Vander Stoepfa1aa142015-07-10 17:19:56 -04003317 error = ioctl_has_perm(cred, file, FILE__IOCTL, (u16) cmd);
Eric Paris0b24dcb2011-02-25 15:39:20 -05003318 }
3319 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003320}
3321
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003322static int default_noexec;
3323
Linus Torvalds1da177e2005-04-16 15:20:36 -07003324static int file_map_prot_check(struct file *file, unsigned long prot, int shared)
3325{
David Howells88e67f32008-11-14 10:39:21 +11003326 const struct cred *cred = current_cred();
David Howellsd84f4f92008-11-14 10:39:23 +11003327 int rc = 0;
David Howells88e67f32008-11-14 10:39:21 +11003328
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003329 if (default_noexec &&
Stephen Smalley892e8ca2015-07-10 09:40:59 -04003330 (prot & PROT_EXEC) && (!file || IS_PRIVATE(file_inode(file)) ||
3331 (!shared && (prot & PROT_WRITE)))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003332 /*
3333 * We are making executable an anonymous mapping or a
3334 * private file mapping that will also be writable.
3335 * This has an additional check.
3336 */
David Howellsd84f4f92008-11-14 10:39:23 +11003337 rc = cred_has_perm(cred, cred, PROCESS__EXECMEM);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003338 if (rc)
David Howellsd84f4f92008-11-14 10:39:23 +11003339 goto error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003340 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003341
3342 if (file) {
3343 /* read access is always possible with a mapping */
3344 u32 av = FILE__READ;
3345
3346 /* write access only matters if the mapping is shared */
3347 if (shared && (prot & PROT_WRITE))
3348 av |= FILE__WRITE;
3349
3350 if (prot & PROT_EXEC)
3351 av |= FILE__EXECUTE;
3352
David Howells88e67f32008-11-14 10:39:21 +11003353 return file_has_perm(cred, file, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003354 }
David Howellsd84f4f92008-11-14 10:39:23 +11003355
3356error:
3357 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003358}
3359
Al Viroe5467852012-05-30 13:30:51 -04003360static int selinux_mmap_addr(unsigned long addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003361{
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07003362 int rc = 0;
Paul Moore98883bf2014-03-19 16:46:11 -04003363
3364 if (addr < CONFIG_LSM_MMAP_MIN_ADDR) {
3365 u32 sid = current_sid();
3366 rc = avc_has_perm(sid, sid, SECCLASS_MEMPROTECT,
3367 MEMPROTECT__MMAP_ZERO, NULL);
3368 }
3369
3370 return rc;
Al Viroe5467852012-05-30 13:30:51 -04003371}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003372
Al Viroe5467852012-05-30 13:30:51 -04003373static int selinux_mmap_file(struct file *file, unsigned long reqprot,
3374 unsigned long prot, unsigned long flags)
3375{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003376 if (selinux_checkreqprot)
3377 prot = reqprot;
3378
3379 return file_map_prot_check(file, prot,
3380 (flags & MAP_TYPE) == MAP_SHARED);
3381}
3382
3383static int selinux_file_mprotect(struct vm_area_struct *vma,
3384 unsigned long reqprot,
3385 unsigned long prot)
3386{
David Howells88e67f32008-11-14 10:39:21 +11003387 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003388
3389 if (selinux_checkreqprot)
3390 prot = reqprot;
3391
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003392 if (default_noexec &&
3393 (prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) {
James Morrisd541bbe2009-01-29 12:19:51 +11003394 int rc = 0;
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003395 if (vma->vm_start >= vma->vm_mm->start_brk &&
3396 vma->vm_end <= vma->vm_mm->brk) {
David Howellsd84f4f92008-11-14 10:39:23 +11003397 rc = cred_has_perm(cred, cred, PROCESS__EXECHEAP);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003398 } else if (!vma->vm_file &&
3399 vma->vm_start <= vma->vm_mm->start_stack &&
3400 vma->vm_end >= vma->vm_mm->start_stack) {
David Howells3b11a1d2008-11-14 10:39:26 +11003401 rc = current_has_perm(current, PROCESS__EXECSTACK);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003402 } else if (vma->vm_file && vma->anon_vma) {
3403 /*
3404 * We are making executable a file mapping that has
3405 * had some COW done. Since pages might have been
3406 * written, check ability to execute the possibly
3407 * modified content. This typically should only
3408 * occur for text relocations.
3409 */
David Howellsd84f4f92008-11-14 10:39:23 +11003410 rc = file_has_perm(cred, vma->vm_file, FILE__EXECMOD);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003411 }
Lorenzo Hernandez García-Hierro6b992192005-06-25 14:54:34 -07003412 if (rc)
3413 return rc;
3414 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003415
3416 return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED);
3417}
3418
3419static int selinux_file_lock(struct file *file, unsigned int cmd)
3420{
David Howells88e67f32008-11-14 10:39:21 +11003421 const struct cred *cred = current_cred();
3422
3423 return file_has_perm(cred, file, FILE__LOCK);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003424}
3425
3426static int selinux_file_fcntl(struct file *file, unsigned int cmd,
3427 unsigned long arg)
3428{
David Howells88e67f32008-11-14 10:39:21 +11003429 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003430 int err = 0;
3431
3432 switch (cmd) {
Eric Paris828dfe12008-04-17 13:17:49 -04003433 case F_SETFL:
Eric Paris828dfe12008-04-17 13:17:49 -04003434 if ((file->f_flags & O_APPEND) && !(arg & O_APPEND)) {
David Howells88e67f32008-11-14 10:39:21 +11003435 err = file_has_perm(cred, file, FILE__WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003436 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003437 }
3438 /* fall through */
3439 case F_SETOWN:
3440 case F_SETSIG:
3441 case F_GETFL:
3442 case F_GETOWN:
3443 case F_GETSIG:
Cyrill Gorcunov1d151c32012-07-30 14:43:00 -07003444 case F_GETOWNER_UIDS:
Eric Paris828dfe12008-04-17 13:17:49 -04003445 /* Just check FD__USE permission */
David Howells88e67f32008-11-14 10:39:21 +11003446 err = file_has_perm(cred, file, 0);
Eric Paris828dfe12008-04-17 13:17:49 -04003447 break;
3448 case F_GETLK:
3449 case F_SETLK:
3450 case F_SETLKW:
Jeff Layton0d3f7a22014-04-22 08:23:58 -04003451 case F_OFD_GETLK:
3452 case F_OFD_SETLK:
3453 case F_OFD_SETLKW:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003454#if BITS_PER_LONG == 32
Eric Paris828dfe12008-04-17 13:17:49 -04003455 case F_GETLK64:
3456 case F_SETLK64:
3457 case F_SETLKW64:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003458#endif
David Howells88e67f32008-11-14 10:39:21 +11003459 err = file_has_perm(cred, file, FILE__LOCK);
Eric Paris828dfe12008-04-17 13:17:49 -04003460 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003461 }
3462
3463 return err;
3464}
3465
Jeff Laytone0b93ed2014-08-22 11:27:32 -04003466static void selinux_file_set_fowner(struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003467{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003468 struct file_security_struct *fsec;
3469
Linus Torvalds1da177e2005-04-16 15:20:36 -07003470 fsec = file->f_security;
David Howells275bb412008-11-14 10:39:19 +11003471 fsec->fown_sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003472}
3473
3474static int selinux_file_send_sigiotask(struct task_struct *tsk,
3475 struct fown_struct *fown, int signum)
3476{
Eric Paris828dfe12008-04-17 13:17:49 -04003477 struct file *file;
Stephen Smalley65c90bc2009-05-04 15:43:18 -04003478 u32 sid = task_sid(tsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003479 u32 perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003480 struct file_security_struct *fsec;
3481
3482 /* struct fown_struct is never outside the context of a struct file */
Eric Paris828dfe12008-04-17 13:17:49 -04003483 file = container_of(fown, struct file, f_owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003484
Linus Torvalds1da177e2005-04-16 15:20:36 -07003485 fsec = file->f_security;
3486
3487 if (!signum)
3488 perm = signal_to_av(SIGIO); /* as per send_sigio_to_task */
3489 else
3490 perm = signal_to_av(signum);
3491
David Howells275bb412008-11-14 10:39:19 +11003492 return avc_has_perm(fsec->fown_sid, sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003493 SECCLASS_PROCESS, perm, NULL);
3494}
3495
3496static int selinux_file_receive(struct file *file)
3497{
David Howells88e67f32008-11-14 10:39:21 +11003498 const struct cred *cred = current_cred();
3499
3500 return file_has_perm(cred, file, file_to_av(file));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003501}
3502
Eric Paris83d49852012-04-04 13:45:40 -04003503static int selinux_file_open(struct file *file, const struct cred *cred)
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003504{
3505 struct file_security_struct *fsec;
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003506 struct inode_security_struct *isec;
David Howellsd84f4f92008-11-14 10:39:23 +11003507
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003508 fsec = file->f_security;
Al Viro496ad9a2013-01-23 17:07:38 -05003509 isec = file_inode(file)->i_security;
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003510 /*
3511 * Save inode label and policy sequence number
3512 * at open-time so that selinux_file_permission
3513 * can determine whether revalidation is necessary.
3514 * Task label is already saved in the file security
3515 * struct as its SID.
3516 */
3517 fsec->isid = isec->sid;
3518 fsec->pseqno = avc_policy_seqno();
3519 /*
3520 * Since the inode label or policy seqno may have changed
3521 * between the selinux_inode_permission check and the saving
3522 * of state above, recheck that access is still permitted.
3523 * Otherwise, access might never be revalidated against the
3524 * new inode label or new policy.
3525 * This check is not redundant - do not remove.
3526 */
David Howells13f8e982013-06-13 23:37:55 +01003527 return file_path_has_perm(cred, file, open_file_to_av(file));
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003528}
3529
Linus Torvalds1da177e2005-04-16 15:20:36 -07003530/* task security operations */
3531
3532static int selinux_task_create(unsigned long clone_flags)
3533{
David Howells3b11a1d2008-11-14 10:39:26 +11003534 return current_has_perm(current, PROCESS__FORK);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003535}
3536
David Howellsf1752ee2008-11-14 10:39:17 +11003537/*
David Howellsee18d642009-09-02 09:14:21 +01003538 * allocate the SELinux part of blank credentials
3539 */
3540static int selinux_cred_alloc_blank(struct cred *cred, gfp_t gfp)
3541{
3542 struct task_security_struct *tsec;
3543
3544 tsec = kzalloc(sizeof(struct task_security_struct), gfp);
3545 if (!tsec)
3546 return -ENOMEM;
3547
3548 cred->security = tsec;
3549 return 0;
3550}
3551
3552/*
David Howellsf1752ee2008-11-14 10:39:17 +11003553 * detach and free the LSM part of a set of credentials
3554 */
3555static void selinux_cred_free(struct cred *cred)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003556{
David Howellsf1752ee2008-11-14 10:39:17 +11003557 struct task_security_struct *tsec = cred->security;
David Howellse0e81732009-09-02 09:13:40 +01003558
Tetsuo Handa2edeaa32011-02-07 13:36:10 +00003559 /*
3560 * cred->security == NULL if security_cred_alloc_blank() or
3561 * security_prepare_creds() returned an error.
3562 */
3563 BUG_ON(cred->security && (unsigned long) cred->security < PAGE_SIZE);
David Howellse0e81732009-09-02 09:13:40 +01003564 cred->security = (void *) 0x7UL;
David Howellsf1752ee2008-11-14 10:39:17 +11003565 kfree(tsec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003566}
3567
David Howellsd84f4f92008-11-14 10:39:23 +11003568/*
3569 * prepare a new set of credentials for modification
3570 */
3571static int selinux_cred_prepare(struct cred *new, const struct cred *old,
3572 gfp_t gfp)
3573{
3574 const struct task_security_struct *old_tsec;
3575 struct task_security_struct *tsec;
3576
3577 old_tsec = old->security;
3578
3579 tsec = kmemdup(old_tsec, sizeof(struct task_security_struct), gfp);
3580 if (!tsec)
3581 return -ENOMEM;
3582
3583 new->security = tsec;
3584 return 0;
3585}
3586
3587/*
David Howellsee18d642009-09-02 09:14:21 +01003588 * transfer the SELinux data to a blank set of creds
3589 */
3590static void selinux_cred_transfer(struct cred *new, const struct cred *old)
3591{
3592 const struct task_security_struct *old_tsec = old->security;
3593 struct task_security_struct *tsec = new->security;
3594
3595 *tsec = *old_tsec;
3596}
3597
3598/*
David Howells3a3b7ce2008-11-14 10:39:28 +11003599 * set the security data for a kernel service
3600 * - all the creation contexts are set to unlabelled
3601 */
3602static int selinux_kernel_act_as(struct cred *new, u32 secid)
3603{
3604 struct task_security_struct *tsec = new->security;
3605 u32 sid = current_sid();
3606 int ret;
3607
3608 ret = avc_has_perm(sid, secid,
3609 SECCLASS_KERNEL_SERVICE,
3610 KERNEL_SERVICE__USE_AS_OVERRIDE,
3611 NULL);
3612 if (ret == 0) {
3613 tsec->sid = secid;
3614 tsec->create_sid = 0;
3615 tsec->keycreate_sid = 0;
3616 tsec->sockcreate_sid = 0;
3617 }
3618 return ret;
3619}
3620
3621/*
3622 * set the file creation context in a security record to the same as the
3623 * objective context of the specified inode
3624 */
3625static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode)
3626{
3627 struct inode_security_struct *isec = inode->i_security;
3628 struct task_security_struct *tsec = new->security;
3629 u32 sid = current_sid();
3630 int ret;
3631
3632 ret = avc_has_perm(sid, isec->sid,
3633 SECCLASS_KERNEL_SERVICE,
3634 KERNEL_SERVICE__CREATE_FILES_AS,
3635 NULL);
3636
3637 if (ret == 0)
3638 tsec->create_sid = isec->sid;
David Howellsef574712010-02-26 01:56:16 +00003639 return ret;
David Howells3a3b7ce2008-11-14 10:39:28 +11003640}
3641
Eric Parisdd8dbf22009-11-03 16:35:32 +11003642static int selinux_kernel_module_request(char *kmod_name)
Eric Paris25354c42009-08-13 09:45:03 -04003643{
Eric Parisdd8dbf22009-11-03 16:35:32 +11003644 u32 sid;
3645 struct common_audit_data ad;
3646
3647 sid = task_sid(current);
3648
Eric Paris50c205f2012-04-04 15:01:43 -04003649 ad.type = LSM_AUDIT_DATA_KMOD;
Eric Parisdd8dbf22009-11-03 16:35:32 +11003650 ad.u.kmod_name = kmod_name;
3651
3652 return avc_has_perm(sid, SECINITSID_KERNEL, SECCLASS_SYSTEM,
3653 SYSTEM__MODULE_REQUEST, &ad);
Eric Paris25354c42009-08-13 09:45:03 -04003654}
3655
Linus Torvalds1da177e2005-04-16 15:20:36 -07003656static int selinux_task_setpgid(struct task_struct *p, pid_t pgid)
3657{
David Howells3b11a1d2008-11-14 10:39:26 +11003658 return current_has_perm(p, PROCESS__SETPGID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003659}
3660
3661static int selinux_task_getpgid(struct task_struct *p)
3662{
David Howells3b11a1d2008-11-14 10:39:26 +11003663 return current_has_perm(p, PROCESS__GETPGID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003664}
3665
3666static int selinux_task_getsid(struct task_struct *p)
3667{
David Howells3b11a1d2008-11-14 10:39:26 +11003668 return current_has_perm(p, PROCESS__GETSESSION);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003669}
3670
David Quigleyf9008e42006-06-30 01:55:46 -07003671static void selinux_task_getsecid(struct task_struct *p, u32 *secid)
3672{
David Howells275bb412008-11-14 10:39:19 +11003673 *secid = task_sid(p);
David Quigleyf9008e42006-06-30 01:55:46 -07003674}
3675
Linus Torvalds1da177e2005-04-16 15:20:36 -07003676static int selinux_task_setnice(struct task_struct *p, int nice)
3677{
David Howells3b11a1d2008-11-14 10:39:26 +11003678 return current_has_perm(p, PROCESS__SETSCHED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003679}
3680
James Morris03e68062006-06-23 02:03:58 -07003681static int selinux_task_setioprio(struct task_struct *p, int ioprio)
3682{
David Howells3b11a1d2008-11-14 10:39:26 +11003683 return current_has_perm(p, PROCESS__SETSCHED);
James Morris03e68062006-06-23 02:03:58 -07003684}
3685
David Quigleya1836a42006-06-30 01:55:49 -07003686static int selinux_task_getioprio(struct task_struct *p)
3687{
David Howells3b11a1d2008-11-14 10:39:26 +11003688 return current_has_perm(p, PROCESS__GETSCHED);
David Quigleya1836a42006-06-30 01:55:49 -07003689}
3690
Jiri Slaby8fd00b42009-08-26 18:41:16 +02003691static int selinux_task_setrlimit(struct task_struct *p, unsigned int resource,
3692 struct rlimit *new_rlim)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003693{
Jiri Slaby8fd00b42009-08-26 18:41:16 +02003694 struct rlimit *old_rlim = p->signal->rlim + resource;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003695
3696 /* Control the ability to change the hard limit (whether
3697 lowering or raising it), so that the hard limit can
3698 later be used as a safe reset point for the soft limit
David Howellsd84f4f92008-11-14 10:39:23 +11003699 upon context transitions. See selinux_bprm_committing_creds. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003700 if (old_rlim->rlim_max != new_rlim->rlim_max)
Jiri Slaby8fd00b42009-08-26 18:41:16 +02003701 return current_has_perm(p, PROCESS__SETRLIMIT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003702
3703 return 0;
3704}
3705
KOSAKI Motohirob0ae1982010-10-15 04:21:18 +09003706static int selinux_task_setscheduler(struct task_struct *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003707{
David Howells3b11a1d2008-11-14 10:39:26 +11003708 return current_has_perm(p, PROCESS__SETSCHED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003709}
3710
3711static int selinux_task_getscheduler(struct task_struct *p)
3712{
David Howells3b11a1d2008-11-14 10:39:26 +11003713 return current_has_perm(p, PROCESS__GETSCHED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003714}
3715
David Quigley35601542006-06-23 02:04:01 -07003716static int selinux_task_movememory(struct task_struct *p)
3717{
David Howells3b11a1d2008-11-14 10:39:26 +11003718 return current_has_perm(p, PROCESS__SETSCHED);
David Quigley35601542006-06-23 02:04:01 -07003719}
3720
David Quigleyf9008e42006-06-30 01:55:46 -07003721static int selinux_task_kill(struct task_struct *p, struct siginfo *info,
3722 int sig, u32 secid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003723{
3724 u32 perm;
3725 int rc;
3726
Linus Torvalds1da177e2005-04-16 15:20:36 -07003727 if (!sig)
3728 perm = PROCESS__SIGNULL; /* null signal; existence test */
3729 else
3730 perm = signal_to_av(sig);
David Quigleyf9008e42006-06-30 01:55:46 -07003731 if (secid)
David Howells275bb412008-11-14 10:39:19 +11003732 rc = avc_has_perm(secid, task_sid(p),
3733 SECCLASS_PROCESS, perm, NULL);
David Quigleyf9008e42006-06-30 01:55:46 -07003734 else
David Howells3b11a1d2008-11-14 10:39:26 +11003735 rc = current_has_perm(p, perm);
David Quigleyf9008e42006-06-30 01:55:46 -07003736 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003737}
3738
Linus Torvalds1da177e2005-04-16 15:20:36 -07003739static int selinux_task_wait(struct task_struct *p)
3740{
Eric Paris8a535142007-10-22 16:10:31 -04003741 return task_has_perm(p, current, PROCESS__SIGCHLD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003742}
3743
Linus Torvalds1da177e2005-04-16 15:20:36 -07003744static void selinux_task_to_inode(struct task_struct *p,
3745 struct inode *inode)
3746{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003747 struct inode_security_struct *isec = inode->i_security;
David Howells275bb412008-11-14 10:39:19 +11003748 u32 sid = task_sid(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003749
David Howells275bb412008-11-14 10:39:19 +11003750 isec->sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003751 isec->initialized = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003752}
3753
Linus Torvalds1da177e2005-04-16 15:20:36 -07003754/* Returns error only if unable to parse addresses */
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003755static int selinux_parse_skb_ipv4(struct sk_buff *skb,
Thomas Liu2bf49692009-07-14 12:14:09 -04003756 struct common_audit_data *ad, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003757{
3758 int offset, ihlen, ret = -EINVAL;
3759 struct iphdr _iph, *ih;
3760
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03003761 offset = skb_network_offset(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003762 ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph);
3763 if (ih == NULL)
3764 goto out;
3765
3766 ihlen = ih->ihl * 4;
3767 if (ihlen < sizeof(_iph))
3768 goto out;
3769
Eric Paris48c62af2012-04-02 13:15:44 -04003770 ad->u.net->v4info.saddr = ih->saddr;
3771 ad->u.net->v4info.daddr = ih->daddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003772 ret = 0;
3773
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003774 if (proto)
3775 *proto = ih->protocol;
3776
Linus Torvalds1da177e2005-04-16 15:20:36 -07003777 switch (ih->protocol) {
Eric Paris828dfe12008-04-17 13:17:49 -04003778 case IPPROTO_TCP: {
3779 struct tcphdr _tcph, *th;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003780
Eric Paris828dfe12008-04-17 13:17:49 -04003781 if (ntohs(ih->frag_off) & IP_OFFSET)
3782 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003783
3784 offset += ihlen;
3785 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
3786 if (th == NULL)
3787 break;
3788
Eric Paris48c62af2012-04-02 13:15:44 -04003789 ad->u.net->sport = th->source;
3790 ad->u.net->dport = th->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003791 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003792 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003793
Eric Paris828dfe12008-04-17 13:17:49 -04003794 case IPPROTO_UDP: {
3795 struct udphdr _udph, *uh;
3796
3797 if (ntohs(ih->frag_off) & IP_OFFSET)
3798 break;
3799
3800 offset += ihlen;
3801 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
3802 if (uh == NULL)
3803 break;
3804
Eric Paris48c62af2012-04-02 13:15:44 -04003805 ad->u.net->sport = uh->source;
3806 ad->u.net->dport = uh->dest;
Eric Paris828dfe12008-04-17 13:17:49 -04003807 break;
3808 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003809
James Morris2ee92d42006-11-13 16:09:01 -08003810 case IPPROTO_DCCP: {
3811 struct dccp_hdr _dccph, *dh;
3812
3813 if (ntohs(ih->frag_off) & IP_OFFSET)
3814 break;
3815
3816 offset += ihlen;
3817 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
3818 if (dh == NULL)
3819 break;
3820
Eric Paris48c62af2012-04-02 13:15:44 -04003821 ad->u.net->sport = dh->dccph_sport;
3822 ad->u.net->dport = dh->dccph_dport;
James Morris2ee92d42006-11-13 16:09:01 -08003823 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003824 }
James Morris2ee92d42006-11-13 16:09:01 -08003825
Eric Paris828dfe12008-04-17 13:17:49 -04003826 default:
3827 break;
3828 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003829out:
3830 return ret;
3831}
3832
3833#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
3834
3835/* Returns error only if unable to parse addresses */
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003836static int selinux_parse_skb_ipv6(struct sk_buff *skb,
Thomas Liu2bf49692009-07-14 12:14:09 -04003837 struct common_audit_data *ad, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003838{
3839 u8 nexthdr;
3840 int ret = -EINVAL, offset;
3841 struct ipv6hdr _ipv6h, *ip6;
Jesse Gross75f28112011-11-30 17:05:51 -08003842 __be16 frag_off;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003843
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03003844 offset = skb_network_offset(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003845 ip6 = skb_header_pointer(skb, offset, sizeof(_ipv6h), &_ipv6h);
3846 if (ip6 == NULL)
3847 goto out;
3848
Eric Paris48c62af2012-04-02 13:15:44 -04003849 ad->u.net->v6info.saddr = ip6->saddr;
3850 ad->u.net->v6info.daddr = ip6->daddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003851 ret = 0;
3852
3853 nexthdr = ip6->nexthdr;
3854 offset += sizeof(_ipv6h);
Jesse Gross75f28112011-11-30 17:05:51 -08003855 offset = ipv6_skip_exthdr(skb, offset, &nexthdr, &frag_off);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003856 if (offset < 0)
3857 goto out;
3858
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003859 if (proto)
3860 *proto = nexthdr;
3861
Linus Torvalds1da177e2005-04-16 15:20:36 -07003862 switch (nexthdr) {
3863 case IPPROTO_TCP: {
Eric Paris828dfe12008-04-17 13:17:49 -04003864 struct tcphdr _tcph, *th;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003865
3866 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
3867 if (th == NULL)
3868 break;
3869
Eric Paris48c62af2012-04-02 13:15:44 -04003870 ad->u.net->sport = th->source;
3871 ad->u.net->dport = th->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003872 break;
3873 }
3874
3875 case IPPROTO_UDP: {
3876 struct udphdr _udph, *uh;
3877
3878 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
3879 if (uh == NULL)
3880 break;
3881
Eric Paris48c62af2012-04-02 13:15:44 -04003882 ad->u.net->sport = uh->source;
3883 ad->u.net->dport = uh->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003884 break;
3885 }
3886
James Morris2ee92d42006-11-13 16:09:01 -08003887 case IPPROTO_DCCP: {
3888 struct dccp_hdr _dccph, *dh;
3889
3890 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
3891 if (dh == NULL)
3892 break;
3893
Eric Paris48c62af2012-04-02 13:15:44 -04003894 ad->u.net->sport = dh->dccph_sport;
3895 ad->u.net->dport = dh->dccph_dport;
James Morris2ee92d42006-11-13 16:09:01 -08003896 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003897 }
James Morris2ee92d42006-11-13 16:09:01 -08003898
Linus Torvalds1da177e2005-04-16 15:20:36 -07003899 /* includes fragments */
3900 default:
3901 break;
3902 }
3903out:
3904 return ret;
3905}
3906
3907#endif /* IPV6 */
3908
Thomas Liu2bf49692009-07-14 12:14:09 -04003909static int selinux_parse_skb(struct sk_buff *skb, struct common_audit_data *ad,
David Howellscf9481e2008-07-27 21:31:07 +10003910 char **_addrp, int src, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003911{
David Howellscf9481e2008-07-27 21:31:07 +10003912 char *addrp;
3913 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003914
Eric Paris48c62af2012-04-02 13:15:44 -04003915 switch (ad->u.net->family) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003916 case PF_INET:
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003917 ret = selinux_parse_skb_ipv4(skb, ad, proto);
David Howellscf9481e2008-07-27 21:31:07 +10003918 if (ret)
3919 goto parse_error;
Eric Paris48c62af2012-04-02 13:15:44 -04003920 addrp = (char *)(src ? &ad->u.net->v4info.saddr :
3921 &ad->u.net->v4info.daddr);
David Howellscf9481e2008-07-27 21:31:07 +10003922 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003923
3924#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
3925 case PF_INET6:
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003926 ret = selinux_parse_skb_ipv6(skb, ad, proto);
David Howellscf9481e2008-07-27 21:31:07 +10003927 if (ret)
3928 goto parse_error;
Eric Paris48c62af2012-04-02 13:15:44 -04003929 addrp = (char *)(src ? &ad->u.net->v6info.saddr :
3930 &ad->u.net->v6info.daddr);
David Howellscf9481e2008-07-27 21:31:07 +10003931 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003932#endif /* IPV6 */
3933 default:
David Howellscf9481e2008-07-27 21:31:07 +10003934 addrp = NULL;
3935 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003936 }
3937
David Howellscf9481e2008-07-27 21:31:07 +10003938parse_error:
3939 printk(KERN_WARNING
3940 "SELinux: failure in selinux_parse_skb(),"
3941 " unable to parse packet\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003942 return ret;
David Howellscf9481e2008-07-27 21:31:07 +10003943
3944okay:
3945 if (_addrp)
3946 *_addrp = addrp;
3947 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003948}
3949
Paul Moore4f6a9932007-03-01 14:35:22 -05003950/**
Paul Moore220deb92008-01-29 08:38:23 -05003951 * selinux_skb_peerlbl_sid - Determine the peer label of a packet
Paul Moore4f6a9932007-03-01 14:35:22 -05003952 * @skb: the packet
Paul Moore75e22912008-01-29 08:38:04 -05003953 * @family: protocol family
Paul Moore220deb92008-01-29 08:38:23 -05003954 * @sid: the packet's peer label SID
Paul Moore4f6a9932007-03-01 14:35:22 -05003955 *
3956 * Description:
Paul Moore220deb92008-01-29 08:38:23 -05003957 * Check the various different forms of network peer labeling and determine
3958 * the peer label/SID for the packet; most of the magic actually occurs in
3959 * the security server function security_net_peersid_cmp(). The function
3960 * returns zero if the value in @sid is valid (although it may be SECSID_NULL)
3961 * or -EACCES if @sid is invalid due to inconsistencies with the different
3962 * peer labels.
Paul Moore4f6a9932007-03-01 14:35:22 -05003963 *
3964 */
Paul Moore220deb92008-01-29 08:38:23 -05003965static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)
Paul Moore4f6a9932007-03-01 14:35:22 -05003966{
Paul Moore71f1cb02008-01-29 08:51:16 -05003967 int err;
Paul Moore4f6a9932007-03-01 14:35:22 -05003968 u32 xfrm_sid;
3969 u32 nlbl_sid;
Paul Moore220deb92008-01-29 08:38:23 -05003970 u32 nlbl_type;
Paul Moore4f6a9932007-03-01 14:35:22 -05003971
Paul Moore817eff72013-12-10 14:57:54 -05003972 err = selinux_xfrm_skb_sid(skb, &xfrm_sid);
Paul Moorebed4d7e2013-07-23 17:38:40 -04003973 if (unlikely(err))
3974 return -EACCES;
3975 err = selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid);
3976 if (unlikely(err))
3977 return -EACCES;
Paul Moore220deb92008-01-29 08:38:23 -05003978
Paul Moore71f1cb02008-01-29 08:51:16 -05003979 err = security_net_peersid_resolve(nlbl_sid, nlbl_type, xfrm_sid, sid);
3980 if (unlikely(err)) {
3981 printk(KERN_WARNING
3982 "SELinux: failure in selinux_skb_peerlbl_sid(),"
3983 " unable to determine packet's peer label\n");
Paul Moore220deb92008-01-29 08:38:23 -05003984 return -EACCES;
Paul Moore71f1cb02008-01-29 08:51:16 -05003985 }
Paul Moore220deb92008-01-29 08:38:23 -05003986
3987 return 0;
Paul Moore4f6a9932007-03-01 14:35:22 -05003988}
3989
Paul Moore446b8022013-12-04 16:10:51 -05003990/**
3991 * selinux_conn_sid - Determine the child socket label for a connection
3992 * @sk_sid: the parent socket's SID
3993 * @skb_sid: the packet's SID
3994 * @conn_sid: the resulting connection SID
3995 *
3996 * If @skb_sid is valid then the user:role:type information from @sk_sid is
3997 * combined with the MLS information from @skb_sid in order to create
3998 * @conn_sid. If @skb_sid is not valid then then @conn_sid is simply a copy
3999 * of @sk_sid. Returns zero on success, negative values on failure.
4000 *
4001 */
4002static int selinux_conn_sid(u32 sk_sid, u32 skb_sid, u32 *conn_sid)
4003{
4004 int err = 0;
4005
4006 if (skb_sid != SECSID_NULL)
4007 err = security_sid_mls_copy(sk_sid, skb_sid, conn_sid);
4008 else
4009 *conn_sid = sk_sid;
4010
4011 return err;
4012}
4013
Linus Torvalds1da177e2005-04-16 15:20:36 -07004014/* socket security operations */
Paul Moored4f2d972010-04-22 14:46:18 -04004015
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004016static int socket_sockcreate_sid(const struct task_security_struct *tsec,
4017 u16 secclass, u32 *socksid)
Paul Moored4f2d972010-04-22 14:46:18 -04004018{
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004019 if (tsec->sockcreate_sid > SECSID_NULL) {
4020 *socksid = tsec->sockcreate_sid;
4021 return 0;
4022 }
4023
4024 return security_transition_sid(tsec->sid, tsec->sid, secclass, NULL,
4025 socksid);
Paul Moored4f2d972010-04-22 14:46:18 -04004026}
4027
Paul Moore253bfae2010-04-22 14:46:19 -04004028static int sock_has_perm(struct task_struct *task, struct sock *sk, u32 perms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004029{
Paul Moore253bfae2010-04-22 14:46:19 -04004030 struct sk_security_struct *sksec = sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004031 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004032 struct lsm_network_audit net = {0,};
Paul Moore253bfae2010-04-22 14:46:19 -04004033 u32 tsid = task_sid(task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004034
Paul Moore253bfae2010-04-22 14:46:19 -04004035 if (sksec->sid == SECINITSID_KERNEL)
4036 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004037
Eric Paris50c205f2012-04-04 15:01:43 -04004038 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004039 ad.u.net = &net;
4040 ad.u.net->sk = sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004041
Paul Moore253bfae2010-04-22 14:46:19 -04004042 return avc_has_perm(tsid, sksec->sid, sksec->sclass, perms, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004043}
4044
4045static int selinux_socket_create(int family, int type,
4046 int protocol, int kern)
4047{
Paul Moore5fb49872010-04-22 14:46:19 -04004048 const struct task_security_struct *tsec = current_security();
Paul Moored4f2d972010-04-22 14:46:18 -04004049 u32 newsid;
David Howells275bb412008-11-14 10:39:19 +11004050 u16 secclass;
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004051 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004052
4053 if (kern)
Paul Moored4f2d972010-04-22 14:46:18 -04004054 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004055
David Howells275bb412008-11-14 10:39:19 +11004056 secclass = socket_type_to_security_class(family, type, protocol);
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004057 rc = socket_sockcreate_sid(tsec, secclass, &newsid);
4058 if (rc)
4059 return rc;
4060
Paul Moored4f2d972010-04-22 14:46:18 -04004061 return avc_has_perm(tsec->sid, newsid, secclass, SOCKET__CREATE, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004062}
4063
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07004064static int selinux_socket_post_create(struct socket *sock, int family,
4065 int type, int protocol, int kern)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004066{
Paul Moore5fb49872010-04-22 14:46:19 -04004067 const struct task_security_struct *tsec = current_security();
Paul Moored4f2d972010-04-22 14:46:18 -04004068 struct inode_security_struct *isec = SOCK_INODE(sock)->i_security;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004069 struct sk_security_struct *sksec;
David Howells275bb412008-11-14 10:39:19 +11004070 int err = 0;
4071
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004072 isec->sclass = socket_type_to_security_class(family, type, protocol);
4073
David Howells275bb412008-11-14 10:39:19 +11004074 if (kern)
4075 isec->sid = SECINITSID_KERNEL;
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004076 else {
4077 err = socket_sockcreate_sid(tsec, isec->sclass, &(isec->sid));
4078 if (err)
4079 return err;
4080 }
David Howells275bb412008-11-14 10:39:19 +11004081
Linus Torvalds1da177e2005-04-16 15:20:36 -07004082 isec->initialized = 1;
4083
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004084 if (sock->sk) {
4085 sksec = sock->sk->sk_security;
4086 sksec->sid = isec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05004087 sksec->sclass = isec->sclass;
Paul Moore389fb8002009-03-27 17:10:34 -04004088 err = selinux_netlbl_socket_post_create(sock->sk, family);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004089 }
4090
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07004091 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004092}
4093
4094/* Range of port numbers used to automatically bind.
4095 Need to determine whether we should perform a name_bind
4096 permission check between the socket and the port number. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004097
4098static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen)
4099{
Paul Moore253bfae2010-04-22 14:46:19 -04004100 struct sock *sk = sock->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004101 u16 family;
4102 int err;
4103
Paul Moore253bfae2010-04-22 14:46:19 -04004104 err = sock_has_perm(current, sk, SOCKET__BIND);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004105 if (err)
4106 goto out;
4107
4108 /*
4109 * If PF_INET or PF_INET6, check name_bind permission for the port.
James Morris13402582005-09-30 14:24:34 -04004110 * Multiple address binding for SCTP is not supported yet: we just
4111 * check the first address now.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004112 */
Paul Moore253bfae2010-04-22 14:46:19 -04004113 family = sk->sk_family;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004114 if (family == PF_INET || family == PF_INET6) {
4115 char *addrp;
Paul Moore253bfae2010-04-22 14:46:19 -04004116 struct sk_security_struct *sksec = sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004117 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004118 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004119 struct sockaddr_in *addr4 = NULL;
4120 struct sockaddr_in6 *addr6 = NULL;
4121 unsigned short snum;
James Morrise399f982008-06-12 01:39:58 +10004122 u32 sid, node_perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004123
Linus Torvalds1da177e2005-04-16 15:20:36 -07004124 if (family == PF_INET) {
4125 addr4 = (struct sockaddr_in *)address;
4126 snum = ntohs(addr4->sin_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004127 addrp = (char *)&addr4->sin_addr.s_addr;
4128 } else {
4129 addr6 = (struct sockaddr_in6 *)address;
4130 snum = ntohs(addr6->sin6_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004131 addrp = (char *)&addr6->sin6_addr.s6_addr;
4132 }
4133
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004134 if (snum) {
4135 int low, high;
4136
Eric W. Biederman0bbf87d2013-09-28 14:10:59 -07004137 inet_get_local_port_range(sock_net(sk), &low, &high);
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004138
4139 if (snum < max(PROT_SOCK, low) || snum > high) {
Paul Moore3e112172008-04-10 10:48:14 -04004140 err = sel_netport_sid(sk->sk_protocol,
4141 snum, &sid);
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004142 if (err)
4143 goto out;
Eric Paris50c205f2012-04-04 15:01:43 -04004144 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004145 ad.u.net = &net;
4146 ad.u.net->sport = htons(snum);
4147 ad.u.net->family = family;
Paul Moore253bfae2010-04-22 14:46:19 -04004148 err = avc_has_perm(sksec->sid, sid,
4149 sksec->sclass,
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004150 SOCKET__NAME_BIND, &ad);
4151 if (err)
4152 goto out;
4153 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004154 }
Eric Paris828dfe12008-04-17 13:17:49 -04004155
Paul Moore253bfae2010-04-22 14:46:19 -04004156 switch (sksec->sclass) {
James Morris13402582005-09-30 14:24:34 -04004157 case SECCLASS_TCP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004158 node_perm = TCP_SOCKET__NODE_BIND;
4159 break;
Eric Paris828dfe12008-04-17 13:17:49 -04004160
James Morris13402582005-09-30 14:24:34 -04004161 case SECCLASS_UDP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004162 node_perm = UDP_SOCKET__NODE_BIND;
4163 break;
James Morris2ee92d42006-11-13 16:09:01 -08004164
4165 case SECCLASS_DCCP_SOCKET:
4166 node_perm = DCCP_SOCKET__NODE_BIND;
4167 break;
4168
Linus Torvalds1da177e2005-04-16 15:20:36 -07004169 default:
4170 node_perm = RAWIP_SOCKET__NODE_BIND;
4171 break;
4172 }
Eric Paris828dfe12008-04-17 13:17:49 -04004173
Paul Moore224dfbd2008-01-29 08:38:13 -05004174 err = sel_netnode_sid(addrp, family, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004175 if (err)
4176 goto out;
Eric Paris828dfe12008-04-17 13:17:49 -04004177
Eric Paris50c205f2012-04-04 15:01:43 -04004178 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004179 ad.u.net = &net;
4180 ad.u.net->sport = htons(snum);
4181 ad.u.net->family = family;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004182
4183 if (family == PF_INET)
Eric Paris48c62af2012-04-02 13:15:44 -04004184 ad.u.net->v4info.saddr = addr4->sin_addr.s_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004185 else
Eric Paris48c62af2012-04-02 13:15:44 -04004186 ad.u.net->v6info.saddr = addr6->sin6_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004187
Paul Moore253bfae2010-04-22 14:46:19 -04004188 err = avc_has_perm(sksec->sid, sid,
4189 sksec->sclass, node_perm, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004190 if (err)
4191 goto out;
4192 }
4193out:
4194 return err;
4195}
4196
4197static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen)
4198{
Paul Moore014ab192008-10-10 10:16:33 -04004199 struct sock *sk = sock->sk;
Paul Moore253bfae2010-04-22 14:46:19 -04004200 struct sk_security_struct *sksec = sk->sk_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004201 int err;
4202
Paul Moore253bfae2010-04-22 14:46:19 -04004203 err = sock_has_perm(current, sk, SOCKET__CONNECT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004204 if (err)
4205 return err;
4206
4207 /*
James Morris2ee92d42006-11-13 16:09:01 -08004208 * If a TCP or DCCP socket, check name_connect permission for the port.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004209 */
Paul Moore253bfae2010-04-22 14:46:19 -04004210 if (sksec->sclass == SECCLASS_TCP_SOCKET ||
4211 sksec->sclass == SECCLASS_DCCP_SOCKET) {
Thomas Liu2bf49692009-07-14 12:14:09 -04004212 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004213 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004214 struct sockaddr_in *addr4 = NULL;
4215 struct sockaddr_in6 *addr6 = NULL;
4216 unsigned short snum;
James Morris2ee92d42006-11-13 16:09:01 -08004217 u32 sid, perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004218
4219 if (sk->sk_family == PF_INET) {
4220 addr4 = (struct sockaddr_in *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07004221 if (addrlen < sizeof(struct sockaddr_in))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004222 return -EINVAL;
4223 snum = ntohs(addr4->sin_port);
4224 } else {
4225 addr6 = (struct sockaddr_in6 *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07004226 if (addrlen < SIN6_LEN_RFC2133)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004227 return -EINVAL;
4228 snum = ntohs(addr6->sin6_port);
4229 }
4230
Paul Moore3e112172008-04-10 10:48:14 -04004231 err = sel_netport_sid(sk->sk_protocol, snum, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004232 if (err)
4233 goto out;
4234
Paul Moore253bfae2010-04-22 14:46:19 -04004235 perm = (sksec->sclass == SECCLASS_TCP_SOCKET) ?
James Morris2ee92d42006-11-13 16:09:01 -08004236 TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT;
4237
Eric Paris50c205f2012-04-04 15:01:43 -04004238 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004239 ad.u.net = &net;
4240 ad.u.net->dport = htons(snum);
4241 ad.u.net->family = sk->sk_family;
Paul Moore253bfae2010-04-22 14:46:19 -04004242 err = avc_has_perm(sksec->sid, sid, sksec->sclass, perm, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004243 if (err)
4244 goto out;
4245 }
4246
Paul Moore014ab192008-10-10 10:16:33 -04004247 err = selinux_netlbl_socket_connect(sk, address);
4248
Linus Torvalds1da177e2005-04-16 15:20:36 -07004249out:
4250 return err;
4251}
4252
4253static int selinux_socket_listen(struct socket *sock, int backlog)
4254{
Paul Moore253bfae2010-04-22 14:46:19 -04004255 return sock_has_perm(current, sock->sk, SOCKET__LISTEN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004256}
4257
4258static int selinux_socket_accept(struct socket *sock, struct socket *newsock)
4259{
4260 int err;
4261 struct inode_security_struct *isec;
4262 struct inode_security_struct *newisec;
4263
Paul Moore253bfae2010-04-22 14:46:19 -04004264 err = sock_has_perm(current, sock->sk, SOCKET__ACCEPT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004265 if (err)
4266 return err;
4267
4268 newisec = SOCK_INODE(newsock)->i_security;
4269
4270 isec = SOCK_INODE(sock)->i_security;
4271 newisec->sclass = isec->sclass;
4272 newisec->sid = isec->sid;
4273 newisec->initialized = 1;
4274
4275 return 0;
4276}
4277
4278static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg,
Eric Paris828dfe12008-04-17 13:17:49 -04004279 int size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004280{
Paul Moore253bfae2010-04-22 14:46:19 -04004281 return sock_has_perm(current, sock->sk, SOCKET__WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004282}
4283
4284static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg,
4285 int size, int flags)
4286{
Paul Moore253bfae2010-04-22 14:46:19 -04004287 return sock_has_perm(current, sock->sk, SOCKET__READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004288}
4289
4290static int selinux_socket_getsockname(struct socket *sock)
4291{
Paul Moore253bfae2010-04-22 14:46:19 -04004292 return sock_has_perm(current, sock->sk, SOCKET__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004293}
4294
4295static int selinux_socket_getpeername(struct socket *sock)
4296{
Paul Moore253bfae2010-04-22 14:46:19 -04004297 return sock_has_perm(current, sock->sk, SOCKET__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004298}
4299
Eric Paris828dfe12008-04-17 13:17:49 -04004300static int selinux_socket_setsockopt(struct socket *sock, int level, int optname)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004301{
Paul Mooref8687af2006-10-30 15:22:15 -08004302 int err;
4303
Paul Moore253bfae2010-04-22 14:46:19 -04004304 err = sock_has_perm(current, sock->sk, SOCKET__SETOPT);
Paul Mooref8687af2006-10-30 15:22:15 -08004305 if (err)
4306 return err;
4307
4308 return selinux_netlbl_socket_setsockopt(sock, level, optname);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004309}
4310
4311static int selinux_socket_getsockopt(struct socket *sock, int level,
4312 int optname)
4313{
Paul Moore253bfae2010-04-22 14:46:19 -04004314 return sock_has_perm(current, sock->sk, SOCKET__GETOPT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004315}
4316
4317static int selinux_socket_shutdown(struct socket *sock, int how)
4318{
Paul Moore253bfae2010-04-22 14:46:19 -04004319 return sock_has_perm(current, sock->sk, SOCKET__SHUTDOWN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004320}
4321
David S. Miller3610cda2011-01-05 15:38:53 -08004322static int selinux_socket_unix_stream_connect(struct sock *sock,
4323 struct sock *other,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004324 struct sock *newsk)
4325{
David S. Miller3610cda2011-01-05 15:38:53 -08004326 struct sk_security_struct *sksec_sock = sock->sk_security;
4327 struct sk_security_struct *sksec_other = other->sk_security;
Paul Moore4d1e2452010-04-22 14:46:18 -04004328 struct sk_security_struct *sksec_new = newsk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004329 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004330 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004331 int err;
4332
Eric Paris50c205f2012-04-04 15:01:43 -04004333 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004334 ad.u.net = &net;
4335 ad.u.net->sk = other;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004336
Paul Moore4d1e2452010-04-22 14:46:18 -04004337 err = avc_has_perm(sksec_sock->sid, sksec_other->sid,
4338 sksec_other->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004339 UNIX_STREAM_SOCKET__CONNECTTO, &ad);
4340 if (err)
4341 return err;
4342
Linus Torvalds1da177e2005-04-16 15:20:36 -07004343 /* server child socket */
Paul Moore4d1e2452010-04-22 14:46:18 -04004344 sksec_new->peer_sid = sksec_sock->sid;
4345 err = security_sid_mls_copy(sksec_other->sid, sksec_sock->sid,
4346 &sksec_new->sid);
4347 if (err)
4348 return err;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004349
Paul Moore4d1e2452010-04-22 14:46:18 -04004350 /* connecting socket */
4351 sksec_sock->peer_sid = sksec_new->sid;
4352
4353 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004354}
4355
4356static int selinux_socket_unix_may_send(struct socket *sock,
4357 struct socket *other)
4358{
Paul Moore253bfae2010-04-22 14:46:19 -04004359 struct sk_security_struct *ssec = sock->sk->sk_security;
4360 struct sk_security_struct *osec = other->sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004361 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004362 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004363
Eric Paris50c205f2012-04-04 15:01:43 -04004364 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004365 ad.u.net = &net;
4366 ad.u.net->sk = other->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004367
Paul Moore253bfae2010-04-22 14:46:19 -04004368 return avc_has_perm(ssec->sid, osec->sid, osec->sclass, SOCKET__SENDTO,
4369 &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004370}
4371
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004372static int selinux_inet_sys_rcv_skb(struct net *ns, int ifindex,
4373 char *addrp, u16 family, u32 peer_sid,
Thomas Liu2bf49692009-07-14 12:14:09 -04004374 struct common_audit_data *ad)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004375{
4376 int err;
4377 u32 if_sid;
4378 u32 node_sid;
4379
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004380 err = sel_netif_sid(ns, ifindex, &if_sid);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004381 if (err)
4382 return err;
4383 err = avc_has_perm(peer_sid, if_sid,
4384 SECCLASS_NETIF, NETIF__INGRESS, ad);
4385 if (err)
4386 return err;
4387
4388 err = sel_netnode_sid(addrp, family, &node_sid);
4389 if (err)
4390 return err;
4391 return avc_has_perm(peer_sid, node_sid,
4392 SECCLASS_NODE, NODE__RECVFROM, ad);
4393}
4394
Paul Moore220deb92008-01-29 08:38:23 -05004395static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
Paul Moored8395c82008-10-10 10:16:30 -04004396 u16 family)
Paul Moore220deb92008-01-29 08:38:23 -05004397{
Paul Moore277d3422008-12-31 12:54:11 -05004398 int err = 0;
Paul Moore220deb92008-01-29 08:38:23 -05004399 struct sk_security_struct *sksec = sk->sk_security;
Paul Moore220deb92008-01-29 08:38:23 -05004400 u32 sk_sid = sksec->sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04004401 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004402 struct lsm_network_audit net = {0,};
Paul Moored8395c82008-10-10 10:16:30 -04004403 char *addrp;
4404
Eric Paris50c205f2012-04-04 15:01:43 -04004405 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004406 ad.u.net = &net;
4407 ad.u.net->netif = skb->skb_iif;
4408 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04004409 err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
4410 if (err)
4411 return err;
Paul Moore220deb92008-01-29 08:38:23 -05004412
Paul Moore58bfbb52009-03-27 17:10:41 -04004413 if (selinux_secmark_enabled()) {
Paul Moore220deb92008-01-29 08:38:23 -05004414 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
Paul Moored8395c82008-10-10 10:16:30 -04004415 PACKET__RECV, &ad);
Paul Moore58bfbb52009-03-27 17:10:41 -04004416 if (err)
4417 return err;
4418 }
Paul Moore220deb92008-01-29 08:38:23 -05004419
Steffen Klassertb9679a72011-02-23 12:55:21 +01004420 err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, &ad);
4421 if (err)
4422 return err;
4423 err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, &ad);
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004424
James Morris4e5ab4c2006-06-09 00:33:33 -07004425 return err;
4426}
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004427
James Morris4e5ab4c2006-06-09 00:33:33 -07004428static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
4429{
Paul Moore220deb92008-01-29 08:38:23 -05004430 int err;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004431 struct sk_security_struct *sksec = sk->sk_security;
Paul Moore220deb92008-01-29 08:38:23 -05004432 u16 family = sk->sk_family;
4433 u32 sk_sid = sksec->sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04004434 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004435 struct lsm_network_audit net = {0,};
Paul Moore220deb92008-01-29 08:38:23 -05004436 char *addrp;
Paul Moored8395c82008-10-10 10:16:30 -04004437 u8 secmark_active;
4438 u8 peerlbl_active;
James Morris4e5ab4c2006-06-09 00:33:33 -07004439
James Morris4e5ab4c2006-06-09 00:33:33 -07004440 if (family != PF_INET && family != PF_INET6)
Paul Moore220deb92008-01-29 08:38:23 -05004441 return 0;
James Morris4e5ab4c2006-06-09 00:33:33 -07004442
4443 /* Handle mapped IPv4 packets arriving via IPv6 sockets */
Al Viro87fcd702006-12-04 22:00:55 +00004444 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
James Morris4e5ab4c2006-06-09 00:33:33 -07004445 family = PF_INET;
4446
Paul Moored8395c82008-10-10 10:16:30 -04004447 /* If any sort of compatibility mode is enabled then handoff processing
4448 * to the selinux_sock_rcv_skb_compat() function to deal with the
4449 * special handling. We do this in an attempt to keep this function
4450 * as fast and as clean as possible. */
Paul Moore58bfbb52009-03-27 17:10:41 -04004451 if (!selinux_policycap_netpeer)
Paul Moored8395c82008-10-10 10:16:30 -04004452 return selinux_sock_rcv_skb_compat(sk, skb, family);
4453
4454 secmark_active = selinux_secmark_enabled();
Chris PeBenito2be4d742013-05-03 09:05:39 -04004455 peerlbl_active = selinux_peerlbl_enabled();
Paul Moored8395c82008-10-10 10:16:30 -04004456 if (!secmark_active && !peerlbl_active)
4457 return 0;
4458
Eric Paris50c205f2012-04-04 15:01:43 -04004459 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004460 ad.u.net = &net;
4461 ad.u.net->netif = skb->skb_iif;
4462 ad.u.net->family = family;
Paul Moore224dfbd2008-01-29 08:38:13 -05004463 err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
James Morris4e5ab4c2006-06-09 00:33:33 -07004464 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05004465 return err;
James Morris4e5ab4c2006-06-09 00:33:33 -07004466
Paul Moored8395c82008-10-10 10:16:30 -04004467 if (peerlbl_active) {
Paul Moored621d352008-01-29 08:43:36 -05004468 u32 peer_sid;
4469
4470 err = selinux_skb_peerlbl_sid(skb, family, &peer_sid);
4471 if (err)
4472 return err;
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004473 err = selinux_inet_sys_rcv_skb(sock_net(sk), skb->skb_iif,
4474 addrp, family, peer_sid, &ad);
Paul Mooredfaebe92008-10-10 10:16:31 -04004475 if (err) {
4476 selinux_netlbl_err(skb, err, 0);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004477 return err;
Paul Mooredfaebe92008-10-10 10:16:31 -04004478 }
Paul Moored621d352008-01-29 08:43:36 -05004479 err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER,
4480 PEER__RECV, &ad);
Chad Hanson46d01d62013-12-23 17:45:01 -05004481 if (err) {
Paul Mooredfaebe92008-10-10 10:16:31 -04004482 selinux_netlbl_err(skb, err, 0);
Chad Hanson46d01d62013-12-23 17:45:01 -05004483 return err;
4484 }
Paul Moored621d352008-01-29 08:43:36 -05004485 }
4486
Paul Moored8395c82008-10-10 10:16:30 -04004487 if (secmark_active) {
Paul Mooreeffad8d2008-01-29 08:49:27 -05004488 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
4489 PACKET__RECV, &ad);
4490 if (err)
4491 return err;
4492 }
4493
Paul Moored621d352008-01-29 08:43:36 -05004494 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004495}
4496
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004497static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *optval,
4498 int __user *optlen, unsigned len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004499{
4500 int err = 0;
4501 char *scontext;
4502 u32 scontext_len;
Paul Moore253bfae2010-04-22 14:46:19 -04004503 struct sk_security_struct *sksec = sock->sk->sk_security;
Paul Moore3de4bab2006-11-17 17:38:54 -05004504 u32 peer_sid = SECSID_NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004505
Paul Moore253bfae2010-04-22 14:46:19 -04004506 if (sksec->sclass == SECCLASS_UNIX_STREAM_SOCKET ||
4507 sksec->sclass == SECCLASS_TCP_SOCKET)
Eric Parisdd3e7832010-04-07 15:08:46 -04004508 peer_sid = sksec->peer_sid;
Paul Moore253bfae2010-04-22 14:46:19 -04004509 if (peer_sid == SECSID_NULL)
4510 return -ENOPROTOOPT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004511
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004512 err = security_sid_to_context(peer_sid, &scontext, &scontext_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004513 if (err)
Paul Moore253bfae2010-04-22 14:46:19 -04004514 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004515
4516 if (scontext_len > len) {
4517 err = -ERANGE;
4518 goto out_len;
4519 }
4520
4521 if (copy_to_user(optval, scontext, scontext_len))
4522 err = -EFAULT;
4523
4524out_len:
4525 if (put_user(scontext_len, optlen))
4526 err = -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004527 kfree(scontext);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004528 return err;
4529}
4530
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004531static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid)
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004532{
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004533 u32 peer_secid = SECSID_NULL;
Paul Moore75e22912008-01-29 08:38:04 -05004534 u16 family;
Catherine Zhang877ce7c2006-06-29 12:27:47 -07004535
Paul Mooreaa862902008-10-10 10:16:29 -04004536 if (skb && skb->protocol == htons(ETH_P_IP))
4537 family = PF_INET;
4538 else if (skb && skb->protocol == htons(ETH_P_IPV6))
4539 family = PF_INET6;
4540 else if (sock)
Paul Moore75e22912008-01-29 08:38:04 -05004541 family = sock->sk->sk_family;
Paul Moore75e22912008-01-29 08:38:04 -05004542 else
4543 goto out;
4544
4545 if (sock && family == PF_UNIX)
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02004546 selinux_inode_getsecid(SOCK_INODE(sock), &peer_secid);
Paul Moore3de4bab2006-11-17 17:38:54 -05004547 else if (skb)
Paul Moore220deb92008-01-29 08:38:23 -05004548 selinux_skb_peerlbl_sid(skb, family, &peer_secid);
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004549
Paul Moore75e22912008-01-29 08:38:04 -05004550out:
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004551 *secid = peer_secid;
Paul Moore75e22912008-01-29 08:38:04 -05004552 if (peer_secid == SECSID_NULL)
4553 return -EINVAL;
4554 return 0;
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004555}
4556
Al Viro7d877f32005-10-21 03:20:43 -04004557static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004558{
Paul Moore84914b72010-04-22 14:46:18 -04004559 struct sk_security_struct *sksec;
4560
4561 sksec = kzalloc(sizeof(*sksec), priority);
4562 if (!sksec)
4563 return -ENOMEM;
4564
4565 sksec->peer_sid = SECINITSID_UNLABELED;
4566 sksec->sid = SECINITSID_UNLABELED;
Stephen Smalley5dee25d2015-07-10 17:19:57 -04004567 sksec->sclass = SECCLASS_SOCKET;
Paul Moore84914b72010-04-22 14:46:18 -04004568 selinux_netlbl_sk_security_reset(sksec);
4569 sk->sk_security = sksec;
4570
4571 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004572}
4573
4574static void selinux_sk_free_security(struct sock *sk)
4575{
Paul Moore84914b72010-04-22 14:46:18 -04004576 struct sk_security_struct *sksec = sk->sk_security;
4577
4578 sk->sk_security = NULL;
4579 selinux_netlbl_sk_security_free(sksec);
4580 kfree(sksec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004581}
4582
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004583static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk)
4584{
Eric Parisdd3e7832010-04-07 15:08:46 -04004585 struct sk_security_struct *sksec = sk->sk_security;
4586 struct sk_security_struct *newsksec = newsk->sk_security;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004587
Eric Parisdd3e7832010-04-07 15:08:46 -04004588 newsksec->sid = sksec->sid;
4589 newsksec->peer_sid = sksec->peer_sid;
4590 newsksec->sclass = sksec->sclass;
Paul Moore99f59ed2006-08-29 17:53:48 -07004591
Eric Parisdd3e7832010-04-07 15:08:46 -04004592 selinux_netlbl_sk_security_reset(newsksec);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004593}
4594
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004595static void selinux_sk_getsecid(struct sock *sk, u32 *secid)
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004596{
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004597 if (!sk)
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004598 *secid = SECINITSID_ANY_SOCKET;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004599 else {
4600 struct sk_security_struct *sksec = sk->sk_security;
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004601
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004602 *secid = sksec->sid;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004603 }
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004604}
4605
Eric Paris828dfe12008-04-17 13:17:49 -04004606static void selinux_sock_graft(struct sock *sk, struct socket *parent)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004607{
4608 struct inode_security_struct *isec = SOCK_INODE(parent)->i_security;
4609 struct sk_security_struct *sksec = sk->sk_security;
4610
Paul Moore2873ead2014-07-28 10:42:48 -04004611 if (sk->sk_family == PF_INET || sk->sk_family == PF_INET6 ||
4612 sk->sk_family == PF_UNIX)
David Woodhouse2148ccc2006-09-29 15:50:25 -07004613 isec->sid = sksec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05004614 sksec->sclass = isec->sclass;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004615}
4616
Adrian Bunk9a673e52006-08-15 00:03:53 -07004617static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
4618 struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004619{
4620 struct sk_security_struct *sksec = sk->sk_security;
4621 int err;
Paul Moore0b1f24e2013-12-03 11:39:13 -05004622 u16 family = req->rsk_ops->family;
Paul Moore446b8022013-12-04 16:10:51 -05004623 u32 connsid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004624 u32 peersid;
4625
Paul Mooreaa862902008-10-10 10:16:29 -04004626 err = selinux_skb_peerlbl_sid(skb, family, &peersid);
Paul Moore220deb92008-01-29 08:38:23 -05004627 if (err)
4628 return err;
Paul Moore446b8022013-12-04 16:10:51 -05004629 err = selinux_conn_sid(sksec->sid, peersid, &connsid);
4630 if (err)
4631 return err;
4632 req->secid = connsid;
4633 req->peer_secid = peersid;
Venkat Yekkiralaa51c64f2006-07-27 22:01:34 -07004634
Paul Moore389fb8002009-03-27 17:10:34 -04004635 return selinux_netlbl_inet_conn_request(req, family);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004636}
4637
Adrian Bunk9a673e52006-08-15 00:03:53 -07004638static void selinux_inet_csk_clone(struct sock *newsk,
4639 const struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004640{
4641 struct sk_security_struct *newsksec = newsk->sk_security;
4642
4643 newsksec->sid = req->secid;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004644 newsksec->peer_sid = req->peer_secid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004645 /* NOTE: Ideally, we should also get the isec->sid for the
4646 new socket in sync, but we don't have the isec available yet.
4647 So we will wait until sock_graft to do it, by which
4648 time it will have been created and available. */
Paul Moore99f59ed2006-08-29 17:53:48 -07004649
Paul Moore9f2ad662006-11-17 17:38:53 -05004650 /* We don't need to take any sort of lock here as we are the only
4651 * thread with access to newsksec */
Paul Moore389fb8002009-03-27 17:10:34 -04004652 selinux_netlbl_inet_csk_clone(newsk, req->rsk_ops->family);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004653}
4654
Paul Moore014ab192008-10-10 10:16:33 -04004655static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb)
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004656{
Paul Mooreaa862902008-10-10 10:16:29 -04004657 u16 family = sk->sk_family;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004658 struct sk_security_struct *sksec = sk->sk_security;
4659
Paul Mooreaa862902008-10-10 10:16:29 -04004660 /* handle mapped IPv4 packets arriving via IPv6 sockets */
4661 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
4662 family = PF_INET;
4663
4664 selinux_skb_peerlbl_sid(skb, family, &sksec->peer_sid);
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004665}
4666
Eric Paris2606fd12010-10-13 16:24:41 -04004667static int selinux_secmark_relabel_packet(u32 sid)
4668{
4669 const struct task_security_struct *__tsec;
4670 u32 tsid;
4671
4672 __tsec = current_security();
4673 tsid = __tsec->sid;
4674
4675 return avc_has_perm(tsid, sid, SECCLASS_PACKET, PACKET__RELABELTO, NULL);
4676}
4677
4678static void selinux_secmark_refcount_inc(void)
4679{
4680 atomic_inc(&selinux_secmark_refcount);
4681}
4682
4683static void selinux_secmark_refcount_dec(void)
4684{
4685 atomic_dec(&selinux_secmark_refcount);
4686}
4687
Adrian Bunk9a673e52006-08-15 00:03:53 -07004688static void selinux_req_classify_flow(const struct request_sock *req,
4689 struct flowi *fl)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004690{
David S. Miller1d28f422011-03-12 00:29:39 -05004691 fl->flowi_secid = req->secid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004692}
4693
Paul Moore5dbbaf22013-01-14 07:12:19 +00004694static int selinux_tun_dev_alloc_security(void **security)
4695{
4696 struct tun_security_struct *tunsec;
4697
4698 tunsec = kzalloc(sizeof(*tunsec), GFP_KERNEL);
4699 if (!tunsec)
4700 return -ENOMEM;
4701 tunsec->sid = current_sid();
4702
4703 *security = tunsec;
4704 return 0;
4705}
4706
4707static void selinux_tun_dev_free_security(void *security)
4708{
4709 kfree(security);
4710}
4711
Paul Mooreed6d76e2009-08-28 18:12:49 -04004712static int selinux_tun_dev_create(void)
4713{
4714 u32 sid = current_sid();
4715
4716 /* we aren't taking into account the "sockcreate" SID since the socket
4717 * that is being created here is not a socket in the traditional sense,
4718 * instead it is a private sock, accessible only to the kernel, and
4719 * representing a wide range of network traffic spanning multiple
4720 * connections unlike traditional sockets - check the TUN driver to
4721 * get a better understanding of why this socket is special */
4722
4723 return avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET, TUN_SOCKET__CREATE,
4724 NULL);
4725}
4726
Paul Moore5dbbaf22013-01-14 07:12:19 +00004727static int selinux_tun_dev_attach_queue(void *security)
Paul Mooreed6d76e2009-08-28 18:12:49 -04004728{
Paul Moore5dbbaf22013-01-14 07:12:19 +00004729 struct tun_security_struct *tunsec = security;
4730
4731 return avc_has_perm(current_sid(), tunsec->sid, SECCLASS_TUN_SOCKET,
4732 TUN_SOCKET__ATTACH_QUEUE, NULL);
4733}
4734
4735static int selinux_tun_dev_attach(struct sock *sk, void *security)
4736{
4737 struct tun_security_struct *tunsec = security;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004738 struct sk_security_struct *sksec = sk->sk_security;
4739
4740 /* we don't currently perform any NetLabel based labeling here and it
4741 * isn't clear that we would want to do so anyway; while we could apply
4742 * labeling without the support of the TUN user the resulting labeled
4743 * traffic from the other end of the connection would almost certainly
4744 * cause confusion to the TUN user that had no idea network labeling
4745 * protocols were being used */
4746
Paul Moore5dbbaf22013-01-14 07:12:19 +00004747 sksec->sid = tunsec->sid;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004748 sksec->sclass = SECCLASS_TUN_SOCKET;
Paul Moore5dbbaf22013-01-14 07:12:19 +00004749
4750 return 0;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004751}
4752
Paul Moore5dbbaf22013-01-14 07:12:19 +00004753static int selinux_tun_dev_open(void *security)
Paul Mooreed6d76e2009-08-28 18:12:49 -04004754{
Paul Moore5dbbaf22013-01-14 07:12:19 +00004755 struct tun_security_struct *tunsec = security;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004756 u32 sid = current_sid();
4757 int err;
4758
Paul Moore5dbbaf22013-01-14 07:12:19 +00004759 err = avc_has_perm(sid, tunsec->sid, SECCLASS_TUN_SOCKET,
Paul Mooreed6d76e2009-08-28 18:12:49 -04004760 TUN_SOCKET__RELABELFROM, NULL);
4761 if (err)
4762 return err;
4763 err = avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET,
4764 TUN_SOCKET__RELABELTO, NULL);
4765 if (err)
4766 return err;
Paul Moore5dbbaf22013-01-14 07:12:19 +00004767 tunsec->sid = sid;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004768
4769 return 0;
4770}
4771
Linus Torvalds1da177e2005-04-16 15:20:36 -07004772static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
4773{
4774 int err = 0;
4775 u32 perm;
4776 struct nlmsghdr *nlh;
Paul Moore253bfae2010-04-22 14:46:19 -04004777 struct sk_security_struct *sksec = sk->sk_security;
Eric Paris828dfe12008-04-17 13:17:49 -04004778
Hong zhi guo77954982013-03-27 06:49:35 +00004779 if (skb->len < NLMSG_HDRLEN) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004780 err = -EINVAL;
4781 goto out;
4782 }
Arnaldo Carvalho de Melob529ccf2007-04-25 19:08:35 -07004783 nlh = nlmsg_hdr(skb);
Eric Paris828dfe12008-04-17 13:17:49 -04004784
Paul Moore253bfae2010-04-22 14:46:19 -04004785 err = selinux_nlmsg_lookup(sksec->sclass, nlh->nlmsg_type, &perm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004786 if (err) {
4787 if (err == -EINVAL) {
Richard Guy Briggsd950f842014-11-12 14:01:34 -05004788 printk(KERN_WARNING
4789 "SELinux: unrecognized netlink message:"
Marek Milkoviccded3ff2015-06-04 16:22:16 -04004790 " protocol=%hu nlmsg_type=%hu sclass=%s\n",
4791 sk->sk_protocol, nlh->nlmsg_type,
4792 secclass_map[sksec->sclass - 1].name);
Eric Paris39c9aed2008-11-05 09:34:42 -05004793 if (!selinux_enforcing || security_get_allow_unknown())
Linus Torvalds1da177e2005-04-16 15:20:36 -07004794 err = 0;
4795 }
4796
4797 /* Ignore */
4798 if (err == -ENOENT)
4799 err = 0;
4800 goto out;
4801 }
4802
Paul Moore253bfae2010-04-22 14:46:19 -04004803 err = sock_has_perm(current, sk, perm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004804out:
4805 return err;
4806}
4807
4808#ifdef CONFIG_NETFILTER
4809
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004810static unsigned int selinux_ip_forward(struct sk_buff *skb,
4811 const struct net_device *indev,
Paul Mooreeffad8d2008-01-29 08:49:27 -05004812 u16 family)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004813{
Paul Mooredfaebe92008-10-10 10:16:31 -04004814 int err;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004815 char *addrp;
4816 u32 peer_sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04004817 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004818 struct lsm_network_audit net = {0,};
Paul Mooreeffad8d2008-01-29 08:49:27 -05004819 u8 secmark_active;
Paul Moore948bf852008-10-10 10:16:32 -04004820 u8 netlbl_active;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004821 u8 peerlbl_active;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004822
Paul Mooreeffad8d2008-01-29 08:49:27 -05004823 if (!selinux_policycap_netpeer)
4824 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004825
Paul Mooreeffad8d2008-01-29 08:49:27 -05004826 secmark_active = selinux_secmark_enabled();
Paul Moore948bf852008-10-10 10:16:32 -04004827 netlbl_active = netlbl_enabled();
Chris PeBenito2be4d742013-05-03 09:05:39 -04004828 peerlbl_active = selinux_peerlbl_enabled();
Paul Mooreeffad8d2008-01-29 08:49:27 -05004829 if (!secmark_active && !peerlbl_active)
4830 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004831
Paul Moored8395c82008-10-10 10:16:30 -04004832 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0)
4833 return NF_DROP;
4834
Eric Paris50c205f2012-04-04 15:01:43 -04004835 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004836 ad.u.net = &net;
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004837 ad.u.net->netif = indev->ifindex;
Eric Paris48c62af2012-04-02 13:15:44 -04004838 ad.u.net->family = family;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004839 if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0)
4840 return NF_DROP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004841
Paul Mooredfaebe92008-10-10 10:16:31 -04004842 if (peerlbl_active) {
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004843 err = selinux_inet_sys_rcv_skb(dev_net(indev), indev->ifindex,
4844 addrp, family, peer_sid, &ad);
Paul Mooredfaebe92008-10-10 10:16:31 -04004845 if (err) {
4846 selinux_netlbl_err(skb, err, 1);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004847 return NF_DROP;
Paul Mooredfaebe92008-10-10 10:16:31 -04004848 }
4849 }
Paul Mooreeffad8d2008-01-29 08:49:27 -05004850
4851 if (secmark_active)
4852 if (avc_has_perm(peer_sid, skb->secmark,
4853 SECCLASS_PACKET, PACKET__FORWARD_IN, &ad))
4854 return NF_DROP;
4855
Paul Moore948bf852008-10-10 10:16:32 -04004856 if (netlbl_active)
4857 /* we do this in the FORWARD path and not the POST_ROUTING
4858 * path because we want to make sure we apply the necessary
4859 * labeling before IPsec is applied so we can leverage AH
4860 * protection */
4861 if (selinux_netlbl_skbuff_setsid(skb, family, peer_sid) != 0)
4862 return NF_DROP;
4863
Paul Mooreeffad8d2008-01-29 08:49:27 -05004864 return NF_ACCEPT;
4865}
4866
Eric W. Biederman06198b32015-09-18 14:33:06 -05004867static unsigned int selinux_ipv4_forward(void *priv,
Paul Mooreeffad8d2008-01-29 08:49:27 -05004868 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04004869 const struct nf_hook_state *state)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004870{
David S. Miller238e54c2015-04-03 20:32:56 -04004871 return selinux_ip_forward(skb, state->in, PF_INET);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004872}
4873
4874#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Eric W. Biederman06198b32015-09-18 14:33:06 -05004875static unsigned int selinux_ipv6_forward(void *priv,
Paul Mooreeffad8d2008-01-29 08:49:27 -05004876 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04004877 const struct nf_hook_state *state)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004878{
David S. Miller238e54c2015-04-03 20:32:56 -04004879 return selinux_ip_forward(skb, state->in, PF_INET6);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004880}
4881#endif /* IPV6 */
4882
Paul Moore948bf852008-10-10 10:16:32 -04004883static unsigned int selinux_ip_output(struct sk_buff *skb,
4884 u16 family)
4885{
Paul Moore47180062013-12-04 16:10:45 -05004886 struct sock *sk;
Paul Moore948bf852008-10-10 10:16:32 -04004887 u32 sid;
4888
4889 if (!netlbl_enabled())
4890 return NF_ACCEPT;
4891
4892 /* we do this in the LOCAL_OUT path and not the POST_ROUTING path
4893 * because we want to make sure we apply the necessary labeling
4894 * before IPsec is applied so we can leverage AH protection */
Paul Moore47180062013-12-04 16:10:45 -05004895 sk = skb->sk;
4896 if (sk) {
4897 struct sk_security_struct *sksec;
4898
Eric Dumazete446f9d2015-10-08 05:01:55 -07004899 if (sk_listener(sk))
Paul Moore47180062013-12-04 16:10:45 -05004900 /* if the socket is the listening state then this
4901 * packet is a SYN-ACK packet which means it needs to
4902 * be labeled based on the connection/request_sock and
4903 * not the parent socket. unfortunately, we can't
4904 * lookup the request_sock yet as it isn't queued on
4905 * the parent socket until after the SYN-ACK is sent.
4906 * the "solution" is to simply pass the packet as-is
4907 * as any IP option based labeling should be copied
4908 * from the initial connection request (in the IP
4909 * layer). it is far from ideal, but until we get a
4910 * security label in the packet itself this is the
4911 * best we can do. */
4912 return NF_ACCEPT;
4913
4914 /* standard practice, label using the parent socket */
4915 sksec = sk->sk_security;
Paul Moore948bf852008-10-10 10:16:32 -04004916 sid = sksec->sid;
4917 } else
4918 sid = SECINITSID_KERNEL;
4919 if (selinux_netlbl_skbuff_setsid(skb, family, sid) != 0)
4920 return NF_DROP;
4921
4922 return NF_ACCEPT;
4923}
4924
Eric W. Biederman06198b32015-09-18 14:33:06 -05004925static unsigned int selinux_ipv4_output(void *priv,
Paul Moore948bf852008-10-10 10:16:32 -04004926 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04004927 const struct nf_hook_state *state)
Paul Moore948bf852008-10-10 10:16:32 -04004928{
4929 return selinux_ip_output(skb, PF_INET);
4930}
4931
Paul Mooreeffad8d2008-01-29 08:49:27 -05004932static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
4933 int ifindex,
Paul Moored8395c82008-10-10 10:16:30 -04004934 u16 family)
James Morris4e5ab4c2006-06-09 00:33:33 -07004935{
Eric Dumazet54abc682015-11-08 10:54:07 -08004936 struct sock *sk = skb_to_full_sk(skb);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004937 struct sk_security_struct *sksec;
Thomas Liu2bf49692009-07-14 12:14:09 -04004938 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004939 struct lsm_network_audit net = {0,};
Paul Moored8395c82008-10-10 10:16:30 -04004940 char *addrp;
4941 u8 proto;
James Morris4e5ab4c2006-06-09 00:33:33 -07004942
Paul Mooreeffad8d2008-01-29 08:49:27 -05004943 if (sk == NULL)
4944 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004945 sksec = sk->sk_security;
James Morris4e5ab4c2006-06-09 00:33:33 -07004946
Eric Paris50c205f2012-04-04 15:01:43 -04004947 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004948 ad.u.net = &net;
4949 ad.u.net->netif = ifindex;
4950 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04004951 if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto))
4952 return NF_DROP;
4953
Paul Moore58bfbb52009-03-27 17:10:41 -04004954 if (selinux_secmark_enabled())
Paul Mooreeffad8d2008-01-29 08:49:27 -05004955 if (avc_has_perm(sksec->sid, skb->secmark,
Paul Moored8395c82008-10-10 10:16:30 -04004956 SECCLASS_PACKET, PACKET__SEND, &ad))
Eric Paris2fe66ec2010-11-23 06:28:08 +00004957 return NF_DROP_ERR(-ECONNREFUSED);
James Morris4e5ab4c2006-06-09 00:33:33 -07004958
Steffen Klassertb9679a72011-02-23 12:55:21 +01004959 if (selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto))
4960 return NF_DROP_ERR(-ECONNREFUSED);
James Morris4e5ab4c2006-06-09 00:33:33 -07004961
Paul Mooreeffad8d2008-01-29 08:49:27 -05004962 return NF_ACCEPT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004963}
4964
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004965static unsigned int selinux_ip_postroute(struct sk_buff *skb,
4966 const struct net_device *outdev,
Paul Mooreeffad8d2008-01-29 08:49:27 -05004967 u16 family)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004968{
Paul Mooreeffad8d2008-01-29 08:49:27 -05004969 u32 secmark_perm;
4970 u32 peer_sid;
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004971 int ifindex = outdev->ifindex;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004972 struct sock *sk;
Thomas Liu2bf49692009-07-14 12:14:09 -04004973 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004974 struct lsm_network_audit net = {0,};
Paul Mooreeffad8d2008-01-29 08:49:27 -05004975 char *addrp;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004976 u8 secmark_active;
4977 u8 peerlbl_active;
4978
Paul Mooreeffad8d2008-01-29 08:49:27 -05004979 /* If any sort of compatibility mode is enabled then handoff processing
4980 * to the selinux_ip_postroute_compat() function to deal with the
4981 * special handling. We do this in an attempt to keep this function
4982 * as fast and as clean as possible. */
Paul Moore58bfbb52009-03-27 17:10:41 -04004983 if (!selinux_policycap_netpeer)
Paul Moored8395c82008-10-10 10:16:30 -04004984 return selinux_ip_postroute_compat(skb, ifindex, family);
Paul Moorec0828e52013-12-10 14:58:01 -05004985
Paul Mooreeffad8d2008-01-29 08:49:27 -05004986 secmark_active = selinux_secmark_enabled();
Chris PeBenito2be4d742013-05-03 09:05:39 -04004987 peerlbl_active = selinux_peerlbl_enabled();
Paul Mooreeffad8d2008-01-29 08:49:27 -05004988 if (!secmark_active && !peerlbl_active)
4989 return NF_ACCEPT;
4990
Eric Dumazet54abc682015-11-08 10:54:07 -08004991 sk = skb_to_full_sk(skb);
Paul Moorec0828e52013-12-10 14:58:01 -05004992
Paul Mooreeffad8d2008-01-29 08:49:27 -05004993#ifdef CONFIG_XFRM
4994 /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec
4995 * packet transformation so allow the packet to pass without any checks
4996 * since we'll have another chance to perform access control checks
4997 * when the packet is on it's final way out.
4998 * NOTE: there appear to be some IPv6 multicast cases where skb->dst
Paul Moorec0828e52013-12-10 14:58:01 -05004999 * is NULL, in this case go ahead and apply access control.
5000 * NOTE: if this is a local socket (skb->sk != NULL) that is in the
5001 * TCP listening state we cannot wait until the XFRM processing
5002 * is done as we will miss out on the SA label if we do;
5003 * unfortunately, this means more work, but it is only once per
5004 * connection. */
5005 if (skb_dst(skb) != NULL && skb_dst(skb)->xfrm != NULL &&
Eric Dumazete446f9d2015-10-08 05:01:55 -07005006 !(sk && sk_listener(sk)))
Paul Mooreeffad8d2008-01-29 08:49:27 -05005007 return NF_ACCEPT;
5008#endif
Paul Mooreeffad8d2008-01-29 08:49:27 -05005009
Paul Moored8395c82008-10-10 10:16:30 -04005010 if (sk == NULL) {
Paul Moore446b8022013-12-04 16:10:51 -05005011 /* Without an associated socket the packet is either coming
5012 * from the kernel or it is being forwarded; check the packet
5013 * to determine which and if the packet is being forwarded
5014 * query the packet directly to determine the security label. */
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01005015 if (skb->skb_iif) {
5016 secmark_perm = PACKET__FORWARD_OUT;
Paul Moored8395c82008-10-10 10:16:30 -04005017 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00005018 return NF_DROP;
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01005019 } else {
5020 secmark_perm = PACKET__SEND;
Paul Moored8395c82008-10-10 10:16:30 -04005021 peer_sid = SECINITSID_KERNEL;
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01005022 }
Eric Dumazete446f9d2015-10-08 05:01:55 -07005023 } else if (sk_listener(sk)) {
Paul Moore446b8022013-12-04 16:10:51 -05005024 /* Locally generated packet but the associated socket is in the
5025 * listening state which means this is a SYN-ACK packet. In
5026 * this particular case the correct security label is assigned
5027 * to the connection/request_sock but unfortunately we can't
5028 * query the request_sock as it isn't queued on the parent
5029 * socket until after the SYN-ACK packet is sent; the only
5030 * viable choice is to regenerate the label like we do in
5031 * selinux_inet_conn_request(). See also selinux_ip_output()
5032 * for similar problems. */
5033 u32 skb_sid;
Eric Dumazete446f9d2015-10-08 05:01:55 -07005034 struct sk_security_struct *sksec;
5035
Eric Dumazete446f9d2015-10-08 05:01:55 -07005036 sksec = sk->sk_security;
Paul Moore446b8022013-12-04 16:10:51 -05005037 if (selinux_skb_peerlbl_sid(skb, family, &skb_sid))
5038 return NF_DROP;
Paul Moorec0828e52013-12-10 14:58:01 -05005039 /* At this point, if the returned skb peerlbl is SECSID_NULL
5040 * and the packet has been through at least one XFRM
5041 * transformation then we must be dealing with the "final"
5042 * form of labeled IPsec packet; since we've already applied
5043 * all of our access controls on this packet we can safely
5044 * pass the packet. */
5045 if (skb_sid == SECSID_NULL) {
5046 switch (family) {
5047 case PF_INET:
5048 if (IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED)
5049 return NF_ACCEPT;
5050 break;
5051 case PF_INET6:
5052 if (IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED)
5053 return NF_ACCEPT;
Paul Moorea7a91a12014-09-03 10:51:59 -04005054 break;
Paul Moorec0828e52013-12-10 14:58:01 -05005055 default:
5056 return NF_DROP_ERR(-ECONNREFUSED);
5057 }
5058 }
Paul Moore446b8022013-12-04 16:10:51 -05005059 if (selinux_conn_sid(sksec->sid, skb_sid, &peer_sid))
5060 return NF_DROP;
5061 secmark_perm = PACKET__SEND;
Paul Moored8395c82008-10-10 10:16:30 -04005062 } else {
Paul Moore446b8022013-12-04 16:10:51 -05005063 /* Locally generated packet, fetch the security label from the
5064 * associated socket. */
Paul Mooreeffad8d2008-01-29 08:49:27 -05005065 struct sk_security_struct *sksec = sk->sk_security;
5066 peer_sid = sksec->sid;
5067 secmark_perm = PACKET__SEND;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005068 }
5069
Eric Paris50c205f2012-04-04 15:01:43 -04005070 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04005071 ad.u.net = &net;
5072 ad.u.net->netif = ifindex;
5073 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04005074 if (selinux_parse_skb(skb, &ad, &addrp, 0, NULL))
Eric Paris04f6d702010-11-23 06:28:02 +00005075 return NF_DROP;
Paul Moored8395c82008-10-10 10:16:30 -04005076
Paul Mooreeffad8d2008-01-29 08:49:27 -05005077 if (secmark_active)
5078 if (avc_has_perm(peer_sid, skb->secmark,
5079 SECCLASS_PACKET, secmark_perm, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00005080 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005081
5082 if (peerlbl_active) {
5083 u32 if_sid;
5084 u32 node_sid;
5085
Paul Moorecbe0d6e2014-09-10 17:09:57 -04005086 if (sel_netif_sid(dev_net(outdev), ifindex, &if_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00005087 return NF_DROP;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005088 if (avc_has_perm(peer_sid, if_sid,
5089 SECCLASS_NETIF, NETIF__EGRESS, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00005090 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005091
5092 if (sel_netnode_sid(addrp, family, &node_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00005093 return NF_DROP;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005094 if (avc_has_perm(peer_sid, node_sid,
5095 SECCLASS_NODE, NODE__SENDTO, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00005096 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005097 }
5098
5099 return NF_ACCEPT;
5100}
5101
Eric W. Biederman06198b32015-09-18 14:33:06 -05005102static unsigned int selinux_ipv4_postroute(void *priv,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005103 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04005104 const struct nf_hook_state *state)
Paul Mooreeffad8d2008-01-29 08:49:27 -05005105{
David S. Miller238e54c2015-04-03 20:32:56 -04005106 return selinux_ip_postroute(skb, state->out, PF_INET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005107}
5108
5109#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Eric W. Biederman06198b32015-09-18 14:33:06 -05005110static unsigned int selinux_ipv6_postroute(void *priv,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005111 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04005112 const struct nf_hook_state *state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005113{
David S. Miller238e54c2015-04-03 20:32:56 -04005114 return selinux_ip_postroute(skb, state->out, PF_INET6);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005115}
Linus Torvalds1da177e2005-04-16 15:20:36 -07005116#endif /* IPV6 */
5117
5118#endif /* CONFIG_NETFILTER */
5119
Linus Torvalds1da177e2005-04-16 15:20:36 -07005120static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb)
5121{
Stephen Smalley941fc5b2009-10-01 14:48:23 -04005122 return selinux_nlmsg_perm(sk, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005123}
5124
Linus Torvalds1da177e2005-04-16 15:20:36 -07005125static int ipc_alloc_security(struct task_struct *task,
5126 struct kern_ipc_perm *perm,
5127 u16 sclass)
5128{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005129 struct ipc_security_struct *isec;
David Howells275bb412008-11-14 10:39:19 +11005130 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005131
James Morris89d155e2005-10-30 14:59:21 -08005132 isec = kzalloc(sizeof(struct ipc_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005133 if (!isec)
5134 return -ENOMEM;
5135
David Howells275bb412008-11-14 10:39:19 +11005136 sid = task_sid(task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005137 isec->sclass = sclass;
David Howells275bb412008-11-14 10:39:19 +11005138 isec->sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005139 perm->security = isec;
5140
5141 return 0;
5142}
5143
5144static void ipc_free_security(struct kern_ipc_perm *perm)
5145{
5146 struct ipc_security_struct *isec = perm->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005147 perm->security = NULL;
5148 kfree(isec);
5149}
5150
5151static int msg_msg_alloc_security(struct msg_msg *msg)
5152{
5153 struct msg_security_struct *msec;
5154
James Morris89d155e2005-10-30 14:59:21 -08005155 msec = kzalloc(sizeof(struct msg_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005156 if (!msec)
5157 return -ENOMEM;
5158
Linus Torvalds1da177e2005-04-16 15:20:36 -07005159 msec->sid = SECINITSID_UNLABELED;
5160 msg->security = msec;
5161
5162 return 0;
5163}
5164
5165static void msg_msg_free_security(struct msg_msg *msg)
5166{
5167 struct msg_security_struct *msec = msg->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005168
5169 msg->security = NULL;
5170 kfree(msec);
5171}
5172
5173static int ipc_has_perm(struct kern_ipc_perm *ipc_perms,
Stephen Smalley6af963f2005-05-01 08:58:39 -07005174 u32 perms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005175{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005176 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005177 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005178 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005179
Linus Torvalds1da177e2005-04-16 15:20:36 -07005180 isec = ipc_perms->security;
5181
Eric Paris50c205f2012-04-04 15:01:43 -04005182 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005183 ad.u.ipc_id = ipc_perms->key;
5184
David Howells275bb412008-11-14 10:39:19 +11005185 return avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005186}
5187
5188static int selinux_msg_msg_alloc_security(struct msg_msg *msg)
5189{
5190 return msg_msg_alloc_security(msg);
5191}
5192
5193static void selinux_msg_msg_free_security(struct msg_msg *msg)
5194{
5195 msg_msg_free_security(msg);
5196}
5197
5198/* message queue security operations */
5199static int selinux_msg_queue_alloc_security(struct msg_queue *msq)
5200{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005201 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005202 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005203 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005204 int rc;
5205
5206 rc = ipc_alloc_security(current, &msq->q_perm, SECCLASS_MSGQ);
5207 if (rc)
5208 return rc;
5209
Linus Torvalds1da177e2005-04-16 15:20:36 -07005210 isec = msq->q_perm.security;
5211
Eric Paris50c205f2012-04-04 15:01:43 -04005212 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04005213 ad.u.ipc_id = msq->q_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005214
David Howells275bb412008-11-14 10:39:19 +11005215 rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005216 MSGQ__CREATE, &ad);
5217 if (rc) {
5218 ipc_free_security(&msq->q_perm);
5219 return rc;
5220 }
5221 return 0;
5222}
5223
5224static void selinux_msg_queue_free_security(struct msg_queue *msq)
5225{
5226 ipc_free_security(&msq->q_perm);
5227}
5228
5229static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg)
5230{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005231 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005232 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005233 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005234
Linus Torvalds1da177e2005-04-16 15:20:36 -07005235 isec = msq->q_perm.security;
5236
Eric Paris50c205f2012-04-04 15:01:43 -04005237 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005238 ad.u.ipc_id = msq->q_perm.key;
5239
David Howells275bb412008-11-14 10:39:19 +11005240 return avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005241 MSGQ__ASSOCIATE, &ad);
5242}
5243
5244static int selinux_msg_queue_msgctl(struct msg_queue *msq, int cmd)
5245{
5246 int err;
5247 int perms;
5248
Eric Paris828dfe12008-04-17 13:17:49 -04005249 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005250 case IPC_INFO:
5251 case MSG_INFO:
5252 /* No specific object, just general system-wide information. */
5253 return task_has_system(current, SYSTEM__IPC_INFO);
5254 case IPC_STAT:
5255 case MSG_STAT:
5256 perms = MSGQ__GETATTR | MSGQ__ASSOCIATE;
5257 break;
5258 case IPC_SET:
5259 perms = MSGQ__SETATTR;
5260 break;
5261 case IPC_RMID:
5262 perms = MSGQ__DESTROY;
5263 break;
5264 default:
5265 return 0;
5266 }
5267
Stephen Smalley6af963f2005-05-01 08:58:39 -07005268 err = ipc_has_perm(&msq->q_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005269 return err;
5270}
5271
5272static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, int msqflg)
5273{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005274 struct ipc_security_struct *isec;
5275 struct msg_security_struct *msec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005276 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005277 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005278 int rc;
5279
Linus Torvalds1da177e2005-04-16 15:20:36 -07005280 isec = msq->q_perm.security;
5281 msec = msg->security;
5282
5283 /*
5284 * First time through, need to assign label to the message
5285 */
5286 if (msec->sid == SECINITSID_UNLABELED) {
5287 /*
5288 * Compute new sid based on current process and
5289 * message queue this message will be stored in
5290 */
David Howells275bb412008-11-14 10:39:19 +11005291 rc = security_transition_sid(sid, isec->sid, SECCLASS_MSG,
Eric Paris652bb9b2011-02-01 11:05:40 -05005292 NULL, &msec->sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005293 if (rc)
5294 return rc;
5295 }
5296
Eric Paris50c205f2012-04-04 15:01:43 -04005297 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005298 ad.u.ipc_id = msq->q_perm.key;
5299
5300 /* Can this process write to the queue? */
David Howells275bb412008-11-14 10:39:19 +11005301 rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005302 MSGQ__WRITE, &ad);
5303 if (!rc)
5304 /* Can this process send the message */
David Howells275bb412008-11-14 10:39:19 +11005305 rc = avc_has_perm(sid, msec->sid, SECCLASS_MSG,
5306 MSG__SEND, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005307 if (!rc)
5308 /* Can the message be put in the queue? */
David Howells275bb412008-11-14 10:39:19 +11005309 rc = avc_has_perm(msec->sid, isec->sid, SECCLASS_MSGQ,
5310 MSGQ__ENQUEUE, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005311
5312 return rc;
5313}
5314
5315static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
5316 struct task_struct *target,
5317 long type, int mode)
5318{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005319 struct ipc_security_struct *isec;
5320 struct msg_security_struct *msec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005321 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005322 u32 sid = task_sid(target);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005323 int rc;
5324
Linus Torvalds1da177e2005-04-16 15:20:36 -07005325 isec = msq->q_perm.security;
5326 msec = msg->security;
5327
Eric Paris50c205f2012-04-04 15:01:43 -04005328 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04005329 ad.u.ipc_id = msq->q_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005330
David Howells275bb412008-11-14 10:39:19 +11005331 rc = avc_has_perm(sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005332 SECCLASS_MSGQ, MSGQ__READ, &ad);
5333 if (!rc)
David Howells275bb412008-11-14 10:39:19 +11005334 rc = avc_has_perm(sid, msec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005335 SECCLASS_MSG, MSG__RECEIVE, &ad);
5336 return rc;
5337}
5338
5339/* Shared Memory security operations */
5340static int selinux_shm_alloc_security(struct shmid_kernel *shp)
5341{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005342 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005343 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005344 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005345 int rc;
5346
5347 rc = ipc_alloc_security(current, &shp->shm_perm, SECCLASS_SHM);
5348 if (rc)
5349 return rc;
5350
Linus Torvalds1da177e2005-04-16 15:20:36 -07005351 isec = shp->shm_perm.security;
5352
Eric Paris50c205f2012-04-04 15:01:43 -04005353 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04005354 ad.u.ipc_id = shp->shm_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005355
David Howells275bb412008-11-14 10:39:19 +11005356 rc = avc_has_perm(sid, isec->sid, SECCLASS_SHM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005357 SHM__CREATE, &ad);
5358 if (rc) {
5359 ipc_free_security(&shp->shm_perm);
5360 return rc;
5361 }
5362 return 0;
5363}
5364
5365static void selinux_shm_free_security(struct shmid_kernel *shp)
5366{
5367 ipc_free_security(&shp->shm_perm);
5368}
5369
5370static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg)
5371{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005372 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005373 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005374 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005375
Linus Torvalds1da177e2005-04-16 15:20:36 -07005376 isec = shp->shm_perm.security;
5377
Eric Paris50c205f2012-04-04 15:01:43 -04005378 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005379 ad.u.ipc_id = shp->shm_perm.key;
5380
David Howells275bb412008-11-14 10:39:19 +11005381 return avc_has_perm(sid, isec->sid, SECCLASS_SHM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005382 SHM__ASSOCIATE, &ad);
5383}
5384
5385/* Note, at this point, shp is locked down */
5386static int selinux_shm_shmctl(struct shmid_kernel *shp, int cmd)
5387{
5388 int perms;
5389 int err;
5390
Eric Paris828dfe12008-04-17 13:17:49 -04005391 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005392 case IPC_INFO:
5393 case SHM_INFO:
5394 /* No specific object, just general system-wide information. */
5395 return task_has_system(current, SYSTEM__IPC_INFO);
5396 case IPC_STAT:
5397 case SHM_STAT:
5398 perms = SHM__GETATTR | SHM__ASSOCIATE;
5399 break;
5400 case IPC_SET:
5401 perms = SHM__SETATTR;
5402 break;
5403 case SHM_LOCK:
5404 case SHM_UNLOCK:
5405 perms = SHM__LOCK;
5406 break;
5407 case IPC_RMID:
5408 perms = SHM__DESTROY;
5409 break;
5410 default:
5411 return 0;
5412 }
5413
Stephen Smalley6af963f2005-05-01 08:58:39 -07005414 err = ipc_has_perm(&shp->shm_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005415 return err;
5416}
5417
5418static int selinux_shm_shmat(struct shmid_kernel *shp,
5419 char __user *shmaddr, int shmflg)
5420{
5421 u32 perms;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005422
5423 if (shmflg & SHM_RDONLY)
5424 perms = SHM__READ;
5425 else
5426 perms = SHM__READ | SHM__WRITE;
5427
Stephen Smalley6af963f2005-05-01 08:58:39 -07005428 return ipc_has_perm(&shp->shm_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005429}
5430
5431/* Semaphore security operations */
5432static int selinux_sem_alloc_security(struct sem_array *sma)
5433{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005434 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005435 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005436 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005437 int rc;
5438
5439 rc = ipc_alloc_security(current, &sma->sem_perm, SECCLASS_SEM);
5440 if (rc)
5441 return rc;
5442
Linus Torvalds1da177e2005-04-16 15:20:36 -07005443 isec = sma->sem_perm.security;
5444
Eric Paris50c205f2012-04-04 15:01:43 -04005445 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04005446 ad.u.ipc_id = sma->sem_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005447
David Howells275bb412008-11-14 10:39:19 +11005448 rc = avc_has_perm(sid, isec->sid, SECCLASS_SEM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005449 SEM__CREATE, &ad);
5450 if (rc) {
5451 ipc_free_security(&sma->sem_perm);
5452 return rc;
5453 }
5454 return 0;
5455}
5456
5457static void selinux_sem_free_security(struct sem_array *sma)
5458{
5459 ipc_free_security(&sma->sem_perm);
5460}
5461
5462static int selinux_sem_associate(struct sem_array *sma, int semflg)
5463{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005464 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005465 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005466 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005467
Linus Torvalds1da177e2005-04-16 15:20:36 -07005468 isec = sma->sem_perm.security;
5469
Eric Paris50c205f2012-04-04 15:01:43 -04005470 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005471 ad.u.ipc_id = sma->sem_perm.key;
5472
David Howells275bb412008-11-14 10:39:19 +11005473 return avc_has_perm(sid, isec->sid, SECCLASS_SEM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005474 SEM__ASSOCIATE, &ad);
5475}
5476
5477/* Note, at this point, sma is locked down */
5478static int selinux_sem_semctl(struct sem_array *sma, int cmd)
5479{
5480 int err;
5481 u32 perms;
5482
Eric Paris828dfe12008-04-17 13:17:49 -04005483 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005484 case IPC_INFO:
5485 case SEM_INFO:
5486 /* No specific object, just general system-wide information. */
5487 return task_has_system(current, SYSTEM__IPC_INFO);
5488 case GETPID:
5489 case GETNCNT:
5490 case GETZCNT:
5491 perms = SEM__GETATTR;
5492 break;
5493 case GETVAL:
5494 case GETALL:
5495 perms = SEM__READ;
5496 break;
5497 case SETVAL:
5498 case SETALL:
5499 perms = SEM__WRITE;
5500 break;
5501 case IPC_RMID:
5502 perms = SEM__DESTROY;
5503 break;
5504 case IPC_SET:
5505 perms = SEM__SETATTR;
5506 break;
5507 case IPC_STAT:
5508 case SEM_STAT:
5509 perms = SEM__GETATTR | SEM__ASSOCIATE;
5510 break;
5511 default:
5512 return 0;
5513 }
5514
Stephen Smalley6af963f2005-05-01 08:58:39 -07005515 err = ipc_has_perm(&sma->sem_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005516 return err;
5517}
5518
5519static int selinux_sem_semop(struct sem_array *sma,
5520 struct sembuf *sops, unsigned nsops, int alter)
5521{
5522 u32 perms;
5523
5524 if (alter)
5525 perms = SEM__READ | SEM__WRITE;
5526 else
5527 perms = SEM__READ;
5528
Stephen Smalley6af963f2005-05-01 08:58:39 -07005529 return ipc_has_perm(&sma->sem_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005530}
5531
5532static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
5533{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005534 u32 av = 0;
5535
Linus Torvalds1da177e2005-04-16 15:20:36 -07005536 av = 0;
5537 if (flag & S_IRUGO)
5538 av |= IPC__UNIX_READ;
5539 if (flag & S_IWUGO)
5540 av |= IPC__UNIX_WRITE;
5541
5542 if (av == 0)
5543 return 0;
5544
Stephen Smalley6af963f2005-05-01 08:58:39 -07005545 return ipc_has_perm(ipcp, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005546}
5547
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02005548static void selinux_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
5549{
5550 struct ipc_security_struct *isec = ipcp->security;
5551 *secid = isec->sid;
5552}
5553
Eric Paris828dfe12008-04-17 13:17:49 -04005554static void selinux_d_instantiate(struct dentry *dentry, struct inode *inode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005555{
5556 if (inode)
5557 inode_doinit_with_dentry(inode, dentry);
5558}
5559
5560static int selinux_getprocattr(struct task_struct *p,
Al Viro04ff9702007-03-12 16:17:58 +00005561 char *name, char **value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005562{
David Howells275bb412008-11-14 10:39:19 +11005563 const struct task_security_struct *__tsec;
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00005564 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005565 int error;
Al Viro04ff9702007-03-12 16:17:58 +00005566 unsigned len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005567
5568 if (current != p) {
David Howells3b11a1d2008-11-14 10:39:26 +11005569 error = current_has_perm(p, PROCESS__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005570 if (error)
5571 return error;
5572 }
5573
David Howells275bb412008-11-14 10:39:19 +11005574 rcu_read_lock();
5575 __tsec = __task_cred(p)->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005576
5577 if (!strcmp(name, "current"))
David Howells275bb412008-11-14 10:39:19 +11005578 sid = __tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005579 else if (!strcmp(name, "prev"))
David Howells275bb412008-11-14 10:39:19 +11005580 sid = __tsec->osid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005581 else if (!strcmp(name, "exec"))
David Howells275bb412008-11-14 10:39:19 +11005582 sid = __tsec->exec_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005583 else if (!strcmp(name, "fscreate"))
David Howells275bb412008-11-14 10:39:19 +11005584 sid = __tsec->create_sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005585 else if (!strcmp(name, "keycreate"))
David Howells275bb412008-11-14 10:39:19 +11005586 sid = __tsec->keycreate_sid;
Eric Paris42c3e032006-06-26 00:26:03 -07005587 else if (!strcmp(name, "sockcreate"))
David Howells275bb412008-11-14 10:39:19 +11005588 sid = __tsec->sockcreate_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005589 else
David Howells275bb412008-11-14 10:39:19 +11005590 goto invalid;
5591 rcu_read_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005592
5593 if (!sid)
5594 return 0;
5595
Al Viro04ff9702007-03-12 16:17:58 +00005596 error = security_sid_to_context(sid, value, &len);
5597 if (error)
5598 return error;
5599 return len;
David Howells275bb412008-11-14 10:39:19 +11005600
5601invalid:
5602 rcu_read_unlock();
5603 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005604}
5605
5606static int selinux_setprocattr(struct task_struct *p,
5607 char *name, void *value, size_t size)
5608{
5609 struct task_security_struct *tsec;
Roland McGrath03563572008-03-26 15:46:39 -07005610 struct task_struct *tracer;
David Howellsd84f4f92008-11-14 10:39:23 +11005611 struct cred *new;
5612 u32 sid = 0, ptsid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005613 int error;
5614 char *str = value;
5615
5616 if (current != p) {
5617 /* SELinux only allows a process to change its own
5618 security attributes. */
5619 return -EACCES;
5620 }
5621
5622 /*
5623 * Basic control over ability to set these attributes at all.
5624 * current == p, but we'll pass them separately in case the
5625 * above restriction is ever removed.
5626 */
5627 if (!strcmp(name, "exec"))
David Howells3b11a1d2008-11-14 10:39:26 +11005628 error = current_has_perm(p, PROCESS__SETEXEC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005629 else if (!strcmp(name, "fscreate"))
David Howells3b11a1d2008-11-14 10:39:26 +11005630 error = current_has_perm(p, PROCESS__SETFSCREATE);
Michael LeMay4eb582c2006-06-26 00:24:57 -07005631 else if (!strcmp(name, "keycreate"))
David Howells3b11a1d2008-11-14 10:39:26 +11005632 error = current_has_perm(p, PROCESS__SETKEYCREATE);
Eric Paris42c3e032006-06-26 00:26:03 -07005633 else if (!strcmp(name, "sockcreate"))
David Howells3b11a1d2008-11-14 10:39:26 +11005634 error = current_has_perm(p, PROCESS__SETSOCKCREATE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005635 else if (!strcmp(name, "current"))
David Howells3b11a1d2008-11-14 10:39:26 +11005636 error = current_has_perm(p, PROCESS__SETCURRENT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005637 else
5638 error = -EINVAL;
5639 if (error)
5640 return error;
5641
5642 /* Obtain a SID for the context, if one was specified. */
5643 if (size && str[1] && str[1] != '\n') {
5644 if (str[size-1] == '\n') {
5645 str[size-1] = 0;
5646 size--;
5647 }
Nikolay Aleksandrov52a4c642014-03-07 12:44:19 +01005648 error = security_context_to_sid(value, size, &sid, GFP_KERNEL);
Stephen Smalley12b29f32008-05-07 13:03:20 -04005649 if (error == -EINVAL && !strcmp(name, "fscreate")) {
Eric Parisd6ea83e2012-04-04 13:45:49 -04005650 if (!capable(CAP_MAC_ADMIN)) {
5651 struct audit_buffer *ab;
5652 size_t audit_size;
5653
5654 /* We strip a nul only if it is at the end, otherwise the
5655 * context contains a nul and we should audit that */
5656 if (str[size - 1] == '\0')
5657 audit_size = size - 1;
5658 else
5659 audit_size = size;
5660 ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR);
5661 audit_log_format(ab, "op=fscreate invalid_context=");
5662 audit_log_n_untrustedstring(ab, value, audit_size);
5663 audit_log_end(ab);
5664
Stephen Smalley12b29f32008-05-07 13:03:20 -04005665 return error;
Eric Parisd6ea83e2012-04-04 13:45:49 -04005666 }
Stephen Smalley12b29f32008-05-07 13:03:20 -04005667 error = security_context_to_sid_force(value, size,
5668 &sid);
5669 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005670 if (error)
5671 return error;
5672 }
5673
David Howellsd84f4f92008-11-14 10:39:23 +11005674 new = prepare_creds();
5675 if (!new)
5676 return -ENOMEM;
5677
Linus Torvalds1da177e2005-04-16 15:20:36 -07005678 /* Permission checking based on the specified context is
5679 performed during the actual operation (execve,
5680 open/mkdir/...), when we know the full context of the
David Howellsd84f4f92008-11-14 10:39:23 +11005681 operation. See selinux_bprm_set_creds for the execve
Linus Torvalds1da177e2005-04-16 15:20:36 -07005682 checks and may_create for the file creation checks. The
5683 operation will then fail if the context is not permitted. */
David Howellsd84f4f92008-11-14 10:39:23 +11005684 tsec = new->security;
5685 if (!strcmp(name, "exec")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005686 tsec->exec_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005687 } else if (!strcmp(name, "fscreate")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005688 tsec->create_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005689 } else if (!strcmp(name, "keycreate")) {
Michael LeMay4eb582c2006-06-26 00:24:57 -07005690 error = may_create_key(sid, p);
5691 if (error)
David Howellsd84f4f92008-11-14 10:39:23 +11005692 goto abort_change;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005693 tsec->keycreate_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005694 } else if (!strcmp(name, "sockcreate")) {
Eric Paris42c3e032006-06-26 00:26:03 -07005695 tsec->sockcreate_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005696 } else if (!strcmp(name, "current")) {
5697 error = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005698 if (sid == 0)
David Howellsd84f4f92008-11-14 10:39:23 +11005699 goto abort_change;
KaiGai Koheid9250de2008-08-28 16:35:57 +09005700
David Howellsd84f4f92008-11-14 10:39:23 +11005701 /* Only allow single threaded processes to change context */
5702 error = -EPERM;
Oleg Nesterov5bb459b2009-07-10 03:48:23 +02005703 if (!current_is_single_threaded()) {
David Howellsd84f4f92008-11-14 10:39:23 +11005704 error = security_bounded_transition(tsec->sid, sid);
5705 if (error)
5706 goto abort_change;
Eric Paris828dfe12008-04-17 13:17:49 -04005707 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005708
5709 /* Check permissions for the transition. */
5710 error = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS,
Eric Paris828dfe12008-04-17 13:17:49 -04005711 PROCESS__DYNTRANSITION, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005712 if (error)
David Howellsd84f4f92008-11-14 10:39:23 +11005713 goto abort_change;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005714
5715 /* Check for ptracing, and update the task SID if ok.
5716 Otherwise, leave SID unchanged and fail. */
David Howellsd84f4f92008-11-14 10:39:23 +11005717 ptsid = 0;
Oleg Nesterovc0c14392013-12-23 17:45:01 -05005718 rcu_read_lock();
Tejun Heo06d98472011-06-17 16:50:40 +02005719 tracer = ptrace_parent(p);
David Howellsd84f4f92008-11-14 10:39:23 +11005720 if (tracer)
5721 ptsid = task_sid(tracer);
Oleg Nesterovc0c14392013-12-23 17:45:01 -05005722 rcu_read_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005723
David Howellsd84f4f92008-11-14 10:39:23 +11005724 if (tracer) {
5725 error = avc_has_perm(ptsid, sid, SECCLASS_PROCESS,
5726 PROCESS__PTRACE, NULL);
5727 if (error)
5728 goto abort_change;
5729 }
5730
5731 tsec->sid = sid;
5732 } else {
5733 error = -EINVAL;
5734 goto abort_change;
5735 }
5736
5737 commit_creds(new);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005738 return size;
David Howellsd84f4f92008-11-14 10:39:23 +11005739
5740abort_change:
5741 abort_creds(new);
5742 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005743}
5744
David Quigley746df9b2013-05-22 12:50:35 -04005745static int selinux_ismaclabel(const char *name)
5746{
5747 return (strcmp(name, XATTR_SELINUX_SUFFIX) == 0);
5748}
5749
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005750static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
5751{
5752 return security_sid_to_context(secid, secdata, seclen);
5753}
5754
David Howells7bf570d2008-04-29 20:52:51 +01005755static int selinux_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
David Howells63cb3442008-01-15 23:47:35 +00005756{
Nikolay Aleksandrov52a4c642014-03-07 12:44:19 +01005757 return security_context_to_sid(secdata, seclen, secid, GFP_KERNEL);
David Howells63cb3442008-01-15 23:47:35 +00005758}
5759
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005760static void selinux_release_secctx(char *secdata, u32 seclen)
5761{
Paul Moore088999e2007-08-01 11:12:58 -04005762 kfree(secdata);
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005763}
5764
David P. Quigley1ee65e32009-09-03 14:25:57 -04005765/*
5766 * called with inode->i_mutex locked
5767 */
5768static int selinux_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen)
5769{
5770 return selinux_inode_setsecurity(inode, XATTR_SELINUX_SUFFIX, ctx, ctxlen, 0);
5771}
5772
5773/*
5774 * called with inode->i_mutex locked
5775 */
5776static int selinux_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen)
5777{
5778 return __vfs_setxattr_noperm(dentry, XATTR_NAME_SELINUX, ctx, ctxlen, 0);
5779}
5780
5781static int selinux_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen)
5782{
5783 int len = 0;
5784 len = selinux_inode_getsecurity(inode, XATTR_SELINUX_SUFFIX,
5785 ctx, true);
5786 if (len < 0)
5787 return len;
5788 *ctxlen = len;
5789 return 0;
5790}
Michael LeMayd7200242006-06-22 14:47:17 -07005791#ifdef CONFIG_KEYS
5792
David Howellsd84f4f92008-11-14 10:39:23 +11005793static int selinux_key_alloc(struct key *k, const struct cred *cred,
David Howells7e047ef2006-06-26 00:24:50 -07005794 unsigned long flags)
Michael LeMayd7200242006-06-22 14:47:17 -07005795{
David Howellsd84f4f92008-11-14 10:39:23 +11005796 const struct task_security_struct *tsec;
Michael LeMayd7200242006-06-22 14:47:17 -07005797 struct key_security_struct *ksec;
5798
5799 ksec = kzalloc(sizeof(struct key_security_struct), GFP_KERNEL);
5800 if (!ksec)
5801 return -ENOMEM;
5802
David Howellsd84f4f92008-11-14 10:39:23 +11005803 tsec = cred->security;
5804 if (tsec->keycreate_sid)
5805 ksec->sid = tsec->keycreate_sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005806 else
David Howellsd84f4f92008-11-14 10:39:23 +11005807 ksec->sid = tsec->sid;
Michael LeMayd7200242006-06-22 14:47:17 -07005808
David Howells275bb412008-11-14 10:39:19 +11005809 k->security = ksec;
Michael LeMayd7200242006-06-22 14:47:17 -07005810 return 0;
5811}
5812
5813static void selinux_key_free(struct key *k)
5814{
5815 struct key_security_struct *ksec = k->security;
5816
5817 k->security = NULL;
5818 kfree(ksec);
5819}
5820
5821static int selinux_key_permission(key_ref_t key_ref,
David Howellsd84f4f92008-11-14 10:39:23 +11005822 const struct cred *cred,
David Howellsf5895942014-03-14 17:44:49 +00005823 unsigned perm)
Michael LeMayd7200242006-06-22 14:47:17 -07005824{
5825 struct key *key;
Michael LeMayd7200242006-06-22 14:47:17 -07005826 struct key_security_struct *ksec;
David Howells275bb412008-11-14 10:39:19 +11005827 u32 sid;
Michael LeMayd7200242006-06-22 14:47:17 -07005828
5829 /* if no specific permissions are requested, we skip the
5830 permission check. No serious, additional covert channels
5831 appear to be created. */
5832 if (perm == 0)
5833 return 0;
5834
David Howellsd84f4f92008-11-14 10:39:23 +11005835 sid = cred_sid(cred);
David Howells275bb412008-11-14 10:39:19 +11005836
5837 key = key_ref_to_ptr(key_ref);
5838 ksec = key->security;
5839
5840 return avc_has_perm(sid, ksec->sid, SECCLASS_KEY, perm, NULL);
Michael LeMayd7200242006-06-22 14:47:17 -07005841}
5842
David Howells70a5bb72008-04-29 01:01:26 -07005843static int selinux_key_getsecurity(struct key *key, char **_buffer)
5844{
5845 struct key_security_struct *ksec = key->security;
5846 char *context = NULL;
5847 unsigned len;
5848 int rc;
5849
5850 rc = security_sid_to_context(ksec->sid, &context, &len);
5851 if (!rc)
5852 rc = len;
5853 *_buffer = context;
5854 return rc;
5855}
5856
Michael LeMayd7200242006-06-22 14:47:17 -07005857#endif
5858
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07005859static struct security_hook_list selinux_hooks[] = {
Casey Schauflere20b0432015-05-02 15:11:36 -07005860 LSM_HOOK_INIT(binder_set_context_mgr, selinux_binder_set_context_mgr),
5861 LSM_HOOK_INIT(binder_transaction, selinux_binder_transaction),
5862 LSM_HOOK_INIT(binder_transfer_binder, selinux_binder_transfer_binder),
5863 LSM_HOOK_INIT(binder_transfer_file, selinux_binder_transfer_file),
Ahmed S. Darwish076c54c2008-03-06 18:09:10 +02005864
Casey Schauflere20b0432015-05-02 15:11:36 -07005865 LSM_HOOK_INIT(ptrace_access_check, selinux_ptrace_access_check),
5866 LSM_HOOK_INIT(ptrace_traceme, selinux_ptrace_traceme),
5867 LSM_HOOK_INIT(capget, selinux_capget),
5868 LSM_HOOK_INIT(capset, selinux_capset),
5869 LSM_HOOK_INIT(capable, selinux_capable),
5870 LSM_HOOK_INIT(quotactl, selinux_quotactl),
5871 LSM_HOOK_INIT(quota_on, selinux_quota_on),
5872 LSM_HOOK_INIT(syslog, selinux_syslog),
5873 LSM_HOOK_INIT(vm_enough_memory, selinux_vm_enough_memory),
Stephen Smalley79af7302015-01-21 10:54:10 -05005874
Casey Schauflere20b0432015-05-02 15:11:36 -07005875 LSM_HOOK_INIT(netlink_send, selinux_netlink_send),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005876
Casey Schauflere20b0432015-05-02 15:11:36 -07005877 LSM_HOOK_INIT(bprm_set_creds, selinux_bprm_set_creds),
5878 LSM_HOOK_INIT(bprm_committing_creds, selinux_bprm_committing_creds),
5879 LSM_HOOK_INIT(bprm_committed_creds, selinux_bprm_committed_creds),
5880 LSM_HOOK_INIT(bprm_secureexec, selinux_bprm_secureexec),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005881
Casey Schauflere20b0432015-05-02 15:11:36 -07005882 LSM_HOOK_INIT(sb_alloc_security, selinux_sb_alloc_security),
5883 LSM_HOOK_INIT(sb_free_security, selinux_sb_free_security),
5884 LSM_HOOK_INIT(sb_copy_data, selinux_sb_copy_data),
5885 LSM_HOOK_INIT(sb_remount, selinux_sb_remount),
5886 LSM_HOOK_INIT(sb_kern_mount, selinux_sb_kern_mount),
5887 LSM_HOOK_INIT(sb_show_options, selinux_sb_show_options),
5888 LSM_HOOK_INIT(sb_statfs, selinux_sb_statfs),
5889 LSM_HOOK_INIT(sb_mount, selinux_mount),
5890 LSM_HOOK_INIT(sb_umount, selinux_umount),
5891 LSM_HOOK_INIT(sb_set_mnt_opts, selinux_set_mnt_opts),
5892 LSM_HOOK_INIT(sb_clone_mnt_opts, selinux_sb_clone_mnt_opts),
5893 LSM_HOOK_INIT(sb_parse_opts_str, selinux_parse_opts_str),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005894
Casey Schauflere20b0432015-05-02 15:11:36 -07005895 LSM_HOOK_INIT(dentry_init_security, selinux_dentry_init_security),
Eric Parise0007522008-03-05 10:31:54 -05005896
Casey Schauflere20b0432015-05-02 15:11:36 -07005897 LSM_HOOK_INIT(inode_alloc_security, selinux_inode_alloc_security),
5898 LSM_HOOK_INIT(inode_free_security, selinux_inode_free_security),
5899 LSM_HOOK_INIT(inode_init_security, selinux_inode_init_security),
5900 LSM_HOOK_INIT(inode_create, selinux_inode_create),
5901 LSM_HOOK_INIT(inode_link, selinux_inode_link),
5902 LSM_HOOK_INIT(inode_unlink, selinux_inode_unlink),
5903 LSM_HOOK_INIT(inode_symlink, selinux_inode_symlink),
5904 LSM_HOOK_INIT(inode_mkdir, selinux_inode_mkdir),
5905 LSM_HOOK_INIT(inode_rmdir, selinux_inode_rmdir),
5906 LSM_HOOK_INIT(inode_mknod, selinux_inode_mknod),
5907 LSM_HOOK_INIT(inode_rename, selinux_inode_rename),
5908 LSM_HOOK_INIT(inode_readlink, selinux_inode_readlink),
5909 LSM_HOOK_INIT(inode_follow_link, selinux_inode_follow_link),
5910 LSM_HOOK_INIT(inode_permission, selinux_inode_permission),
5911 LSM_HOOK_INIT(inode_setattr, selinux_inode_setattr),
5912 LSM_HOOK_INIT(inode_getattr, selinux_inode_getattr),
5913 LSM_HOOK_INIT(inode_setxattr, selinux_inode_setxattr),
5914 LSM_HOOK_INIT(inode_post_setxattr, selinux_inode_post_setxattr),
5915 LSM_HOOK_INIT(inode_getxattr, selinux_inode_getxattr),
5916 LSM_HOOK_INIT(inode_listxattr, selinux_inode_listxattr),
5917 LSM_HOOK_INIT(inode_removexattr, selinux_inode_removexattr),
5918 LSM_HOOK_INIT(inode_getsecurity, selinux_inode_getsecurity),
5919 LSM_HOOK_INIT(inode_setsecurity, selinux_inode_setsecurity),
5920 LSM_HOOK_INIT(inode_listsecurity, selinux_inode_listsecurity),
5921 LSM_HOOK_INIT(inode_getsecid, selinux_inode_getsecid),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005922
Casey Schauflere20b0432015-05-02 15:11:36 -07005923 LSM_HOOK_INIT(file_permission, selinux_file_permission),
5924 LSM_HOOK_INIT(file_alloc_security, selinux_file_alloc_security),
5925 LSM_HOOK_INIT(file_free_security, selinux_file_free_security),
5926 LSM_HOOK_INIT(file_ioctl, selinux_file_ioctl),
5927 LSM_HOOK_INIT(mmap_file, selinux_mmap_file),
5928 LSM_HOOK_INIT(mmap_addr, selinux_mmap_addr),
5929 LSM_HOOK_INIT(file_mprotect, selinux_file_mprotect),
5930 LSM_HOOK_INIT(file_lock, selinux_file_lock),
5931 LSM_HOOK_INIT(file_fcntl, selinux_file_fcntl),
5932 LSM_HOOK_INIT(file_set_fowner, selinux_file_set_fowner),
5933 LSM_HOOK_INIT(file_send_sigiotask, selinux_file_send_sigiotask),
5934 LSM_HOOK_INIT(file_receive, selinux_file_receive),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005935
Casey Schauflere20b0432015-05-02 15:11:36 -07005936 LSM_HOOK_INIT(file_open, selinux_file_open),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005937
Casey Schauflere20b0432015-05-02 15:11:36 -07005938 LSM_HOOK_INIT(task_create, selinux_task_create),
5939 LSM_HOOK_INIT(cred_alloc_blank, selinux_cred_alloc_blank),
5940 LSM_HOOK_INIT(cred_free, selinux_cred_free),
5941 LSM_HOOK_INIT(cred_prepare, selinux_cred_prepare),
5942 LSM_HOOK_INIT(cred_transfer, selinux_cred_transfer),
5943 LSM_HOOK_INIT(kernel_act_as, selinux_kernel_act_as),
5944 LSM_HOOK_INIT(kernel_create_files_as, selinux_kernel_create_files_as),
5945 LSM_HOOK_INIT(kernel_module_request, selinux_kernel_module_request),
5946 LSM_HOOK_INIT(task_setpgid, selinux_task_setpgid),
5947 LSM_HOOK_INIT(task_getpgid, selinux_task_getpgid),
5948 LSM_HOOK_INIT(task_getsid, selinux_task_getsid),
5949 LSM_HOOK_INIT(task_getsecid, selinux_task_getsecid),
5950 LSM_HOOK_INIT(task_setnice, selinux_task_setnice),
5951 LSM_HOOK_INIT(task_setioprio, selinux_task_setioprio),
5952 LSM_HOOK_INIT(task_getioprio, selinux_task_getioprio),
5953 LSM_HOOK_INIT(task_setrlimit, selinux_task_setrlimit),
5954 LSM_HOOK_INIT(task_setscheduler, selinux_task_setscheduler),
5955 LSM_HOOK_INIT(task_getscheduler, selinux_task_getscheduler),
5956 LSM_HOOK_INIT(task_movememory, selinux_task_movememory),
5957 LSM_HOOK_INIT(task_kill, selinux_task_kill),
5958 LSM_HOOK_INIT(task_wait, selinux_task_wait),
5959 LSM_HOOK_INIT(task_to_inode, selinux_task_to_inode),
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09005960
Casey Schauflere20b0432015-05-02 15:11:36 -07005961 LSM_HOOK_INIT(ipc_permission, selinux_ipc_permission),
5962 LSM_HOOK_INIT(ipc_getsecid, selinux_ipc_getsecid),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005963
Casey Schauflere20b0432015-05-02 15:11:36 -07005964 LSM_HOOK_INIT(msg_msg_alloc_security, selinux_msg_msg_alloc_security),
5965 LSM_HOOK_INIT(msg_msg_free_security, selinux_msg_msg_free_security),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005966
Casey Schauflere20b0432015-05-02 15:11:36 -07005967 LSM_HOOK_INIT(msg_queue_alloc_security,
5968 selinux_msg_queue_alloc_security),
5969 LSM_HOOK_INIT(msg_queue_free_security, selinux_msg_queue_free_security),
5970 LSM_HOOK_INIT(msg_queue_associate, selinux_msg_queue_associate),
5971 LSM_HOOK_INIT(msg_queue_msgctl, selinux_msg_queue_msgctl),
5972 LSM_HOOK_INIT(msg_queue_msgsnd, selinux_msg_queue_msgsnd),
5973 LSM_HOOK_INIT(msg_queue_msgrcv, selinux_msg_queue_msgrcv),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005974
Casey Schauflere20b0432015-05-02 15:11:36 -07005975 LSM_HOOK_INIT(shm_alloc_security, selinux_shm_alloc_security),
5976 LSM_HOOK_INIT(shm_free_security, selinux_shm_free_security),
5977 LSM_HOOK_INIT(shm_associate, selinux_shm_associate),
5978 LSM_HOOK_INIT(shm_shmctl, selinux_shm_shmctl),
5979 LSM_HOOK_INIT(shm_shmat, selinux_shm_shmat),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005980
Casey Schauflere20b0432015-05-02 15:11:36 -07005981 LSM_HOOK_INIT(sem_alloc_security, selinux_sem_alloc_security),
5982 LSM_HOOK_INIT(sem_free_security, selinux_sem_free_security),
5983 LSM_HOOK_INIT(sem_associate, selinux_sem_associate),
5984 LSM_HOOK_INIT(sem_semctl, selinux_sem_semctl),
5985 LSM_HOOK_INIT(sem_semop, selinux_sem_semop),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005986
Casey Schauflere20b0432015-05-02 15:11:36 -07005987 LSM_HOOK_INIT(d_instantiate, selinux_d_instantiate),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005988
Casey Schauflere20b0432015-05-02 15:11:36 -07005989 LSM_HOOK_INIT(getprocattr, selinux_getprocattr),
5990 LSM_HOOK_INIT(setprocattr, selinux_setprocattr),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005991
Casey Schauflere20b0432015-05-02 15:11:36 -07005992 LSM_HOOK_INIT(ismaclabel, selinux_ismaclabel),
5993 LSM_HOOK_INIT(secid_to_secctx, selinux_secid_to_secctx),
5994 LSM_HOOK_INIT(secctx_to_secid, selinux_secctx_to_secid),
5995 LSM_HOOK_INIT(release_secctx, selinux_release_secctx),
5996 LSM_HOOK_INIT(inode_notifysecctx, selinux_inode_notifysecctx),
5997 LSM_HOOK_INIT(inode_setsecctx, selinux_inode_setsecctx),
5998 LSM_HOOK_INIT(inode_getsecctx, selinux_inode_getsecctx),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005999
Casey Schauflere20b0432015-05-02 15:11:36 -07006000 LSM_HOOK_INIT(unix_stream_connect, selinux_socket_unix_stream_connect),
6001 LSM_HOOK_INIT(unix_may_send, selinux_socket_unix_may_send),
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07006002
Casey Schauflere20b0432015-05-02 15:11:36 -07006003 LSM_HOOK_INIT(socket_create, selinux_socket_create),
6004 LSM_HOOK_INIT(socket_post_create, selinux_socket_post_create),
6005 LSM_HOOK_INIT(socket_bind, selinux_socket_bind),
6006 LSM_HOOK_INIT(socket_connect, selinux_socket_connect),
6007 LSM_HOOK_INIT(socket_listen, selinux_socket_listen),
6008 LSM_HOOK_INIT(socket_accept, selinux_socket_accept),
6009 LSM_HOOK_INIT(socket_sendmsg, selinux_socket_sendmsg),
6010 LSM_HOOK_INIT(socket_recvmsg, selinux_socket_recvmsg),
6011 LSM_HOOK_INIT(socket_getsockname, selinux_socket_getsockname),
6012 LSM_HOOK_INIT(socket_getpeername, selinux_socket_getpeername),
6013 LSM_HOOK_INIT(socket_getsockopt, selinux_socket_getsockopt),
6014 LSM_HOOK_INIT(socket_setsockopt, selinux_socket_setsockopt),
6015 LSM_HOOK_INIT(socket_shutdown, selinux_socket_shutdown),
6016 LSM_HOOK_INIT(socket_sock_rcv_skb, selinux_socket_sock_rcv_skb),
6017 LSM_HOOK_INIT(socket_getpeersec_stream,
6018 selinux_socket_getpeersec_stream),
6019 LSM_HOOK_INIT(socket_getpeersec_dgram, selinux_socket_getpeersec_dgram),
6020 LSM_HOOK_INIT(sk_alloc_security, selinux_sk_alloc_security),
6021 LSM_HOOK_INIT(sk_free_security, selinux_sk_free_security),
6022 LSM_HOOK_INIT(sk_clone_security, selinux_sk_clone_security),
6023 LSM_HOOK_INIT(sk_getsecid, selinux_sk_getsecid),
6024 LSM_HOOK_INIT(sock_graft, selinux_sock_graft),
6025 LSM_HOOK_INIT(inet_conn_request, selinux_inet_conn_request),
6026 LSM_HOOK_INIT(inet_csk_clone, selinux_inet_csk_clone),
6027 LSM_HOOK_INIT(inet_conn_established, selinux_inet_conn_established),
6028 LSM_HOOK_INIT(secmark_relabel_packet, selinux_secmark_relabel_packet),
6029 LSM_HOOK_INIT(secmark_refcount_inc, selinux_secmark_refcount_inc),
6030 LSM_HOOK_INIT(secmark_refcount_dec, selinux_secmark_refcount_dec),
6031 LSM_HOOK_INIT(req_classify_flow, selinux_req_classify_flow),
6032 LSM_HOOK_INIT(tun_dev_alloc_security, selinux_tun_dev_alloc_security),
6033 LSM_HOOK_INIT(tun_dev_free_security, selinux_tun_dev_free_security),
6034 LSM_HOOK_INIT(tun_dev_create, selinux_tun_dev_create),
6035 LSM_HOOK_INIT(tun_dev_attach_queue, selinux_tun_dev_attach_queue),
6036 LSM_HOOK_INIT(tun_dev_attach, selinux_tun_dev_attach),
6037 LSM_HOOK_INIT(tun_dev_open, selinux_tun_dev_open),
Trent Jaegerd28d1e02005-12-13 23:12:40 -08006038
6039#ifdef CONFIG_SECURITY_NETWORK_XFRM
Casey Schauflere20b0432015-05-02 15:11:36 -07006040 LSM_HOOK_INIT(xfrm_policy_alloc_security, selinux_xfrm_policy_alloc),
6041 LSM_HOOK_INIT(xfrm_policy_clone_security, selinux_xfrm_policy_clone),
6042 LSM_HOOK_INIT(xfrm_policy_free_security, selinux_xfrm_policy_free),
6043 LSM_HOOK_INIT(xfrm_policy_delete_security, selinux_xfrm_policy_delete),
6044 LSM_HOOK_INIT(xfrm_state_alloc, selinux_xfrm_state_alloc),
6045 LSM_HOOK_INIT(xfrm_state_alloc_acquire,
6046 selinux_xfrm_state_alloc_acquire),
6047 LSM_HOOK_INIT(xfrm_state_free_security, selinux_xfrm_state_free),
6048 LSM_HOOK_INIT(xfrm_state_delete_security, selinux_xfrm_state_delete),
6049 LSM_HOOK_INIT(xfrm_policy_lookup, selinux_xfrm_policy_lookup),
6050 LSM_HOOK_INIT(xfrm_state_pol_flow_match,
6051 selinux_xfrm_state_pol_flow_match),
6052 LSM_HOOK_INIT(xfrm_decode_session, selinux_xfrm_decode_session),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006053#endif
Michael LeMayd7200242006-06-22 14:47:17 -07006054
6055#ifdef CONFIG_KEYS
Casey Schauflere20b0432015-05-02 15:11:36 -07006056 LSM_HOOK_INIT(key_alloc, selinux_key_alloc),
6057 LSM_HOOK_INIT(key_free, selinux_key_free),
6058 LSM_HOOK_INIT(key_permission, selinux_key_permission),
6059 LSM_HOOK_INIT(key_getsecurity, selinux_key_getsecurity),
Michael LeMayd7200242006-06-22 14:47:17 -07006060#endif
Ahmed S. Darwish9d57a7f2008-03-01 22:03:14 +02006061
6062#ifdef CONFIG_AUDIT
Casey Schauflere20b0432015-05-02 15:11:36 -07006063 LSM_HOOK_INIT(audit_rule_init, selinux_audit_rule_init),
6064 LSM_HOOK_INIT(audit_rule_known, selinux_audit_rule_known),
6065 LSM_HOOK_INIT(audit_rule_match, selinux_audit_rule_match),
6066 LSM_HOOK_INIT(audit_rule_free, selinux_audit_rule_free),
Ahmed S. Darwish9d57a7f2008-03-01 22:03:14 +02006067#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07006068};
6069
6070static __init int selinux_init(void)
6071{
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07006072 if (!security_module_enable("selinux")) {
Ahmed S. Darwish076c54c2008-03-06 18:09:10 +02006073 selinux_enabled = 0;
6074 return 0;
6075 }
6076
Linus Torvalds1da177e2005-04-16 15:20:36 -07006077 if (!selinux_enabled) {
6078 printk(KERN_INFO "SELinux: Disabled at boot.\n");
6079 return 0;
6080 }
6081
6082 printk(KERN_INFO "SELinux: Initializing.\n");
6083
6084 /* Set the security state for the initial task. */
David Howellsd84f4f92008-11-14 10:39:23 +11006085 cred_init_security();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006086
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04006087 default_noexec = !(VM_DATA_DEFAULT_FLAGS & VM_EXEC);
6088
James Morris7cae7e22006-03-22 00:09:22 -08006089 sel_inode_cache = kmem_cache_create("selinux_inode_security",
6090 sizeof(struct inode_security_struct),
Paul Mundt20c2df82007-07-20 10:11:58 +09006091 0, SLAB_PANIC, NULL);
Sangwoo63205652015-10-21 17:44:30 -04006092 file_security_cache = kmem_cache_create("selinux_file_security",
6093 sizeof(struct file_security_struct),
6094 0, SLAB_PANIC, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006095 avc_init();
6096
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07006097 security_add_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006098
Paul Moore615e51f2014-06-26 14:33:56 -04006099 if (avc_add_callback(selinux_netcache_avc_callback, AVC_CALLBACK_RESET))
6100 panic("SELinux: Unable to register AVC netcache callback\n");
6101
Eric Paris828dfe12008-04-17 13:17:49 -04006102 if (selinux_enforcing)
Eric Parisfadcdb42007-02-22 18:11:31 -05006103 printk(KERN_DEBUG "SELinux: Starting in enforcing mode\n");
Eric Paris828dfe12008-04-17 13:17:49 -04006104 else
Eric Parisfadcdb42007-02-22 18:11:31 -05006105 printk(KERN_DEBUG "SELinux: Starting in permissive mode\n");
Michael LeMayd7200242006-06-22 14:47:17 -07006106
Linus Torvalds1da177e2005-04-16 15:20:36 -07006107 return 0;
6108}
6109
Al Viroe8c26252010-03-23 06:36:54 -04006110static void delayed_superblock_init(struct super_block *sb, void *unused)
6111{
6112 superblock_doinit(sb, NULL);
6113}
6114
Linus Torvalds1da177e2005-04-16 15:20:36 -07006115void selinux_complete_init(void)
6116{
Eric Parisfadcdb42007-02-22 18:11:31 -05006117 printk(KERN_DEBUG "SELinux: Completing initialization.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07006118
6119 /* Set up any superblocks initialized prior to the policy load. */
Eric Parisfadcdb42007-02-22 18:11:31 -05006120 printk(KERN_DEBUG "SELinux: Setting up existing superblocks.\n");
Al Viroe8c26252010-03-23 06:36:54 -04006121 iterate_supers(delayed_superblock_init, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006122}
6123
6124/* SELinux requires early initialization in order to label
6125 all processes and objects when they are created. */
6126security_initcall(selinux_init);
6127
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08006128#if defined(CONFIG_NETFILTER)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006129
Jiri Pirko25db6be2014-09-03 17:42:13 +02006130static struct nf_hook_ops selinux_nf_ops[] = {
Paul Mooreeffad8d2008-01-29 08:49:27 -05006131 {
6132 .hook = selinux_ipv4_postroute,
Alban Crequy2597a832012-05-14 03:56:39 +00006133 .pf = NFPROTO_IPV4,
Paul Mooreeffad8d2008-01-29 08:49:27 -05006134 .hooknum = NF_INET_POST_ROUTING,
6135 .priority = NF_IP_PRI_SELINUX_LAST,
6136 },
6137 {
6138 .hook = selinux_ipv4_forward,
Alban Crequy2597a832012-05-14 03:56:39 +00006139 .pf = NFPROTO_IPV4,
Paul Mooreeffad8d2008-01-29 08:49:27 -05006140 .hooknum = NF_INET_FORWARD,
6141 .priority = NF_IP_PRI_SELINUX_FIRST,
Paul Moore948bf852008-10-10 10:16:32 -04006142 },
6143 {
6144 .hook = selinux_ipv4_output,
Alban Crequy2597a832012-05-14 03:56:39 +00006145 .pf = NFPROTO_IPV4,
Paul Moore948bf852008-10-10 10:16:32 -04006146 .hooknum = NF_INET_LOCAL_OUT,
6147 .priority = NF_IP_PRI_SELINUX_FIRST,
Jiri Pirko25db6be2014-09-03 17:42:13 +02006148 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07006149#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Paul Mooreeffad8d2008-01-29 08:49:27 -05006150 {
6151 .hook = selinux_ipv6_postroute,
Alban Crequy2597a832012-05-14 03:56:39 +00006152 .pf = NFPROTO_IPV6,
Paul Mooreeffad8d2008-01-29 08:49:27 -05006153 .hooknum = NF_INET_POST_ROUTING,
6154 .priority = NF_IP6_PRI_SELINUX_LAST,
6155 },
6156 {
6157 .hook = selinux_ipv6_forward,
Alban Crequy2597a832012-05-14 03:56:39 +00006158 .pf = NFPROTO_IPV6,
Paul Mooreeffad8d2008-01-29 08:49:27 -05006159 .hooknum = NF_INET_FORWARD,
6160 .priority = NF_IP6_PRI_SELINUX_FIRST,
Jiri Pirko25db6be2014-09-03 17:42:13 +02006161 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07006162#endif /* IPV6 */
Jiri Pirko25db6be2014-09-03 17:42:13 +02006163};
Linus Torvalds1da177e2005-04-16 15:20:36 -07006164
6165static int __init selinux_nf_ip_init(void)
6166{
Jiri Pirko25db6be2014-09-03 17:42:13 +02006167 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006168
6169 if (!selinux_enabled)
Jiri Pirko25db6be2014-09-03 17:42:13 +02006170 return 0;
Eric Parisfadcdb42007-02-22 18:11:31 -05006171
6172 printk(KERN_DEBUG "SELinux: Registering netfilter hooks\n");
6173
Jiri Pirko25db6be2014-09-03 17:42:13 +02006174 err = nf_register_hooks(selinux_nf_ops, ARRAY_SIZE(selinux_nf_ops));
Alexey Dobriyan6c5a9d22008-07-26 17:48:15 -07006175 if (err)
Jiri Pirko25db6be2014-09-03 17:42:13 +02006176 panic("SELinux: nf_register_hooks: error %d\n", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006177
Jiri Pirko25db6be2014-09-03 17:42:13 +02006178 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006179}
6180
6181__initcall(selinux_nf_ip_init);
6182
6183#ifdef CONFIG_SECURITY_SELINUX_DISABLE
6184static void selinux_nf_ip_exit(void)
6185{
Eric Parisfadcdb42007-02-22 18:11:31 -05006186 printk(KERN_DEBUG "SELinux: Unregistering netfilter hooks\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07006187
Jiri Pirko25db6be2014-09-03 17:42:13 +02006188 nf_unregister_hooks(selinux_nf_ops, ARRAY_SIZE(selinux_nf_ops));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006189}
6190#endif
6191
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08006192#else /* CONFIG_NETFILTER */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006193
6194#ifdef CONFIG_SECURITY_SELINUX_DISABLE
6195#define selinux_nf_ip_exit()
6196#endif
6197
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08006198#endif /* CONFIG_NETFILTER */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006199
6200#ifdef CONFIG_SECURITY_SELINUX_DISABLE
Eric Paris828dfe12008-04-17 13:17:49 -04006201static int selinux_disabled;
6202
Linus Torvalds1da177e2005-04-16 15:20:36 -07006203int selinux_disable(void)
6204{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006205 if (ss_initialized) {
6206 /* Not permitted after initial policy load. */
6207 return -EINVAL;
6208 }
6209
6210 if (selinux_disabled) {
6211 /* Only do this once. */
6212 return -EINVAL;
6213 }
6214
6215 printk(KERN_INFO "SELinux: Disabled at runtime.\n");
6216
6217 selinux_disabled = 1;
Stephen Smalley30d55282006-05-03 10:52:36 -04006218 selinux_enabled = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006219
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07006220 security_delete_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006221
Eric Parisaf8ff042009-09-20 21:23:01 -04006222 /* Try to destroy the avc node cache */
6223 avc_disable();
6224
Linus Torvalds1da177e2005-04-16 15:20:36 -07006225 /* Unregister netfilter hooks. */
6226 selinux_nf_ip_exit();
6227
6228 /* Unregister selinuxfs. */
6229 exit_sel_fs();
6230
6231 return 0;
6232}
6233#endif