blob: c253caa90bb45ec62c2d4fa56b995c66587fcb9a [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>
32#include <linux/security.h>
33#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[] */
Eric Dumazetca10b9e2013-04-08 17:58:11 +000054#include <net/sock.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070055#include <net/tcp.h> /* struct or_callable used in sock_rcv_skb */
Paul Moore47180062013-12-04 16:10:45 -050056#include <net/inet_connection_sock.h>
Paul Moore220deb92008-01-29 08:38:23 -050057#include <net/net_namespace.h>
Paul Moored621d352008-01-29 08:43:36 -050058#include <net/netlabel.h>
Eric Parisf5269712008-05-14 11:27:45 -040059#include <linux/uaccess.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070060#include <asm/ioctls.h>
Arun Sharma600634972011-07-26 16:09:06 -070061#include <linux/atomic.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070062#include <linux/bitops.h>
63#include <linux/interrupt.h>
64#include <linux/netdevice.h> /* for network interface checks */
Hong zhi guo77954982013-03-27 06:49:35 +000065#include <net/netlink.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070066#include <linux/tcp.h>
67#include <linux/udp.h>
James Morris2ee92d42006-11-13 16:09:01 -080068#include <linux/dccp.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070069#include <linux/quota.h>
70#include <linux/un.h> /* for Unix socket types */
71#include <net/af_unix.h> /* for Unix socket types */
72#include <linux/parser.h>
73#include <linux/nfs_mount.h>
74#include <net/ipv6.h>
75#include <linux/hugetlb.h>
76#include <linux/personality.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070077#include <linux/audit.h>
Eric Paris6931dfc2005-06-30 02:58:51 -070078#include <linux/string.h>
Catherine Zhang877ce7c2006-06-29 12:27:47 -070079#include <linux/selinux.h>
Eric Paris23970742006-09-25 23:32:01 -070080#include <linux/mutex.h>
Frank Mayharf06febc2008-09-12 09:54:39 -070081#include <linux/posix-timers.h>
Kees Cook00234592010-02-03 15:36:43 -080082#include <linux/syslog.h>
Serge E. Hallyn34867402011-03-23 16:43:17 -070083#include <linux/user_namespace.h>
Paul Gortmaker44fc7ea2011-05-26 20:52:10 -040084#include <linux/export.h>
Al Viro40401532012-02-13 03:58:52 +000085#include <linux/msg.h>
86#include <linux/shm.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070087
88#include "avc.h"
89#include "objsec.h"
90#include "netif.h"
Paul Moore224dfbd2008-01-29 08:38:13 -050091#include "netnode.h"
Paul Moore3e1121722008-04-10 10:48:14 -040092#include "netport.h"
Trent Jaegerd28d1e02005-12-13 23:12:40 -080093#include "xfrm.h"
Paul Moorec60475b2007-02-28 15:14:23 -050094#include "netlabel.h"
Ahmed S. Darwish9d57a7f2008-03-01 22:03:14 +020095#include "audit.h"
James Morris7b98a582011-08-30 12:52:32 +100096#include "avc_ss.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070097
Paul Moored621d352008-01-29 08:43:36 -050098/* SECMARK reference count */
James Morris56a4ca92011-08-17 11:08:43 +100099static atomic_t selinux_secmark_refcount = ATOMIC_INIT(0);
Paul Moored621d352008-01-29 08:43:36 -0500100
Linus Torvalds1da177e2005-04-16 15:20:36 -0700101#ifdef CONFIG_SECURITY_SELINUX_DEVELOP
Eric Paris828dfe12008-04-17 13:17:49 -0400102int selinux_enforcing;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700103
104static int __init enforcing_setup(char *str)
105{
Eric Parisf5269712008-05-14 11:27:45 -0400106 unsigned long enforcing;
Jingoo Han29707b22014-02-05 15:13:14 +0900107 if (!kstrtoul(str, 0, &enforcing))
Eric Parisf5269712008-05-14 11:27:45 -0400108 selinux_enforcing = enforcing ? 1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109 return 1;
110}
111__setup("enforcing=", enforcing_setup);
112#endif
113
114#ifdef CONFIG_SECURITY_SELINUX_BOOTPARAM
115int selinux_enabled = CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE;
116
117static int __init selinux_enabled_setup(char *str)
118{
Eric Parisf5269712008-05-14 11:27:45 -0400119 unsigned long enabled;
Jingoo Han29707b22014-02-05 15:13:14 +0900120 if (!kstrtoul(str, 0, &enabled))
Eric Parisf5269712008-05-14 11:27:45 -0400121 selinux_enabled = enabled ? 1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700122 return 1;
123}
124__setup("selinux=", selinux_enabled_setup);
Stephen Smalley30d55282006-05-03 10:52:36 -0400125#else
126int selinux_enabled = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127#endif
128
Christoph Lametere18b8902006-12-06 20:33:20 -0800129static struct kmem_cache *sel_inode_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
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258 spin_lock(&sbsec->isec_lock);
259 if (!list_empty(&isec->list))
260 list_del_init(&isec->list);
261 spin_unlock(&sbsec->isec_lock);
262
Steven Rostedt3dc91d42014-01-09 21:46:34 -0500263 /*
264 * The inode may still be referenced in a path walk and
265 * a call to selinux_inode_permission() can be made
266 * after inode_free_security() is called. Ideally, the VFS
267 * wouldn't do this, but fixing that is a much harder
268 * job. For now, simply free the i_security via RCU, and
269 * leave the current inode->i_security pointer intact.
270 * The inode will be freed after the RCU grace period too.
271 */
272 call_rcu(&isec->rcu, inode_free_rcu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273}
274
275static int file_alloc_security(struct file *file)
276{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700277 struct file_security_struct *fsec;
David Howells275bb412008-11-14 10:39:19 +1100278 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279
Stephen Smalley26d2a4b2006-02-01 03:05:55 -0800280 fsec = kzalloc(sizeof(struct file_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700281 if (!fsec)
282 return -ENOMEM;
283
David Howells275bb412008-11-14 10:39:19 +1100284 fsec->sid = sid;
285 fsec->fown_sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700286 file->f_security = fsec;
287
288 return 0;
289}
290
291static void file_free_security(struct file *file)
292{
293 struct file_security_struct *fsec = file->f_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294 file->f_security = NULL;
295 kfree(fsec);
296}
297
298static int superblock_alloc_security(struct super_block *sb)
299{
300 struct superblock_security_struct *sbsec;
301
James Morris89d155e2005-10-30 14:59:21 -0800302 sbsec = kzalloc(sizeof(struct superblock_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700303 if (!sbsec)
304 return -ENOMEM;
305
Eric Parisbc7e9822006-09-25 23:32:02 -0700306 mutex_init(&sbsec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307 INIT_LIST_HEAD(&sbsec->isec_head);
308 spin_lock_init(&sbsec->isec_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700309 sbsec->sb = sb;
310 sbsec->sid = SECINITSID_UNLABELED;
311 sbsec->def_sid = SECINITSID_FILE;
Eric Parisc312feb2006-07-10 04:43:53 -0700312 sbsec->mntpoint_sid = SECINITSID_UNLABELED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700313 sb->s_security = sbsec;
314
315 return 0;
316}
317
318static void superblock_free_security(struct super_block *sb)
319{
320 struct superblock_security_struct *sbsec = sb->s_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700321 sb->s_security = NULL;
322 kfree(sbsec);
323}
324
Linus Torvalds1da177e2005-04-16 15:20:36 -0700325/* The file system's label must be initialized prior to use. */
326
David Quigleyeb9ae682013-05-22 12:50:37 -0400327static const char *labeling_behaviors[7] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700328 "uses xattr",
329 "uses transition SIDs",
330 "uses task SIDs",
331 "uses genfs_contexts",
332 "not configured for labeling",
333 "uses mountpoint labeling",
David Quigleyeb9ae682013-05-22 12:50:37 -0400334 "uses native labeling",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700335};
336
337static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry);
338
339static inline int inode_doinit(struct inode *inode)
340{
341 return inode_doinit_with_dentry(inode, NULL);
342}
343
344enum {
Eric Paris31e87932007-09-19 17:19:12 -0400345 Opt_error = -1,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700346 Opt_context = 1,
347 Opt_fscontext = 2,
Eric Parisc9180a52007-11-30 13:00:35 -0500348 Opt_defcontext = 3,
349 Opt_rootcontext = 4,
David P. Quigley11689d42009-01-16 09:22:03 -0500350 Opt_labelsupport = 5,
Eric Parisd355987f2012-08-24 15:58:53 -0400351 Opt_nextmntopt = 6,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700352};
353
Eric Parisd355987f2012-08-24 15:58:53 -0400354#define NUM_SEL_MNT_OPTS (Opt_nextmntopt - 1)
355
Steven Whitehousea447c092008-10-13 10:46:57 +0100356static const match_table_t tokens = {
Eric Paris832cbd92008-04-01 13:24:09 -0400357 {Opt_context, CONTEXT_STR "%s"},
358 {Opt_fscontext, FSCONTEXT_STR "%s"},
359 {Opt_defcontext, DEFCONTEXT_STR "%s"},
360 {Opt_rootcontext, ROOTCONTEXT_STR "%s"},
David P. Quigley11689d42009-01-16 09:22:03 -0500361 {Opt_labelsupport, LABELSUPP_STR},
Eric Paris31e87932007-09-19 17:19:12 -0400362 {Opt_error, NULL},
Linus Torvalds1da177e2005-04-16 15:20:36 -0700363};
364
365#define SEL_MOUNT_FAIL_MSG "SELinux: duplicate or incompatible mount options\n"
366
Eric Parisc312feb2006-07-10 04:43:53 -0700367static int may_context_mount_sb_relabel(u32 sid,
368 struct superblock_security_struct *sbsec,
David Howells275bb412008-11-14 10:39:19 +1100369 const struct cred *cred)
Eric Parisc312feb2006-07-10 04:43:53 -0700370{
David Howells275bb412008-11-14 10:39:19 +1100371 const struct task_security_struct *tsec = cred->security;
Eric Parisc312feb2006-07-10 04:43:53 -0700372 int rc;
373
374 rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
375 FILESYSTEM__RELABELFROM, NULL);
376 if (rc)
377 return rc;
378
379 rc = avc_has_perm(tsec->sid, sid, SECCLASS_FILESYSTEM,
380 FILESYSTEM__RELABELTO, NULL);
381 return rc;
382}
383
Eric Paris08089252006-07-10 04:43:55 -0700384static int may_context_mount_inode_relabel(u32 sid,
385 struct superblock_security_struct *sbsec,
David Howells275bb412008-11-14 10:39:19 +1100386 const struct cred *cred)
Eric Paris08089252006-07-10 04:43:55 -0700387{
David Howells275bb412008-11-14 10:39:19 +1100388 const struct task_security_struct *tsec = cred->security;
Eric Paris08089252006-07-10 04:43:55 -0700389 int rc;
390 rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
391 FILESYSTEM__RELABELFROM, NULL);
392 if (rc)
393 return rc;
394
395 rc = avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM,
396 FILESYSTEM__ASSOCIATE, NULL);
397 return rc;
398}
399
Eric Parisb43e7252012-10-10 14:27:35 -0400400static int selinux_is_sblabel_mnt(struct super_block *sb)
401{
402 struct superblock_security_struct *sbsec = sb->s_security;
403
404 if (sbsec->behavior == SECURITY_FS_USE_XATTR ||
405 sbsec->behavior == SECURITY_FS_USE_TRANS ||
406 sbsec->behavior == SECURITY_FS_USE_TASK)
407 return 1;
408
409 /* Special handling for sysfs. Is genfs but also has setxattr handler*/
410 if (strncmp(sb->s_type->name, "sysfs", sizeof("sysfs")) == 0)
411 return 1;
412
413 /*
414 * Special handling for rootfs. Is genfs but supports
415 * setting SELinux context on in-core inodes.
416 */
417 if (strncmp(sb->s_type->name, "rootfs", sizeof("rootfs")) == 0)
418 return 1;
419
420 return 0;
421}
422
Eric Parisc9180a52007-11-30 13:00:35 -0500423static int sb_finish_set_opts(struct super_block *sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424{
425 struct superblock_security_struct *sbsec = sb->s_security;
426 struct dentry *root = sb->s_root;
Eric Parisc9180a52007-11-30 13:00:35 -0500427 struct inode *root_inode = root->d_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428 int rc = 0;
429
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430 if (sbsec->behavior == SECURITY_FS_USE_XATTR) {
431 /* Make sure that the xattr handler exists and that no
432 error other than -ENODATA is returned by getxattr on
433 the root directory. -ENODATA is ok, as this may be
434 the first boot of the SELinux kernel before we have
435 assigned xattr values to the filesystem. */
Eric Parisc9180a52007-11-30 13:00:35 -0500436 if (!root_inode->i_op->getxattr) {
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800437 printk(KERN_WARNING "SELinux: (dev %s, type %s) has no "
438 "xattr support\n", sb->s_id, sb->s_type->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439 rc = -EOPNOTSUPP;
440 goto out;
441 }
Eric Parisc9180a52007-11-30 13:00:35 -0500442 rc = root_inode->i_op->getxattr(root, XATTR_NAME_SELINUX, NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443 if (rc < 0 && rc != -ENODATA) {
444 if (rc == -EOPNOTSUPP)
445 printk(KERN_WARNING "SELinux: (dev %s, type "
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800446 "%s) has no security xattr handler\n",
447 sb->s_id, sb->s_type->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700448 else
449 printk(KERN_WARNING "SELinux: (dev %s, type "
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800450 "%s) getxattr errno %d\n", sb->s_id,
451 sb->s_type->name, -rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452 goto out;
453 }
454 }
455
Eric Parisc9180a52007-11-30 13:00:35 -0500456 if (sbsec->behavior > ARRAY_SIZE(labeling_behaviors))
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800457 printk(KERN_ERR "SELinux: initialized (dev %s, type %s), unknown behavior\n",
458 sb->s_id, sb->s_type->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700459
Eric Pariseadcabc2012-08-24 15:59:14 -0400460 sbsec->flags |= SE_SBINITIALIZED;
Eric Parisb43e7252012-10-10 14:27:35 -0400461 if (selinux_is_sblabel_mnt(sb))
Eric Paris12f348b2012-10-09 10:56:25 -0400462 sbsec->flags |= SBLABEL_MNT;
David P. Quigleyddd29ec2009-09-09 14:25:37 -0400463
Linus Torvalds1da177e2005-04-16 15:20:36 -0700464 /* Initialize the root inode. */
Eric Parisc9180a52007-11-30 13:00:35 -0500465 rc = inode_doinit_with_dentry(root_inode, root);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700466
467 /* Initialize any other inodes associated with the superblock, e.g.
468 inodes created prior to initial policy load or inodes created
469 during get_sb by a pseudo filesystem that directly
470 populates itself. */
471 spin_lock(&sbsec->isec_lock);
472next_inode:
473 if (!list_empty(&sbsec->isec_head)) {
474 struct inode_security_struct *isec =
475 list_entry(sbsec->isec_head.next,
Eric Parisc9180a52007-11-30 13:00:35 -0500476 struct inode_security_struct, list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477 struct inode *inode = isec->inode;
Stephen Smalley923190d2014-10-06 16:32:52 -0400478 list_del_init(&isec->list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700479 spin_unlock(&sbsec->isec_lock);
480 inode = igrab(inode);
481 if (inode) {
Eric Parisc9180a52007-11-30 13:00:35 -0500482 if (!IS_PRIVATE(inode))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483 inode_doinit(inode);
484 iput(inode);
485 }
486 spin_lock(&sbsec->isec_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700487 goto next_inode;
488 }
489 spin_unlock(&sbsec->isec_lock);
490out:
Eric Parisc9180a52007-11-30 13:00:35 -0500491 return rc;
492}
493
494/*
495 * This function should allow an FS to ask what it's mount security
496 * options were so it can use those later for submounts, displaying
497 * mount options, or whatever.
498 */
499static int selinux_get_mnt_opts(const struct super_block *sb,
Eric Parise0007522008-03-05 10:31:54 -0500500 struct security_mnt_opts *opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500501{
502 int rc = 0, i;
503 struct superblock_security_struct *sbsec = sb->s_security;
504 char *context = NULL;
505 u32 len;
506 char tmp;
507
Eric Parise0007522008-03-05 10:31:54 -0500508 security_init_mnt_opts(opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500509
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500510 if (!(sbsec->flags & SE_SBINITIALIZED))
Eric Parisc9180a52007-11-30 13:00:35 -0500511 return -EINVAL;
512
513 if (!ss_initialized)
514 return -EINVAL;
515
Eric Parisaf8e50c2012-08-24 15:59:00 -0400516 /* make sure we always check enough bits to cover the mask */
517 BUILD_BUG_ON(SE_MNTMASK >= (1 << NUM_SEL_MNT_OPTS));
518
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500519 tmp = sbsec->flags & SE_MNTMASK;
Eric Parisc9180a52007-11-30 13:00:35 -0500520 /* count the number of mount options for this sb */
Eric Parisaf8e50c2012-08-24 15:59:00 -0400521 for (i = 0; i < NUM_SEL_MNT_OPTS; i++) {
Eric Parisc9180a52007-11-30 13:00:35 -0500522 if (tmp & 0x01)
Eric Parise0007522008-03-05 10:31:54 -0500523 opts->num_mnt_opts++;
Eric Parisc9180a52007-11-30 13:00:35 -0500524 tmp >>= 1;
525 }
David P. Quigley11689d42009-01-16 09:22:03 -0500526 /* Check if the Label support flag is set */
Eric Paris0b4bdb32013-08-28 13:32:42 -0400527 if (sbsec->flags & SBLABEL_MNT)
David P. Quigley11689d42009-01-16 09:22:03 -0500528 opts->num_mnt_opts++;
Eric Parisc9180a52007-11-30 13:00:35 -0500529
Eric Parise0007522008-03-05 10:31:54 -0500530 opts->mnt_opts = kcalloc(opts->num_mnt_opts, sizeof(char *), GFP_ATOMIC);
531 if (!opts->mnt_opts) {
Eric Parisc9180a52007-11-30 13:00:35 -0500532 rc = -ENOMEM;
533 goto out_free;
534 }
535
Eric Parise0007522008-03-05 10:31:54 -0500536 opts->mnt_opts_flags = kcalloc(opts->num_mnt_opts, sizeof(int), GFP_ATOMIC);
537 if (!opts->mnt_opts_flags) {
Eric Parisc9180a52007-11-30 13:00:35 -0500538 rc = -ENOMEM;
539 goto out_free;
540 }
541
542 i = 0;
543 if (sbsec->flags & FSCONTEXT_MNT) {
544 rc = security_sid_to_context(sbsec->sid, &context, &len);
545 if (rc)
546 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500547 opts->mnt_opts[i] = context;
548 opts->mnt_opts_flags[i++] = FSCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500549 }
550 if (sbsec->flags & CONTEXT_MNT) {
551 rc = security_sid_to_context(sbsec->mntpoint_sid, &context, &len);
552 if (rc)
553 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500554 opts->mnt_opts[i] = context;
555 opts->mnt_opts_flags[i++] = CONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500556 }
557 if (sbsec->flags & DEFCONTEXT_MNT) {
558 rc = security_sid_to_context(sbsec->def_sid, &context, &len);
559 if (rc)
560 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500561 opts->mnt_opts[i] = context;
562 opts->mnt_opts_flags[i++] = DEFCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500563 }
564 if (sbsec->flags & ROOTCONTEXT_MNT) {
565 struct inode *root = sbsec->sb->s_root->d_inode;
566 struct inode_security_struct *isec = root->i_security;
567
568 rc = security_sid_to_context(isec->sid, &context, &len);
569 if (rc)
570 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500571 opts->mnt_opts[i] = context;
572 opts->mnt_opts_flags[i++] = ROOTCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500573 }
Eric Paris12f348b2012-10-09 10:56:25 -0400574 if (sbsec->flags & SBLABEL_MNT) {
David P. Quigley11689d42009-01-16 09:22:03 -0500575 opts->mnt_opts[i] = NULL;
Eric Paris12f348b2012-10-09 10:56:25 -0400576 opts->mnt_opts_flags[i++] = SBLABEL_MNT;
David P. Quigley11689d42009-01-16 09:22:03 -0500577 }
Eric Parisc9180a52007-11-30 13:00:35 -0500578
Eric Parise0007522008-03-05 10:31:54 -0500579 BUG_ON(i != opts->num_mnt_opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500580
581 return 0;
582
583out_free:
Eric Parise0007522008-03-05 10:31:54 -0500584 security_free_mnt_opts(opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500585 return rc;
586}
587
588static int bad_option(struct superblock_security_struct *sbsec, char flag,
589 u32 old_sid, u32 new_sid)
590{
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500591 char mnt_flags = sbsec->flags & SE_MNTMASK;
592
Eric Parisc9180a52007-11-30 13:00:35 -0500593 /* check if the old mount command had the same options */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500594 if (sbsec->flags & SE_SBINITIALIZED)
Eric Parisc9180a52007-11-30 13:00:35 -0500595 if (!(sbsec->flags & flag) ||
596 (old_sid != new_sid))
597 return 1;
598
599 /* check if we were passed the same options twice,
600 * aka someone passed context=a,context=b
601 */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500602 if (!(sbsec->flags & SE_SBINITIALIZED))
603 if (mnt_flags & flag)
Eric Parisc9180a52007-11-30 13:00:35 -0500604 return 1;
605 return 0;
606}
Eric Parise0007522008-03-05 10:31:54 -0500607
Eric Parisc9180a52007-11-30 13:00:35 -0500608/*
609 * Allow filesystems with binary mount data to explicitly set mount point
610 * labeling information.
611 */
Eric Parise0007522008-03-05 10:31:54 -0500612static int selinux_set_mnt_opts(struct super_block *sb,
David Quigley649f6e72013-05-22 12:50:36 -0400613 struct security_mnt_opts *opts,
614 unsigned long kern_flags,
615 unsigned long *set_kern_flags)
Eric Parisc9180a52007-11-30 13:00:35 -0500616{
David Howells275bb412008-11-14 10:39:19 +1100617 const struct cred *cred = current_cred();
Eric Parisc9180a52007-11-30 13:00:35 -0500618 int rc = 0, i;
Eric Parisc9180a52007-11-30 13:00:35 -0500619 struct superblock_security_struct *sbsec = sb->s_security;
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800620 const char *name = sb->s_type->name;
James Morris089be432008-07-15 18:32:49 +1000621 struct inode *inode = sbsec->sb->s_root->d_inode;
622 struct inode_security_struct *root_isec = inode->i_security;
Eric Parisc9180a52007-11-30 13:00:35 -0500623 u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0;
624 u32 defcontext_sid = 0;
Eric Parise0007522008-03-05 10:31:54 -0500625 char **mount_options = opts->mnt_opts;
626 int *flags = opts->mnt_opts_flags;
627 int num_opts = opts->num_mnt_opts;
Eric Parisc9180a52007-11-30 13:00:35 -0500628
629 mutex_lock(&sbsec->lock);
630
631 if (!ss_initialized) {
632 if (!num_opts) {
633 /* Defer initialization until selinux_complete_init,
634 after the initial policy is loaded and the security
635 server is ready to handle calls. */
Eric Parisc9180a52007-11-30 13:00:35 -0500636 goto out;
637 }
638 rc = -EINVAL;
Eric Paris744ba352008-04-17 11:52:44 -0400639 printk(KERN_WARNING "SELinux: Unable to set superblock options "
640 "before the security server is initialized\n");
Eric Parisc9180a52007-11-30 13:00:35 -0500641 goto out;
642 }
David Quigley649f6e72013-05-22 12:50:36 -0400643 if (kern_flags && !set_kern_flags) {
644 /* Specifying internal flags without providing a place to
645 * place the results is not allowed */
646 rc = -EINVAL;
647 goto out;
648 }
Eric Parisc9180a52007-11-30 13:00:35 -0500649
650 /*
Eric Parise0007522008-03-05 10:31:54 -0500651 * Binary mount data FS will come through this function twice. Once
652 * from an explicit call and once from the generic calls from the vfs.
653 * Since the generic VFS calls will not contain any security mount data
654 * we need to skip the double mount verification.
655 *
656 * This does open a hole in which we will not notice if the first
657 * mount using this sb set explict options and a second mount using
658 * this sb does not set any security options. (The first options
659 * will be used for both mounts)
660 */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500661 if ((sbsec->flags & SE_SBINITIALIZED) && (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)
Eric Parise0007522008-03-05 10:31:54 -0500662 && (num_opts == 0))
Eric Parisf5269712008-05-14 11:27:45 -0400663 goto out;
Eric Parise0007522008-03-05 10:31:54 -0500664
665 /*
Eric Parisc9180a52007-11-30 13:00:35 -0500666 * parse the mount options, check if they are valid sids.
667 * also check if someone is trying to mount the same sb more
668 * than once with different security options.
669 */
670 for (i = 0; i < num_opts; i++) {
671 u32 sid;
David P. Quigley11689d42009-01-16 09:22:03 -0500672
Eric Paris12f348b2012-10-09 10:56:25 -0400673 if (flags[i] == SBLABEL_MNT)
David P. Quigley11689d42009-01-16 09:22:03 -0500674 continue;
Eric Parisc9180a52007-11-30 13:00:35 -0500675 rc = security_context_to_sid(mount_options[i],
Nikolay Aleksandrov52a4c642014-03-07 12:44:19 +0100676 strlen(mount_options[i]), &sid, GFP_KERNEL);
Eric Parisc9180a52007-11-30 13:00:35 -0500677 if (rc) {
678 printk(KERN_WARNING "SELinux: security_context_to_sid"
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800679 "(%s) failed for (dev %s, type %s) errno=%d\n",
680 mount_options[i], sb->s_id, name, rc);
Eric Parisc9180a52007-11-30 13:00:35 -0500681 goto out;
682 }
683 switch (flags[i]) {
684 case FSCONTEXT_MNT:
685 fscontext_sid = sid;
686
687 if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid,
688 fscontext_sid))
689 goto out_double_mount;
690
691 sbsec->flags |= FSCONTEXT_MNT;
692 break;
693 case CONTEXT_MNT:
694 context_sid = sid;
695
696 if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid,
697 context_sid))
698 goto out_double_mount;
699
700 sbsec->flags |= CONTEXT_MNT;
701 break;
702 case ROOTCONTEXT_MNT:
703 rootcontext_sid = sid;
704
705 if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid,
706 rootcontext_sid))
707 goto out_double_mount;
708
709 sbsec->flags |= ROOTCONTEXT_MNT;
710
711 break;
712 case DEFCONTEXT_MNT:
713 defcontext_sid = sid;
714
715 if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid,
716 defcontext_sid))
717 goto out_double_mount;
718
719 sbsec->flags |= DEFCONTEXT_MNT;
720
721 break;
722 default:
723 rc = -EINVAL;
724 goto out;
725 }
726 }
727
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500728 if (sbsec->flags & SE_SBINITIALIZED) {
Eric Parisc9180a52007-11-30 13:00:35 -0500729 /* previously mounted with options, but not on this attempt? */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500730 if ((sbsec->flags & SE_MNTMASK) && !num_opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500731 goto out_double_mount;
732 rc = 0;
733 goto out;
734 }
735
James Morris089be432008-07-15 18:32:49 +1000736 if (strcmp(sb->s_type->name, "proc") == 0)
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500737 sbsec->flags |= SE_SBPROC;
Eric Parisc9180a52007-11-30 13:00:35 -0500738
David Quigleyeb9ae682013-05-22 12:50:37 -0400739 if (!sbsec->behavior) {
740 /*
741 * Determine the labeling behavior to use for this
742 * filesystem type.
743 */
Paul Moore98f700f2013-09-18 13:52:20 -0400744 rc = security_fs_use(sb);
David Quigleyeb9ae682013-05-22 12:50:37 -0400745 if (rc) {
746 printk(KERN_WARNING
747 "%s: security_fs_use(%s) returned %d\n",
748 __func__, sb->s_type->name, rc);
749 goto out;
750 }
Eric Parisc9180a52007-11-30 13:00:35 -0500751 }
Eric Parisc9180a52007-11-30 13:00:35 -0500752 /* sets the context of the superblock for the fs being mounted. */
753 if (fscontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100754 rc = may_context_mount_sb_relabel(fscontext_sid, sbsec, cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500755 if (rc)
756 goto out;
757
758 sbsec->sid = fscontext_sid;
759 }
760
761 /*
762 * Switch to using mount point labeling behavior.
763 * sets the label used on all file below the mountpoint, and will set
764 * the superblock context if not already set.
765 */
David Quigleyeb9ae682013-05-22 12:50:37 -0400766 if (kern_flags & SECURITY_LSM_NATIVE_LABELS && !context_sid) {
767 sbsec->behavior = SECURITY_FS_USE_NATIVE;
768 *set_kern_flags |= SECURITY_LSM_NATIVE_LABELS;
769 }
770
Eric Parisc9180a52007-11-30 13:00:35 -0500771 if (context_sid) {
772 if (!fscontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100773 rc = may_context_mount_sb_relabel(context_sid, sbsec,
774 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500775 if (rc)
776 goto out;
777 sbsec->sid = context_sid;
778 } else {
David Howells275bb412008-11-14 10:39:19 +1100779 rc = may_context_mount_inode_relabel(context_sid, sbsec,
780 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500781 if (rc)
782 goto out;
783 }
784 if (!rootcontext_sid)
785 rootcontext_sid = context_sid;
786
787 sbsec->mntpoint_sid = context_sid;
788 sbsec->behavior = SECURITY_FS_USE_MNTPOINT;
789 }
790
791 if (rootcontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100792 rc = may_context_mount_inode_relabel(rootcontext_sid, sbsec,
793 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500794 if (rc)
795 goto out;
796
797 root_isec->sid = rootcontext_sid;
798 root_isec->initialized = 1;
799 }
800
801 if (defcontext_sid) {
David Quigleyeb9ae682013-05-22 12:50:37 -0400802 if (sbsec->behavior != SECURITY_FS_USE_XATTR &&
803 sbsec->behavior != SECURITY_FS_USE_NATIVE) {
Eric Parisc9180a52007-11-30 13:00:35 -0500804 rc = -EINVAL;
805 printk(KERN_WARNING "SELinux: defcontext option is "
806 "invalid for this filesystem type\n");
807 goto out;
808 }
809
810 if (defcontext_sid != sbsec->def_sid) {
811 rc = may_context_mount_inode_relabel(defcontext_sid,
David Howells275bb412008-11-14 10:39:19 +1100812 sbsec, cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500813 if (rc)
814 goto out;
815 }
816
817 sbsec->def_sid = defcontext_sid;
818 }
819
820 rc = sb_finish_set_opts(sb);
821out:
Eric Parisbc7e9822006-09-25 23:32:02 -0700822 mutex_unlock(&sbsec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700823 return rc;
Eric Parisc9180a52007-11-30 13:00:35 -0500824out_double_mount:
825 rc = -EINVAL;
826 printk(KERN_WARNING "SELinux: mount invalid. Same superblock, different "
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800827 "security settings for (dev %s, type %s)\n", sb->s_id, name);
Eric Parisc9180a52007-11-30 13:00:35 -0500828 goto out;
829}
830
Jeff Layton094f7b62013-04-01 08:14:24 -0400831static int selinux_cmp_sb_context(const struct super_block *oldsb,
832 const struct super_block *newsb)
833{
834 struct superblock_security_struct *old = oldsb->s_security;
835 struct superblock_security_struct *new = newsb->s_security;
836 char oldflags = old->flags & SE_MNTMASK;
837 char newflags = new->flags & SE_MNTMASK;
838
839 if (oldflags != newflags)
840 goto mismatch;
841 if ((oldflags & FSCONTEXT_MNT) && old->sid != new->sid)
842 goto mismatch;
843 if ((oldflags & CONTEXT_MNT) && old->mntpoint_sid != new->mntpoint_sid)
844 goto mismatch;
845 if ((oldflags & DEFCONTEXT_MNT) && old->def_sid != new->def_sid)
846 goto mismatch;
847 if (oldflags & ROOTCONTEXT_MNT) {
848 struct inode_security_struct *oldroot = oldsb->s_root->d_inode->i_security;
849 struct inode_security_struct *newroot = newsb->s_root->d_inode->i_security;
850 if (oldroot->sid != newroot->sid)
851 goto mismatch;
852 }
853 return 0;
854mismatch:
855 printk(KERN_WARNING "SELinux: mount invalid. Same superblock, "
856 "different security settings for (dev %s, "
857 "type %s)\n", newsb->s_id, newsb->s_type->name);
858 return -EBUSY;
859}
860
861static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
Eric Parisc9180a52007-11-30 13:00:35 -0500862 struct super_block *newsb)
863{
864 const struct superblock_security_struct *oldsbsec = oldsb->s_security;
865 struct superblock_security_struct *newsbsec = newsb->s_security;
866
867 int set_fscontext = (oldsbsec->flags & FSCONTEXT_MNT);
868 int set_context = (oldsbsec->flags & CONTEXT_MNT);
869 int set_rootcontext = (oldsbsec->flags & ROOTCONTEXT_MNT);
870
Eric Paris0f5e6422008-04-21 16:24:11 -0400871 /*
872 * if the parent was able to be mounted it clearly had no special lsm
Al Viroe8c26252010-03-23 06:36:54 -0400873 * mount options. thus we can safely deal with this superblock later
Eric Paris0f5e6422008-04-21 16:24:11 -0400874 */
Al Viroe8c26252010-03-23 06:36:54 -0400875 if (!ss_initialized)
Jeff Layton094f7b62013-04-01 08:14:24 -0400876 return 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500877
Eric Parisc9180a52007-11-30 13:00:35 -0500878 /* how can we clone if the old one wasn't set up?? */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500879 BUG_ON(!(oldsbsec->flags & SE_SBINITIALIZED));
Eric Parisc9180a52007-11-30 13:00:35 -0500880
Jeff Layton094f7b62013-04-01 08:14:24 -0400881 /* if fs is reusing a sb, make sure that the contexts match */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500882 if (newsbsec->flags & SE_SBINITIALIZED)
Jeff Layton094f7b62013-04-01 08:14:24 -0400883 return selinux_cmp_sb_context(oldsb, newsb);
Eric Paris5a552612008-04-09 14:08:35 -0400884
Eric Parisc9180a52007-11-30 13:00:35 -0500885 mutex_lock(&newsbsec->lock);
886
887 newsbsec->flags = oldsbsec->flags;
888
889 newsbsec->sid = oldsbsec->sid;
890 newsbsec->def_sid = oldsbsec->def_sid;
891 newsbsec->behavior = oldsbsec->behavior;
892
893 if (set_context) {
894 u32 sid = oldsbsec->mntpoint_sid;
895
896 if (!set_fscontext)
897 newsbsec->sid = sid;
898 if (!set_rootcontext) {
899 struct inode *newinode = newsb->s_root->d_inode;
900 struct inode_security_struct *newisec = newinode->i_security;
901 newisec->sid = sid;
902 }
903 newsbsec->mntpoint_sid = sid;
904 }
905 if (set_rootcontext) {
906 const struct inode *oldinode = oldsb->s_root->d_inode;
907 const struct inode_security_struct *oldisec = oldinode->i_security;
908 struct inode *newinode = newsb->s_root->d_inode;
909 struct inode_security_struct *newisec = newinode->i_security;
910
911 newisec->sid = oldisec->sid;
912 }
913
914 sb_finish_set_opts(newsb);
915 mutex_unlock(&newsbsec->lock);
Jeff Layton094f7b62013-04-01 08:14:24 -0400916 return 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500917}
918
Adrian Bunk2e1479d2008-03-17 22:29:23 +0200919static int selinux_parse_opts_str(char *options,
920 struct security_mnt_opts *opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500921{
Eric Parise0007522008-03-05 10:31:54 -0500922 char *p;
Eric Parisc9180a52007-11-30 13:00:35 -0500923 char *context = NULL, *defcontext = NULL;
924 char *fscontext = NULL, *rootcontext = NULL;
Eric Parise0007522008-03-05 10:31:54 -0500925 int rc, num_mnt_opts = 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500926
Eric Parise0007522008-03-05 10:31:54 -0500927 opts->num_mnt_opts = 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500928
929 /* Standard string-based options. */
930 while ((p = strsep(&options, "|")) != NULL) {
931 int token;
932 substring_t args[MAX_OPT_ARGS];
933
934 if (!*p)
935 continue;
936
937 token = match_token(p, tokens, args);
938
939 switch (token) {
940 case Opt_context:
941 if (context || defcontext) {
942 rc = -EINVAL;
943 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
944 goto out_err;
945 }
946 context = match_strdup(&args[0]);
947 if (!context) {
948 rc = -ENOMEM;
949 goto out_err;
950 }
951 break;
952
953 case Opt_fscontext:
954 if (fscontext) {
955 rc = -EINVAL;
956 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
957 goto out_err;
958 }
959 fscontext = match_strdup(&args[0]);
960 if (!fscontext) {
961 rc = -ENOMEM;
962 goto out_err;
963 }
964 break;
965
966 case Opt_rootcontext:
967 if (rootcontext) {
968 rc = -EINVAL;
969 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
970 goto out_err;
971 }
972 rootcontext = match_strdup(&args[0]);
973 if (!rootcontext) {
974 rc = -ENOMEM;
975 goto out_err;
976 }
977 break;
978
979 case Opt_defcontext:
980 if (context || defcontext) {
981 rc = -EINVAL;
982 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
983 goto out_err;
984 }
985 defcontext = match_strdup(&args[0]);
986 if (!defcontext) {
987 rc = -ENOMEM;
988 goto out_err;
989 }
990 break;
David P. Quigley11689d42009-01-16 09:22:03 -0500991 case Opt_labelsupport:
992 break;
Eric Parisc9180a52007-11-30 13:00:35 -0500993 default:
994 rc = -EINVAL;
995 printk(KERN_WARNING "SELinux: unknown mount option\n");
996 goto out_err;
997
998 }
999 }
1000
Eric Parise0007522008-03-05 10:31:54 -05001001 rc = -ENOMEM;
1002 opts->mnt_opts = kcalloc(NUM_SEL_MNT_OPTS, sizeof(char *), GFP_ATOMIC);
1003 if (!opts->mnt_opts)
1004 goto out_err;
1005
1006 opts->mnt_opts_flags = kcalloc(NUM_SEL_MNT_OPTS, sizeof(int), GFP_ATOMIC);
1007 if (!opts->mnt_opts_flags) {
1008 kfree(opts->mnt_opts);
1009 goto out_err;
Eric Parisc9180a52007-11-30 13:00:35 -05001010 }
1011
Eric Parise0007522008-03-05 10:31:54 -05001012 if (fscontext) {
1013 opts->mnt_opts[num_mnt_opts] = fscontext;
1014 opts->mnt_opts_flags[num_mnt_opts++] = FSCONTEXT_MNT;
1015 }
1016 if (context) {
1017 opts->mnt_opts[num_mnt_opts] = context;
1018 opts->mnt_opts_flags[num_mnt_opts++] = CONTEXT_MNT;
1019 }
1020 if (rootcontext) {
1021 opts->mnt_opts[num_mnt_opts] = rootcontext;
1022 opts->mnt_opts_flags[num_mnt_opts++] = ROOTCONTEXT_MNT;
1023 }
1024 if (defcontext) {
1025 opts->mnt_opts[num_mnt_opts] = defcontext;
1026 opts->mnt_opts_flags[num_mnt_opts++] = DEFCONTEXT_MNT;
1027 }
1028
1029 opts->num_mnt_opts = num_mnt_opts;
1030 return 0;
1031
Eric Parisc9180a52007-11-30 13:00:35 -05001032out_err:
1033 kfree(context);
1034 kfree(defcontext);
1035 kfree(fscontext);
1036 kfree(rootcontext);
1037 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001038}
Eric Parise0007522008-03-05 10:31:54 -05001039/*
1040 * string mount options parsing and call set the sbsec
1041 */
1042static int superblock_doinit(struct super_block *sb, void *data)
1043{
1044 int rc = 0;
1045 char *options = data;
1046 struct security_mnt_opts opts;
1047
1048 security_init_mnt_opts(&opts);
1049
1050 if (!data)
1051 goto out;
1052
1053 BUG_ON(sb->s_type->fs_flags & FS_BINARY_MOUNTDATA);
1054
1055 rc = selinux_parse_opts_str(options, &opts);
1056 if (rc)
1057 goto out_err;
1058
1059out:
David Quigley649f6e72013-05-22 12:50:36 -04001060 rc = selinux_set_mnt_opts(sb, &opts, 0, NULL);
Eric Parise0007522008-03-05 10:31:54 -05001061
1062out_err:
1063 security_free_mnt_opts(&opts);
1064 return rc;
1065}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066
Adrian Bunk3583a712008-07-22 20:21:23 +03001067static void selinux_write_opts(struct seq_file *m,
1068 struct security_mnt_opts *opts)
Eric Paris2069f452008-07-04 09:47:13 +10001069{
1070 int i;
1071 char *prefix;
1072
1073 for (i = 0; i < opts->num_mnt_opts; i++) {
David P. Quigley11689d42009-01-16 09:22:03 -05001074 char *has_comma;
1075
1076 if (opts->mnt_opts[i])
1077 has_comma = strchr(opts->mnt_opts[i], ',');
1078 else
1079 has_comma = NULL;
Eric Paris2069f452008-07-04 09:47:13 +10001080
1081 switch (opts->mnt_opts_flags[i]) {
1082 case CONTEXT_MNT:
1083 prefix = CONTEXT_STR;
1084 break;
1085 case FSCONTEXT_MNT:
1086 prefix = FSCONTEXT_STR;
1087 break;
1088 case ROOTCONTEXT_MNT:
1089 prefix = ROOTCONTEXT_STR;
1090 break;
1091 case DEFCONTEXT_MNT:
1092 prefix = DEFCONTEXT_STR;
1093 break;
Eric Paris12f348b2012-10-09 10:56:25 -04001094 case SBLABEL_MNT:
David P. Quigley11689d42009-01-16 09:22:03 -05001095 seq_putc(m, ',');
1096 seq_puts(m, LABELSUPP_STR);
1097 continue;
Eric Paris2069f452008-07-04 09:47:13 +10001098 default:
1099 BUG();
Eric Parisa35c6c832011-04-20 10:21:28 -04001100 return;
Eric Paris2069f452008-07-04 09:47:13 +10001101 };
1102 /* we need a comma before each option */
1103 seq_putc(m, ',');
1104 seq_puts(m, prefix);
1105 if (has_comma)
1106 seq_putc(m, '\"');
1107 seq_puts(m, opts->mnt_opts[i]);
1108 if (has_comma)
1109 seq_putc(m, '\"');
1110 }
1111}
1112
1113static int selinux_sb_show_options(struct seq_file *m, struct super_block *sb)
1114{
1115 struct security_mnt_opts opts;
1116 int rc;
1117
1118 rc = selinux_get_mnt_opts(sb, &opts);
Eric Paris383795c2008-07-29 17:07:26 -04001119 if (rc) {
1120 /* before policy load we may get EINVAL, don't show anything */
1121 if (rc == -EINVAL)
1122 rc = 0;
Eric Paris2069f452008-07-04 09:47:13 +10001123 return rc;
Eric Paris383795c2008-07-29 17:07:26 -04001124 }
Eric Paris2069f452008-07-04 09:47:13 +10001125
1126 selinux_write_opts(m, &opts);
1127
1128 security_free_mnt_opts(&opts);
1129
1130 return rc;
1131}
1132
Linus Torvalds1da177e2005-04-16 15:20:36 -07001133static inline u16 inode_mode_to_security_class(umode_t mode)
1134{
1135 switch (mode & S_IFMT) {
1136 case S_IFSOCK:
1137 return SECCLASS_SOCK_FILE;
1138 case S_IFLNK:
1139 return SECCLASS_LNK_FILE;
1140 case S_IFREG:
1141 return SECCLASS_FILE;
1142 case S_IFBLK:
1143 return SECCLASS_BLK_FILE;
1144 case S_IFDIR:
1145 return SECCLASS_DIR;
1146 case S_IFCHR:
1147 return SECCLASS_CHR_FILE;
1148 case S_IFIFO:
1149 return SECCLASS_FIFO_FILE;
1150
1151 }
1152
1153 return SECCLASS_FILE;
1154}
1155
James Morris13402582005-09-30 14:24:34 -04001156static inline int default_protocol_stream(int protocol)
1157{
1158 return (protocol == IPPROTO_IP || protocol == IPPROTO_TCP);
1159}
1160
1161static inline int default_protocol_dgram(int protocol)
1162{
1163 return (protocol == IPPROTO_IP || protocol == IPPROTO_UDP);
1164}
1165
Linus Torvalds1da177e2005-04-16 15:20:36 -07001166static inline u16 socket_type_to_security_class(int family, int type, int protocol)
1167{
1168 switch (family) {
1169 case PF_UNIX:
1170 switch (type) {
1171 case SOCK_STREAM:
1172 case SOCK_SEQPACKET:
1173 return SECCLASS_UNIX_STREAM_SOCKET;
1174 case SOCK_DGRAM:
1175 return SECCLASS_UNIX_DGRAM_SOCKET;
1176 }
1177 break;
1178 case PF_INET:
1179 case PF_INET6:
1180 switch (type) {
1181 case SOCK_STREAM:
James Morris13402582005-09-30 14:24:34 -04001182 if (default_protocol_stream(protocol))
1183 return SECCLASS_TCP_SOCKET;
1184 else
1185 return SECCLASS_RAWIP_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001186 case SOCK_DGRAM:
James Morris13402582005-09-30 14:24:34 -04001187 if (default_protocol_dgram(protocol))
1188 return SECCLASS_UDP_SOCKET;
1189 else
1190 return SECCLASS_RAWIP_SOCKET;
James Morris2ee92d42006-11-13 16:09:01 -08001191 case SOCK_DCCP:
1192 return SECCLASS_DCCP_SOCKET;
James Morris13402582005-09-30 14:24:34 -04001193 default:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001194 return SECCLASS_RAWIP_SOCKET;
1195 }
1196 break;
1197 case PF_NETLINK:
1198 switch (protocol) {
1199 case NETLINK_ROUTE:
1200 return SECCLASS_NETLINK_ROUTE_SOCKET;
1201 case NETLINK_FIREWALL:
1202 return SECCLASS_NETLINK_FIREWALL_SOCKET;
Pavel Emelyanov7f1fb602011-12-06 07:56:43 +00001203 case NETLINK_SOCK_DIAG:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001204 return SECCLASS_NETLINK_TCPDIAG_SOCKET;
1205 case NETLINK_NFLOG:
1206 return SECCLASS_NETLINK_NFLOG_SOCKET;
1207 case NETLINK_XFRM:
1208 return SECCLASS_NETLINK_XFRM_SOCKET;
1209 case NETLINK_SELINUX:
1210 return SECCLASS_NETLINK_SELINUX_SOCKET;
1211 case NETLINK_AUDIT:
1212 return SECCLASS_NETLINK_AUDIT_SOCKET;
1213 case NETLINK_IP6_FW:
1214 return SECCLASS_NETLINK_IP6FW_SOCKET;
1215 case NETLINK_DNRTMSG:
1216 return SECCLASS_NETLINK_DNRT_SOCKET;
James Morris0c9b7942005-04-16 15:24:13 -07001217 case NETLINK_KOBJECT_UEVENT:
1218 return SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001219 default:
1220 return SECCLASS_NETLINK_SOCKET;
1221 }
1222 case PF_PACKET:
1223 return SECCLASS_PACKET_SOCKET;
1224 case PF_KEY:
1225 return SECCLASS_KEY_SOCKET;
Christopher J. PeBenito3e3ff152006-06-09 00:25:03 -07001226 case PF_APPLETALK:
1227 return SECCLASS_APPLETALK_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001228 }
1229
1230 return SECCLASS_SOCKET;
1231}
1232
1233#ifdef CONFIG_PROC_FS
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001234static int selinux_proc_get_sid(struct dentry *dentry,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001235 u16 tclass,
1236 u32 *sid)
1237{
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001238 int rc;
1239 char *buffer, *path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001240
Eric Paris828dfe12008-04-17 13:17:49 -04001241 buffer = (char *)__get_free_page(GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001242 if (!buffer)
1243 return -ENOMEM;
1244
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001245 path = dentry_path_raw(dentry, buffer, PAGE_SIZE);
1246 if (IS_ERR(path))
1247 rc = PTR_ERR(path);
1248 else {
1249 /* each process gets a /proc/PID/ entry. Strip off the
1250 * PID part to get a valid selinux labeling.
1251 * e.g. /proc/1/net/rpc/nfs -> /net/rpc/nfs */
1252 while (path[1] >= '0' && path[1] <= '9') {
1253 path[1] = '/';
1254 path++;
1255 }
1256 rc = security_genfs_sid("proc", path, tclass, sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001257 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001258 free_page((unsigned long)buffer);
1259 return rc;
1260}
1261#else
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001262static int selinux_proc_get_sid(struct dentry *dentry,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001263 u16 tclass,
1264 u32 *sid)
1265{
1266 return -EINVAL;
1267}
1268#endif
1269
1270/* The inode's security attributes must be initialized before first use. */
1271static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry)
1272{
1273 struct superblock_security_struct *sbsec = NULL;
1274 struct inode_security_struct *isec = inode->i_security;
1275 u32 sid;
1276 struct dentry *dentry;
1277#define INITCONTEXTLEN 255
1278 char *context = NULL;
1279 unsigned len = 0;
1280 int rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001281
1282 if (isec->initialized)
1283 goto out;
1284
Eric Paris23970742006-09-25 23:32:01 -07001285 mutex_lock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001286 if (isec->initialized)
Eric Paris23970742006-09-25 23:32:01 -07001287 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001288
1289 sbsec = inode->i_sb->s_security;
David P. Quigley0d90a7e2009-01-16 09:22:02 -05001290 if (!(sbsec->flags & SE_SBINITIALIZED)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001291 /* Defer initialization until selinux_complete_init,
1292 after the initial policy is loaded and the security
1293 server is ready to handle calls. */
1294 spin_lock(&sbsec->isec_lock);
1295 if (list_empty(&isec->list))
1296 list_add(&isec->list, &sbsec->isec_head);
1297 spin_unlock(&sbsec->isec_lock);
Eric Paris23970742006-09-25 23:32:01 -07001298 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001299 }
1300
1301 switch (sbsec->behavior) {
David Quigleyeb9ae682013-05-22 12:50:37 -04001302 case SECURITY_FS_USE_NATIVE:
1303 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001304 case SECURITY_FS_USE_XATTR:
1305 if (!inode->i_op->getxattr) {
1306 isec->sid = sbsec->def_sid;
1307 break;
1308 }
1309
1310 /* Need a dentry, since the xattr API requires one.
1311 Life would be simpler if we could just pass the inode. */
1312 if (opt_dentry) {
1313 /* Called from d_instantiate or d_splice_alias. */
1314 dentry = dget(opt_dentry);
1315 } else {
1316 /* Called from selinux_complete_init, try to find a dentry. */
1317 dentry = d_find_alias(inode);
1318 }
1319 if (!dentry) {
Eric Parisdf7f54c2009-03-09 14:35:58 -04001320 /*
1321 * this is can be hit on boot when a file is accessed
1322 * before the policy is loaded. When we load policy we
1323 * may find inodes that have no dentry on the
1324 * sbsec->isec_head list. No reason to complain as these
1325 * will get fixed up the next time we go through
1326 * inode_doinit with a dentry, before these inodes could
1327 * be used again by userspace.
1328 */
Eric Paris23970742006-09-25 23:32:01 -07001329 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001330 }
1331
1332 len = INITCONTEXTLEN;
Eric Paris4cb912f2009-02-12 14:50:05 -05001333 context = kmalloc(len+1, GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001334 if (!context) {
1335 rc = -ENOMEM;
1336 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001337 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001338 }
Eric Paris4cb912f2009-02-12 14:50:05 -05001339 context[len] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001340 rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX,
1341 context, len);
1342 if (rc == -ERANGE) {
James Morris314dabb2009-08-10 22:00:13 +10001343 kfree(context);
1344
Linus Torvalds1da177e2005-04-16 15:20:36 -07001345 /* Need a larger buffer. Query for the right size. */
1346 rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX,
1347 NULL, 0);
1348 if (rc < 0) {
1349 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001350 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001351 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001352 len = rc;
Eric Paris4cb912f2009-02-12 14:50:05 -05001353 context = kmalloc(len+1, GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001354 if (!context) {
1355 rc = -ENOMEM;
1356 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001357 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001358 }
Eric Paris4cb912f2009-02-12 14:50:05 -05001359 context[len] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001360 rc = inode->i_op->getxattr(dentry,
1361 XATTR_NAME_SELINUX,
1362 context, len);
1363 }
1364 dput(dentry);
1365 if (rc < 0) {
1366 if (rc != -ENODATA) {
Eric Paris744ba352008-04-17 11:52:44 -04001367 printk(KERN_WARNING "SELinux: %s: getxattr returned "
Harvey Harrisondd6f9532008-03-06 10:03:59 +11001368 "%d for dev=%s ino=%ld\n", __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001369 -rc, inode->i_sb->s_id, inode->i_ino);
1370 kfree(context);
Eric Paris23970742006-09-25 23:32:01 -07001371 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001372 }
1373 /* Map ENODATA to the default file SID */
1374 sid = sbsec->def_sid;
1375 rc = 0;
1376 } else {
James Morrisf5c1d5b2005-07-28 01:07:37 -07001377 rc = security_context_to_sid_default(context, rc, &sid,
Stephen Smalley869ab512008-04-04 08:46:05 -04001378 sbsec->def_sid,
1379 GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001380 if (rc) {
Eric Paris4ba0a8a2009-02-12 15:01:10 -05001381 char *dev = inode->i_sb->s_id;
1382 unsigned long ino = inode->i_ino;
1383
1384 if (rc == -EINVAL) {
1385 if (printk_ratelimit())
1386 printk(KERN_NOTICE "SELinux: inode=%lu on dev=%s was found to have an invalid "
1387 "context=%s. This indicates you may need to relabel the inode or the "
1388 "filesystem in question.\n", ino, dev, context);
1389 } else {
1390 printk(KERN_WARNING "SELinux: %s: context_to_sid(%s) "
1391 "returned %d for dev=%s ino=%ld\n",
1392 __func__, context, -rc, dev, ino);
1393 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001394 kfree(context);
1395 /* Leave with the unlabeled SID */
1396 rc = 0;
1397 break;
1398 }
1399 }
1400 kfree(context);
1401 isec->sid = sid;
1402 break;
1403 case SECURITY_FS_USE_TASK:
1404 isec->sid = isec->task_sid;
1405 break;
1406 case SECURITY_FS_USE_TRANS:
1407 /* Default to the fs SID. */
1408 isec->sid = sbsec->sid;
1409
1410 /* Try to obtain a transition SID. */
1411 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Eric Paris652bb9b2011-02-01 11:05:40 -05001412 rc = security_transition_sid(isec->task_sid, sbsec->sid,
1413 isec->sclass, NULL, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001414 if (rc)
Eric Paris23970742006-09-25 23:32:01 -07001415 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001416 isec->sid = sid;
1417 break;
Eric Parisc312feb2006-07-10 04:43:53 -07001418 case SECURITY_FS_USE_MNTPOINT:
1419 isec->sid = sbsec->mntpoint_sid;
1420 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001421 default:
Eric Parisc312feb2006-07-10 04:43:53 -07001422 /* Default to the fs superblock SID. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001423 isec->sid = sbsec->sid;
1424
David P. Quigley0d90a7e2009-01-16 09:22:02 -05001425 if ((sbsec->flags & SE_SBPROC) && !S_ISLNK(inode->i_mode)) {
Paul Mooref64410e2014-03-19 16:46:18 -04001426 /* We must have a dentry to determine the label on
1427 * procfs inodes */
1428 if (opt_dentry)
1429 /* Called from d_instantiate or
1430 * d_splice_alias. */
1431 dentry = dget(opt_dentry);
1432 else
1433 /* Called from selinux_complete_init, try to
1434 * find a dentry. */
1435 dentry = d_find_alias(inode);
1436 /*
1437 * This can be hit on boot when a file is accessed
1438 * before the policy is loaded. When we load policy we
1439 * may find inodes that have no dentry on the
1440 * sbsec->isec_head list. No reason to complain as
1441 * these will get fixed up the next time we go through
1442 * inode_doinit() with a dentry, before these inodes
1443 * could be used again by userspace.
1444 */
1445 if (!dentry)
1446 goto out_unlock;
1447 isec->sclass = inode_mode_to_security_class(inode->i_mode);
1448 rc = selinux_proc_get_sid(dentry, isec->sclass, &sid);
1449 dput(dentry);
1450 if (rc)
1451 goto out_unlock;
1452 isec->sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001453 }
1454 break;
1455 }
1456
1457 isec->initialized = 1;
1458
Eric Paris23970742006-09-25 23:32:01 -07001459out_unlock:
1460 mutex_unlock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001461out:
1462 if (isec->sclass == SECCLASS_FILE)
1463 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001464 return rc;
1465}
1466
1467/* Convert a Linux signal to an access vector. */
1468static inline u32 signal_to_av(int sig)
1469{
1470 u32 perm = 0;
1471
1472 switch (sig) {
1473 case SIGCHLD:
1474 /* Commonly granted from child to parent. */
1475 perm = PROCESS__SIGCHLD;
1476 break;
1477 case SIGKILL:
1478 /* Cannot be caught or ignored */
1479 perm = PROCESS__SIGKILL;
1480 break;
1481 case SIGSTOP:
1482 /* Cannot be caught or ignored */
1483 perm = PROCESS__SIGSTOP;
1484 break;
1485 default:
1486 /* All other signals. */
1487 perm = PROCESS__SIGNAL;
1488 break;
1489 }
1490
1491 return perm;
1492}
1493
David Howells275bb412008-11-14 10:39:19 +11001494/*
David Howellsd84f4f92008-11-14 10:39:23 +11001495 * Check permission between a pair of credentials
1496 * fork check, ptrace check, etc.
1497 */
1498static int cred_has_perm(const struct cred *actor,
1499 const struct cred *target,
1500 u32 perms)
1501{
1502 u32 asid = cred_sid(actor), tsid = cred_sid(target);
1503
1504 return avc_has_perm(asid, tsid, SECCLASS_PROCESS, perms, NULL);
1505}
1506
1507/*
David Howells88e67f32008-11-14 10:39:21 +11001508 * Check permission between a pair of tasks, e.g. signal checks,
David Howells275bb412008-11-14 10:39:19 +11001509 * fork check, ptrace check, etc.
1510 * tsk1 is the actor and tsk2 is the target
David Howells3b11a1d2008-11-14 10:39:26 +11001511 * - this uses the default subjective creds of tsk1
David Howells275bb412008-11-14 10:39:19 +11001512 */
1513static int task_has_perm(const struct task_struct *tsk1,
1514 const struct task_struct *tsk2,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001515 u32 perms)
1516{
David Howells275bb412008-11-14 10:39:19 +11001517 const struct task_security_struct *__tsec1, *__tsec2;
1518 u32 sid1, sid2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001519
David Howells275bb412008-11-14 10:39:19 +11001520 rcu_read_lock();
1521 __tsec1 = __task_cred(tsk1)->security; sid1 = __tsec1->sid;
1522 __tsec2 = __task_cred(tsk2)->security; sid2 = __tsec2->sid;
1523 rcu_read_unlock();
1524 return avc_has_perm(sid1, sid2, SECCLASS_PROCESS, perms, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001525}
1526
David Howells3b11a1d2008-11-14 10:39:26 +11001527/*
1528 * Check permission between current and another task, e.g. signal checks,
1529 * fork check, ptrace check, etc.
1530 * current is the actor and tsk2 is the target
1531 * - this uses current's subjective creds
1532 */
1533static int current_has_perm(const struct task_struct *tsk,
1534 u32 perms)
1535{
1536 u32 sid, tsid;
1537
1538 sid = current_sid();
1539 tsid = task_sid(tsk);
1540 return avc_has_perm(sid, tsid, SECCLASS_PROCESS, perms, NULL);
1541}
1542
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001543#if CAP_LAST_CAP > 63
1544#error Fix SELinux to handle capabilities > 63.
1545#endif
1546
Linus Torvalds1da177e2005-04-16 15:20:36 -07001547/* Check whether a task is allowed to use a capability. */
Eric Paris6a9de492012-01-03 12:25:14 -05001548static int cred_has_capability(const struct cred *cred,
Eric Paris06112162008-11-11 22:02:50 +11001549 int cap, int audit)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001550{
Thomas Liu2bf49692009-07-14 12:14:09 -04001551 struct common_audit_data ad;
Eric Paris06112162008-11-11 22:02:50 +11001552 struct av_decision avd;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001553 u16 sclass;
David Howells3699c532009-01-06 22:27:01 +00001554 u32 sid = cred_sid(cred);
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001555 u32 av = CAP_TO_MASK(cap);
Eric Paris06112162008-11-11 22:02:50 +11001556 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001557
Eric Paris50c205f2012-04-04 15:01:43 -04001558 ad.type = LSM_AUDIT_DATA_CAP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001559 ad.u.cap = cap;
1560
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001561 switch (CAP_TO_INDEX(cap)) {
1562 case 0:
1563 sclass = SECCLASS_CAPABILITY;
1564 break;
1565 case 1:
1566 sclass = SECCLASS_CAPABILITY2;
1567 break;
1568 default:
1569 printk(KERN_ERR
1570 "SELinux: out of range capability %d\n", cap);
1571 BUG();
Eric Parisa35c6c832011-04-20 10:21:28 -04001572 return -EINVAL;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001573 }
Eric Paris06112162008-11-11 22:02:50 +11001574
David Howells275bb412008-11-14 10:39:19 +11001575 rc = avc_has_perm_noaudit(sid, sid, sclass, av, 0, &avd);
Eric Paris9ade0cf2011-04-25 16:26:29 -04001576 if (audit == SECURITY_CAP_AUDIT) {
Linus Torvaldsab354062013-10-04 14:05:38 -07001577 int rc2 = avc_audit(sid, sid, sclass, av, &avd, rc, &ad);
Eric Paris9ade0cf2011-04-25 16:26:29 -04001578 if (rc2)
1579 return rc2;
1580 }
Eric Paris06112162008-11-11 22:02:50 +11001581 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001582}
1583
1584/* Check whether a task is allowed to use a system operation. */
1585static int task_has_system(struct task_struct *tsk,
1586 u32 perms)
1587{
David Howells275bb412008-11-14 10:39:19 +11001588 u32 sid = task_sid(tsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001589
David Howells275bb412008-11-14 10:39:19 +11001590 return avc_has_perm(sid, SECINITSID_KERNEL,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001591 SECCLASS_SYSTEM, perms, NULL);
1592}
1593
1594/* Check whether a task has a particular permission to an inode.
1595 The 'adp' parameter is optional and allows other audit
1596 data to be passed (e.g. the dentry). */
David Howells88e67f32008-11-14 10:39:21 +11001597static int inode_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001598 struct inode *inode,
1599 u32 perms,
Linus Torvalds19e49832013-10-04 12:54:11 -07001600 struct common_audit_data *adp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001601{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001602 struct inode_security_struct *isec;
David Howells275bb412008-11-14 10:39:19 +11001603 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001604
David Howellse0e81732009-09-02 09:13:40 +01001605 validate_creds(cred);
1606
Eric Paris828dfe12008-04-17 13:17:49 -04001607 if (unlikely(IS_PRIVATE(inode)))
Stephen Smalleybbaca6c2007-02-14 00:34:16 -08001608 return 0;
1609
David Howells88e67f32008-11-14 10:39:21 +11001610 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001611 isec = inode->i_security;
1612
Linus Torvalds19e49832013-10-04 12:54:11 -07001613 return avc_has_perm(sid, isec->sid, isec->sclass, perms, adp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001614}
1615
1616/* Same as inode_has_perm, but pass explicit audit data containing
1617 the dentry to help the auditing code to more easily generate the
1618 pathname if needed. */
David Howells88e67f32008-11-14 10:39:21 +11001619static inline int dentry_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001620 struct dentry *dentry,
1621 u32 av)
1622{
1623 struct inode *inode = dentry->d_inode;
Thomas Liu2bf49692009-07-14 12:14:09 -04001624 struct common_audit_data ad;
David Howells88e67f32008-11-14 10:39:21 +11001625
Eric Paris50c205f2012-04-04 15:01:43 -04001626 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Paris2875fa02011-04-28 16:04:24 -04001627 ad.u.dentry = dentry;
Linus Torvalds19e49832013-10-04 12:54:11 -07001628 return inode_has_perm(cred, inode, av, &ad);
Eric Paris2875fa02011-04-28 16:04:24 -04001629}
1630
1631/* Same as inode_has_perm, but pass explicit audit data containing
1632 the path to help the auditing code to more easily generate the
1633 pathname if needed. */
1634static inline int path_has_perm(const struct cred *cred,
1635 struct path *path,
1636 u32 av)
1637{
1638 struct inode *inode = path->dentry->d_inode;
1639 struct common_audit_data ad;
1640
Eric Paris50c205f2012-04-04 15:01:43 -04001641 ad.type = LSM_AUDIT_DATA_PATH;
Eric Paris2875fa02011-04-28 16:04:24 -04001642 ad.u.path = *path;
Linus Torvalds19e49832013-10-04 12:54:11 -07001643 return inode_has_perm(cred, inode, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001644}
1645
David Howells13f8e982013-06-13 23:37:55 +01001646/* Same as path_has_perm, but uses the inode from the file struct. */
1647static inline int file_path_has_perm(const struct cred *cred,
1648 struct file *file,
1649 u32 av)
1650{
1651 struct common_audit_data ad;
1652
1653 ad.type = LSM_AUDIT_DATA_PATH;
1654 ad.u.path = file->f_path;
Linus Torvalds19e49832013-10-04 12:54:11 -07001655 return inode_has_perm(cred, file_inode(file), av, &ad);
David Howells13f8e982013-06-13 23:37:55 +01001656}
1657
Linus Torvalds1da177e2005-04-16 15:20:36 -07001658/* Check whether a task can use an open file descriptor to
1659 access an inode in a given way. Check access to the
1660 descriptor itself, and then use dentry_has_perm to
1661 check a particular permission to the file.
1662 Access to the descriptor is implicitly granted if it
1663 has the same SID as the process. If av is zero, then
1664 access to the file is not checked, e.g. for cases
1665 where only the descriptor is affected like seek. */
David Howells88e67f32008-11-14 10:39:21 +11001666static int file_has_perm(const struct cred *cred,
1667 struct file *file,
1668 u32 av)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001669{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001670 struct file_security_struct *fsec = file->f_security;
Al Viro496ad9a2013-01-23 17:07:38 -05001671 struct inode *inode = file_inode(file);
Thomas Liu2bf49692009-07-14 12:14:09 -04001672 struct common_audit_data ad;
David Howells88e67f32008-11-14 10:39:21 +11001673 u32 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001674 int rc;
1675
Eric Paris50c205f2012-04-04 15:01:43 -04001676 ad.type = LSM_AUDIT_DATA_PATH;
Eric Parisf48b7392011-04-25 12:54:27 -04001677 ad.u.path = file->f_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001678
David Howells275bb412008-11-14 10:39:19 +11001679 if (sid != fsec->sid) {
1680 rc = avc_has_perm(sid, fsec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001681 SECCLASS_FD,
1682 FD__USE,
1683 &ad);
1684 if (rc)
David Howells88e67f32008-11-14 10:39:21 +11001685 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001686 }
1687
1688 /* av is zero if only checking access to the descriptor. */
David Howells88e67f32008-11-14 10:39:21 +11001689 rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001690 if (av)
Linus Torvalds19e49832013-10-04 12:54:11 -07001691 rc = inode_has_perm(cred, inode, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001692
David Howells88e67f32008-11-14 10:39:21 +11001693out:
1694 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001695}
1696
1697/* Check whether a task can create a file. */
1698static int may_create(struct inode *dir,
1699 struct dentry *dentry,
1700 u16 tclass)
1701{
Paul Moore5fb49872010-04-22 14:46:19 -04001702 const struct task_security_struct *tsec = current_security();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001703 struct inode_security_struct *dsec;
1704 struct superblock_security_struct *sbsec;
David Howells275bb412008-11-14 10:39:19 +11001705 u32 sid, newsid;
Thomas Liu2bf49692009-07-14 12:14:09 -04001706 struct common_audit_data ad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001707 int rc;
1708
Linus Torvalds1da177e2005-04-16 15:20:36 -07001709 dsec = dir->i_security;
1710 sbsec = dir->i_sb->s_security;
1711
David Howells275bb412008-11-14 10:39:19 +11001712 sid = tsec->sid;
1713 newsid = tsec->create_sid;
1714
Eric Paris50c205f2012-04-04 15:01:43 -04001715 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04001716 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001717
David Howells275bb412008-11-14 10:39:19 +11001718 rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001719 DIR__ADD_NAME | DIR__SEARCH,
1720 &ad);
1721 if (rc)
1722 return rc;
1723
Eric Paris12f348b2012-10-09 10:56:25 -04001724 if (!newsid || !(sbsec->flags & SBLABEL_MNT)) {
Eric Pariscb1e9222011-04-28 15:11:21 -04001725 rc = security_transition_sid(sid, dsec->sid, tclass,
1726 &dentry->d_name, &newsid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001727 if (rc)
1728 return rc;
1729 }
1730
David Howells275bb412008-11-14 10:39:19 +11001731 rc = avc_has_perm(sid, newsid, tclass, FILE__CREATE, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001732 if (rc)
1733 return rc;
1734
1735 return avc_has_perm(newsid, sbsec->sid,
1736 SECCLASS_FILESYSTEM,
1737 FILESYSTEM__ASSOCIATE, &ad);
1738}
1739
Michael LeMay4eb582c2006-06-26 00:24:57 -07001740/* Check whether a task can create a key. */
1741static int may_create_key(u32 ksid,
1742 struct task_struct *ctx)
1743{
David Howells275bb412008-11-14 10:39:19 +11001744 u32 sid = task_sid(ctx);
Michael LeMay4eb582c2006-06-26 00:24:57 -07001745
David Howells275bb412008-11-14 10:39:19 +11001746 return avc_has_perm(sid, ksid, SECCLASS_KEY, KEY__CREATE, NULL);
Michael LeMay4eb582c2006-06-26 00:24:57 -07001747}
1748
Eric Paris828dfe12008-04-17 13:17:49 -04001749#define MAY_LINK 0
1750#define MAY_UNLINK 1
1751#define MAY_RMDIR 2
Linus Torvalds1da177e2005-04-16 15:20:36 -07001752
1753/* Check whether a task can link, unlink, or rmdir a file/directory. */
1754static int may_link(struct inode *dir,
1755 struct dentry *dentry,
1756 int kind)
1757
1758{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001759 struct inode_security_struct *dsec, *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04001760 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11001761 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001762 u32 av;
1763 int rc;
1764
Linus Torvalds1da177e2005-04-16 15:20:36 -07001765 dsec = dir->i_security;
1766 isec = dentry->d_inode->i_security;
1767
Eric Paris50c205f2012-04-04 15:01:43 -04001768 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04001769 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001770
1771 av = DIR__SEARCH;
1772 av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME);
David Howells275bb412008-11-14 10:39:19 +11001773 rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001774 if (rc)
1775 return rc;
1776
1777 switch (kind) {
1778 case MAY_LINK:
1779 av = FILE__LINK;
1780 break;
1781 case MAY_UNLINK:
1782 av = FILE__UNLINK;
1783 break;
1784 case MAY_RMDIR:
1785 av = DIR__RMDIR;
1786 break;
1787 default:
Eric Paris744ba352008-04-17 11:52:44 -04001788 printk(KERN_WARNING "SELinux: %s: unrecognized kind %d\n",
1789 __func__, kind);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001790 return 0;
1791 }
1792
David Howells275bb412008-11-14 10:39:19 +11001793 rc = avc_has_perm(sid, isec->sid, isec->sclass, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001794 return rc;
1795}
1796
1797static inline int may_rename(struct inode *old_dir,
1798 struct dentry *old_dentry,
1799 struct inode *new_dir,
1800 struct dentry *new_dentry)
1801{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001802 struct inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04001803 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11001804 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001805 u32 av;
1806 int old_is_dir, new_is_dir;
1807 int rc;
1808
Linus Torvalds1da177e2005-04-16 15:20:36 -07001809 old_dsec = old_dir->i_security;
1810 old_isec = old_dentry->d_inode->i_security;
1811 old_is_dir = S_ISDIR(old_dentry->d_inode->i_mode);
1812 new_dsec = new_dir->i_security;
1813
Eric Paris50c205f2012-04-04 15:01:43 -04001814 ad.type = LSM_AUDIT_DATA_DENTRY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001815
Eric Parisa2694342011-04-25 13:10:27 -04001816 ad.u.dentry = old_dentry;
David Howells275bb412008-11-14 10:39:19 +11001817 rc = avc_has_perm(sid, old_dsec->sid, SECCLASS_DIR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001818 DIR__REMOVE_NAME | DIR__SEARCH, &ad);
1819 if (rc)
1820 return rc;
David Howells275bb412008-11-14 10:39:19 +11001821 rc = avc_has_perm(sid, old_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001822 old_isec->sclass, FILE__RENAME, &ad);
1823 if (rc)
1824 return rc;
1825 if (old_is_dir && new_dir != old_dir) {
David Howells275bb412008-11-14 10:39:19 +11001826 rc = avc_has_perm(sid, old_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001827 old_isec->sclass, DIR__REPARENT, &ad);
1828 if (rc)
1829 return rc;
1830 }
1831
Eric Parisa2694342011-04-25 13:10:27 -04001832 ad.u.dentry = new_dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001833 av = DIR__ADD_NAME | DIR__SEARCH;
1834 if (new_dentry->d_inode)
1835 av |= DIR__REMOVE_NAME;
David Howells275bb412008-11-14 10:39:19 +11001836 rc = avc_has_perm(sid, new_dsec->sid, SECCLASS_DIR, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001837 if (rc)
1838 return rc;
1839 if (new_dentry->d_inode) {
1840 new_isec = new_dentry->d_inode->i_security;
1841 new_is_dir = S_ISDIR(new_dentry->d_inode->i_mode);
David Howells275bb412008-11-14 10:39:19 +11001842 rc = avc_has_perm(sid, new_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001843 new_isec->sclass,
1844 (new_is_dir ? DIR__RMDIR : FILE__UNLINK), &ad);
1845 if (rc)
1846 return rc;
1847 }
1848
1849 return 0;
1850}
1851
1852/* Check whether a task can perform a filesystem operation. */
David Howells88e67f32008-11-14 10:39:21 +11001853static int superblock_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001854 struct super_block *sb,
1855 u32 perms,
Thomas Liu2bf49692009-07-14 12:14:09 -04001856 struct common_audit_data *ad)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001857{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001858 struct superblock_security_struct *sbsec;
David Howells88e67f32008-11-14 10:39:21 +11001859 u32 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001860
Linus Torvalds1da177e2005-04-16 15:20:36 -07001861 sbsec = sb->s_security;
David Howells275bb412008-11-14 10:39:19 +11001862 return avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM, perms, ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001863}
1864
1865/* Convert a Linux mode and permission mask to an access vector. */
1866static inline u32 file_mask_to_av(int mode, int mask)
1867{
1868 u32 av = 0;
1869
Al Virodba19c62011-07-25 20:49:29 -04001870 if (!S_ISDIR(mode)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001871 if (mask & MAY_EXEC)
1872 av |= FILE__EXECUTE;
1873 if (mask & MAY_READ)
1874 av |= FILE__READ;
1875
1876 if (mask & MAY_APPEND)
1877 av |= FILE__APPEND;
1878 else if (mask & MAY_WRITE)
1879 av |= FILE__WRITE;
1880
1881 } else {
1882 if (mask & MAY_EXEC)
1883 av |= DIR__SEARCH;
1884 if (mask & MAY_WRITE)
1885 av |= DIR__WRITE;
1886 if (mask & MAY_READ)
1887 av |= DIR__READ;
1888 }
1889
1890 return av;
1891}
1892
1893/* Convert a Linux file to an access vector. */
1894static inline u32 file_to_av(struct file *file)
1895{
1896 u32 av = 0;
1897
1898 if (file->f_mode & FMODE_READ)
1899 av |= FILE__READ;
1900 if (file->f_mode & FMODE_WRITE) {
1901 if (file->f_flags & O_APPEND)
1902 av |= FILE__APPEND;
1903 else
1904 av |= FILE__WRITE;
1905 }
Stephen Smalley0794c662008-03-17 08:55:18 -04001906 if (!av) {
1907 /*
1908 * Special file opened with flags 3 for ioctl-only use.
1909 */
1910 av = FILE__IOCTL;
1911 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001912
1913 return av;
1914}
1915
Eric Paris8b6a5a32008-10-29 17:06:46 -04001916/*
1917 * Convert a file to an access vector and include the correct open
1918 * open permission.
1919 */
1920static inline u32 open_file_to_av(struct file *file)
1921{
1922 u32 av = file_to_av(file);
1923
Eric Paris49b7b8d2010-07-23 11:44:09 -04001924 if (selinux_policycap_openperm)
1925 av |= FILE__OPEN;
1926
Eric Paris8b6a5a32008-10-29 17:06:46 -04001927 return av;
1928}
1929
Linus Torvalds1da177e2005-04-16 15:20:36 -07001930/* Hook functions begin here. */
1931
Ingo Molnar9e488582009-05-07 19:26:19 +10001932static int selinux_ptrace_access_check(struct task_struct *child,
David Howells5cd9c582008-08-14 11:37:28 +01001933 unsigned int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001934{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001935 int rc;
1936
Ingo Molnar9e488582009-05-07 19:26:19 +10001937 rc = cap_ptrace_access_check(child, mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001938 if (rc)
1939 return rc;
1940
Eric Paris69f594a2012-01-03 12:25:15 -05001941 if (mode & PTRACE_MODE_READ) {
David Howells275bb412008-11-14 10:39:19 +11001942 u32 sid = current_sid();
1943 u32 csid = task_sid(child);
1944 return avc_has_perm(sid, csid, SECCLASS_FILE, FILE__READ, NULL);
Stephen Smalley006ebb42008-05-19 08:32:49 -04001945 }
1946
David Howells3b11a1d2008-11-14 10:39:26 +11001947 return current_has_perm(child, PROCESS__PTRACE);
David Howells5cd9c582008-08-14 11:37:28 +01001948}
1949
1950static int selinux_ptrace_traceme(struct task_struct *parent)
1951{
1952 int rc;
1953
Eric Paris200ac532009-02-12 15:01:04 -05001954 rc = cap_ptrace_traceme(parent);
David Howells5cd9c582008-08-14 11:37:28 +01001955 if (rc)
1956 return rc;
1957
1958 return task_has_perm(parent, current, PROCESS__PTRACE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001959}
1960
1961static int selinux_capget(struct task_struct *target, kernel_cap_t *effective,
Eric Paris828dfe12008-04-17 13:17:49 -04001962 kernel_cap_t *inheritable, kernel_cap_t *permitted)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001963{
1964 int error;
1965
David Howells3b11a1d2008-11-14 10:39:26 +11001966 error = current_has_perm(target, PROCESS__GETCAP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001967 if (error)
1968 return error;
1969
Eric Paris200ac532009-02-12 15:01:04 -05001970 return cap_capget(target, effective, inheritable, permitted);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001971}
1972
David Howellsd84f4f92008-11-14 10:39:23 +11001973static int selinux_capset(struct cred *new, const struct cred *old,
1974 const kernel_cap_t *effective,
1975 const kernel_cap_t *inheritable,
1976 const kernel_cap_t *permitted)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001977{
1978 int error;
1979
Eric Paris200ac532009-02-12 15:01:04 -05001980 error = cap_capset(new, old,
David Howellsd84f4f92008-11-14 10:39:23 +11001981 effective, inheritable, permitted);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001982 if (error)
1983 return error;
1984
David Howellsd84f4f92008-11-14 10:39:23 +11001985 return cred_has_perm(old, new, PROCESS__SETCAP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001986}
1987
James Morris5626d3e2009-01-30 10:05:06 +11001988/*
1989 * (This comment used to live with the selinux_task_setuid hook,
1990 * which was removed).
1991 *
1992 * Since setuid only affects the current process, and since the SELinux
1993 * controls are not based on the Linux identity attributes, SELinux does not
1994 * need to control this operation. However, SELinux does control the use of
1995 * the CAP_SETUID and CAP_SETGID capabilities using the capable hook.
1996 */
1997
Eric Paris6a9de492012-01-03 12:25:14 -05001998static int selinux_capable(const struct cred *cred, struct user_namespace *ns,
1999 int cap, int audit)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002000{
2001 int rc;
2002
Eric Paris6a9de492012-01-03 12:25:14 -05002003 rc = cap_capable(cred, ns, cap, audit);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002004 if (rc)
2005 return rc;
2006
Eric Paris6a9de492012-01-03 12:25:14 -05002007 return cred_has_capability(cred, cap, audit);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002008}
2009
Linus Torvalds1da177e2005-04-16 15:20:36 -07002010static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb)
2011{
David Howells88e67f32008-11-14 10:39:21 +11002012 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002013 int rc = 0;
2014
2015 if (!sb)
2016 return 0;
2017
2018 switch (cmds) {
Eric Paris828dfe12008-04-17 13:17:49 -04002019 case Q_SYNC:
2020 case Q_QUOTAON:
2021 case Q_QUOTAOFF:
2022 case Q_SETINFO:
2023 case Q_SETQUOTA:
David Howells88e67f32008-11-14 10:39:21 +11002024 rc = superblock_has_perm(cred, sb, FILESYSTEM__QUOTAMOD, NULL);
Eric Paris828dfe12008-04-17 13:17:49 -04002025 break;
2026 case Q_GETFMT:
2027 case Q_GETINFO:
2028 case Q_GETQUOTA:
David Howells88e67f32008-11-14 10:39:21 +11002029 rc = superblock_has_perm(cred, sb, FILESYSTEM__QUOTAGET, NULL);
Eric Paris828dfe12008-04-17 13:17:49 -04002030 break;
2031 default:
2032 rc = 0; /* let the kernel handle invalid cmds */
2033 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002034 }
2035 return rc;
2036}
2037
2038static int selinux_quota_on(struct dentry *dentry)
2039{
David Howells88e67f32008-11-14 10:39:21 +11002040 const struct cred *cred = current_cred();
2041
Eric Paris2875fa02011-04-28 16:04:24 -04002042 return dentry_has_perm(cred, dentry, FILE__QUOTAON);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002043}
2044
Eric Paris12b30522010-11-15 18:36:29 -05002045static int selinux_syslog(int type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002046{
2047 int rc;
2048
Linus Torvalds1da177e2005-04-16 15:20:36 -07002049 switch (type) {
Kees Cookd78ca3c2010-02-03 15:37:13 -08002050 case SYSLOG_ACTION_READ_ALL: /* Read last kernel messages */
2051 case SYSLOG_ACTION_SIZE_BUFFER: /* Return size of the log buffer */
Eric Paris828dfe12008-04-17 13:17:49 -04002052 rc = task_has_system(current, SYSTEM__SYSLOG_READ);
2053 break;
Kees Cookd78ca3c2010-02-03 15:37:13 -08002054 case SYSLOG_ACTION_CONSOLE_OFF: /* Disable logging to console */
2055 case SYSLOG_ACTION_CONSOLE_ON: /* Enable logging to console */
2056 /* Set level of messages printed to console */
2057 case SYSLOG_ACTION_CONSOLE_LEVEL:
Eric Paris828dfe12008-04-17 13:17:49 -04002058 rc = task_has_system(current, SYSTEM__SYSLOG_CONSOLE);
2059 break;
Kees Cookd78ca3c2010-02-03 15:37:13 -08002060 case SYSLOG_ACTION_CLOSE: /* Close log */
2061 case SYSLOG_ACTION_OPEN: /* Open log */
2062 case SYSLOG_ACTION_READ: /* Read from log */
2063 case SYSLOG_ACTION_READ_CLEAR: /* Read/clear last kernel messages */
2064 case SYSLOG_ACTION_CLEAR: /* Clear ring buffer */
Eric Paris828dfe12008-04-17 13:17:49 -04002065 default:
2066 rc = task_has_system(current, SYSTEM__SYSLOG_MOD);
2067 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002068 }
2069 return rc;
2070}
2071
2072/*
2073 * Check that a process has enough memory to allocate a new virtual
2074 * mapping. 0 means there is enough memory for the allocation to
2075 * succeed and -ENOMEM implies there is not.
2076 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07002077 * Do not audit the selinux permission check, as this is applied to all
2078 * processes that allocate mappings.
2079 */
Alan Cox34b4e4a2007-08-22 14:01:28 -07002080static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002081{
2082 int rc, cap_sys_admin = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002083
Eric Paris6a9de492012-01-03 12:25:14 -05002084 rc = selinux_capable(current_cred(), &init_user_ns, CAP_SYS_ADMIN,
David Howells3699c532009-01-06 22:27:01 +00002085 SECURITY_CAP_NOAUDIT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002086 if (rc == 0)
2087 cap_sys_admin = 1;
2088
Alan Cox34b4e4a2007-08-22 14:01:28 -07002089 return __vm_enough_memory(mm, pages, cap_sys_admin);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002090}
2091
2092/* binprm security operations */
2093
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002094static int check_nnp_nosuid(const struct linux_binprm *bprm,
2095 const struct task_security_struct *old_tsec,
2096 const struct task_security_struct *new_tsec)
2097{
2098 int nnp = (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS);
2099 int nosuid = (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID);
2100 int rc;
2101
2102 if (!nnp && !nosuid)
2103 return 0; /* neither NNP nor nosuid */
2104
2105 if (new_tsec->sid == old_tsec->sid)
2106 return 0; /* No change in credentials */
2107
2108 /*
2109 * The only transitions we permit under NNP or nosuid
2110 * are transitions to bounded SIDs, i.e. SIDs that are
2111 * guaranteed to only be allowed a subset of the permissions
2112 * of the current SID.
2113 */
2114 rc = security_bounded_transition(old_tsec->sid, new_tsec->sid);
2115 if (rc) {
2116 /*
2117 * On failure, preserve the errno values for NNP vs nosuid.
2118 * NNP: Operation not permitted for caller.
2119 * nosuid: Permission denied to file.
2120 */
2121 if (nnp)
2122 return -EPERM;
2123 else
2124 return -EACCES;
2125 }
2126 return 0;
2127}
2128
David Howellsa6f76f22008-11-14 10:39:24 +11002129static int selinux_bprm_set_creds(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002130{
David Howellsa6f76f22008-11-14 10:39:24 +11002131 const struct task_security_struct *old_tsec;
2132 struct task_security_struct *new_tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002133 struct inode_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04002134 struct common_audit_data ad;
Al Viro496ad9a2013-01-23 17:07:38 -05002135 struct inode *inode = file_inode(bprm->file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002136 int rc;
2137
Eric Paris200ac532009-02-12 15:01:04 -05002138 rc = cap_bprm_set_creds(bprm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002139 if (rc)
2140 return rc;
2141
David Howellsa6f76f22008-11-14 10:39:24 +11002142 /* SELinux context only depends on initial program or script and not
2143 * the script interpreter */
2144 if (bprm->cred_prepared)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002145 return 0;
2146
David Howellsa6f76f22008-11-14 10:39:24 +11002147 old_tsec = current_security();
2148 new_tsec = bprm->cred->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002149 isec = inode->i_security;
2150
2151 /* Default to the current task SID. */
David Howellsa6f76f22008-11-14 10:39:24 +11002152 new_tsec->sid = old_tsec->sid;
2153 new_tsec->osid = old_tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002154
Michael LeMay28eba5b2006-06-27 02:53:42 -07002155 /* Reset fs, key, and sock SIDs on execve. */
David Howellsa6f76f22008-11-14 10:39:24 +11002156 new_tsec->create_sid = 0;
2157 new_tsec->keycreate_sid = 0;
2158 new_tsec->sockcreate_sid = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002159
David Howellsa6f76f22008-11-14 10:39:24 +11002160 if (old_tsec->exec_sid) {
2161 new_tsec->sid = old_tsec->exec_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002162 /* Reset exec SID on execve. */
David Howellsa6f76f22008-11-14 10:39:24 +11002163 new_tsec->exec_sid = 0;
Andy Lutomirski259e5e62012-04-12 16:47:50 -05002164
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002165 /* Fail on NNP or nosuid if not an allowed transition. */
2166 rc = check_nnp_nosuid(bprm, old_tsec, new_tsec);
2167 if (rc)
2168 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002169 } else {
2170 /* Check for a default transition on this program. */
David Howellsa6f76f22008-11-14 10:39:24 +11002171 rc = security_transition_sid(old_tsec->sid, isec->sid,
Eric Paris652bb9b2011-02-01 11:05:40 -05002172 SECCLASS_PROCESS, NULL,
2173 &new_tsec->sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002174 if (rc)
2175 return rc;
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002176
2177 /*
2178 * Fallback to old SID on NNP or nosuid if not an allowed
2179 * transition.
2180 */
2181 rc = check_nnp_nosuid(bprm, old_tsec, new_tsec);
2182 if (rc)
2183 new_tsec->sid = old_tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002184 }
2185
Eric Paris50c205f2012-04-04 15:01:43 -04002186 ad.type = LSM_AUDIT_DATA_PATH;
Eric Parisf48b7392011-04-25 12:54:27 -04002187 ad.u.path = bprm->file->f_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002188
David Howellsa6f76f22008-11-14 10:39:24 +11002189 if (new_tsec->sid == old_tsec->sid) {
2190 rc = avc_has_perm(old_tsec->sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002191 SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, &ad);
2192 if (rc)
2193 return rc;
2194 } else {
2195 /* Check permissions for the transition. */
David Howellsa6f76f22008-11-14 10:39:24 +11002196 rc = avc_has_perm(old_tsec->sid, new_tsec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002197 SECCLASS_PROCESS, PROCESS__TRANSITION, &ad);
2198 if (rc)
2199 return rc;
2200
David Howellsa6f76f22008-11-14 10:39:24 +11002201 rc = avc_has_perm(new_tsec->sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002202 SECCLASS_FILE, FILE__ENTRYPOINT, &ad);
2203 if (rc)
2204 return rc;
2205
David Howellsa6f76f22008-11-14 10:39:24 +11002206 /* Check for shared state */
2207 if (bprm->unsafe & LSM_UNSAFE_SHARE) {
2208 rc = avc_has_perm(old_tsec->sid, new_tsec->sid,
2209 SECCLASS_PROCESS, PROCESS__SHARE,
2210 NULL);
2211 if (rc)
2212 return -EPERM;
2213 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002214
David Howellsa6f76f22008-11-14 10:39:24 +11002215 /* Make sure that anyone attempting to ptrace over a task that
2216 * changes its SID has the appropriate permit */
2217 if (bprm->unsafe &
2218 (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) {
2219 struct task_struct *tracer;
2220 struct task_security_struct *sec;
2221 u32 ptsid = 0;
2222
2223 rcu_read_lock();
Tejun Heo06d98472011-06-17 16:50:40 +02002224 tracer = ptrace_parent(current);
David Howellsa6f76f22008-11-14 10:39:24 +11002225 if (likely(tracer != NULL)) {
2226 sec = __task_cred(tracer)->security;
2227 ptsid = sec->sid;
2228 }
2229 rcu_read_unlock();
2230
2231 if (ptsid != 0) {
2232 rc = avc_has_perm(ptsid, new_tsec->sid,
2233 SECCLASS_PROCESS,
2234 PROCESS__PTRACE, NULL);
2235 if (rc)
2236 return -EPERM;
2237 }
2238 }
2239
2240 /* Clear any possibly unsafe personality bits on exec: */
2241 bprm->per_clear |= PER_CLEAR_ON_SETID;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002242 }
2243
Linus Torvalds1da177e2005-04-16 15:20:36 -07002244 return 0;
2245}
2246
Eric Paris828dfe12008-04-17 13:17:49 -04002247static int selinux_bprm_secureexec(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002248{
Paul Moore5fb49872010-04-22 14:46:19 -04002249 const struct task_security_struct *tsec = current_security();
David Howells275bb412008-11-14 10:39:19 +11002250 u32 sid, osid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002251 int atsecure = 0;
2252
David Howells275bb412008-11-14 10:39:19 +11002253 sid = tsec->sid;
2254 osid = tsec->osid;
2255
2256 if (osid != sid) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002257 /* Enable secure mode for SIDs transitions unless
2258 the noatsecure permission is granted between
2259 the two SIDs, i.e. ahp returns 0. */
David Howells275bb412008-11-14 10:39:19 +11002260 atsecure = avc_has_perm(osid, sid,
David Howellsa6f76f22008-11-14 10:39:24 +11002261 SECCLASS_PROCESS,
2262 PROCESS__NOATSECURE, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002263 }
2264
Eric Paris200ac532009-02-12 15:01:04 -05002265 return (atsecure || cap_bprm_secureexec(bprm));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002266}
2267
Al Viroc3c073f2012-08-21 22:32:06 -04002268static int match_file(const void *p, struct file *file, unsigned fd)
2269{
2270 return file_has_perm(p, file, file_to_av(file)) ? fd + 1 : 0;
2271}
2272
Linus Torvalds1da177e2005-04-16 15:20:36 -07002273/* Derived from fs/exec.c:flush_old_files. */
David Howells745ca242008-11-14 10:39:22 +11002274static inline void flush_unauthorized_files(const struct cred *cred,
2275 struct files_struct *files)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002276{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002277 struct file *file, *devnull = NULL;
Stephen Smalleyb20c8122006-09-25 23:32:03 -07002278 struct tty_struct *tty;
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002279 int drop_tty = 0;
Al Viroc3c073f2012-08-21 22:32:06 -04002280 unsigned n;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002281
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002282 tty = get_current_tty();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002283 if (tty) {
Nick Pigginee2ffa02010-08-18 04:37:35 +10002284 spin_lock(&tty_files_lock);
Eric Paris37dd0bd2008-10-31 17:40:00 -04002285 if (!list_empty(&tty->tty_files)) {
Nick Piggind996b622010-08-18 04:37:36 +10002286 struct tty_file_private *file_priv;
Eric Paris37dd0bd2008-10-31 17:40:00 -04002287
Linus Torvalds1da177e2005-04-16 15:20:36 -07002288 /* Revalidate access to controlling tty.
David Howells13f8e982013-06-13 23:37:55 +01002289 Use file_path_has_perm on the tty path directly
2290 rather than using file_has_perm, as this particular
2291 open file may belong to another process and we are
2292 only interested in the inode-based check here. */
Nick Piggind996b622010-08-18 04:37:36 +10002293 file_priv = list_first_entry(&tty->tty_files,
2294 struct tty_file_private, list);
2295 file = file_priv->file;
David Howells13f8e982013-06-13 23:37:55 +01002296 if (file_path_has_perm(cred, file, FILE__READ | FILE__WRITE))
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002297 drop_tty = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002298 }
Nick Pigginee2ffa02010-08-18 04:37:35 +10002299 spin_unlock(&tty_files_lock);
Alan Cox452a00d2008-10-13 10:39:13 +01002300 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002301 }
Eric W. Biederman98a27ba2007-05-08 00:26:56 -07002302 /* Reset controlling tty. */
2303 if (drop_tty)
2304 no_tty();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002305
2306 /* Revalidate access to inherited open files. */
Al Viroc3c073f2012-08-21 22:32:06 -04002307 n = iterate_fd(files, 0, match_file, cred);
2308 if (!n) /* none found? */
2309 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002310
Al Viroc3c073f2012-08-21 22:32:06 -04002311 devnull = dentry_open(&selinux_null, O_RDWR, cred);
Al Viro45525b22012-10-16 13:30:07 -04002312 if (IS_ERR(devnull))
2313 devnull = NULL;
2314 /* replace all the matching ones with this */
2315 do {
2316 replace_fd(n - 1, devnull, 0);
2317 } while ((n = iterate_fd(files, n, match_file, cred)) != 0);
2318 if (devnull)
Al Viroc3c073f2012-08-21 22:32:06 -04002319 fput(devnull);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002320}
2321
Linus Torvalds1da177e2005-04-16 15:20:36 -07002322/*
David Howellsa6f76f22008-11-14 10:39:24 +11002323 * Prepare a process for imminent new credential changes due to exec
Linus Torvalds1da177e2005-04-16 15:20:36 -07002324 */
David Howellsa6f76f22008-11-14 10:39:24 +11002325static void selinux_bprm_committing_creds(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002326{
David Howellsa6f76f22008-11-14 10:39:24 +11002327 struct task_security_struct *new_tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002328 struct rlimit *rlim, *initrlim;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002329 int rc, i;
2330
David Howellsa6f76f22008-11-14 10:39:24 +11002331 new_tsec = bprm->cred->security;
2332 if (new_tsec->sid == new_tsec->osid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002333 return;
2334
2335 /* Close files for which the new task SID is not authorized. */
David Howellsa6f76f22008-11-14 10:39:24 +11002336 flush_unauthorized_files(bprm->cred, current->files);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002337
David Howellsa6f76f22008-11-14 10:39:24 +11002338 /* Always clear parent death signal on SID transitions. */
2339 current->pdeath_signal = 0;
2340
2341 /* Check whether the new SID can inherit resource limits from the old
2342 * SID. If not, reset all soft limits to the lower of the current
2343 * task's hard limit and the init task's soft limit.
2344 *
2345 * Note that the setting of hard limits (even to lower them) can be
2346 * controlled by the setrlimit check. The inclusion of the init task's
2347 * soft limit into the computation is to avoid resetting soft limits
2348 * higher than the default soft limit for cases where the default is
2349 * lower than the hard limit, e.g. RLIMIT_CORE or RLIMIT_STACK.
2350 */
2351 rc = avc_has_perm(new_tsec->osid, new_tsec->sid, SECCLASS_PROCESS,
2352 PROCESS__RLIMITINH, NULL);
2353 if (rc) {
Oleg Nesteroveb2d55a2010-06-23 22:43:32 +02002354 /* protect against do_prlimit() */
2355 task_lock(current);
David Howellsa6f76f22008-11-14 10:39:24 +11002356 for (i = 0; i < RLIM_NLIMITS; i++) {
2357 rlim = current->signal->rlim + i;
2358 initrlim = init_task.signal->rlim + i;
2359 rlim->rlim_cur = min(rlim->rlim_max, initrlim->rlim_cur);
2360 }
Oleg Nesteroveb2d55a2010-06-23 22:43:32 +02002361 task_unlock(current);
2362 update_rlimit_cpu(current, rlimit(RLIMIT_CPU));
David Howellsa6f76f22008-11-14 10:39:24 +11002363 }
2364}
2365
2366/*
2367 * Clean up the process immediately after the installation of new credentials
2368 * due to exec
2369 */
2370static void selinux_bprm_committed_creds(struct linux_binprm *bprm)
2371{
2372 const struct task_security_struct *tsec = current_security();
2373 struct itimerval itimer;
David Howellsa6f76f22008-11-14 10:39:24 +11002374 u32 osid, sid;
2375 int rc, i;
David Howellsa6f76f22008-11-14 10:39:24 +11002376
David Howellsa6f76f22008-11-14 10:39:24 +11002377 osid = tsec->osid;
2378 sid = tsec->sid;
2379
2380 if (sid == osid)
2381 return;
2382
2383 /* Check whether the new SID can inherit signal state from the old SID.
2384 * If not, clear itimers to avoid subsequent signal generation and
2385 * flush and unblock signals.
2386 *
2387 * This must occur _after_ the task SID has been updated so that any
2388 * kill done after the flush will be checked against the new SID.
2389 */
2390 rc = avc_has_perm(osid, sid, SECCLASS_PROCESS, PROCESS__SIGINH, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002391 if (rc) {
2392 memset(&itimer, 0, sizeof itimer);
2393 for (i = 0; i < 3; i++)
2394 do_setitimer(i, &itimer, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002395 spin_lock_irq(&current->sighand->siglock);
David Howells3bcac022009-04-29 13:45:05 +01002396 if (!(current->signal->flags & SIGNAL_GROUP_EXIT)) {
2397 __flush_signals(current);
2398 flush_signal_handlers(current, 1);
2399 sigemptyset(&current->blocked);
2400 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002401 spin_unlock_irq(&current->sighand->siglock);
2402 }
2403
David Howellsa6f76f22008-11-14 10:39:24 +11002404 /* Wake up the parent if it is waiting so that it can recheck
2405 * wait permission to the new task SID. */
Oleg Nesterovecd6de32009-04-29 16:02:24 +02002406 read_lock(&tasklist_lock);
Oleg Nesterov0b7570e2009-09-23 15:56:46 -07002407 __wake_up_parent(current, current->real_parent);
Oleg Nesterovecd6de32009-04-29 16:02:24 +02002408 read_unlock(&tasklist_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002409}
2410
2411/* superblock security operations */
2412
2413static int selinux_sb_alloc_security(struct super_block *sb)
2414{
2415 return superblock_alloc_security(sb);
2416}
2417
2418static void selinux_sb_free_security(struct super_block *sb)
2419{
2420 superblock_free_security(sb);
2421}
2422
2423static inline int match_prefix(char *prefix, int plen, char *option, int olen)
2424{
2425 if (plen > olen)
2426 return 0;
2427
2428 return !memcmp(prefix, option, plen);
2429}
2430
2431static inline int selinux_option(char *option, int len)
2432{
Eric Paris832cbd92008-04-01 13:24:09 -04002433 return (match_prefix(CONTEXT_STR, sizeof(CONTEXT_STR)-1, option, len) ||
2434 match_prefix(FSCONTEXT_STR, sizeof(FSCONTEXT_STR)-1, option, len) ||
2435 match_prefix(DEFCONTEXT_STR, sizeof(DEFCONTEXT_STR)-1, option, len) ||
David P. Quigley11689d42009-01-16 09:22:03 -05002436 match_prefix(ROOTCONTEXT_STR, sizeof(ROOTCONTEXT_STR)-1, option, len) ||
2437 match_prefix(LABELSUPP_STR, sizeof(LABELSUPP_STR)-1, option, len));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002438}
2439
2440static inline void take_option(char **to, char *from, int *first, int len)
2441{
2442 if (!*first) {
2443 **to = ',';
2444 *to += 1;
Cory Olmo3528a952006-09-29 01:58:44 -07002445 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002446 *first = 0;
2447 memcpy(*to, from, len);
2448 *to += len;
2449}
2450
Eric Paris828dfe12008-04-17 13:17:49 -04002451static inline void take_selinux_option(char **to, char *from, int *first,
2452 int len)
Cory Olmo3528a952006-09-29 01:58:44 -07002453{
2454 int current_size = 0;
2455
2456 if (!*first) {
2457 **to = '|';
2458 *to += 1;
Eric Paris828dfe12008-04-17 13:17:49 -04002459 } else
Cory Olmo3528a952006-09-29 01:58:44 -07002460 *first = 0;
2461
2462 while (current_size < len) {
2463 if (*from != '"') {
2464 **to = *from;
2465 *to += 1;
2466 }
2467 from += 1;
2468 current_size += 1;
2469 }
2470}
2471
Eric Parise0007522008-03-05 10:31:54 -05002472static int selinux_sb_copy_data(char *orig, char *copy)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002473{
2474 int fnosec, fsec, rc = 0;
2475 char *in_save, *in_curr, *in_end;
2476 char *sec_curr, *nosec_save, *nosec;
Cory Olmo3528a952006-09-29 01:58:44 -07002477 int open_quote = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002478
2479 in_curr = orig;
2480 sec_curr = copy;
2481
Linus Torvalds1da177e2005-04-16 15:20:36 -07002482 nosec = (char *)get_zeroed_page(GFP_KERNEL);
2483 if (!nosec) {
2484 rc = -ENOMEM;
2485 goto out;
2486 }
2487
2488 nosec_save = nosec;
2489 fnosec = fsec = 1;
2490 in_save = in_end = orig;
2491
2492 do {
Cory Olmo3528a952006-09-29 01:58:44 -07002493 if (*in_end == '"')
2494 open_quote = !open_quote;
2495 if ((*in_end == ',' && open_quote == 0) ||
2496 *in_end == '\0') {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002497 int len = in_end - in_curr;
2498
2499 if (selinux_option(in_curr, len))
Cory Olmo3528a952006-09-29 01:58:44 -07002500 take_selinux_option(&sec_curr, in_curr, &fsec, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002501 else
2502 take_option(&nosec, in_curr, &fnosec, len);
2503
2504 in_curr = in_end + 1;
2505 }
2506 } while (*in_end++);
2507
Eric Paris6931dfc2005-06-30 02:58:51 -07002508 strcpy(in_save, nosec_save);
Gerald Schaeferda3caa22005-06-21 17:15:18 -07002509 free_page((unsigned long)nosec_save);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002510out:
2511 return rc;
2512}
2513
Eric Paris026eb162011-03-03 16:09:14 -05002514static int selinux_sb_remount(struct super_block *sb, void *data)
2515{
2516 int rc, i, *flags;
2517 struct security_mnt_opts opts;
2518 char *secdata, **mount_options;
2519 struct superblock_security_struct *sbsec = sb->s_security;
2520
2521 if (!(sbsec->flags & SE_SBINITIALIZED))
2522 return 0;
2523
2524 if (!data)
2525 return 0;
2526
2527 if (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)
2528 return 0;
2529
2530 security_init_mnt_opts(&opts);
2531 secdata = alloc_secdata();
2532 if (!secdata)
2533 return -ENOMEM;
2534 rc = selinux_sb_copy_data(data, secdata);
2535 if (rc)
2536 goto out_free_secdata;
2537
2538 rc = selinux_parse_opts_str(secdata, &opts);
2539 if (rc)
2540 goto out_free_secdata;
2541
2542 mount_options = opts.mnt_opts;
2543 flags = opts.mnt_opts_flags;
2544
2545 for (i = 0; i < opts.num_mnt_opts; i++) {
2546 u32 sid;
2547 size_t len;
2548
Eric Paris12f348b2012-10-09 10:56:25 -04002549 if (flags[i] == SBLABEL_MNT)
Eric Paris026eb162011-03-03 16:09:14 -05002550 continue;
2551 len = strlen(mount_options[i]);
Nikolay Aleksandrov52a4c642014-03-07 12:44:19 +01002552 rc = security_context_to_sid(mount_options[i], len, &sid,
2553 GFP_KERNEL);
Eric Paris026eb162011-03-03 16:09:14 -05002554 if (rc) {
2555 printk(KERN_WARNING "SELinux: security_context_to_sid"
Linus Torvalds29b1deb2013-12-15 11:17:45 -08002556 "(%s) failed for (dev %s, type %s) errno=%d\n",
2557 mount_options[i], sb->s_id, sb->s_type->name, rc);
Eric Paris026eb162011-03-03 16:09:14 -05002558 goto out_free_opts;
2559 }
2560 rc = -EINVAL;
2561 switch (flags[i]) {
2562 case FSCONTEXT_MNT:
2563 if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid, sid))
2564 goto out_bad_option;
2565 break;
2566 case CONTEXT_MNT:
2567 if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid, sid))
2568 goto out_bad_option;
2569 break;
2570 case ROOTCONTEXT_MNT: {
2571 struct inode_security_struct *root_isec;
2572 root_isec = sb->s_root->d_inode->i_security;
2573
2574 if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid, sid))
2575 goto out_bad_option;
2576 break;
2577 }
2578 case DEFCONTEXT_MNT:
2579 if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid, sid))
2580 goto out_bad_option;
2581 break;
2582 default:
2583 goto out_free_opts;
2584 }
2585 }
2586
2587 rc = 0;
2588out_free_opts:
2589 security_free_mnt_opts(&opts);
2590out_free_secdata:
2591 free_secdata(secdata);
2592 return rc;
2593out_bad_option:
2594 printk(KERN_WARNING "SELinux: unable to change security options "
Linus Torvalds29b1deb2013-12-15 11:17:45 -08002595 "during remount (dev %s, type=%s)\n", sb->s_id,
2596 sb->s_type->name);
Eric Paris026eb162011-03-03 16:09:14 -05002597 goto out_free_opts;
2598}
2599
James Morris12204e22008-12-19 10:44:42 +11002600static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002601{
David Howells88e67f32008-11-14 10:39:21 +11002602 const struct cred *cred = current_cred();
Thomas Liu2bf49692009-07-14 12:14:09 -04002603 struct common_audit_data ad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002604 int rc;
2605
2606 rc = superblock_doinit(sb, data);
2607 if (rc)
2608 return rc;
2609
James Morris74192242008-12-19 11:41:10 +11002610 /* Allow all mounts performed by the kernel */
2611 if (flags & MS_KERNMOUNT)
2612 return 0;
2613
Eric Paris50c205f2012-04-04 15:01:43 -04002614 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04002615 ad.u.dentry = sb->s_root;
David Howells88e67f32008-11-14 10:39:21 +11002616 return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002617}
2618
David Howells726c3342006-06-23 02:02:58 -07002619static int selinux_sb_statfs(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002620{
David Howells88e67f32008-11-14 10:39:21 +11002621 const struct cred *cred = current_cred();
Thomas Liu2bf49692009-07-14 12:14:09 -04002622 struct common_audit_data ad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002623
Eric Paris50c205f2012-04-04 15:01:43 -04002624 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04002625 ad.u.dentry = dentry->d_sb->s_root;
David Howells88e67f32008-11-14 10:39:21 +11002626 return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002627}
2628
Al Viro808d4e32012-10-11 11:42:01 -04002629static int selinux_mount(const char *dev_name,
Al Virob5266eb2008-03-22 17:48:24 -04002630 struct path *path,
Al Viro808d4e32012-10-11 11:42:01 -04002631 const char *type,
Eric Paris828dfe12008-04-17 13:17:49 -04002632 unsigned long flags,
2633 void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002634{
David Howells88e67f32008-11-14 10:39:21 +11002635 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002636
2637 if (flags & MS_REMOUNT)
Al Virod8c95842011-12-07 18:16:57 -05002638 return superblock_has_perm(cred, path->dentry->d_sb,
Eric Paris828dfe12008-04-17 13:17:49 -04002639 FILESYSTEM__REMOUNT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002640 else
Eric Paris2875fa02011-04-28 16:04:24 -04002641 return path_has_perm(cred, path, FILE__MOUNTON);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002642}
2643
2644static int selinux_umount(struct vfsmount *mnt, int flags)
2645{
David Howells88e67f32008-11-14 10:39:21 +11002646 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002647
David Howells88e67f32008-11-14 10:39:21 +11002648 return superblock_has_perm(cred, mnt->mnt_sb,
Eric Paris828dfe12008-04-17 13:17:49 -04002649 FILESYSTEM__UNMOUNT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002650}
2651
2652/* inode security operations */
2653
2654static int selinux_inode_alloc_security(struct inode *inode)
2655{
2656 return inode_alloc_security(inode);
2657}
2658
2659static void selinux_inode_free_security(struct inode *inode)
2660{
2661 inode_free_security(inode);
2662}
2663
David Quigleyd47be3d2013-05-22 12:50:34 -04002664static int selinux_dentry_init_security(struct dentry *dentry, int mode,
2665 struct qstr *name, void **ctx,
2666 u32 *ctxlen)
2667{
2668 const struct cred *cred = current_cred();
2669 struct task_security_struct *tsec;
2670 struct inode_security_struct *dsec;
2671 struct superblock_security_struct *sbsec;
2672 struct inode *dir = dentry->d_parent->d_inode;
2673 u32 newsid;
2674 int rc;
2675
2676 tsec = cred->security;
2677 dsec = dir->i_security;
2678 sbsec = dir->i_sb->s_security;
2679
2680 if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) {
2681 newsid = tsec->create_sid;
2682 } else {
2683 rc = security_transition_sid(tsec->sid, dsec->sid,
2684 inode_mode_to_security_class(mode),
2685 name,
2686 &newsid);
2687 if (rc) {
2688 printk(KERN_WARNING
2689 "%s: security_transition_sid failed, rc=%d\n",
2690 __func__, -rc);
2691 return rc;
2692 }
2693 }
2694
2695 return security_sid_to_context(newsid, (char **)ctx, ctxlen);
2696}
2697
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002698static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
Tetsuo Handa95489062013-07-25 05:44:02 +09002699 const struct qstr *qstr,
2700 const char **name,
Eric Paris2a7dba32011-02-01 11:05:39 -05002701 void **value, size_t *len)
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002702{
Paul Moore5fb49872010-04-22 14:46:19 -04002703 const struct task_security_struct *tsec = current_security();
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002704 struct inode_security_struct *dsec;
2705 struct superblock_security_struct *sbsec;
David Howells275bb412008-11-14 10:39:19 +11002706 u32 sid, newsid, clen;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002707 int rc;
Tetsuo Handa95489062013-07-25 05:44:02 +09002708 char *context;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002709
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002710 dsec = dir->i_security;
2711 sbsec = dir->i_sb->s_security;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002712
David Howells275bb412008-11-14 10:39:19 +11002713 sid = tsec->sid;
2714 newsid = tsec->create_sid;
2715
Eric Paris415103f2010-12-02 16:13:40 -05002716 if ((sbsec->flags & SE_SBINITIALIZED) &&
2717 (sbsec->behavior == SECURITY_FS_USE_MNTPOINT))
2718 newsid = sbsec->mntpoint_sid;
Eric Paris12f348b2012-10-09 10:56:25 -04002719 else if (!newsid || !(sbsec->flags & SBLABEL_MNT)) {
David Howells275bb412008-11-14 10:39:19 +11002720 rc = security_transition_sid(sid, dsec->sid,
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002721 inode_mode_to_security_class(inode->i_mode),
Eric Paris652bb9b2011-02-01 11:05:40 -05002722 qstr, &newsid);
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002723 if (rc) {
2724 printk(KERN_WARNING "%s: "
2725 "security_transition_sid failed, rc=%d (dev=%s "
2726 "ino=%ld)\n",
Harvey Harrisondd6f9532008-03-06 10:03:59 +11002727 __func__,
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002728 -rc, inode->i_sb->s_id, inode->i_ino);
2729 return rc;
2730 }
2731 }
2732
Eric Paris296fddf2006-09-25 23:32:00 -07002733 /* Possibly defer initialization to selinux_complete_init. */
David P. Quigley0d90a7e2009-01-16 09:22:02 -05002734 if (sbsec->flags & SE_SBINITIALIZED) {
Eric Paris296fddf2006-09-25 23:32:00 -07002735 struct inode_security_struct *isec = inode->i_security;
2736 isec->sclass = inode_mode_to_security_class(inode->i_mode);
2737 isec->sid = newsid;
2738 isec->initialized = 1;
2739 }
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002740
Eric Paris12f348b2012-10-09 10:56:25 -04002741 if (!ss_initialized || !(sbsec->flags & SBLABEL_MNT))
Stephen Smalley25a74f32005-11-08 21:34:33 -08002742 return -EOPNOTSUPP;
2743
Tetsuo Handa95489062013-07-25 05:44:02 +09002744 if (name)
2745 *name = XATTR_SELINUX_SUFFIX;
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002746
2747 if (value && len) {
Stephen Smalley12b29f32008-05-07 13:03:20 -04002748 rc = security_sid_to_context_force(newsid, &context, &clen);
Tetsuo Handa95489062013-07-25 05:44:02 +09002749 if (rc)
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002750 return rc;
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002751 *value = context;
2752 *len = clen;
2753 }
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002754
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002755 return 0;
2756}
2757
Al Viro4acdaf22011-07-26 01:42:34 -04002758static int selinux_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002759{
2760 return may_create(dir, dentry, SECCLASS_FILE);
2761}
2762
Linus Torvalds1da177e2005-04-16 15:20:36 -07002763static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
2764{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002765 return may_link(dir, old_dentry, MAY_LINK);
2766}
2767
Linus Torvalds1da177e2005-04-16 15:20:36 -07002768static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry)
2769{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002770 return may_link(dir, dentry, MAY_UNLINK);
2771}
2772
2773static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry, const char *name)
2774{
2775 return may_create(dir, dentry, SECCLASS_LNK_FILE);
2776}
2777
Al Viro18bb1db2011-07-26 01:41:39 -04002778static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry, umode_t mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002779{
2780 return may_create(dir, dentry, SECCLASS_DIR);
2781}
2782
Linus Torvalds1da177e2005-04-16 15:20:36 -07002783static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry)
2784{
2785 return may_link(dir, dentry, MAY_RMDIR);
2786}
2787
Al Viro1a67aaf2011-07-26 01:52:52 -04002788static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002789{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002790 return may_create(dir, dentry, inode_mode_to_security_class(mode));
2791}
2792
Linus Torvalds1da177e2005-04-16 15:20:36 -07002793static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
Eric Paris828dfe12008-04-17 13:17:49 -04002794 struct inode *new_inode, struct dentry *new_dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002795{
2796 return may_rename(old_inode, old_dentry, new_inode, new_dentry);
2797}
2798
Linus Torvalds1da177e2005-04-16 15:20:36 -07002799static int selinux_inode_readlink(struct dentry *dentry)
2800{
David Howells88e67f32008-11-14 10:39:21 +11002801 const struct cred *cred = current_cred();
2802
Eric Paris2875fa02011-04-28 16:04:24 -04002803 return dentry_has_perm(cred, dentry, FILE__READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002804}
2805
2806static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *nameidata)
2807{
David Howells88e67f32008-11-14 10:39:21 +11002808 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002809
Eric Paris2875fa02011-04-28 16:04:24 -04002810 return dentry_has_perm(cred, dentry, FILE__READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002811}
2812
Eric Parisd4cf970d2012-04-04 15:01:42 -04002813static noinline int audit_inode_permission(struct inode *inode,
2814 u32 perms, u32 audited, u32 denied,
Stephen Smalley626b9742014-04-29 11:29:04 -07002815 int result,
Eric Parisd4cf970d2012-04-04 15:01:42 -04002816 unsigned flags)
2817{
2818 struct common_audit_data ad;
Eric Parisd4cf970d2012-04-04 15:01:42 -04002819 struct inode_security_struct *isec = inode->i_security;
2820 int rc;
2821
Eric Paris50c205f2012-04-04 15:01:43 -04002822 ad.type = LSM_AUDIT_DATA_INODE;
Eric Parisd4cf970d2012-04-04 15:01:42 -04002823 ad.u.inode = inode;
2824
2825 rc = slow_avc_audit(current_sid(), isec->sid, isec->sclass, perms,
Stephen Smalley626b9742014-04-29 11:29:04 -07002826 audited, denied, result, &ad, flags);
Eric Parisd4cf970d2012-04-04 15:01:42 -04002827 if (rc)
2828 return rc;
2829 return 0;
2830}
2831
Al Viroe74f71e2011-06-20 19:38:15 -04002832static int selinux_inode_permission(struct inode *inode, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002833{
David Howells88e67f32008-11-14 10:39:21 +11002834 const struct cred *cred = current_cred();
Eric Parisb782e0a2010-07-23 11:44:03 -04002835 u32 perms;
2836 bool from_access;
Al Virocf1dd1d2011-06-20 19:44:08 -04002837 unsigned flags = mask & MAY_NOT_BLOCK;
Eric Paris2e334052012-04-04 15:01:42 -04002838 struct inode_security_struct *isec;
2839 u32 sid;
2840 struct av_decision avd;
2841 int rc, rc2;
2842 u32 audited, denied;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002843
Eric Parisb782e0a2010-07-23 11:44:03 -04002844 from_access = mask & MAY_ACCESS;
Eric Parisd09ca732010-07-23 11:43:57 -04002845 mask &= (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND);
2846
Eric Parisb782e0a2010-07-23 11:44:03 -04002847 /* No permission to check. Existence test. */
2848 if (!mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002849 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002850
Eric Paris2e334052012-04-04 15:01:42 -04002851 validate_creds(cred);
Eric Parisb782e0a2010-07-23 11:44:03 -04002852
Eric Paris2e334052012-04-04 15:01:42 -04002853 if (unlikely(IS_PRIVATE(inode)))
2854 return 0;
Eric Parisb782e0a2010-07-23 11:44:03 -04002855
2856 perms = file_mask_to_av(inode->i_mode, mask);
2857
Eric Paris2e334052012-04-04 15:01:42 -04002858 sid = cred_sid(cred);
2859 isec = inode->i_security;
2860
2861 rc = avc_has_perm_noaudit(sid, isec->sid, isec->sclass, perms, 0, &avd);
2862 audited = avc_audit_required(perms, &avd, rc,
2863 from_access ? FILE__AUDIT_ACCESS : 0,
2864 &denied);
2865 if (likely(!audited))
2866 return rc;
2867
Stephen Smalley626b9742014-04-29 11:29:04 -07002868 rc2 = audit_inode_permission(inode, perms, audited, denied, rc, flags);
Eric Paris2e334052012-04-04 15:01:42 -04002869 if (rc2)
2870 return rc2;
2871 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002872}
2873
2874static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
2875{
David Howells88e67f32008-11-14 10:39:21 +11002876 const struct cred *cred = current_cred();
Amerigo Wangbc6a6002009-08-20 19:29:02 -07002877 unsigned int ia_valid = iattr->ia_valid;
Eric Paris95dbf732012-04-04 13:45:34 -04002878 __u32 av = FILE__WRITE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002879
Amerigo Wangbc6a6002009-08-20 19:29:02 -07002880 /* ATTR_FORCE is just used for ATTR_KILL_S[UG]ID. */
2881 if (ia_valid & ATTR_FORCE) {
2882 ia_valid &= ~(ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_MODE |
2883 ATTR_FORCE);
2884 if (!ia_valid)
2885 return 0;
2886 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002887
Amerigo Wangbc6a6002009-08-20 19:29:02 -07002888 if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID |
2889 ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_TIMES_SET))
Eric Paris2875fa02011-04-28 16:04:24 -04002890 return dentry_has_perm(cred, dentry, FILE__SETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002891
Eric Paris3d2195c2012-07-06 14:13:30 -04002892 if (selinux_policycap_openperm && (ia_valid & ATTR_SIZE))
Eric Paris95dbf732012-04-04 13:45:34 -04002893 av |= FILE__OPEN;
2894
2895 return dentry_has_perm(cred, dentry, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002896}
2897
2898static int selinux_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
2899{
David Howells88e67f32008-11-14 10:39:21 +11002900 const struct cred *cred = current_cred();
Eric Paris2875fa02011-04-28 16:04:24 -04002901 struct path path;
David Howells88e67f32008-11-14 10:39:21 +11002902
Eric Paris2875fa02011-04-28 16:04:24 -04002903 path.dentry = dentry;
2904 path.mnt = mnt;
2905
2906 return path_has_perm(cred, &path, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002907}
2908
David Howells8f0cfa52008-04-29 00:59:41 -07002909static int selinux_inode_setotherxattr(struct dentry *dentry, const char *name)
Serge E. Hallynb5376772007-10-16 23:31:36 -07002910{
David Howells88e67f32008-11-14 10:39:21 +11002911 const struct cred *cred = current_cred();
2912
Serge E. Hallynb5376772007-10-16 23:31:36 -07002913 if (!strncmp(name, XATTR_SECURITY_PREFIX,
2914 sizeof XATTR_SECURITY_PREFIX - 1)) {
2915 if (!strcmp(name, XATTR_NAME_CAPS)) {
2916 if (!capable(CAP_SETFCAP))
2917 return -EPERM;
2918 } else if (!capable(CAP_SYS_ADMIN)) {
2919 /* A different attribute in the security namespace.
2920 Restrict to administrator. */
2921 return -EPERM;
2922 }
2923 }
2924
2925 /* Not an attribute we recognize, so just check the
2926 ordinary setattr permission. */
Eric Paris2875fa02011-04-28 16:04:24 -04002927 return dentry_has_perm(cred, dentry, FILE__SETATTR);
Serge E. Hallynb5376772007-10-16 23:31:36 -07002928}
2929
David Howells8f0cfa52008-04-29 00:59:41 -07002930static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
2931 const void *value, size_t size, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002932{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002933 struct inode *inode = dentry->d_inode;
2934 struct inode_security_struct *isec = inode->i_security;
2935 struct superblock_security_struct *sbsec;
Thomas Liu2bf49692009-07-14 12:14:09 -04002936 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11002937 u32 newsid, sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002938 int rc = 0;
2939
Serge E. Hallynb5376772007-10-16 23:31:36 -07002940 if (strcmp(name, XATTR_NAME_SELINUX))
2941 return selinux_inode_setotherxattr(dentry, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002942
2943 sbsec = inode->i_sb->s_security;
Eric Paris12f348b2012-10-09 10:56:25 -04002944 if (!(sbsec->flags & SBLABEL_MNT))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002945 return -EOPNOTSUPP;
2946
Serge E. Hallyn2e149672011-03-23 16:43:26 -07002947 if (!inode_owner_or_capable(inode))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002948 return -EPERM;
2949
Eric Paris50c205f2012-04-04 15:01:43 -04002950 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04002951 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002952
David Howells275bb412008-11-14 10:39:19 +11002953 rc = avc_has_perm(sid, isec->sid, isec->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002954 FILE__RELABELFROM, &ad);
2955 if (rc)
2956 return rc;
2957
Nikolay Aleksandrov52a4c642014-03-07 12:44:19 +01002958 rc = security_context_to_sid(value, size, &newsid, GFP_KERNEL);
Stephen Smalley12b29f32008-05-07 13:03:20 -04002959 if (rc == -EINVAL) {
Eric Parisd6ea83e2012-04-04 13:45:49 -04002960 if (!capable(CAP_MAC_ADMIN)) {
2961 struct audit_buffer *ab;
2962 size_t audit_size;
2963 const char *str;
2964
2965 /* We strip a nul only if it is at the end, otherwise the
2966 * context contains a nul and we should audit that */
Al Viroe3fea3f2012-06-09 08:15:16 +01002967 if (value) {
2968 str = value;
2969 if (str[size - 1] == '\0')
2970 audit_size = size - 1;
2971 else
2972 audit_size = size;
2973 } else {
2974 str = "";
2975 audit_size = 0;
2976 }
Eric Parisd6ea83e2012-04-04 13:45:49 -04002977 ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR);
2978 audit_log_format(ab, "op=setxattr invalid_context=");
2979 audit_log_n_untrustedstring(ab, value, audit_size);
2980 audit_log_end(ab);
2981
Stephen Smalley12b29f32008-05-07 13:03:20 -04002982 return rc;
Eric Parisd6ea83e2012-04-04 13:45:49 -04002983 }
Stephen Smalley12b29f32008-05-07 13:03:20 -04002984 rc = security_context_to_sid_force(value, size, &newsid);
2985 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002986 if (rc)
2987 return rc;
2988
David Howells275bb412008-11-14 10:39:19 +11002989 rc = avc_has_perm(sid, newsid, isec->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002990 FILE__RELABELTO, &ad);
2991 if (rc)
2992 return rc;
2993
David Howells275bb412008-11-14 10:39:19 +11002994 rc = security_validate_transition(isec->sid, newsid, sid,
Eric Paris828dfe12008-04-17 13:17:49 -04002995 isec->sclass);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002996 if (rc)
2997 return rc;
2998
2999 return avc_has_perm(newsid,
3000 sbsec->sid,
3001 SECCLASS_FILESYSTEM,
3002 FILESYSTEM__ASSOCIATE,
3003 &ad);
3004}
3005
David Howells8f0cfa52008-04-29 00:59:41 -07003006static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
Eric Parisf5269712008-05-14 11:27:45 -04003007 const void *value, size_t size,
David Howells8f0cfa52008-04-29 00:59:41 -07003008 int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003009{
3010 struct inode *inode = dentry->d_inode;
3011 struct inode_security_struct *isec = inode->i_security;
3012 u32 newsid;
3013 int rc;
3014
3015 if (strcmp(name, XATTR_NAME_SELINUX)) {
3016 /* Not an attribute we recognize, so nothing to do. */
3017 return;
3018 }
3019
Stephen Smalley12b29f32008-05-07 13:03:20 -04003020 rc = security_context_to_sid_force(value, size, &newsid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003021 if (rc) {
Stephen Smalley12b29f32008-05-07 13:03:20 -04003022 printk(KERN_ERR "SELinux: unable to map context to SID"
3023 "for (%s, %lu), rc=%d\n",
3024 inode->i_sb->s_id, inode->i_ino, -rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003025 return;
3026 }
3027
David Quigleyaa9c2662013-05-22 12:50:44 -04003028 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003029 isec->sid = newsid;
David Quigleyaa9c2662013-05-22 12:50:44 -04003030 isec->initialized = 1;
3031
Linus Torvalds1da177e2005-04-16 15:20:36 -07003032 return;
3033}
3034
David Howells8f0cfa52008-04-29 00:59:41 -07003035static int selinux_inode_getxattr(struct dentry *dentry, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003036{
David Howells88e67f32008-11-14 10:39:21 +11003037 const struct cred *cred = current_cred();
3038
Eric Paris2875fa02011-04-28 16:04:24 -04003039 return dentry_has_perm(cred, dentry, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003040}
3041
Eric Paris828dfe12008-04-17 13:17:49 -04003042static int selinux_inode_listxattr(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003043{
David Howells88e67f32008-11-14 10:39:21 +11003044 const struct cred *cred = current_cred();
3045
Eric Paris2875fa02011-04-28 16:04:24 -04003046 return dentry_has_perm(cred, dentry, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003047}
3048
David Howells8f0cfa52008-04-29 00:59:41 -07003049static int selinux_inode_removexattr(struct dentry *dentry, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003050{
Serge E. Hallynb5376772007-10-16 23:31:36 -07003051 if (strcmp(name, XATTR_NAME_SELINUX))
3052 return selinux_inode_setotherxattr(dentry, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003053
3054 /* No one is allowed to remove a SELinux security label.
3055 You can change the label, but all data must be labeled. */
3056 return -EACCES;
3057}
3058
James Morrisd381d8a2005-10-30 14:59:22 -08003059/*
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04003060 * Copy the inode security context value to the user.
James Morrisd381d8a2005-10-30 14:59:22 -08003061 *
3062 * Permission check is handled by selinux_inode_getxattr hook.
3063 */
David P. Quigley42492592008-02-04 22:29:39 -08003064static int selinux_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003065{
David P. Quigley42492592008-02-04 22:29:39 -08003066 u32 size;
3067 int error;
3068 char *context = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003069 struct inode_security_struct *isec = inode->i_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003070
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00003071 if (strcmp(name, XATTR_SELINUX_SUFFIX))
3072 return -EOPNOTSUPP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003073
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04003074 /*
3075 * If the caller has CAP_MAC_ADMIN, then get the raw context
3076 * value even if it is not defined by current policy; otherwise,
3077 * use the in-core value under current policy.
3078 * Use the non-auditing forms of the permission checks since
3079 * getxattr may be called by unprivileged processes commonly
3080 * and lack of permission just means that we fall back to the
3081 * in-core context value, not a denial.
3082 */
Eric Paris6a9de492012-01-03 12:25:14 -05003083 error = selinux_capable(current_cred(), &init_user_ns, CAP_MAC_ADMIN,
David Howells3699c532009-01-06 22:27:01 +00003084 SECURITY_CAP_NOAUDIT);
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04003085 if (!error)
3086 error = security_sid_to_context_force(isec->sid, &context,
3087 &size);
3088 else
3089 error = security_sid_to_context(isec->sid, &context, &size);
David P. Quigley42492592008-02-04 22:29:39 -08003090 if (error)
3091 return error;
3092 error = size;
3093 if (alloc) {
3094 *buffer = context;
3095 goto out_nofree;
3096 }
3097 kfree(context);
3098out_nofree:
3099 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003100}
3101
3102static int selinux_inode_setsecurity(struct inode *inode, const char *name,
Eric Paris828dfe12008-04-17 13:17:49 -04003103 const void *value, size_t size, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003104{
3105 struct inode_security_struct *isec = inode->i_security;
3106 u32 newsid;
3107 int rc;
3108
3109 if (strcmp(name, XATTR_SELINUX_SUFFIX))
3110 return -EOPNOTSUPP;
3111
3112 if (!value || !size)
3113 return -EACCES;
3114
Nikolay Aleksandrov52a4c642014-03-07 12:44:19 +01003115 rc = security_context_to_sid((void *)value, size, &newsid, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003116 if (rc)
3117 return rc;
3118
David Quigleyaa9c2662013-05-22 12:50:44 -04003119 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003120 isec->sid = newsid;
David P. Quigleyddd29ec2009-09-09 14:25:37 -04003121 isec->initialized = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003122 return 0;
3123}
3124
3125static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size)
3126{
3127 const int len = sizeof(XATTR_NAME_SELINUX);
3128 if (buffer && len <= buffer_size)
3129 memcpy(buffer, XATTR_NAME_SELINUX, len);
3130 return len;
3131}
3132
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02003133static void selinux_inode_getsecid(const struct inode *inode, u32 *secid)
3134{
3135 struct inode_security_struct *isec = inode->i_security;
3136 *secid = isec->sid;
3137}
3138
Linus Torvalds1da177e2005-04-16 15:20:36 -07003139/* file security operations */
3140
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003141static int selinux_revalidate_file_permission(struct file *file, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003142{
David Howells88e67f32008-11-14 10:39:21 +11003143 const struct cred *cred = current_cred();
Al Viro496ad9a2013-01-23 17:07:38 -05003144 struct inode *inode = file_inode(file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003145
Linus Torvalds1da177e2005-04-16 15:20:36 -07003146 /* file_mask_to_av won't add FILE__WRITE if MAY_APPEND is set */
3147 if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE))
3148 mask |= MAY_APPEND;
3149
Paul Moore389fb8002009-03-27 17:10:34 -04003150 return file_has_perm(cred, file,
3151 file_mask_to_av(inode->i_mode, mask));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003152}
3153
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003154static int selinux_file_permission(struct file *file, int mask)
3155{
Al Viro496ad9a2013-01-23 17:07:38 -05003156 struct inode *inode = file_inode(file);
Stephen Smalley20dda182009-06-22 14:54:53 -04003157 struct file_security_struct *fsec = file->f_security;
3158 struct inode_security_struct *isec = inode->i_security;
3159 u32 sid = current_sid();
3160
Paul Moore389fb8002009-03-27 17:10:34 -04003161 if (!mask)
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003162 /* No permission to check. Existence test. */
3163 return 0;
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003164
Stephen Smalley20dda182009-06-22 14:54:53 -04003165 if (sid == fsec->sid && fsec->isid == isec->sid &&
3166 fsec->pseqno == avc_policy_seqno())
Eric Paris83d49852012-04-04 13:45:40 -04003167 /* No change since file_open check. */
Stephen Smalley20dda182009-06-22 14:54:53 -04003168 return 0;
3169
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003170 return selinux_revalidate_file_permission(file, mask);
3171}
3172
Linus Torvalds1da177e2005-04-16 15:20:36 -07003173static int selinux_file_alloc_security(struct file *file)
3174{
3175 return file_alloc_security(file);
3176}
3177
3178static void selinux_file_free_security(struct file *file)
3179{
3180 file_free_security(file);
3181}
3182
3183static int selinux_file_ioctl(struct file *file, unsigned int cmd,
3184 unsigned long arg)
3185{
David Howells88e67f32008-11-14 10:39:21 +11003186 const struct cred *cred = current_cred();
Eric Paris0b24dcb2011-02-25 15:39:20 -05003187 int error = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003188
Eric Paris0b24dcb2011-02-25 15:39:20 -05003189 switch (cmd) {
3190 case FIONREAD:
3191 /* fall through */
3192 case FIBMAP:
3193 /* fall through */
3194 case FIGETBSZ:
3195 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003196 case FS_IOC_GETFLAGS:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003197 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003198 case FS_IOC_GETVERSION:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003199 error = file_has_perm(cred, file, FILE__GETATTR);
3200 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003201
Al Viro2f99c362012-03-23 16:04:05 -04003202 case FS_IOC_SETFLAGS:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003203 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003204 case FS_IOC_SETVERSION:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003205 error = file_has_perm(cred, file, FILE__SETATTR);
3206 break;
3207
3208 /* sys_ioctl() checks */
3209 case FIONBIO:
3210 /* fall through */
3211 case FIOASYNC:
3212 error = file_has_perm(cred, file, 0);
3213 break;
3214
3215 case KDSKBENT:
3216 case KDSKBSENT:
Eric Paris6a9de492012-01-03 12:25:14 -05003217 error = cred_has_capability(cred, CAP_SYS_TTY_CONFIG,
3218 SECURITY_CAP_AUDIT);
Eric Paris0b24dcb2011-02-25 15:39:20 -05003219 break;
3220
3221 /* default case assumes that the command will go
3222 * to the file's ioctl() function.
3223 */
3224 default:
3225 error = file_has_perm(cred, file, FILE__IOCTL);
3226 }
3227 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003228}
3229
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003230static int default_noexec;
3231
Linus Torvalds1da177e2005-04-16 15:20:36 -07003232static int file_map_prot_check(struct file *file, unsigned long prot, int shared)
3233{
David Howells88e67f32008-11-14 10:39:21 +11003234 const struct cred *cred = current_cred();
David Howellsd84f4f92008-11-14 10:39:23 +11003235 int rc = 0;
David Howells88e67f32008-11-14 10:39:21 +11003236
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003237 if (default_noexec &&
3238 (prot & PROT_EXEC) && (!file || (!shared && (prot & PROT_WRITE)))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003239 /*
3240 * We are making executable an anonymous mapping or a
3241 * private file mapping that will also be writable.
3242 * This has an additional check.
3243 */
David Howellsd84f4f92008-11-14 10:39:23 +11003244 rc = cred_has_perm(cred, cred, PROCESS__EXECMEM);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003245 if (rc)
David Howellsd84f4f92008-11-14 10:39:23 +11003246 goto error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003247 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003248
3249 if (file) {
3250 /* read access is always possible with a mapping */
3251 u32 av = FILE__READ;
3252
3253 /* write access only matters if the mapping is shared */
3254 if (shared && (prot & PROT_WRITE))
3255 av |= FILE__WRITE;
3256
3257 if (prot & PROT_EXEC)
3258 av |= FILE__EXECUTE;
3259
David Howells88e67f32008-11-14 10:39:21 +11003260 return file_has_perm(cred, file, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003261 }
David Howellsd84f4f92008-11-14 10:39:23 +11003262
3263error:
3264 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003265}
3266
Al Viroe5467852012-05-30 13:30:51 -04003267static int selinux_mmap_addr(unsigned long addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003268{
Paul Moore98883bf2014-03-19 16:46:11 -04003269 int rc;
Eric Paris84336d1a2009-07-31 12:54:05 -04003270
3271 /* do DAC check on address space usage */
Paul Moore98883bf2014-03-19 16:46:11 -04003272 rc = cap_mmap_addr(addr);
3273 if (rc)
3274 return rc;
3275
3276 if (addr < CONFIG_LSM_MMAP_MIN_ADDR) {
3277 u32 sid = current_sid();
3278 rc = avc_has_perm(sid, sid, SECCLASS_MEMPROTECT,
3279 MEMPROTECT__MMAP_ZERO, NULL);
3280 }
3281
3282 return rc;
Al Viroe5467852012-05-30 13:30:51 -04003283}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003284
Al Viroe5467852012-05-30 13:30:51 -04003285static int selinux_mmap_file(struct file *file, unsigned long reqprot,
3286 unsigned long prot, unsigned long flags)
3287{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003288 if (selinux_checkreqprot)
3289 prot = reqprot;
3290
3291 return file_map_prot_check(file, prot,
3292 (flags & MAP_TYPE) == MAP_SHARED);
3293}
3294
3295static int selinux_file_mprotect(struct vm_area_struct *vma,
3296 unsigned long reqprot,
3297 unsigned long prot)
3298{
David Howells88e67f32008-11-14 10:39:21 +11003299 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003300
3301 if (selinux_checkreqprot)
3302 prot = reqprot;
3303
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003304 if (default_noexec &&
3305 (prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) {
James Morrisd541bbe2009-01-29 12:19:51 +11003306 int rc = 0;
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003307 if (vma->vm_start >= vma->vm_mm->start_brk &&
3308 vma->vm_end <= vma->vm_mm->brk) {
David Howellsd84f4f92008-11-14 10:39:23 +11003309 rc = cred_has_perm(cred, cred, PROCESS__EXECHEAP);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003310 } else if (!vma->vm_file &&
3311 vma->vm_start <= vma->vm_mm->start_stack &&
3312 vma->vm_end >= vma->vm_mm->start_stack) {
David Howells3b11a1d2008-11-14 10:39:26 +11003313 rc = current_has_perm(current, PROCESS__EXECSTACK);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003314 } else if (vma->vm_file && vma->anon_vma) {
3315 /*
3316 * We are making executable a file mapping that has
3317 * had some COW done. Since pages might have been
3318 * written, check ability to execute the possibly
3319 * modified content. This typically should only
3320 * occur for text relocations.
3321 */
David Howellsd84f4f92008-11-14 10:39:23 +11003322 rc = file_has_perm(cred, vma->vm_file, FILE__EXECMOD);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003323 }
Lorenzo Hernandez García-Hierro6b992192005-06-25 14:54:34 -07003324 if (rc)
3325 return rc;
3326 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003327
3328 return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED);
3329}
3330
3331static int selinux_file_lock(struct file *file, unsigned int cmd)
3332{
David Howells88e67f32008-11-14 10:39:21 +11003333 const struct cred *cred = current_cred();
3334
3335 return file_has_perm(cred, file, FILE__LOCK);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003336}
3337
3338static int selinux_file_fcntl(struct file *file, unsigned int cmd,
3339 unsigned long arg)
3340{
David Howells88e67f32008-11-14 10:39:21 +11003341 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003342 int err = 0;
3343
3344 switch (cmd) {
Eric Paris828dfe12008-04-17 13:17:49 -04003345 case F_SETFL:
Eric Paris828dfe12008-04-17 13:17:49 -04003346 if ((file->f_flags & O_APPEND) && !(arg & O_APPEND)) {
David Howells88e67f32008-11-14 10:39:21 +11003347 err = file_has_perm(cred, file, FILE__WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003348 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003349 }
3350 /* fall through */
3351 case F_SETOWN:
3352 case F_SETSIG:
3353 case F_GETFL:
3354 case F_GETOWN:
3355 case F_GETSIG:
Cyrill Gorcunov1d151c32012-07-30 14:43:00 -07003356 case F_GETOWNER_UIDS:
Eric Paris828dfe12008-04-17 13:17:49 -04003357 /* Just check FD__USE permission */
David Howells88e67f32008-11-14 10:39:21 +11003358 err = file_has_perm(cred, file, 0);
Eric Paris828dfe12008-04-17 13:17:49 -04003359 break;
3360 case F_GETLK:
3361 case F_SETLK:
3362 case F_SETLKW:
Jeff Layton0d3f7a22014-04-22 08:23:58 -04003363 case F_OFD_GETLK:
3364 case F_OFD_SETLK:
3365 case F_OFD_SETLKW:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003366#if BITS_PER_LONG == 32
Eric Paris828dfe12008-04-17 13:17:49 -04003367 case F_GETLK64:
3368 case F_SETLK64:
3369 case F_SETLKW64:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003370#endif
David Howells88e67f32008-11-14 10:39:21 +11003371 err = file_has_perm(cred, file, FILE__LOCK);
Eric Paris828dfe12008-04-17 13:17:49 -04003372 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003373 }
3374
3375 return err;
3376}
3377
Jeff Laytone0b93ed2014-08-22 11:27:32 -04003378static void selinux_file_set_fowner(struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003379{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003380 struct file_security_struct *fsec;
3381
Linus Torvalds1da177e2005-04-16 15:20:36 -07003382 fsec = file->f_security;
David Howells275bb412008-11-14 10:39:19 +11003383 fsec->fown_sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003384}
3385
3386static int selinux_file_send_sigiotask(struct task_struct *tsk,
3387 struct fown_struct *fown, int signum)
3388{
Eric Paris828dfe12008-04-17 13:17:49 -04003389 struct file *file;
Stephen Smalley65c90bc2009-05-04 15:43:18 -04003390 u32 sid = task_sid(tsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003391 u32 perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003392 struct file_security_struct *fsec;
3393
3394 /* struct fown_struct is never outside the context of a struct file */
Eric Paris828dfe12008-04-17 13:17:49 -04003395 file = container_of(fown, struct file, f_owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003396
Linus Torvalds1da177e2005-04-16 15:20:36 -07003397 fsec = file->f_security;
3398
3399 if (!signum)
3400 perm = signal_to_av(SIGIO); /* as per send_sigio_to_task */
3401 else
3402 perm = signal_to_av(signum);
3403
David Howells275bb412008-11-14 10:39:19 +11003404 return avc_has_perm(fsec->fown_sid, sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003405 SECCLASS_PROCESS, perm, NULL);
3406}
3407
3408static int selinux_file_receive(struct file *file)
3409{
David Howells88e67f32008-11-14 10:39:21 +11003410 const struct cred *cred = current_cred();
3411
3412 return file_has_perm(cred, file, file_to_av(file));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003413}
3414
Eric Paris83d49852012-04-04 13:45:40 -04003415static int selinux_file_open(struct file *file, const struct cred *cred)
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003416{
3417 struct file_security_struct *fsec;
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003418 struct inode_security_struct *isec;
David Howellsd84f4f92008-11-14 10:39:23 +11003419
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003420 fsec = file->f_security;
Al Viro496ad9a2013-01-23 17:07:38 -05003421 isec = file_inode(file)->i_security;
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003422 /*
3423 * Save inode label and policy sequence number
3424 * at open-time so that selinux_file_permission
3425 * can determine whether revalidation is necessary.
3426 * Task label is already saved in the file security
3427 * struct as its SID.
3428 */
3429 fsec->isid = isec->sid;
3430 fsec->pseqno = avc_policy_seqno();
3431 /*
3432 * Since the inode label or policy seqno may have changed
3433 * between the selinux_inode_permission check and the saving
3434 * of state above, recheck that access is still permitted.
3435 * Otherwise, access might never be revalidated against the
3436 * new inode label or new policy.
3437 * This check is not redundant - do not remove.
3438 */
David Howells13f8e982013-06-13 23:37:55 +01003439 return file_path_has_perm(cred, file, open_file_to_av(file));
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003440}
3441
Linus Torvalds1da177e2005-04-16 15:20:36 -07003442/* task security operations */
3443
3444static int selinux_task_create(unsigned long clone_flags)
3445{
David Howells3b11a1d2008-11-14 10:39:26 +11003446 return current_has_perm(current, PROCESS__FORK);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003447}
3448
David Howellsf1752ee2008-11-14 10:39:17 +11003449/*
David Howellsee18d642009-09-02 09:14:21 +01003450 * allocate the SELinux part of blank credentials
3451 */
3452static int selinux_cred_alloc_blank(struct cred *cred, gfp_t gfp)
3453{
3454 struct task_security_struct *tsec;
3455
3456 tsec = kzalloc(sizeof(struct task_security_struct), gfp);
3457 if (!tsec)
3458 return -ENOMEM;
3459
3460 cred->security = tsec;
3461 return 0;
3462}
3463
3464/*
David Howellsf1752ee2008-11-14 10:39:17 +11003465 * detach and free the LSM part of a set of credentials
3466 */
3467static void selinux_cred_free(struct cred *cred)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003468{
David Howellsf1752ee2008-11-14 10:39:17 +11003469 struct task_security_struct *tsec = cred->security;
David Howellse0e81732009-09-02 09:13:40 +01003470
Tetsuo Handa2edeaa32011-02-07 13:36:10 +00003471 /*
3472 * cred->security == NULL if security_cred_alloc_blank() or
3473 * security_prepare_creds() returned an error.
3474 */
3475 BUG_ON(cred->security && (unsigned long) cred->security < PAGE_SIZE);
David Howellse0e81732009-09-02 09:13:40 +01003476 cred->security = (void *) 0x7UL;
David Howellsf1752ee2008-11-14 10:39:17 +11003477 kfree(tsec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003478}
3479
David Howellsd84f4f92008-11-14 10:39:23 +11003480/*
3481 * prepare a new set of credentials for modification
3482 */
3483static int selinux_cred_prepare(struct cred *new, const struct cred *old,
3484 gfp_t gfp)
3485{
3486 const struct task_security_struct *old_tsec;
3487 struct task_security_struct *tsec;
3488
3489 old_tsec = old->security;
3490
3491 tsec = kmemdup(old_tsec, sizeof(struct task_security_struct), gfp);
3492 if (!tsec)
3493 return -ENOMEM;
3494
3495 new->security = tsec;
3496 return 0;
3497}
3498
3499/*
David Howellsee18d642009-09-02 09:14:21 +01003500 * transfer the SELinux data to a blank set of creds
3501 */
3502static void selinux_cred_transfer(struct cred *new, const struct cred *old)
3503{
3504 const struct task_security_struct *old_tsec = old->security;
3505 struct task_security_struct *tsec = new->security;
3506
3507 *tsec = *old_tsec;
3508}
3509
3510/*
David Howells3a3b7ce2008-11-14 10:39:28 +11003511 * set the security data for a kernel service
3512 * - all the creation contexts are set to unlabelled
3513 */
3514static int selinux_kernel_act_as(struct cred *new, u32 secid)
3515{
3516 struct task_security_struct *tsec = new->security;
3517 u32 sid = current_sid();
3518 int ret;
3519
3520 ret = avc_has_perm(sid, secid,
3521 SECCLASS_KERNEL_SERVICE,
3522 KERNEL_SERVICE__USE_AS_OVERRIDE,
3523 NULL);
3524 if (ret == 0) {
3525 tsec->sid = secid;
3526 tsec->create_sid = 0;
3527 tsec->keycreate_sid = 0;
3528 tsec->sockcreate_sid = 0;
3529 }
3530 return ret;
3531}
3532
3533/*
3534 * set the file creation context in a security record to the same as the
3535 * objective context of the specified inode
3536 */
3537static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode)
3538{
3539 struct inode_security_struct *isec = inode->i_security;
3540 struct task_security_struct *tsec = new->security;
3541 u32 sid = current_sid();
3542 int ret;
3543
3544 ret = avc_has_perm(sid, isec->sid,
3545 SECCLASS_KERNEL_SERVICE,
3546 KERNEL_SERVICE__CREATE_FILES_AS,
3547 NULL);
3548
3549 if (ret == 0)
3550 tsec->create_sid = isec->sid;
David Howellsef574712010-02-26 01:56:16 +00003551 return ret;
David Howells3a3b7ce2008-11-14 10:39:28 +11003552}
3553
Eric Parisdd8dbf22009-11-03 16:35:32 +11003554static int selinux_kernel_module_request(char *kmod_name)
Eric Paris25354c42009-08-13 09:45:03 -04003555{
Eric Parisdd8dbf22009-11-03 16:35:32 +11003556 u32 sid;
3557 struct common_audit_data ad;
3558
3559 sid = task_sid(current);
3560
Eric Paris50c205f2012-04-04 15:01:43 -04003561 ad.type = LSM_AUDIT_DATA_KMOD;
Eric Parisdd8dbf22009-11-03 16:35:32 +11003562 ad.u.kmod_name = kmod_name;
3563
3564 return avc_has_perm(sid, SECINITSID_KERNEL, SECCLASS_SYSTEM,
3565 SYSTEM__MODULE_REQUEST, &ad);
Eric Paris25354c42009-08-13 09:45:03 -04003566}
3567
Linus Torvalds1da177e2005-04-16 15:20:36 -07003568static int selinux_task_setpgid(struct task_struct *p, pid_t pgid)
3569{
David Howells3b11a1d2008-11-14 10:39:26 +11003570 return current_has_perm(p, PROCESS__SETPGID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003571}
3572
3573static int selinux_task_getpgid(struct task_struct *p)
3574{
David Howells3b11a1d2008-11-14 10:39:26 +11003575 return current_has_perm(p, PROCESS__GETPGID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003576}
3577
3578static int selinux_task_getsid(struct task_struct *p)
3579{
David Howells3b11a1d2008-11-14 10:39:26 +11003580 return current_has_perm(p, PROCESS__GETSESSION);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003581}
3582
David Quigleyf9008e4c2006-06-30 01:55:46 -07003583static void selinux_task_getsecid(struct task_struct *p, u32 *secid)
3584{
David Howells275bb412008-11-14 10:39:19 +11003585 *secid = task_sid(p);
David Quigleyf9008e4c2006-06-30 01:55:46 -07003586}
3587
Linus Torvalds1da177e2005-04-16 15:20:36 -07003588static int selinux_task_setnice(struct task_struct *p, int nice)
3589{
3590 int rc;
3591
Eric Paris200ac532009-02-12 15:01:04 -05003592 rc = cap_task_setnice(p, nice);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003593 if (rc)
3594 return rc;
3595
David Howells3b11a1d2008-11-14 10:39:26 +11003596 return current_has_perm(p, PROCESS__SETSCHED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003597}
3598
James Morris03e68062006-06-23 02:03:58 -07003599static int selinux_task_setioprio(struct task_struct *p, int ioprio)
3600{
Serge E. Hallynb5376772007-10-16 23:31:36 -07003601 int rc;
3602
Eric Paris200ac532009-02-12 15:01:04 -05003603 rc = cap_task_setioprio(p, ioprio);
Serge E. Hallynb5376772007-10-16 23:31:36 -07003604 if (rc)
3605 return rc;
3606
David Howells3b11a1d2008-11-14 10:39:26 +11003607 return current_has_perm(p, PROCESS__SETSCHED);
James Morris03e68062006-06-23 02:03:58 -07003608}
3609
David Quigleya1836a42006-06-30 01:55:49 -07003610static int selinux_task_getioprio(struct task_struct *p)
3611{
David Howells3b11a1d2008-11-14 10:39:26 +11003612 return current_has_perm(p, PROCESS__GETSCHED);
David Quigleya1836a42006-06-30 01:55:49 -07003613}
3614
Jiri Slaby8fd00b42009-08-26 18:41:16 +02003615static int selinux_task_setrlimit(struct task_struct *p, unsigned int resource,
3616 struct rlimit *new_rlim)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003617{
Jiri Slaby8fd00b42009-08-26 18:41:16 +02003618 struct rlimit *old_rlim = p->signal->rlim + resource;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003619
3620 /* Control the ability to change the hard limit (whether
3621 lowering or raising it), so that the hard limit can
3622 later be used as a safe reset point for the soft limit
David Howellsd84f4f92008-11-14 10:39:23 +11003623 upon context transitions. See selinux_bprm_committing_creds. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003624 if (old_rlim->rlim_max != new_rlim->rlim_max)
Jiri Slaby8fd00b42009-08-26 18:41:16 +02003625 return current_has_perm(p, PROCESS__SETRLIMIT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003626
3627 return 0;
3628}
3629
KOSAKI Motohirob0ae1982010-10-15 04:21:18 +09003630static int selinux_task_setscheduler(struct task_struct *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003631{
Serge E. Hallynb5376772007-10-16 23:31:36 -07003632 int rc;
3633
KOSAKI Motohirob0ae1982010-10-15 04:21:18 +09003634 rc = cap_task_setscheduler(p);
Serge E. Hallynb5376772007-10-16 23:31:36 -07003635 if (rc)
3636 return rc;
3637
David Howells3b11a1d2008-11-14 10:39:26 +11003638 return current_has_perm(p, PROCESS__SETSCHED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003639}
3640
3641static int selinux_task_getscheduler(struct task_struct *p)
3642{
David Howells3b11a1d2008-11-14 10:39:26 +11003643 return current_has_perm(p, PROCESS__GETSCHED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003644}
3645
David Quigley35601542006-06-23 02:04:01 -07003646static int selinux_task_movememory(struct task_struct *p)
3647{
David Howells3b11a1d2008-11-14 10:39:26 +11003648 return current_has_perm(p, PROCESS__SETSCHED);
David Quigley35601542006-06-23 02:04:01 -07003649}
3650
David Quigleyf9008e4c2006-06-30 01:55:46 -07003651static int selinux_task_kill(struct task_struct *p, struct siginfo *info,
3652 int sig, u32 secid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003653{
3654 u32 perm;
3655 int rc;
3656
Linus Torvalds1da177e2005-04-16 15:20:36 -07003657 if (!sig)
3658 perm = PROCESS__SIGNULL; /* null signal; existence test */
3659 else
3660 perm = signal_to_av(sig);
David Quigleyf9008e4c2006-06-30 01:55:46 -07003661 if (secid)
David Howells275bb412008-11-14 10:39:19 +11003662 rc = avc_has_perm(secid, task_sid(p),
3663 SECCLASS_PROCESS, perm, NULL);
David Quigleyf9008e4c2006-06-30 01:55:46 -07003664 else
David Howells3b11a1d2008-11-14 10:39:26 +11003665 rc = current_has_perm(p, perm);
David Quigleyf9008e4c2006-06-30 01:55:46 -07003666 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003667}
3668
Linus Torvalds1da177e2005-04-16 15:20:36 -07003669static int selinux_task_wait(struct task_struct *p)
3670{
Eric Paris8a535142007-10-22 16:10:31 -04003671 return task_has_perm(p, current, PROCESS__SIGCHLD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003672}
3673
Linus Torvalds1da177e2005-04-16 15:20:36 -07003674static void selinux_task_to_inode(struct task_struct *p,
3675 struct inode *inode)
3676{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003677 struct inode_security_struct *isec = inode->i_security;
David Howells275bb412008-11-14 10:39:19 +11003678 u32 sid = task_sid(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003679
David Howells275bb412008-11-14 10:39:19 +11003680 isec->sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003681 isec->initialized = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003682}
3683
Linus Torvalds1da177e2005-04-16 15:20:36 -07003684/* Returns error only if unable to parse addresses */
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003685static int selinux_parse_skb_ipv4(struct sk_buff *skb,
Thomas Liu2bf49692009-07-14 12:14:09 -04003686 struct common_audit_data *ad, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003687{
3688 int offset, ihlen, ret = -EINVAL;
3689 struct iphdr _iph, *ih;
3690
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03003691 offset = skb_network_offset(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003692 ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph);
3693 if (ih == NULL)
3694 goto out;
3695
3696 ihlen = ih->ihl * 4;
3697 if (ihlen < sizeof(_iph))
3698 goto out;
3699
Eric Paris48c62af2012-04-02 13:15:44 -04003700 ad->u.net->v4info.saddr = ih->saddr;
3701 ad->u.net->v4info.daddr = ih->daddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003702 ret = 0;
3703
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003704 if (proto)
3705 *proto = ih->protocol;
3706
Linus Torvalds1da177e2005-04-16 15:20:36 -07003707 switch (ih->protocol) {
Eric Paris828dfe12008-04-17 13:17:49 -04003708 case IPPROTO_TCP: {
3709 struct tcphdr _tcph, *th;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003710
Eric Paris828dfe12008-04-17 13:17:49 -04003711 if (ntohs(ih->frag_off) & IP_OFFSET)
3712 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003713
3714 offset += ihlen;
3715 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
3716 if (th == NULL)
3717 break;
3718
Eric Paris48c62af2012-04-02 13:15:44 -04003719 ad->u.net->sport = th->source;
3720 ad->u.net->dport = th->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003721 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003722 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003723
Eric Paris828dfe12008-04-17 13:17:49 -04003724 case IPPROTO_UDP: {
3725 struct udphdr _udph, *uh;
3726
3727 if (ntohs(ih->frag_off) & IP_OFFSET)
3728 break;
3729
3730 offset += ihlen;
3731 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
3732 if (uh == NULL)
3733 break;
3734
Eric Paris48c62af2012-04-02 13:15:44 -04003735 ad->u.net->sport = uh->source;
3736 ad->u.net->dport = uh->dest;
Eric Paris828dfe12008-04-17 13:17:49 -04003737 break;
3738 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003739
James Morris2ee92d42006-11-13 16:09:01 -08003740 case IPPROTO_DCCP: {
3741 struct dccp_hdr _dccph, *dh;
3742
3743 if (ntohs(ih->frag_off) & IP_OFFSET)
3744 break;
3745
3746 offset += ihlen;
3747 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
3748 if (dh == NULL)
3749 break;
3750
Eric Paris48c62af2012-04-02 13:15:44 -04003751 ad->u.net->sport = dh->dccph_sport;
3752 ad->u.net->dport = dh->dccph_dport;
James Morris2ee92d42006-11-13 16:09:01 -08003753 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003754 }
James Morris2ee92d42006-11-13 16:09:01 -08003755
Eric Paris828dfe12008-04-17 13:17:49 -04003756 default:
3757 break;
3758 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003759out:
3760 return ret;
3761}
3762
3763#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
3764
3765/* Returns error only if unable to parse addresses */
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003766static int selinux_parse_skb_ipv6(struct sk_buff *skb,
Thomas Liu2bf49692009-07-14 12:14:09 -04003767 struct common_audit_data *ad, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003768{
3769 u8 nexthdr;
3770 int ret = -EINVAL, offset;
3771 struct ipv6hdr _ipv6h, *ip6;
Jesse Gross75f28112011-11-30 17:05:51 -08003772 __be16 frag_off;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003773
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03003774 offset = skb_network_offset(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003775 ip6 = skb_header_pointer(skb, offset, sizeof(_ipv6h), &_ipv6h);
3776 if (ip6 == NULL)
3777 goto out;
3778
Eric Paris48c62af2012-04-02 13:15:44 -04003779 ad->u.net->v6info.saddr = ip6->saddr;
3780 ad->u.net->v6info.daddr = ip6->daddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003781 ret = 0;
3782
3783 nexthdr = ip6->nexthdr;
3784 offset += sizeof(_ipv6h);
Jesse Gross75f28112011-11-30 17:05:51 -08003785 offset = ipv6_skip_exthdr(skb, offset, &nexthdr, &frag_off);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003786 if (offset < 0)
3787 goto out;
3788
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003789 if (proto)
3790 *proto = nexthdr;
3791
Linus Torvalds1da177e2005-04-16 15:20:36 -07003792 switch (nexthdr) {
3793 case IPPROTO_TCP: {
Eric Paris828dfe12008-04-17 13:17:49 -04003794 struct tcphdr _tcph, *th;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003795
3796 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
3797 if (th == NULL)
3798 break;
3799
Eric Paris48c62af2012-04-02 13:15:44 -04003800 ad->u.net->sport = th->source;
3801 ad->u.net->dport = th->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003802 break;
3803 }
3804
3805 case IPPROTO_UDP: {
3806 struct udphdr _udph, *uh;
3807
3808 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
3809 if (uh == NULL)
3810 break;
3811
Eric Paris48c62af2012-04-02 13:15:44 -04003812 ad->u.net->sport = uh->source;
3813 ad->u.net->dport = uh->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003814 break;
3815 }
3816
James Morris2ee92d42006-11-13 16:09:01 -08003817 case IPPROTO_DCCP: {
3818 struct dccp_hdr _dccph, *dh;
3819
3820 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
3821 if (dh == NULL)
3822 break;
3823
Eric Paris48c62af2012-04-02 13:15:44 -04003824 ad->u.net->sport = dh->dccph_sport;
3825 ad->u.net->dport = dh->dccph_dport;
James Morris2ee92d42006-11-13 16:09:01 -08003826 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003827 }
James Morris2ee92d42006-11-13 16:09:01 -08003828
Linus Torvalds1da177e2005-04-16 15:20:36 -07003829 /* includes fragments */
3830 default:
3831 break;
3832 }
3833out:
3834 return ret;
3835}
3836
3837#endif /* IPV6 */
3838
Thomas Liu2bf49692009-07-14 12:14:09 -04003839static int selinux_parse_skb(struct sk_buff *skb, struct common_audit_data *ad,
David Howellscf9481e2008-07-27 21:31:07 +10003840 char **_addrp, int src, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003841{
David Howellscf9481e2008-07-27 21:31:07 +10003842 char *addrp;
3843 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003844
Eric Paris48c62af2012-04-02 13:15:44 -04003845 switch (ad->u.net->family) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003846 case PF_INET:
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003847 ret = selinux_parse_skb_ipv4(skb, ad, proto);
David Howellscf9481e2008-07-27 21:31:07 +10003848 if (ret)
3849 goto parse_error;
Eric Paris48c62af2012-04-02 13:15:44 -04003850 addrp = (char *)(src ? &ad->u.net->v4info.saddr :
3851 &ad->u.net->v4info.daddr);
David Howellscf9481e2008-07-27 21:31:07 +10003852 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003853
3854#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
3855 case PF_INET6:
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003856 ret = selinux_parse_skb_ipv6(skb, ad, proto);
David Howellscf9481e2008-07-27 21:31:07 +10003857 if (ret)
3858 goto parse_error;
Eric Paris48c62af2012-04-02 13:15:44 -04003859 addrp = (char *)(src ? &ad->u.net->v6info.saddr :
3860 &ad->u.net->v6info.daddr);
David Howellscf9481e2008-07-27 21:31:07 +10003861 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003862#endif /* IPV6 */
3863 default:
David Howellscf9481e2008-07-27 21:31:07 +10003864 addrp = NULL;
3865 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003866 }
3867
David Howellscf9481e2008-07-27 21:31:07 +10003868parse_error:
3869 printk(KERN_WARNING
3870 "SELinux: failure in selinux_parse_skb(),"
3871 " unable to parse packet\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003872 return ret;
David Howellscf9481e2008-07-27 21:31:07 +10003873
3874okay:
3875 if (_addrp)
3876 *_addrp = addrp;
3877 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003878}
3879
Paul Moore4f6a9932007-03-01 14:35:22 -05003880/**
Paul Moore220deb92008-01-29 08:38:23 -05003881 * selinux_skb_peerlbl_sid - Determine the peer label of a packet
Paul Moore4f6a9932007-03-01 14:35:22 -05003882 * @skb: the packet
Paul Moore75e22912008-01-29 08:38:04 -05003883 * @family: protocol family
Paul Moore220deb92008-01-29 08:38:23 -05003884 * @sid: the packet's peer label SID
Paul Moore4f6a9932007-03-01 14:35:22 -05003885 *
3886 * Description:
Paul Moore220deb92008-01-29 08:38:23 -05003887 * Check the various different forms of network peer labeling and determine
3888 * the peer label/SID for the packet; most of the magic actually occurs in
3889 * the security server function security_net_peersid_cmp(). The function
3890 * returns zero if the value in @sid is valid (although it may be SECSID_NULL)
3891 * or -EACCES if @sid is invalid due to inconsistencies with the different
3892 * peer labels.
Paul Moore4f6a9932007-03-01 14:35:22 -05003893 *
3894 */
Paul Moore220deb92008-01-29 08:38:23 -05003895static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)
Paul Moore4f6a9932007-03-01 14:35:22 -05003896{
Paul Moore71f1cb02008-01-29 08:51:16 -05003897 int err;
Paul Moore4f6a9932007-03-01 14:35:22 -05003898 u32 xfrm_sid;
3899 u32 nlbl_sid;
Paul Moore220deb92008-01-29 08:38:23 -05003900 u32 nlbl_type;
Paul Moore4f6a9932007-03-01 14:35:22 -05003901
Paul Moore817eff72013-12-10 14:57:54 -05003902 err = selinux_xfrm_skb_sid(skb, &xfrm_sid);
Paul Moorebed4d7e2013-07-23 17:38:40 -04003903 if (unlikely(err))
3904 return -EACCES;
3905 err = selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid);
3906 if (unlikely(err))
3907 return -EACCES;
Paul Moore220deb92008-01-29 08:38:23 -05003908
Paul Moore71f1cb02008-01-29 08:51:16 -05003909 err = security_net_peersid_resolve(nlbl_sid, nlbl_type, xfrm_sid, sid);
3910 if (unlikely(err)) {
3911 printk(KERN_WARNING
3912 "SELinux: failure in selinux_skb_peerlbl_sid(),"
3913 " unable to determine packet's peer label\n");
Paul Moore220deb92008-01-29 08:38:23 -05003914 return -EACCES;
Paul Moore71f1cb02008-01-29 08:51:16 -05003915 }
Paul Moore220deb92008-01-29 08:38:23 -05003916
3917 return 0;
Paul Moore4f6a9932007-03-01 14:35:22 -05003918}
3919
Paul Moore446b8022013-12-04 16:10:51 -05003920/**
3921 * selinux_conn_sid - Determine the child socket label for a connection
3922 * @sk_sid: the parent socket's SID
3923 * @skb_sid: the packet's SID
3924 * @conn_sid: the resulting connection SID
3925 *
3926 * If @skb_sid is valid then the user:role:type information from @sk_sid is
3927 * combined with the MLS information from @skb_sid in order to create
3928 * @conn_sid. If @skb_sid is not valid then then @conn_sid is simply a copy
3929 * of @sk_sid. Returns zero on success, negative values on failure.
3930 *
3931 */
3932static int selinux_conn_sid(u32 sk_sid, u32 skb_sid, u32 *conn_sid)
3933{
3934 int err = 0;
3935
3936 if (skb_sid != SECSID_NULL)
3937 err = security_sid_mls_copy(sk_sid, skb_sid, conn_sid);
3938 else
3939 *conn_sid = sk_sid;
3940
3941 return err;
3942}
3943
Linus Torvalds1da177e2005-04-16 15:20:36 -07003944/* socket security operations */
Paul Moored4f2d972010-04-22 14:46:18 -04003945
Harry Ciao2ad18bd2011-03-02 13:32:34 +08003946static int socket_sockcreate_sid(const struct task_security_struct *tsec,
3947 u16 secclass, u32 *socksid)
Paul Moored4f2d972010-04-22 14:46:18 -04003948{
Harry Ciao2ad18bd2011-03-02 13:32:34 +08003949 if (tsec->sockcreate_sid > SECSID_NULL) {
3950 *socksid = tsec->sockcreate_sid;
3951 return 0;
3952 }
3953
3954 return security_transition_sid(tsec->sid, tsec->sid, secclass, NULL,
3955 socksid);
Paul Moored4f2d972010-04-22 14:46:18 -04003956}
3957
Paul Moore253bfae2010-04-22 14:46:19 -04003958static int sock_has_perm(struct task_struct *task, struct sock *sk, u32 perms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003959{
Paul Moore253bfae2010-04-22 14:46:19 -04003960 struct sk_security_struct *sksec = sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04003961 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04003962 struct lsm_network_audit net = {0,};
Paul Moore253bfae2010-04-22 14:46:19 -04003963 u32 tsid = task_sid(task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003964
Paul Moore253bfae2010-04-22 14:46:19 -04003965 if (sksec->sid == SECINITSID_KERNEL)
3966 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003967
Eric Paris50c205f2012-04-04 15:01:43 -04003968 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04003969 ad.u.net = &net;
3970 ad.u.net->sk = sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003971
Paul Moore253bfae2010-04-22 14:46:19 -04003972 return avc_has_perm(tsid, sksec->sid, sksec->sclass, perms, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003973}
3974
3975static int selinux_socket_create(int family, int type,
3976 int protocol, int kern)
3977{
Paul Moore5fb49872010-04-22 14:46:19 -04003978 const struct task_security_struct *tsec = current_security();
Paul Moored4f2d972010-04-22 14:46:18 -04003979 u32 newsid;
David Howells275bb412008-11-14 10:39:19 +11003980 u16 secclass;
Harry Ciao2ad18bd2011-03-02 13:32:34 +08003981 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003982
3983 if (kern)
Paul Moored4f2d972010-04-22 14:46:18 -04003984 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003985
David Howells275bb412008-11-14 10:39:19 +11003986 secclass = socket_type_to_security_class(family, type, protocol);
Harry Ciao2ad18bd2011-03-02 13:32:34 +08003987 rc = socket_sockcreate_sid(tsec, secclass, &newsid);
3988 if (rc)
3989 return rc;
3990
Paul Moored4f2d972010-04-22 14:46:18 -04003991 return avc_has_perm(tsec->sid, newsid, secclass, SOCKET__CREATE, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003992}
3993
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07003994static int selinux_socket_post_create(struct socket *sock, int family,
3995 int type, int protocol, int kern)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003996{
Paul Moore5fb49872010-04-22 14:46:19 -04003997 const struct task_security_struct *tsec = current_security();
Paul Moored4f2d972010-04-22 14:46:18 -04003998 struct inode_security_struct *isec = SOCK_INODE(sock)->i_security;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07003999 struct sk_security_struct *sksec;
David Howells275bb412008-11-14 10:39:19 +11004000 int err = 0;
4001
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004002 isec->sclass = socket_type_to_security_class(family, type, protocol);
4003
David Howells275bb412008-11-14 10:39:19 +11004004 if (kern)
4005 isec->sid = SECINITSID_KERNEL;
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004006 else {
4007 err = socket_sockcreate_sid(tsec, isec->sclass, &(isec->sid));
4008 if (err)
4009 return err;
4010 }
David Howells275bb412008-11-14 10:39:19 +11004011
Linus Torvalds1da177e2005-04-16 15:20:36 -07004012 isec->initialized = 1;
4013
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004014 if (sock->sk) {
4015 sksec = sock->sk->sk_security;
4016 sksec->sid = isec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05004017 sksec->sclass = isec->sclass;
Paul Moore389fb8002009-03-27 17:10:34 -04004018 err = selinux_netlbl_socket_post_create(sock->sk, family);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004019 }
4020
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07004021 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004022}
4023
4024/* Range of port numbers used to automatically bind.
4025 Need to determine whether we should perform a name_bind
4026 permission check between the socket and the port number. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004027
4028static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen)
4029{
Paul Moore253bfae2010-04-22 14:46:19 -04004030 struct sock *sk = sock->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004031 u16 family;
4032 int err;
4033
Paul Moore253bfae2010-04-22 14:46:19 -04004034 err = sock_has_perm(current, sk, SOCKET__BIND);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004035 if (err)
4036 goto out;
4037
4038 /*
4039 * If PF_INET or PF_INET6, check name_bind permission for the port.
James Morris13402582005-09-30 14:24:34 -04004040 * Multiple address binding for SCTP is not supported yet: we just
4041 * check the first address now.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004042 */
Paul Moore253bfae2010-04-22 14:46:19 -04004043 family = sk->sk_family;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004044 if (family == PF_INET || family == PF_INET6) {
4045 char *addrp;
Paul Moore253bfae2010-04-22 14:46:19 -04004046 struct sk_security_struct *sksec = sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004047 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004048 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004049 struct sockaddr_in *addr4 = NULL;
4050 struct sockaddr_in6 *addr6 = NULL;
4051 unsigned short snum;
James Morrise399f982008-06-12 01:39:58 +10004052 u32 sid, node_perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004053
Linus Torvalds1da177e2005-04-16 15:20:36 -07004054 if (family == PF_INET) {
4055 addr4 = (struct sockaddr_in *)address;
4056 snum = ntohs(addr4->sin_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004057 addrp = (char *)&addr4->sin_addr.s_addr;
4058 } else {
4059 addr6 = (struct sockaddr_in6 *)address;
4060 snum = ntohs(addr6->sin6_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004061 addrp = (char *)&addr6->sin6_addr.s6_addr;
4062 }
4063
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004064 if (snum) {
4065 int low, high;
4066
Eric W. Biederman0bbf87d2013-09-28 14:10:59 -07004067 inet_get_local_port_range(sock_net(sk), &low, &high);
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004068
4069 if (snum < max(PROT_SOCK, low) || snum > high) {
Paul Moore3e1121722008-04-10 10:48:14 -04004070 err = sel_netport_sid(sk->sk_protocol,
4071 snum, &sid);
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004072 if (err)
4073 goto out;
Eric Paris50c205f2012-04-04 15:01:43 -04004074 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004075 ad.u.net = &net;
4076 ad.u.net->sport = htons(snum);
4077 ad.u.net->family = family;
Paul Moore253bfae2010-04-22 14:46:19 -04004078 err = avc_has_perm(sksec->sid, sid,
4079 sksec->sclass,
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004080 SOCKET__NAME_BIND, &ad);
4081 if (err)
4082 goto out;
4083 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004084 }
Eric Paris828dfe12008-04-17 13:17:49 -04004085
Paul Moore253bfae2010-04-22 14:46:19 -04004086 switch (sksec->sclass) {
James Morris13402582005-09-30 14:24:34 -04004087 case SECCLASS_TCP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004088 node_perm = TCP_SOCKET__NODE_BIND;
4089 break;
Eric Paris828dfe12008-04-17 13:17:49 -04004090
James Morris13402582005-09-30 14:24:34 -04004091 case SECCLASS_UDP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004092 node_perm = UDP_SOCKET__NODE_BIND;
4093 break;
James Morris2ee92d42006-11-13 16:09:01 -08004094
4095 case SECCLASS_DCCP_SOCKET:
4096 node_perm = DCCP_SOCKET__NODE_BIND;
4097 break;
4098
Linus Torvalds1da177e2005-04-16 15:20:36 -07004099 default:
4100 node_perm = RAWIP_SOCKET__NODE_BIND;
4101 break;
4102 }
Eric Paris828dfe12008-04-17 13:17:49 -04004103
Paul Moore224dfbd2008-01-29 08:38:13 -05004104 err = sel_netnode_sid(addrp, family, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004105 if (err)
4106 goto out;
Eric Paris828dfe12008-04-17 13:17:49 -04004107
Eric Paris50c205f2012-04-04 15:01:43 -04004108 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004109 ad.u.net = &net;
4110 ad.u.net->sport = htons(snum);
4111 ad.u.net->family = family;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004112
4113 if (family == PF_INET)
Eric Paris48c62af2012-04-02 13:15:44 -04004114 ad.u.net->v4info.saddr = addr4->sin_addr.s_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004115 else
Eric Paris48c62af2012-04-02 13:15:44 -04004116 ad.u.net->v6info.saddr = addr6->sin6_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004117
Paul Moore253bfae2010-04-22 14:46:19 -04004118 err = avc_has_perm(sksec->sid, sid,
4119 sksec->sclass, node_perm, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004120 if (err)
4121 goto out;
4122 }
4123out:
4124 return err;
4125}
4126
4127static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen)
4128{
Paul Moore014ab192008-10-10 10:16:33 -04004129 struct sock *sk = sock->sk;
Paul Moore253bfae2010-04-22 14:46:19 -04004130 struct sk_security_struct *sksec = sk->sk_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004131 int err;
4132
Paul Moore253bfae2010-04-22 14:46:19 -04004133 err = sock_has_perm(current, sk, SOCKET__CONNECT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004134 if (err)
4135 return err;
4136
4137 /*
James Morris2ee92d42006-11-13 16:09:01 -08004138 * If a TCP or DCCP socket, check name_connect permission for the port.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004139 */
Paul Moore253bfae2010-04-22 14:46:19 -04004140 if (sksec->sclass == SECCLASS_TCP_SOCKET ||
4141 sksec->sclass == SECCLASS_DCCP_SOCKET) {
Thomas Liu2bf49692009-07-14 12:14:09 -04004142 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004143 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004144 struct sockaddr_in *addr4 = NULL;
4145 struct sockaddr_in6 *addr6 = NULL;
4146 unsigned short snum;
James Morris2ee92d42006-11-13 16:09:01 -08004147 u32 sid, perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004148
4149 if (sk->sk_family == PF_INET) {
4150 addr4 = (struct sockaddr_in *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07004151 if (addrlen < sizeof(struct sockaddr_in))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004152 return -EINVAL;
4153 snum = ntohs(addr4->sin_port);
4154 } else {
4155 addr6 = (struct sockaddr_in6 *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07004156 if (addrlen < SIN6_LEN_RFC2133)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004157 return -EINVAL;
4158 snum = ntohs(addr6->sin6_port);
4159 }
4160
Paul Moore3e1121722008-04-10 10:48:14 -04004161 err = sel_netport_sid(sk->sk_protocol, snum, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004162 if (err)
4163 goto out;
4164
Paul Moore253bfae2010-04-22 14:46:19 -04004165 perm = (sksec->sclass == SECCLASS_TCP_SOCKET) ?
James Morris2ee92d42006-11-13 16:09:01 -08004166 TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT;
4167
Eric Paris50c205f2012-04-04 15:01:43 -04004168 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004169 ad.u.net = &net;
4170 ad.u.net->dport = htons(snum);
4171 ad.u.net->family = sk->sk_family;
Paul Moore253bfae2010-04-22 14:46:19 -04004172 err = avc_has_perm(sksec->sid, sid, sksec->sclass, perm, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004173 if (err)
4174 goto out;
4175 }
4176
Paul Moore014ab192008-10-10 10:16:33 -04004177 err = selinux_netlbl_socket_connect(sk, address);
4178
Linus Torvalds1da177e2005-04-16 15:20:36 -07004179out:
4180 return err;
4181}
4182
4183static int selinux_socket_listen(struct socket *sock, int backlog)
4184{
Paul Moore253bfae2010-04-22 14:46:19 -04004185 return sock_has_perm(current, sock->sk, SOCKET__LISTEN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004186}
4187
4188static int selinux_socket_accept(struct socket *sock, struct socket *newsock)
4189{
4190 int err;
4191 struct inode_security_struct *isec;
4192 struct inode_security_struct *newisec;
4193
Paul Moore253bfae2010-04-22 14:46:19 -04004194 err = sock_has_perm(current, sock->sk, SOCKET__ACCEPT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004195 if (err)
4196 return err;
4197
4198 newisec = SOCK_INODE(newsock)->i_security;
4199
4200 isec = SOCK_INODE(sock)->i_security;
4201 newisec->sclass = isec->sclass;
4202 newisec->sid = isec->sid;
4203 newisec->initialized = 1;
4204
4205 return 0;
4206}
4207
4208static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg,
Eric Paris828dfe12008-04-17 13:17:49 -04004209 int size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004210{
Paul Moore253bfae2010-04-22 14:46:19 -04004211 return sock_has_perm(current, sock->sk, SOCKET__WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004212}
4213
4214static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg,
4215 int size, int flags)
4216{
Paul Moore253bfae2010-04-22 14:46:19 -04004217 return sock_has_perm(current, sock->sk, SOCKET__READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004218}
4219
4220static int selinux_socket_getsockname(struct socket *sock)
4221{
Paul Moore253bfae2010-04-22 14:46:19 -04004222 return sock_has_perm(current, sock->sk, SOCKET__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004223}
4224
4225static int selinux_socket_getpeername(struct socket *sock)
4226{
Paul Moore253bfae2010-04-22 14:46:19 -04004227 return sock_has_perm(current, sock->sk, SOCKET__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004228}
4229
Eric Paris828dfe12008-04-17 13:17:49 -04004230static int selinux_socket_setsockopt(struct socket *sock, int level, int optname)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004231{
Paul Mooref8687af2006-10-30 15:22:15 -08004232 int err;
4233
Paul Moore253bfae2010-04-22 14:46:19 -04004234 err = sock_has_perm(current, sock->sk, SOCKET__SETOPT);
Paul Mooref8687af2006-10-30 15:22:15 -08004235 if (err)
4236 return err;
4237
4238 return selinux_netlbl_socket_setsockopt(sock, level, optname);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004239}
4240
4241static int selinux_socket_getsockopt(struct socket *sock, int level,
4242 int optname)
4243{
Paul Moore253bfae2010-04-22 14:46:19 -04004244 return sock_has_perm(current, sock->sk, SOCKET__GETOPT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004245}
4246
4247static int selinux_socket_shutdown(struct socket *sock, int how)
4248{
Paul Moore253bfae2010-04-22 14:46:19 -04004249 return sock_has_perm(current, sock->sk, SOCKET__SHUTDOWN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004250}
4251
David S. Miller3610cda2011-01-05 15:38:53 -08004252static int selinux_socket_unix_stream_connect(struct sock *sock,
4253 struct sock *other,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004254 struct sock *newsk)
4255{
David S. Miller3610cda2011-01-05 15:38:53 -08004256 struct sk_security_struct *sksec_sock = sock->sk_security;
4257 struct sk_security_struct *sksec_other = other->sk_security;
Paul Moore4d1e2452010-04-22 14:46:18 -04004258 struct sk_security_struct *sksec_new = newsk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004259 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004260 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004261 int err;
4262
Eric Paris50c205f2012-04-04 15:01:43 -04004263 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004264 ad.u.net = &net;
4265 ad.u.net->sk = other;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004266
Paul Moore4d1e2452010-04-22 14:46:18 -04004267 err = avc_has_perm(sksec_sock->sid, sksec_other->sid,
4268 sksec_other->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004269 UNIX_STREAM_SOCKET__CONNECTTO, &ad);
4270 if (err)
4271 return err;
4272
Linus Torvalds1da177e2005-04-16 15:20:36 -07004273 /* server child socket */
Paul Moore4d1e2452010-04-22 14:46:18 -04004274 sksec_new->peer_sid = sksec_sock->sid;
4275 err = security_sid_mls_copy(sksec_other->sid, sksec_sock->sid,
4276 &sksec_new->sid);
4277 if (err)
4278 return err;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004279
Paul Moore4d1e2452010-04-22 14:46:18 -04004280 /* connecting socket */
4281 sksec_sock->peer_sid = sksec_new->sid;
4282
4283 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004284}
4285
4286static int selinux_socket_unix_may_send(struct socket *sock,
4287 struct socket *other)
4288{
Paul Moore253bfae2010-04-22 14:46:19 -04004289 struct sk_security_struct *ssec = sock->sk->sk_security;
4290 struct sk_security_struct *osec = other->sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004291 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004292 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004293
Eric Paris50c205f2012-04-04 15:01:43 -04004294 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004295 ad.u.net = &net;
4296 ad.u.net->sk = other->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004297
Paul Moore253bfae2010-04-22 14:46:19 -04004298 return avc_has_perm(ssec->sid, osec->sid, osec->sclass, SOCKET__SENDTO,
4299 &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004300}
4301
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004302static int selinux_inet_sys_rcv_skb(struct net *ns, int ifindex,
4303 char *addrp, u16 family, u32 peer_sid,
Thomas Liu2bf49692009-07-14 12:14:09 -04004304 struct common_audit_data *ad)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004305{
4306 int err;
4307 u32 if_sid;
4308 u32 node_sid;
4309
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004310 err = sel_netif_sid(ns, ifindex, &if_sid);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004311 if (err)
4312 return err;
4313 err = avc_has_perm(peer_sid, if_sid,
4314 SECCLASS_NETIF, NETIF__INGRESS, ad);
4315 if (err)
4316 return err;
4317
4318 err = sel_netnode_sid(addrp, family, &node_sid);
4319 if (err)
4320 return err;
4321 return avc_has_perm(peer_sid, node_sid,
4322 SECCLASS_NODE, NODE__RECVFROM, ad);
4323}
4324
Paul Moore220deb92008-01-29 08:38:23 -05004325static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
Paul Moored8395c82008-10-10 10:16:30 -04004326 u16 family)
Paul Moore220deb92008-01-29 08:38:23 -05004327{
Paul Moore277d3422008-12-31 12:54:11 -05004328 int err = 0;
Paul Moore220deb92008-01-29 08:38:23 -05004329 struct sk_security_struct *sksec = sk->sk_security;
Paul Moore220deb92008-01-29 08:38:23 -05004330 u32 sk_sid = sksec->sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04004331 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004332 struct lsm_network_audit net = {0,};
Paul Moored8395c82008-10-10 10:16:30 -04004333 char *addrp;
4334
Eric Paris50c205f2012-04-04 15:01:43 -04004335 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004336 ad.u.net = &net;
4337 ad.u.net->netif = skb->skb_iif;
4338 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04004339 err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
4340 if (err)
4341 return err;
Paul Moore220deb92008-01-29 08:38:23 -05004342
Paul Moore58bfbb52009-03-27 17:10:41 -04004343 if (selinux_secmark_enabled()) {
Paul Moore220deb92008-01-29 08:38:23 -05004344 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
Paul Moored8395c82008-10-10 10:16:30 -04004345 PACKET__RECV, &ad);
Paul Moore58bfbb52009-03-27 17:10:41 -04004346 if (err)
4347 return err;
4348 }
Paul Moore220deb92008-01-29 08:38:23 -05004349
Steffen Klassertb9679a72011-02-23 12:55:21 +01004350 err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, &ad);
4351 if (err)
4352 return err;
4353 err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, &ad);
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004354
James Morris4e5ab4c2006-06-09 00:33:33 -07004355 return err;
4356}
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004357
James Morris4e5ab4c2006-06-09 00:33:33 -07004358static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
4359{
Paul Moore220deb92008-01-29 08:38:23 -05004360 int err;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004361 struct sk_security_struct *sksec = sk->sk_security;
Paul Moore220deb92008-01-29 08:38:23 -05004362 u16 family = sk->sk_family;
4363 u32 sk_sid = sksec->sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04004364 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004365 struct lsm_network_audit net = {0,};
Paul Moore220deb92008-01-29 08:38:23 -05004366 char *addrp;
Paul Moored8395c82008-10-10 10:16:30 -04004367 u8 secmark_active;
4368 u8 peerlbl_active;
James Morris4e5ab4c2006-06-09 00:33:33 -07004369
James Morris4e5ab4c2006-06-09 00:33:33 -07004370 if (family != PF_INET && family != PF_INET6)
Paul Moore220deb92008-01-29 08:38:23 -05004371 return 0;
James Morris4e5ab4c2006-06-09 00:33:33 -07004372
4373 /* Handle mapped IPv4 packets arriving via IPv6 sockets */
Al Viro87fcd702006-12-04 22:00:55 +00004374 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
James Morris4e5ab4c2006-06-09 00:33:33 -07004375 family = PF_INET;
4376
Paul Moored8395c82008-10-10 10:16:30 -04004377 /* If any sort of compatibility mode is enabled then handoff processing
4378 * to the selinux_sock_rcv_skb_compat() function to deal with the
4379 * special handling. We do this in an attempt to keep this function
4380 * as fast and as clean as possible. */
Paul Moore58bfbb52009-03-27 17:10:41 -04004381 if (!selinux_policycap_netpeer)
Paul Moored8395c82008-10-10 10:16:30 -04004382 return selinux_sock_rcv_skb_compat(sk, skb, family);
4383
4384 secmark_active = selinux_secmark_enabled();
Chris PeBenito2be4d742013-05-03 09:05:39 -04004385 peerlbl_active = selinux_peerlbl_enabled();
Paul Moored8395c82008-10-10 10:16:30 -04004386 if (!secmark_active && !peerlbl_active)
4387 return 0;
4388
Eric Paris50c205f2012-04-04 15:01:43 -04004389 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004390 ad.u.net = &net;
4391 ad.u.net->netif = skb->skb_iif;
4392 ad.u.net->family = family;
Paul Moore224dfbd2008-01-29 08:38:13 -05004393 err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
James Morris4e5ab4c2006-06-09 00:33:33 -07004394 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05004395 return err;
James Morris4e5ab4c2006-06-09 00:33:33 -07004396
Paul Moored8395c82008-10-10 10:16:30 -04004397 if (peerlbl_active) {
Paul Moored621d352008-01-29 08:43:36 -05004398 u32 peer_sid;
4399
4400 err = selinux_skb_peerlbl_sid(skb, family, &peer_sid);
4401 if (err)
4402 return err;
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004403 err = selinux_inet_sys_rcv_skb(sock_net(sk), skb->skb_iif,
4404 addrp, family, peer_sid, &ad);
Paul Mooredfaebe92008-10-10 10:16:31 -04004405 if (err) {
4406 selinux_netlbl_err(skb, err, 0);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004407 return err;
Paul Mooredfaebe92008-10-10 10:16:31 -04004408 }
Paul Moored621d352008-01-29 08:43:36 -05004409 err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER,
4410 PEER__RECV, &ad);
Chad Hanson46d01d62013-12-23 17:45:01 -05004411 if (err) {
Paul Mooredfaebe92008-10-10 10:16:31 -04004412 selinux_netlbl_err(skb, err, 0);
Chad Hanson46d01d62013-12-23 17:45:01 -05004413 return err;
4414 }
Paul Moored621d352008-01-29 08:43:36 -05004415 }
4416
Paul Moored8395c82008-10-10 10:16:30 -04004417 if (secmark_active) {
Paul Mooreeffad8d2008-01-29 08:49:27 -05004418 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
4419 PACKET__RECV, &ad);
4420 if (err)
4421 return err;
4422 }
4423
Paul Moored621d352008-01-29 08:43:36 -05004424 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004425}
4426
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004427static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *optval,
4428 int __user *optlen, unsigned len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004429{
4430 int err = 0;
4431 char *scontext;
4432 u32 scontext_len;
Paul Moore253bfae2010-04-22 14:46:19 -04004433 struct sk_security_struct *sksec = sock->sk->sk_security;
Paul Moore3de4bab2006-11-17 17:38:54 -05004434 u32 peer_sid = SECSID_NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004435
Paul Moore253bfae2010-04-22 14:46:19 -04004436 if (sksec->sclass == SECCLASS_UNIX_STREAM_SOCKET ||
4437 sksec->sclass == SECCLASS_TCP_SOCKET)
Eric Parisdd3e7832010-04-07 15:08:46 -04004438 peer_sid = sksec->peer_sid;
Paul Moore253bfae2010-04-22 14:46:19 -04004439 if (peer_sid == SECSID_NULL)
4440 return -ENOPROTOOPT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004441
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004442 err = security_sid_to_context(peer_sid, &scontext, &scontext_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004443 if (err)
Paul Moore253bfae2010-04-22 14:46:19 -04004444 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004445
4446 if (scontext_len > len) {
4447 err = -ERANGE;
4448 goto out_len;
4449 }
4450
4451 if (copy_to_user(optval, scontext, scontext_len))
4452 err = -EFAULT;
4453
4454out_len:
4455 if (put_user(scontext_len, optlen))
4456 err = -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004457 kfree(scontext);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004458 return err;
4459}
4460
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004461static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid)
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004462{
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004463 u32 peer_secid = SECSID_NULL;
Paul Moore75e22912008-01-29 08:38:04 -05004464 u16 family;
Catherine Zhang877ce7c2006-06-29 12:27:47 -07004465
Paul Mooreaa862902008-10-10 10:16:29 -04004466 if (skb && skb->protocol == htons(ETH_P_IP))
4467 family = PF_INET;
4468 else if (skb && skb->protocol == htons(ETH_P_IPV6))
4469 family = PF_INET6;
4470 else if (sock)
Paul Moore75e22912008-01-29 08:38:04 -05004471 family = sock->sk->sk_family;
Paul Moore75e22912008-01-29 08:38:04 -05004472 else
4473 goto out;
4474
4475 if (sock && family == PF_UNIX)
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02004476 selinux_inode_getsecid(SOCK_INODE(sock), &peer_secid);
Paul Moore3de4bab2006-11-17 17:38:54 -05004477 else if (skb)
Paul Moore220deb92008-01-29 08:38:23 -05004478 selinux_skb_peerlbl_sid(skb, family, &peer_secid);
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004479
Paul Moore75e22912008-01-29 08:38:04 -05004480out:
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004481 *secid = peer_secid;
Paul Moore75e22912008-01-29 08:38:04 -05004482 if (peer_secid == SECSID_NULL)
4483 return -EINVAL;
4484 return 0;
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004485}
4486
Al Viro7d877f32005-10-21 03:20:43 -04004487static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004488{
Paul Moore84914b72010-04-22 14:46:18 -04004489 struct sk_security_struct *sksec;
4490
4491 sksec = kzalloc(sizeof(*sksec), priority);
4492 if (!sksec)
4493 return -ENOMEM;
4494
4495 sksec->peer_sid = SECINITSID_UNLABELED;
4496 sksec->sid = SECINITSID_UNLABELED;
4497 selinux_netlbl_sk_security_reset(sksec);
4498 sk->sk_security = sksec;
4499
4500 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004501}
4502
4503static void selinux_sk_free_security(struct sock *sk)
4504{
Paul Moore84914b72010-04-22 14:46:18 -04004505 struct sk_security_struct *sksec = sk->sk_security;
4506
4507 sk->sk_security = NULL;
4508 selinux_netlbl_sk_security_free(sksec);
4509 kfree(sksec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004510}
4511
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004512static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk)
4513{
Eric Parisdd3e7832010-04-07 15:08:46 -04004514 struct sk_security_struct *sksec = sk->sk_security;
4515 struct sk_security_struct *newsksec = newsk->sk_security;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004516
Eric Parisdd3e7832010-04-07 15:08:46 -04004517 newsksec->sid = sksec->sid;
4518 newsksec->peer_sid = sksec->peer_sid;
4519 newsksec->sclass = sksec->sclass;
Paul Moore99f59ed2006-08-29 17:53:48 -07004520
Eric Parisdd3e7832010-04-07 15:08:46 -04004521 selinux_netlbl_sk_security_reset(newsksec);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004522}
4523
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004524static void selinux_sk_getsecid(struct sock *sk, u32 *secid)
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004525{
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004526 if (!sk)
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004527 *secid = SECINITSID_ANY_SOCKET;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004528 else {
4529 struct sk_security_struct *sksec = sk->sk_security;
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004530
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004531 *secid = sksec->sid;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004532 }
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004533}
4534
Eric Paris828dfe12008-04-17 13:17:49 -04004535static void selinux_sock_graft(struct sock *sk, struct socket *parent)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004536{
4537 struct inode_security_struct *isec = SOCK_INODE(parent)->i_security;
4538 struct sk_security_struct *sksec = sk->sk_security;
4539
Paul Moore2873ead2014-07-28 10:42:48 -04004540 if (sk->sk_family == PF_INET || sk->sk_family == PF_INET6 ||
4541 sk->sk_family == PF_UNIX)
David Woodhouse2148ccc2006-09-29 15:50:25 -07004542 isec->sid = sksec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05004543 sksec->sclass = isec->sclass;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004544}
4545
Adrian Bunk9a673e52006-08-15 00:03:53 -07004546static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
4547 struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004548{
4549 struct sk_security_struct *sksec = sk->sk_security;
4550 int err;
Paul Moore0b1f24e2013-12-03 11:39:13 -05004551 u16 family = req->rsk_ops->family;
Paul Moore446b8022013-12-04 16:10:51 -05004552 u32 connsid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004553 u32 peersid;
4554
Paul Mooreaa862902008-10-10 10:16:29 -04004555 err = selinux_skb_peerlbl_sid(skb, family, &peersid);
Paul Moore220deb92008-01-29 08:38:23 -05004556 if (err)
4557 return err;
Paul Moore446b8022013-12-04 16:10:51 -05004558 err = selinux_conn_sid(sksec->sid, peersid, &connsid);
4559 if (err)
4560 return err;
4561 req->secid = connsid;
4562 req->peer_secid = peersid;
Venkat Yekkiralaa51c64f2006-07-27 22:01:34 -07004563
Paul Moore389fb8002009-03-27 17:10:34 -04004564 return selinux_netlbl_inet_conn_request(req, family);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004565}
4566
Adrian Bunk9a673e52006-08-15 00:03:53 -07004567static void selinux_inet_csk_clone(struct sock *newsk,
4568 const struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004569{
4570 struct sk_security_struct *newsksec = newsk->sk_security;
4571
4572 newsksec->sid = req->secid;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004573 newsksec->peer_sid = req->peer_secid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004574 /* NOTE: Ideally, we should also get the isec->sid for the
4575 new socket in sync, but we don't have the isec available yet.
4576 So we will wait until sock_graft to do it, by which
4577 time it will have been created and available. */
Paul Moore99f59ed2006-08-29 17:53:48 -07004578
Paul Moore9f2ad662006-11-17 17:38:53 -05004579 /* We don't need to take any sort of lock here as we are the only
4580 * thread with access to newsksec */
Paul Moore389fb8002009-03-27 17:10:34 -04004581 selinux_netlbl_inet_csk_clone(newsk, req->rsk_ops->family);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004582}
4583
Paul Moore014ab192008-10-10 10:16:33 -04004584static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb)
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004585{
Paul Mooreaa862902008-10-10 10:16:29 -04004586 u16 family = sk->sk_family;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004587 struct sk_security_struct *sksec = sk->sk_security;
4588
Paul Mooreaa862902008-10-10 10:16:29 -04004589 /* handle mapped IPv4 packets arriving via IPv6 sockets */
4590 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
4591 family = PF_INET;
4592
4593 selinux_skb_peerlbl_sid(skb, family, &sksec->peer_sid);
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004594}
4595
Eric Dumazetca10b9e2013-04-08 17:58:11 +00004596static void selinux_skb_owned_by(struct sk_buff *skb, struct sock *sk)
4597{
4598 skb_set_owner_w(skb, sk);
4599}
4600
Eric Paris2606fd12010-10-13 16:24:41 -04004601static int selinux_secmark_relabel_packet(u32 sid)
4602{
4603 const struct task_security_struct *__tsec;
4604 u32 tsid;
4605
4606 __tsec = current_security();
4607 tsid = __tsec->sid;
4608
4609 return avc_has_perm(tsid, sid, SECCLASS_PACKET, PACKET__RELABELTO, NULL);
4610}
4611
4612static void selinux_secmark_refcount_inc(void)
4613{
4614 atomic_inc(&selinux_secmark_refcount);
4615}
4616
4617static void selinux_secmark_refcount_dec(void)
4618{
4619 atomic_dec(&selinux_secmark_refcount);
4620}
4621
Adrian Bunk9a673e52006-08-15 00:03:53 -07004622static void selinux_req_classify_flow(const struct request_sock *req,
4623 struct flowi *fl)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004624{
David S. Miller1d28f422011-03-12 00:29:39 -05004625 fl->flowi_secid = req->secid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004626}
4627
Paul Moore5dbbaf22013-01-14 07:12:19 +00004628static int selinux_tun_dev_alloc_security(void **security)
4629{
4630 struct tun_security_struct *tunsec;
4631
4632 tunsec = kzalloc(sizeof(*tunsec), GFP_KERNEL);
4633 if (!tunsec)
4634 return -ENOMEM;
4635 tunsec->sid = current_sid();
4636
4637 *security = tunsec;
4638 return 0;
4639}
4640
4641static void selinux_tun_dev_free_security(void *security)
4642{
4643 kfree(security);
4644}
4645
Paul Mooreed6d76e2009-08-28 18:12:49 -04004646static int selinux_tun_dev_create(void)
4647{
4648 u32 sid = current_sid();
4649
4650 /* we aren't taking into account the "sockcreate" SID since the socket
4651 * that is being created here is not a socket in the traditional sense,
4652 * instead it is a private sock, accessible only to the kernel, and
4653 * representing a wide range of network traffic spanning multiple
4654 * connections unlike traditional sockets - check the TUN driver to
4655 * get a better understanding of why this socket is special */
4656
4657 return avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET, TUN_SOCKET__CREATE,
4658 NULL);
4659}
4660
Paul Moore5dbbaf22013-01-14 07:12:19 +00004661static int selinux_tun_dev_attach_queue(void *security)
Paul Mooreed6d76e2009-08-28 18:12:49 -04004662{
Paul Moore5dbbaf22013-01-14 07:12:19 +00004663 struct tun_security_struct *tunsec = security;
4664
4665 return avc_has_perm(current_sid(), tunsec->sid, SECCLASS_TUN_SOCKET,
4666 TUN_SOCKET__ATTACH_QUEUE, NULL);
4667}
4668
4669static int selinux_tun_dev_attach(struct sock *sk, void *security)
4670{
4671 struct tun_security_struct *tunsec = security;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004672 struct sk_security_struct *sksec = sk->sk_security;
4673
4674 /* we don't currently perform any NetLabel based labeling here and it
4675 * isn't clear that we would want to do so anyway; while we could apply
4676 * labeling without the support of the TUN user the resulting labeled
4677 * traffic from the other end of the connection would almost certainly
4678 * cause confusion to the TUN user that had no idea network labeling
4679 * protocols were being used */
4680
Paul Moore5dbbaf22013-01-14 07:12:19 +00004681 sksec->sid = tunsec->sid;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004682 sksec->sclass = SECCLASS_TUN_SOCKET;
Paul Moore5dbbaf22013-01-14 07:12:19 +00004683
4684 return 0;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004685}
4686
Paul Moore5dbbaf22013-01-14 07:12:19 +00004687static int selinux_tun_dev_open(void *security)
Paul Mooreed6d76e2009-08-28 18:12:49 -04004688{
Paul Moore5dbbaf22013-01-14 07:12:19 +00004689 struct tun_security_struct *tunsec = security;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004690 u32 sid = current_sid();
4691 int err;
4692
Paul Moore5dbbaf22013-01-14 07:12:19 +00004693 err = avc_has_perm(sid, tunsec->sid, SECCLASS_TUN_SOCKET,
Paul Mooreed6d76e2009-08-28 18:12:49 -04004694 TUN_SOCKET__RELABELFROM, NULL);
4695 if (err)
4696 return err;
4697 err = avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET,
4698 TUN_SOCKET__RELABELTO, NULL);
4699 if (err)
4700 return err;
Paul Moore5dbbaf22013-01-14 07:12:19 +00004701 tunsec->sid = sid;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004702
4703 return 0;
4704}
4705
Linus Torvalds1da177e2005-04-16 15:20:36 -07004706static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
4707{
4708 int err = 0;
4709 u32 perm;
4710 struct nlmsghdr *nlh;
Paul Moore253bfae2010-04-22 14:46:19 -04004711 struct sk_security_struct *sksec = sk->sk_security;
Eric Paris828dfe12008-04-17 13:17:49 -04004712
Hong zhi guo77954982013-03-27 06:49:35 +00004713 if (skb->len < NLMSG_HDRLEN) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004714 err = -EINVAL;
4715 goto out;
4716 }
Arnaldo Carvalho de Melob529ccf2007-04-25 19:08:35 -07004717 nlh = nlmsg_hdr(skb);
Eric Paris828dfe12008-04-17 13:17:49 -04004718
Paul Moore253bfae2010-04-22 14:46:19 -04004719 err = selinux_nlmsg_lookup(sksec->sclass, nlh->nlmsg_type, &perm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004720 if (err) {
4721 if (err == -EINVAL) {
Richard Guy Briggsd950f842014-11-12 14:01:34 -05004722 printk(KERN_WARNING
4723 "SELinux: unrecognized netlink message:"
4724 " protocol=%hu nlmsg_type=%hu sclass=%hu\n",
4725 sk->sk_protocol, nlh->nlmsg_type, sksec->sclass);
Eric Paris39c9aed2008-11-05 09:34:42 -05004726 if (!selinux_enforcing || security_get_allow_unknown())
Linus Torvalds1da177e2005-04-16 15:20:36 -07004727 err = 0;
4728 }
4729
4730 /* Ignore */
4731 if (err == -ENOENT)
4732 err = 0;
4733 goto out;
4734 }
4735
Paul Moore253bfae2010-04-22 14:46:19 -04004736 err = sock_has_perm(current, sk, perm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004737out:
4738 return err;
4739}
4740
4741#ifdef CONFIG_NETFILTER
4742
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004743static unsigned int selinux_ip_forward(struct sk_buff *skb,
4744 const struct net_device *indev,
Paul Mooreeffad8d2008-01-29 08:49:27 -05004745 u16 family)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004746{
Paul Mooredfaebe92008-10-10 10:16:31 -04004747 int err;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004748 char *addrp;
4749 u32 peer_sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04004750 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004751 struct lsm_network_audit net = {0,};
Paul Mooreeffad8d2008-01-29 08:49:27 -05004752 u8 secmark_active;
Paul Moore948bf852008-10-10 10:16:32 -04004753 u8 netlbl_active;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004754 u8 peerlbl_active;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004755
Paul Mooreeffad8d2008-01-29 08:49:27 -05004756 if (!selinux_policycap_netpeer)
4757 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004758
Paul Mooreeffad8d2008-01-29 08:49:27 -05004759 secmark_active = selinux_secmark_enabled();
Paul Moore948bf852008-10-10 10:16:32 -04004760 netlbl_active = netlbl_enabled();
Chris PeBenito2be4d742013-05-03 09:05:39 -04004761 peerlbl_active = selinux_peerlbl_enabled();
Paul Mooreeffad8d2008-01-29 08:49:27 -05004762 if (!secmark_active && !peerlbl_active)
4763 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004764
Paul Moored8395c82008-10-10 10:16:30 -04004765 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0)
4766 return NF_DROP;
4767
Eric Paris50c205f2012-04-04 15:01:43 -04004768 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004769 ad.u.net = &net;
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004770 ad.u.net->netif = indev->ifindex;
Eric Paris48c62af2012-04-02 13:15:44 -04004771 ad.u.net->family = family;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004772 if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0)
4773 return NF_DROP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004774
Paul Mooredfaebe92008-10-10 10:16:31 -04004775 if (peerlbl_active) {
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004776 err = selinux_inet_sys_rcv_skb(dev_net(indev), indev->ifindex,
4777 addrp, family, peer_sid, &ad);
Paul Mooredfaebe92008-10-10 10:16:31 -04004778 if (err) {
4779 selinux_netlbl_err(skb, err, 1);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004780 return NF_DROP;
Paul Mooredfaebe92008-10-10 10:16:31 -04004781 }
4782 }
Paul Mooreeffad8d2008-01-29 08:49:27 -05004783
4784 if (secmark_active)
4785 if (avc_has_perm(peer_sid, skb->secmark,
4786 SECCLASS_PACKET, PACKET__FORWARD_IN, &ad))
4787 return NF_DROP;
4788
Paul Moore948bf852008-10-10 10:16:32 -04004789 if (netlbl_active)
4790 /* we do this in the FORWARD path and not the POST_ROUTING
4791 * path because we want to make sure we apply the necessary
4792 * labeling before IPsec is applied so we can leverage AH
4793 * protection */
4794 if (selinux_netlbl_skbuff_setsid(skb, family, peer_sid) != 0)
4795 return NF_DROP;
4796
Paul Mooreeffad8d2008-01-29 08:49:27 -05004797 return NF_ACCEPT;
4798}
4799
Patrick McHardy795aa6e2013-10-10 09:21:55 +02004800static unsigned int selinux_ipv4_forward(const struct nf_hook_ops *ops,
Paul Mooreeffad8d2008-01-29 08:49:27 -05004801 struct sk_buff *skb,
4802 const struct net_device *in,
4803 const struct net_device *out,
4804 int (*okfn)(struct sk_buff *))
4805{
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004806 return selinux_ip_forward(skb, in, PF_INET);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004807}
4808
4809#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Patrick McHardy795aa6e2013-10-10 09:21:55 +02004810static unsigned int selinux_ipv6_forward(const struct nf_hook_ops *ops,
Paul Mooreeffad8d2008-01-29 08:49:27 -05004811 struct sk_buff *skb,
4812 const struct net_device *in,
4813 const struct net_device *out,
4814 int (*okfn)(struct sk_buff *))
4815{
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004816 return selinux_ip_forward(skb, in, PF_INET6);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004817}
4818#endif /* IPV6 */
4819
Paul Moore948bf852008-10-10 10:16:32 -04004820static unsigned int selinux_ip_output(struct sk_buff *skb,
4821 u16 family)
4822{
Paul Moore47180062013-12-04 16:10:45 -05004823 struct sock *sk;
Paul Moore948bf852008-10-10 10:16:32 -04004824 u32 sid;
4825
4826 if (!netlbl_enabled())
4827 return NF_ACCEPT;
4828
4829 /* we do this in the LOCAL_OUT path and not the POST_ROUTING path
4830 * because we want to make sure we apply the necessary labeling
4831 * before IPsec is applied so we can leverage AH protection */
Paul Moore47180062013-12-04 16:10:45 -05004832 sk = skb->sk;
4833 if (sk) {
4834 struct sk_security_struct *sksec;
4835
4836 if (sk->sk_state == TCP_LISTEN)
4837 /* if the socket is the listening state then this
4838 * packet is a SYN-ACK packet which means it needs to
4839 * be labeled based on the connection/request_sock and
4840 * not the parent socket. unfortunately, we can't
4841 * lookup the request_sock yet as it isn't queued on
4842 * the parent socket until after the SYN-ACK is sent.
4843 * the "solution" is to simply pass the packet as-is
4844 * as any IP option based labeling should be copied
4845 * from the initial connection request (in the IP
4846 * layer). it is far from ideal, but until we get a
4847 * security label in the packet itself this is the
4848 * best we can do. */
4849 return NF_ACCEPT;
4850
4851 /* standard practice, label using the parent socket */
4852 sksec = sk->sk_security;
Paul Moore948bf852008-10-10 10:16:32 -04004853 sid = sksec->sid;
4854 } else
4855 sid = SECINITSID_KERNEL;
4856 if (selinux_netlbl_skbuff_setsid(skb, family, sid) != 0)
4857 return NF_DROP;
4858
4859 return NF_ACCEPT;
4860}
4861
Patrick McHardy795aa6e2013-10-10 09:21:55 +02004862static unsigned int selinux_ipv4_output(const struct nf_hook_ops *ops,
Paul Moore948bf852008-10-10 10:16:32 -04004863 struct sk_buff *skb,
4864 const struct net_device *in,
4865 const struct net_device *out,
4866 int (*okfn)(struct sk_buff *))
4867{
4868 return selinux_ip_output(skb, PF_INET);
4869}
4870
Paul Mooreeffad8d2008-01-29 08:49:27 -05004871static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
4872 int ifindex,
Paul Moored8395c82008-10-10 10:16:30 -04004873 u16 family)
James Morris4e5ab4c2006-06-09 00:33:33 -07004874{
Paul Mooreeffad8d2008-01-29 08:49:27 -05004875 struct sock *sk = skb->sk;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004876 struct sk_security_struct *sksec;
Thomas Liu2bf49692009-07-14 12:14:09 -04004877 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004878 struct lsm_network_audit net = {0,};
Paul Moored8395c82008-10-10 10:16:30 -04004879 char *addrp;
4880 u8 proto;
James Morris4e5ab4c2006-06-09 00:33:33 -07004881
Paul Mooreeffad8d2008-01-29 08:49:27 -05004882 if (sk == NULL)
4883 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004884 sksec = sk->sk_security;
James Morris4e5ab4c2006-06-09 00:33:33 -07004885
Eric Paris50c205f2012-04-04 15:01:43 -04004886 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004887 ad.u.net = &net;
4888 ad.u.net->netif = ifindex;
4889 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04004890 if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto))
4891 return NF_DROP;
4892
Paul Moore58bfbb52009-03-27 17:10:41 -04004893 if (selinux_secmark_enabled())
Paul Mooreeffad8d2008-01-29 08:49:27 -05004894 if (avc_has_perm(sksec->sid, skb->secmark,
Paul Moored8395c82008-10-10 10:16:30 -04004895 SECCLASS_PACKET, PACKET__SEND, &ad))
Eric Paris2fe66ec2010-11-23 06:28:08 +00004896 return NF_DROP_ERR(-ECONNREFUSED);
James Morris4e5ab4c2006-06-09 00:33:33 -07004897
Steffen Klassertb9679a72011-02-23 12:55:21 +01004898 if (selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto))
4899 return NF_DROP_ERR(-ECONNREFUSED);
James Morris4e5ab4c2006-06-09 00:33:33 -07004900
Paul Mooreeffad8d2008-01-29 08:49:27 -05004901 return NF_ACCEPT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004902}
4903
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004904static unsigned int selinux_ip_postroute(struct sk_buff *skb,
4905 const struct net_device *outdev,
Paul Mooreeffad8d2008-01-29 08:49:27 -05004906 u16 family)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004907{
Paul Mooreeffad8d2008-01-29 08:49:27 -05004908 u32 secmark_perm;
4909 u32 peer_sid;
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004910 int ifindex = outdev->ifindex;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004911 struct sock *sk;
Thomas Liu2bf49692009-07-14 12:14:09 -04004912 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004913 struct lsm_network_audit net = {0,};
Paul Mooreeffad8d2008-01-29 08:49:27 -05004914 char *addrp;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004915 u8 secmark_active;
4916 u8 peerlbl_active;
4917
Paul Mooreeffad8d2008-01-29 08:49:27 -05004918 /* If any sort of compatibility mode is enabled then handoff processing
4919 * to the selinux_ip_postroute_compat() function to deal with the
4920 * special handling. We do this in an attempt to keep this function
4921 * as fast and as clean as possible. */
Paul Moore58bfbb52009-03-27 17:10:41 -04004922 if (!selinux_policycap_netpeer)
Paul Moored8395c82008-10-10 10:16:30 -04004923 return selinux_ip_postroute_compat(skb, ifindex, family);
Paul Moorec0828e52013-12-10 14:58:01 -05004924
Paul Mooreeffad8d2008-01-29 08:49:27 -05004925 secmark_active = selinux_secmark_enabled();
Chris PeBenito2be4d742013-05-03 09:05:39 -04004926 peerlbl_active = selinux_peerlbl_enabled();
Paul Mooreeffad8d2008-01-29 08:49:27 -05004927 if (!secmark_active && !peerlbl_active)
4928 return NF_ACCEPT;
4929
Paul Mooreeffad8d2008-01-29 08:49:27 -05004930 sk = skb->sk;
Paul Moorec0828e52013-12-10 14:58:01 -05004931
Paul Mooreeffad8d2008-01-29 08:49:27 -05004932#ifdef CONFIG_XFRM
4933 /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec
4934 * packet transformation so allow the packet to pass without any checks
4935 * since we'll have another chance to perform access control checks
4936 * when the packet is on it's final way out.
4937 * NOTE: there appear to be some IPv6 multicast cases where skb->dst
Paul Moorec0828e52013-12-10 14:58:01 -05004938 * is NULL, in this case go ahead and apply access control.
4939 * NOTE: if this is a local socket (skb->sk != NULL) that is in the
4940 * TCP listening state we cannot wait until the XFRM processing
4941 * is done as we will miss out on the SA label if we do;
4942 * unfortunately, this means more work, but it is only once per
4943 * connection. */
4944 if (skb_dst(skb) != NULL && skb_dst(skb)->xfrm != NULL &&
4945 !(sk != NULL && sk->sk_state == TCP_LISTEN))
Paul Mooreeffad8d2008-01-29 08:49:27 -05004946 return NF_ACCEPT;
4947#endif
Paul Mooreeffad8d2008-01-29 08:49:27 -05004948
Paul Moored8395c82008-10-10 10:16:30 -04004949 if (sk == NULL) {
Paul Moore446b8022013-12-04 16:10:51 -05004950 /* Without an associated socket the packet is either coming
4951 * from the kernel or it is being forwarded; check the packet
4952 * to determine which and if the packet is being forwarded
4953 * query the packet directly to determine the security label. */
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01004954 if (skb->skb_iif) {
4955 secmark_perm = PACKET__FORWARD_OUT;
Paul Moored8395c82008-10-10 10:16:30 -04004956 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00004957 return NF_DROP;
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01004958 } else {
4959 secmark_perm = PACKET__SEND;
Paul Moored8395c82008-10-10 10:16:30 -04004960 peer_sid = SECINITSID_KERNEL;
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01004961 }
Paul Moore446b8022013-12-04 16:10:51 -05004962 } else if (sk->sk_state == TCP_LISTEN) {
4963 /* Locally generated packet but the associated socket is in the
4964 * listening state which means this is a SYN-ACK packet. In
4965 * this particular case the correct security label is assigned
4966 * to the connection/request_sock but unfortunately we can't
4967 * query the request_sock as it isn't queued on the parent
4968 * socket until after the SYN-ACK packet is sent; the only
4969 * viable choice is to regenerate the label like we do in
4970 * selinux_inet_conn_request(). See also selinux_ip_output()
4971 * for similar problems. */
4972 u32 skb_sid;
4973 struct sk_security_struct *sksec = sk->sk_security;
4974 if (selinux_skb_peerlbl_sid(skb, family, &skb_sid))
4975 return NF_DROP;
Paul Moorec0828e52013-12-10 14:58:01 -05004976 /* At this point, if the returned skb peerlbl is SECSID_NULL
4977 * and the packet has been through at least one XFRM
4978 * transformation then we must be dealing with the "final"
4979 * form of labeled IPsec packet; since we've already applied
4980 * all of our access controls on this packet we can safely
4981 * pass the packet. */
4982 if (skb_sid == SECSID_NULL) {
4983 switch (family) {
4984 case PF_INET:
4985 if (IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED)
4986 return NF_ACCEPT;
4987 break;
4988 case PF_INET6:
4989 if (IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED)
4990 return NF_ACCEPT;
Paul Moorea7a91a12014-09-03 10:51:59 -04004991 break;
Paul Moorec0828e52013-12-10 14:58:01 -05004992 default:
4993 return NF_DROP_ERR(-ECONNREFUSED);
4994 }
4995 }
Paul Moore446b8022013-12-04 16:10:51 -05004996 if (selinux_conn_sid(sksec->sid, skb_sid, &peer_sid))
4997 return NF_DROP;
4998 secmark_perm = PACKET__SEND;
Paul Moored8395c82008-10-10 10:16:30 -04004999 } else {
Paul Moore446b8022013-12-04 16:10:51 -05005000 /* Locally generated packet, fetch the security label from the
5001 * associated socket. */
Paul Mooreeffad8d2008-01-29 08:49:27 -05005002 struct sk_security_struct *sksec = sk->sk_security;
5003 peer_sid = sksec->sid;
5004 secmark_perm = PACKET__SEND;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005005 }
5006
Eric Paris50c205f2012-04-04 15:01:43 -04005007 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04005008 ad.u.net = &net;
5009 ad.u.net->netif = ifindex;
5010 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04005011 if (selinux_parse_skb(skb, &ad, &addrp, 0, NULL))
Eric Paris04f6d702010-11-23 06:28:02 +00005012 return NF_DROP;
Paul Moored8395c82008-10-10 10:16:30 -04005013
Paul Mooreeffad8d2008-01-29 08:49:27 -05005014 if (secmark_active)
5015 if (avc_has_perm(peer_sid, skb->secmark,
5016 SECCLASS_PACKET, secmark_perm, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00005017 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005018
5019 if (peerlbl_active) {
5020 u32 if_sid;
5021 u32 node_sid;
5022
Paul Moorecbe0d6e2014-09-10 17:09:57 -04005023 if (sel_netif_sid(dev_net(outdev), ifindex, &if_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00005024 return NF_DROP;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005025 if (avc_has_perm(peer_sid, if_sid,
5026 SECCLASS_NETIF, NETIF__EGRESS, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00005027 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005028
5029 if (sel_netnode_sid(addrp, family, &node_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00005030 return NF_DROP;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005031 if (avc_has_perm(peer_sid, node_sid,
5032 SECCLASS_NODE, NODE__SENDTO, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00005033 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005034 }
5035
5036 return NF_ACCEPT;
5037}
5038
Patrick McHardy795aa6e2013-10-10 09:21:55 +02005039static unsigned int selinux_ipv4_postroute(const struct nf_hook_ops *ops,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005040 struct sk_buff *skb,
5041 const struct net_device *in,
5042 const struct net_device *out,
5043 int (*okfn)(struct sk_buff *))
5044{
Paul Moorecbe0d6e2014-09-10 17:09:57 -04005045 return selinux_ip_postroute(skb, out, PF_INET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005046}
5047
5048#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Patrick McHardy795aa6e2013-10-10 09:21:55 +02005049static unsigned int selinux_ipv6_postroute(const struct nf_hook_ops *ops,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005050 struct sk_buff *skb,
5051 const struct net_device *in,
5052 const struct net_device *out,
5053 int (*okfn)(struct sk_buff *))
Linus Torvalds1da177e2005-04-16 15:20:36 -07005054{
Paul Moorecbe0d6e2014-09-10 17:09:57 -04005055 return selinux_ip_postroute(skb, out, PF_INET6);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005056}
Linus Torvalds1da177e2005-04-16 15:20:36 -07005057#endif /* IPV6 */
5058
5059#endif /* CONFIG_NETFILTER */
5060
Linus Torvalds1da177e2005-04-16 15:20:36 -07005061static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb)
5062{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005063 int err;
5064
Eric Paris200ac532009-02-12 15:01:04 -05005065 err = cap_netlink_send(sk, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005066 if (err)
5067 return err;
5068
Stephen Smalley941fc5b2009-10-01 14:48:23 -04005069 return selinux_nlmsg_perm(sk, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005070}
5071
Linus Torvalds1da177e2005-04-16 15:20:36 -07005072static int ipc_alloc_security(struct task_struct *task,
5073 struct kern_ipc_perm *perm,
5074 u16 sclass)
5075{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005076 struct ipc_security_struct *isec;
David Howells275bb412008-11-14 10:39:19 +11005077 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005078
James Morris89d155e2005-10-30 14:59:21 -08005079 isec = kzalloc(sizeof(struct ipc_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005080 if (!isec)
5081 return -ENOMEM;
5082
David Howells275bb412008-11-14 10:39:19 +11005083 sid = task_sid(task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005084 isec->sclass = sclass;
David Howells275bb412008-11-14 10:39:19 +11005085 isec->sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005086 perm->security = isec;
5087
5088 return 0;
5089}
5090
5091static void ipc_free_security(struct kern_ipc_perm *perm)
5092{
5093 struct ipc_security_struct *isec = perm->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005094 perm->security = NULL;
5095 kfree(isec);
5096}
5097
5098static int msg_msg_alloc_security(struct msg_msg *msg)
5099{
5100 struct msg_security_struct *msec;
5101
James Morris89d155e2005-10-30 14:59:21 -08005102 msec = kzalloc(sizeof(struct msg_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005103 if (!msec)
5104 return -ENOMEM;
5105
Linus Torvalds1da177e2005-04-16 15:20:36 -07005106 msec->sid = SECINITSID_UNLABELED;
5107 msg->security = msec;
5108
5109 return 0;
5110}
5111
5112static void msg_msg_free_security(struct msg_msg *msg)
5113{
5114 struct msg_security_struct *msec = msg->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005115
5116 msg->security = NULL;
5117 kfree(msec);
5118}
5119
5120static int ipc_has_perm(struct kern_ipc_perm *ipc_perms,
Stephen Smalley6af963f2005-05-01 08:58:39 -07005121 u32 perms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005122{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005123 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005124 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005125 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005126
Linus Torvalds1da177e2005-04-16 15:20:36 -07005127 isec = ipc_perms->security;
5128
Eric Paris50c205f2012-04-04 15:01:43 -04005129 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005130 ad.u.ipc_id = ipc_perms->key;
5131
David Howells275bb412008-11-14 10:39:19 +11005132 return avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005133}
5134
5135static int selinux_msg_msg_alloc_security(struct msg_msg *msg)
5136{
5137 return msg_msg_alloc_security(msg);
5138}
5139
5140static void selinux_msg_msg_free_security(struct msg_msg *msg)
5141{
5142 msg_msg_free_security(msg);
5143}
5144
5145/* message queue security operations */
5146static int selinux_msg_queue_alloc_security(struct msg_queue *msq)
5147{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005148 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005149 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005150 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005151 int rc;
5152
5153 rc = ipc_alloc_security(current, &msq->q_perm, SECCLASS_MSGQ);
5154 if (rc)
5155 return rc;
5156
Linus Torvalds1da177e2005-04-16 15:20:36 -07005157 isec = msq->q_perm.security;
5158
Eric Paris50c205f2012-04-04 15:01:43 -04005159 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04005160 ad.u.ipc_id = msq->q_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005161
David Howells275bb412008-11-14 10:39:19 +11005162 rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005163 MSGQ__CREATE, &ad);
5164 if (rc) {
5165 ipc_free_security(&msq->q_perm);
5166 return rc;
5167 }
5168 return 0;
5169}
5170
5171static void selinux_msg_queue_free_security(struct msg_queue *msq)
5172{
5173 ipc_free_security(&msq->q_perm);
5174}
5175
5176static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg)
5177{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005178 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005179 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005180 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005181
Linus Torvalds1da177e2005-04-16 15:20:36 -07005182 isec = msq->q_perm.security;
5183
Eric Paris50c205f2012-04-04 15:01:43 -04005184 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005185 ad.u.ipc_id = msq->q_perm.key;
5186
David Howells275bb412008-11-14 10:39:19 +11005187 return avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005188 MSGQ__ASSOCIATE, &ad);
5189}
5190
5191static int selinux_msg_queue_msgctl(struct msg_queue *msq, int cmd)
5192{
5193 int err;
5194 int perms;
5195
Eric Paris828dfe12008-04-17 13:17:49 -04005196 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005197 case IPC_INFO:
5198 case MSG_INFO:
5199 /* No specific object, just general system-wide information. */
5200 return task_has_system(current, SYSTEM__IPC_INFO);
5201 case IPC_STAT:
5202 case MSG_STAT:
5203 perms = MSGQ__GETATTR | MSGQ__ASSOCIATE;
5204 break;
5205 case IPC_SET:
5206 perms = MSGQ__SETATTR;
5207 break;
5208 case IPC_RMID:
5209 perms = MSGQ__DESTROY;
5210 break;
5211 default:
5212 return 0;
5213 }
5214
Stephen Smalley6af963f2005-05-01 08:58:39 -07005215 err = ipc_has_perm(&msq->q_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005216 return err;
5217}
5218
5219static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, int msqflg)
5220{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005221 struct ipc_security_struct *isec;
5222 struct msg_security_struct *msec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005223 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005224 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005225 int rc;
5226
Linus Torvalds1da177e2005-04-16 15:20:36 -07005227 isec = msq->q_perm.security;
5228 msec = msg->security;
5229
5230 /*
5231 * First time through, need to assign label to the message
5232 */
5233 if (msec->sid == SECINITSID_UNLABELED) {
5234 /*
5235 * Compute new sid based on current process and
5236 * message queue this message will be stored in
5237 */
David Howells275bb412008-11-14 10:39:19 +11005238 rc = security_transition_sid(sid, isec->sid, SECCLASS_MSG,
Eric Paris652bb9b2011-02-01 11:05:40 -05005239 NULL, &msec->sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005240 if (rc)
5241 return rc;
5242 }
5243
Eric Paris50c205f2012-04-04 15:01:43 -04005244 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005245 ad.u.ipc_id = msq->q_perm.key;
5246
5247 /* Can this process write to the queue? */
David Howells275bb412008-11-14 10:39:19 +11005248 rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005249 MSGQ__WRITE, &ad);
5250 if (!rc)
5251 /* Can this process send the message */
David Howells275bb412008-11-14 10:39:19 +11005252 rc = avc_has_perm(sid, msec->sid, SECCLASS_MSG,
5253 MSG__SEND, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005254 if (!rc)
5255 /* Can the message be put in the queue? */
David Howells275bb412008-11-14 10:39:19 +11005256 rc = avc_has_perm(msec->sid, isec->sid, SECCLASS_MSGQ,
5257 MSGQ__ENQUEUE, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005258
5259 return rc;
5260}
5261
5262static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
5263 struct task_struct *target,
5264 long type, int mode)
5265{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005266 struct ipc_security_struct *isec;
5267 struct msg_security_struct *msec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005268 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005269 u32 sid = task_sid(target);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005270 int rc;
5271
Linus Torvalds1da177e2005-04-16 15:20:36 -07005272 isec = msq->q_perm.security;
5273 msec = msg->security;
5274
Eric Paris50c205f2012-04-04 15:01:43 -04005275 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04005276 ad.u.ipc_id = msq->q_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005277
David Howells275bb412008-11-14 10:39:19 +11005278 rc = avc_has_perm(sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005279 SECCLASS_MSGQ, MSGQ__READ, &ad);
5280 if (!rc)
David Howells275bb412008-11-14 10:39:19 +11005281 rc = avc_has_perm(sid, msec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005282 SECCLASS_MSG, MSG__RECEIVE, &ad);
5283 return rc;
5284}
5285
5286/* Shared Memory security operations */
5287static int selinux_shm_alloc_security(struct shmid_kernel *shp)
5288{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005289 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005290 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005291 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005292 int rc;
5293
5294 rc = ipc_alloc_security(current, &shp->shm_perm, SECCLASS_SHM);
5295 if (rc)
5296 return rc;
5297
Linus Torvalds1da177e2005-04-16 15:20:36 -07005298 isec = shp->shm_perm.security;
5299
Eric Paris50c205f2012-04-04 15:01:43 -04005300 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04005301 ad.u.ipc_id = shp->shm_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005302
David Howells275bb412008-11-14 10:39:19 +11005303 rc = avc_has_perm(sid, isec->sid, SECCLASS_SHM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005304 SHM__CREATE, &ad);
5305 if (rc) {
5306 ipc_free_security(&shp->shm_perm);
5307 return rc;
5308 }
5309 return 0;
5310}
5311
5312static void selinux_shm_free_security(struct shmid_kernel *shp)
5313{
5314 ipc_free_security(&shp->shm_perm);
5315}
5316
5317static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg)
5318{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005319 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005320 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005321 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005322
Linus Torvalds1da177e2005-04-16 15:20:36 -07005323 isec = shp->shm_perm.security;
5324
Eric Paris50c205f2012-04-04 15:01:43 -04005325 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005326 ad.u.ipc_id = shp->shm_perm.key;
5327
David Howells275bb412008-11-14 10:39:19 +11005328 return avc_has_perm(sid, isec->sid, SECCLASS_SHM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005329 SHM__ASSOCIATE, &ad);
5330}
5331
5332/* Note, at this point, shp is locked down */
5333static int selinux_shm_shmctl(struct shmid_kernel *shp, int cmd)
5334{
5335 int perms;
5336 int err;
5337
Eric Paris828dfe12008-04-17 13:17:49 -04005338 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005339 case IPC_INFO:
5340 case SHM_INFO:
5341 /* No specific object, just general system-wide information. */
5342 return task_has_system(current, SYSTEM__IPC_INFO);
5343 case IPC_STAT:
5344 case SHM_STAT:
5345 perms = SHM__GETATTR | SHM__ASSOCIATE;
5346 break;
5347 case IPC_SET:
5348 perms = SHM__SETATTR;
5349 break;
5350 case SHM_LOCK:
5351 case SHM_UNLOCK:
5352 perms = SHM__LOCK;
5353 break;
5354 case IPC_RMID:
5355 perms = SHM__DESTROY;
5356 break;
5357 default:
5358 return 0;
5359 }
5360
Stephen Smalley6af963f2005-05-01 08:58:39 -07005361 err = ipc_has_perm(&shp->shm_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005362 return err;
5363}
5364
5365static int selinux_shm_shmat(struct shmid_kernel *shp,
5366 char __user *shmaddr, int shmflg)
5367{
5368 u32 perms;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005369
5370 if (shmflg & SHM_RDONLY)
5371 perms = SHM__READ;
5372 else
5373 perms = SHM__READ | SHM__WRITE;
5374
Stephen Smalley6af963f2005-05-01 08:58:39 -07005375 return ipc_has_perm(&shp->shm_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005376}
5377
5378/* Semaphore security operations */
5379static int selinux_sem_alloc_security(struct sem_array *sma)
5380{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005381 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005382 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005383 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005384 int rc;
5385
5386 rc = ipc_alloc_security(current, &sma->sem_perm, SECCLASS_SEM);
5387 if (rc)
5388 return rc;
5389
Linus Torvalds1da177e2005-04-16 15:20:36 -07005390 isec = sma->sem_perm.security;
5391
Eric Paris50c205f2012-04-04 15:01:43 -04005392 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04005393 ad.u.ipc_id = sma->sem_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005394
David Howells275bb412008-11-14 10:39:19 +11005395 rc = avc_has_perm(sid, isec->sid, SECCLASS_SEM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005396 SEM__CREATE, &ad);
5397 if (rc) {
5398 ipc_free_security(&sma->sem_perm);
5399 return rc;
5400 }
5401 return 0;
5402}
5403
5404static void selinux_sem_free_security(struct sem_array *sma)
5405{
5406 ipc_free_security(&sma->sem_perm);
5407}
5408
5409static int selinux_sem_associate(struct sem_array *sma, int semflg)
5410{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005411 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005412 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005413 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005414
Linus Torvalds1da177e2005-04-16 15:20:36 -07005415 isec = sma->sem_perm.security;
5416
Eric Paris50c205f2012-04-04 15:01:43 -04005417 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005418 ad.u.ipc_id = sma->sem_perm.key;
5419
David Howells275bb412008-11-14 10:39:19 +11005420 return avc_has_perm(sid, isec->sid, SECCLASS_SEM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005421 SEM__ASSOCIATE, &ad);
5422}
5423
5424/* Note, at this point, sma is locked down */
5425static int selinux_sem_semctl(struct sem_array *sma, int cmd)
5426{
5427 int err;
5428 u32 perms;
5429
Eric Paris828dfe12008-04-17 13:17:49 -04005430 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005431 case IPC_INFO:
5432 case SEM_INFO:
5433 /* No specific object, just general system-wide information. */
5434 return task_has_system(current, SYSTEM__IPC_INFO);
5435 case GETPID:
5436 case GETNCNT:
5437 case GETZCNT:
5438 perms = SEM__GETATTR;
5439 break;
5440 case GETVAL:
5441 case GETALL:
5442 perms = SEM__READ;
5443 break;
5444 case SETVAL:
5445 case SETALL:
5446 perms = SEM__WRITE;
5447 break;
5448 case IPC_RMID:
5449 perms = SEM__DESTROY;
5450 break;
5451 case IPC_SET:
5452 perms = SEM__SETATTR;
5453 break;
5454 case IPC_STAT:
5455 case SEM_STAT:
5456 perms = SEM__GETATTR | SEM__ASSOCIATE;
5457 break;
5458 default:
5459 return 0;
5460 }
5461
Stephen Smalley6af963f2005-05-01 08:58:39 -07005462 err = ipc_has_perm(&sma->sem_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005463 return err;
5464}
5465
5466static int selinux_sem_semop(struct sem_array *sma,
5467 struct sembuf *sops, unsigned nsops, int alter)
5468{
5469 u32 perms;
5470
5471 if (alter)
5472 perms = SEM__READ | SEM__WRITE;
5473 else
5474 perms = SEM__READ;
5475
Stephen Smalley6af963f2005-05-01 08:58:39 -07005476 return ipc_has_perm(&sma->sem_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005477}
5478
5479static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
5480{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005481 u32 av = 0;
5482
Linus Torvalds1da177e2005-04-16 15:20:36 -07005483 av = 0;
5484 if (flag & S_IRUGO)
5485 av |= IPC__UNIX_READ;
5486 if (flag & S_IWUGO)
5487 av |= IPC__UNIX_WRITE;
5488
5489 if (av == 0)
5490 return 0;
5491
Stephen Smalley6af963f2005-05-01 08:58:39 -07005492 return ipc_has_perm(ipcp, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005493}
5494
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02005495static void selinux_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
5496{
5497 struct ipc_security_struct *isec = ipcp->security;
5498 *secid = isec->sid;
5499}
5500
Eric Paris828dfe12008-04-17 13:17:49 -04005501static void selinux_d_instantiate(struct dentry *dentry, struct inode *inode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005502{
5503 if (inode)
5504 inode_doinit_with_dentry(inode, dentry);
5505}
5506
5507static int selinux_getprocattr(struct task_struct *p,
Al Viro04ff9702007-03-12 16:17:58 +00005508 char *name, char **value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005509{
David Howells275bb412008-11-14 10:39:19 +11005510 const struct task_security_struct *__tsec;
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00005511 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005512 int error;
Al Viro04ff9702007-03-12 16:17:58 +00005513 unsigned len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005514
5515 if (current != p) {
David Howells3b11a1d2008-11-14 10:39:26 +11005516 error = current_has_perm(p, PROCESS__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005517 if (error)
5518 return error;
5519 }
5520
David Howells275bb412008-11-14 10:39:19 +11005521 rcu_read_lock();
5522 __tsec = __task_cred(p)->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005523
5524 if (!strcmp(name, "current"))
David Howells275bb412008-11-14 10:39:19 +11005525 sid = __tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005526 else if (!strcmp(name, "prev"))
David Howells275bb412008-11-14 10:39:19 +11005527 sid = __tsec->osid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005528 else if (!strcmp(name, "exec"))
David Howells275bb412008-11-14 10:39:19 +11005529 sid = __tsec->exec_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005530 else if (!strcmp(name, "fscreate"))
David Howells275bb412008-11-14 10:39:19 +11005531 sid = __tsec->create_sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005532 else if (!strcmp(name, "keycreate"))
David Howells275bb412008-11-14 10:39:19 +11005533 sid = __tsec->keycreate_sid;
Eric Paris42c3e032006-06-26 00:26:03 -07005534 else if (!strcmp(name, "sockcreate"))
David Howells275bb412008-11-14 10:39:19 +11005535 sid = __tsec->sockcreate_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005536 else
David Howells275bb412008-11-14 10:39:19 +11005537 goto invalid;
5538 rcu_read_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005539
5540 if (!sid)
5541 return 0;
5542
Al Viro04ff9702007-03-12 16:17:58 +00005543 error = security_sid_to_context(sid, value, &len);
5544 if (error)
5545 return error;
5546 return len;
David Howells275bb412008-11-14 10:39:19 +11005547
5548invalid:
5549 rcu_read_unlock();
5550 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005551}
5552
5553static int selinux_setprocattr(struct task_struct *p,
5554 char *name, void *value, size_t size)
5555{
5556 struct task_security_struct *tsec;
Roland McGrath03563572008-03-26 15:46:39 -07005557 struct task_struct *tracer;
David Howellsd84f4f92008-11-14 10:39:23 +11005558 struct cred *new;
5559 u32 sid = 0, ptsid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005560 int error;
5561 char *str = value;
5562
5563 if (current != p) {
5564 /* SELinux only allows a process to change its own
5565 security attributes. */
5566 return -EACCES;
5567 }
5568
5569 /*
5570 * Basic control over ability to set these attributes at all.
5571 * current == p, but we'll pass them separately in case the
5572 * above restriction is ever removed.
5573 */
5574 if (!strcmp(name, "exec"))
David Howells3b11a1d2008-11-14 10:39:26 +11005575 error = current_has_perm(p, PROCESS__SETEXEC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005576 else if (!strcmp(name, "fscreate"))
David Howells3b11a1d2008-11-14 10:39:26 +11005577 error = current_has_perm(p, PROCESS__SETFSCREATE);
Michael LeMay4eb582c2006-06-26 00:24:57 -07005578 else if (!strcmp(name, "keycreate"))
David Howells3b11a1d2008-11-14 10:39:26 +11005579 error = current_has_perm(p, PROCESS__SETKEYCREATE);
Eric Paris42c3e032006-06-26 00:26:03 -07005580 else if (!strcmp(name, "sockcreate"))
David Howells3b11a1d2008-11-14 10:39:26 +11005581 error = current_has_perm(p, PROCESS__SETSOCKCREATE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005582 else if (!strcmp(name, "current"))
David Howells3b11a1d2008-11-14 10:39:26 +11005583 error = current_has_perm(p, PROCESS__SETCURRENT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005584 else
5585 error = -EINVAL;
5586 if (error)
5587 return error;
5588
5589 /* Obtain a SID for the context, if one was specified. */
5590 if (size && str[1] && str[1] != '\n') {
5591 if (str[size-1] == '\n') {
5592 str[size-1] = 0;
5593 size--;
5594 }
Nikolay Aleksandrov52a4c642014-03-07 12:44:19 +01005595 error = security_context_to_sid(value, size, &sid, GFP_KERNEL);
Stephen Smalley12b29f32008-05-07 13:03:20 -04005596 if (error == -EINVAL && !strcmp(name, "fscreate")) {
Eric Parisd6ea83e2012-04-04 13:45:49 -04005597 if (!capable(CAP_MAC_ADMIN)) {
5598 struct audit_buffer *ab;
5599 size_t audit_size;
5600
5601 /* We strip a nul only if it is at the end, otherwise the
5602 * context contains a nul and we should audit that */
5603 if (str[size - 1] == '\0')
5604 audit_size = size - 1;
5605 else
5606 audit_size = size;
5607 ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR);
5608 audit_log_format(ab, "op=fscreate invalid_context=");
5609 audit_log_n_untrustedstring(ab, value, audit_size);
5610 audit_log_end(ab);
5611
Stephen Smalley12b29f32008-05-07 13:03:20 -04005612 return error;
Eric Parisd6ea83e2012-04-04 13:45:49 -04005613 }
Stephen Smalley12b29f32008-05-07 13:03:20 -04005614 error = security_context_to_sid_force(value, size,
5615 &sid);
5616 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005617 if (error)
5618 return error;
5619 }
5620
David Howellsd84f4f92008-11-14 10:39:23 +11005621 new = prepare_creds();
5622 if (!new)
5623 return -ENOMEM;
5624
Linus Torvalds1da177e2005-04-16 15:20:36 -07005625 /* Permission checking based on the specified context is
5626 performed during the actual operation (execve,
5627 open/mkdir/...), when we know the full context of the
David Howellsd84f4f92008-11-14 10:39:23 +11005628 operation. See selinux_bprm_set_creds for the execve
Linus Torvalds1da177e2005-04-16 15:20:36 -07005629 checks and may_create for the file creation checks. The
5630 operation will then fail if the context is not permitted. */
David Howellsd84f4f92008-11-14 10:39:23 +11005631 tsec = new->security;
5632 if (!strcmp(name, "exec")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005633 tsec->exec_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005634 } else if (!strcmp(name, "fscreate")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005635 tsec->create_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005636 } else if (!strcmp(name, "keycreate")) {
Michael LeMay4eb582c2006-06-26 00:24:57 -07005637 error = may_create_key(sid, p);
5638 if (error)
David Howellsd84f4f92008-11-14 10:39:23 +11005639 goto abort_change;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005640 tsec->keycreate_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005641 } else if (!strcmp(name, "sockcreate")) {
Eric Paris42c3e032006-06-26 00:26:03 -07005642 tsec->sockcreate_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005643 } else if (!strcmp(name, "current")) {
5644 error = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005645 if (sid == 0)
David Howellsd84f4f92008-11-14 10:39:23 +11005646 goto abort_change;
KaiGai Koheid9250de2008-08-28 16:35:57 +09005647
David Howellsd84f4f92008-11-14 10:39:23 +11005648 /* Only allow single threaded processes to change context */
5649 error = -EPERM;
Oleg Nesterov5bb459b2009-07-10 03:48:23 +02005650 if (!current_is_single_threaded()) {
David Howellsd84f4f92008-11-14 10:39:23 +11005651 error = security_bounded_transition(tsec->sid, sid);
5652 if (error)
5653 goto abort_change;
Eric Paris828dfe12008-04-17 13:17:49 -04005654 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005655
5656 /* Check permissions for the transition. */
5657 error = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS,
Eric Paris828dfe12008-04-17 13:17:49 -04005658 PROCESS__DYNTRANSITION, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005659 if (error)
David Howellsd84f4f92008-11-14 10:39:23 +11005660 goto abort_change;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005661
5662 /* Check for ptracing, and update the task SID if ok.
5663 Otherwise, leave SID unchanged and fail. */
David Howellsd84f4f92008-11-14 10:39:23 +11005664 ptsid = 0;
Oleg Nesterovc0c14392013-12-23 17:45:01 -05005665 rcu_read_lock();
Tejun Heo06d98472011-06-17 16:50:40 +02005666 tracer = ptrace_parent(p);
David Howellsd84f4f92008-11-14 10:39:23 +11005667 if (tracer)
5668 ptsid = task_sid(tracer);
Oleg Nesterovc0c14392013-12-23 17:45:01 -05005669 rcu_read_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005670
David Howellsd84f4f92008-11-14 10:39:23 +11005671 if (tracer) {
5672 error = avc_has_perm(ptsid, sid, SECCLASS_PROCESS,
5673 PROCESS__PTRACE, NULL);
5674 if (error)
5675 goto abort_change;
5676 }
5677
5678 tsec->sid = sid;
5679 } else {
5680 error = -EINVAL;
5681 goto abort_change;
5682 }
5683
5684 commit_creds(new);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005685 return size;
David Howellsd84f4f92008-11-14 10:39:23 +11005686
5687abort_change:
5688 abort_creds(new);
5689 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005690}
5691
David Quigley746df9b2013-05-22 12:50:35 -04005692static int selinux_ismaclabel(const char *name)
5693{
5694 return (strcmp(name, XATTR_SELINUX_SUFFIX) == 0);
5695}
5696
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005697static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
5698{
5699 return security_sid_to_context(secid, secdata, seclen);
5700}
5701
David Howells7bf570d2008-04-29 20:52:51 +01005702static int selinux_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
David Howells63cb3442008-01-15 23:47:35 +00005703{
Nikolay Aleksandrov52a4c642014-03-07 12:44:19 +01005704 return security_context_to_sid(secdata, seclen, secid, GFP_KERNEL);
David Howells63cb3442008-01-15 23:47:35 +00005705}
5706
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005707static void selinux_release_secctx(char *secdata, u32 seclen)
5708{
Paul Moore088999e2007-08-01 11:12:58 -04005709 kfree(secdata);
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005710}
5711
David P. Quigley1ee65e32009-09-03 14:25:57 -04005712/*
5713 * called with inode->i_mutex locked
5714 */
5715static int selinux_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen)
5716{
5717 return selinux_inode_setsecurity(inode, XATTR_SELINUX_SUFFIX, ctx, ctxlen, 0);
5718}
5719
5720/*
5721 * called with inode->i_mutex locked
5722 */
5723static int selinux_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen)
5724{
5725 return __vfs_setxattr_noperm(dentry, XATTR_NAME_SELINUX, ctx, ctxlen, 0);
5726}
5727
5728static int selinux_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen)
5729{
5730 int len = 0;
5731 len = selinux_inode_getsecurity(inode, XATTR_SELINUX_SUFFIX,
5732 ctx, true);
5733 if (len < 0)
5734 return len;
5735 *ctxlen = len;
5736 return 0;
5737}
Michael LeMayd7200242006-06-22 14:47:17 -07005738#ifdef CONFIG_KEYS
5739
David Howellsd84f4f92008-11-14 10:39:23 +11005740static int selinux_key_alloc(struct key *k, const struct cred *cred,
David Howells7e047ef2006-06-26 00:24:50 -07005741 unsigned long flags)
Michael LeMayd7200242006-06-22 14:47:17 -07005742{
David Howellsd84f4f92008-11-14 10:39:23 +11005743 const struct task_security_struct *tsec;
Michael LeMayd7200242006-06-22 14:47:17 -07005744 struct key_security_struct *ksec;
5745
5746 ksec = kzalloc(sizeof(struct key_security_struct), GFP_KERNEL);
5747 if (!ksec)
5748 return -ENOMEM;
5749
David Howellsd84f4f92008-11-14 10:39:23 +11005750 tsec = cred->security;
5751 if (tsec->keycreate_sid)
5752 ksec->sid = tsec->keycreate_sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005753 else
David Howellsd84f4f92008-11-14 10:39:23 +11005754 ksec->sid = tsec->sid;
Michael LeMayd7200242006-06-22 14:47:17 -07005755
David Howells275bb412008-11-14 10:39:19 +11005756 k->security = ksec;
Michael LeMayd7200242006-06-22 14:47:17 -07005757 return 0;
5758}
5759
5760static void selinux_key_free(struct key *k)
5761{
5762 struct key_security_struct *ksec = k->security;
5763
5764 k->security = NULL;
5765 kfree(ksec);
5766}
5767
5768static int selinux_key_permission(key_ref_t key_ref,
David Howellsd84f4f92008-11-14 10:39:23 +11005769 const struct cred *cred,
David Howellsf5895942014-03-14 17:44:49 +00005770 unsigned perm)
Michael LeMayd7200242006-06-22 14:47:17 -07005771{
5772 struct key *key;
Michael LeMayd7200242006-06-22 14:47:17 -07005773 struct key_security_struct *ksec;
David Howells275bb412008-11-14 10:39:19 +11005774 u32 sid;
Michael LeMayd7200242006-06-22 14:47:17 -07005775
5776 /* if no specific permissions are requested, we skip the
5777 permission check. No serious, additional covert channels
5778 appear to be created. */
5779 if (perm == 0)
5780 return 0;
5781
David Howellsd84f4f92008-11-14 10:39:23 +11005782 sid = cred_sid(cred);
David Howells275bb412008-11-14 10:39:19 +11005783
5784 key = key_ref_to_ptr(key_ref);
5785 ksec = key->security;
5786
5787 return avc_has_perm(sid, ksec->sid, SECCLASS_KEY, perm, NULL);
Michael LeMayd7200242006-06-22 14:47:17 -07005788}
5789
David Howells70a5bb72008-04-29 01:01:26 -07005790static int selinux_key_getsecurity(struct key *key, char **_buffer)
5791{
5792 struct key_security_struct *ksec = key->security;
5793 char *context = NULL;
5794 unsigned len;
5795 int rc;
5796
5797 rc = security_sid_to_context(ksec->sid, &context, &len);
5798 if (!rc)
5799 rc = len;
5800 *_buffer = context;
5801 return rc;
5802}
5803
Michael LeMayd7200242006-06-22 14:47:17 -07005804#endif
5805
Linus Torvalds1da177e2005-04-16 15:20:36 -07005806static struct security_operations selinux_ops = {
Ahmed S. Darwish076c54c2008-03-06 18:09:10 +02005807 .name = "selinux",
5808
Ingo Molnar9e488582009-05-07 19:26:19 +10005809 .ptrace_access_check = selinux_ptrace_access_check,
David Howells5cd9c582008-08-14 11:37:28 +01005810 .ptrace_traceme = selinux_ptrace_traceme,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005811 .capget = selinux_capget,
David Howellsd84f4f92008-11-14 10:39:23 +11005812 .capset = selinux_capset,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005813 .capable = selinux_capable,
5814 .quotactl = selinux_quotactl,
5815 .quota_on = selinux_quota_on,
5816 .syslog = selinux_syslog,
5817 .vm_enough_memory = selinux_vm_enough_memory,
5818
5819 .netlink_send = selinux_netlink_send,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005820
David Howellsa6f76f22008-11-14 10:39:24 +11005821 .bprm_set_creds = selinux_bprm_set_creds,
David Howellsa6f76f22008-11-14 10:39:24 +11005822 .bprm_committing_creds = selinux_bprm_committing_creds,
5823 .bprm_committed_creds = selinux_bprm_committed_creds,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005824 .bprm_secureexec = selinux_bprm_secureexec,
5825
5826 .sb_alloc_security = selinux_sb_alloc_security,
5827 .sb_free_security = selinux_sb_free_security,
5828 .sb_copy_data = selinux_sb_copy_data,
Eric Paris026eb162011-03-03 16:09:14 -05005829 .sb_remount = selinux_sb_remount,
Eric Paris828dfe12008-04-17 13:17:49 -04005830 .sb_kern_mount = selinux_sb_kern_mount,
Eric Paris2069f452008-07-04 09:47:13 +10005831 .sb_show_options = selinux_sb_show_options,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005832 .sb_statfs = selinux_sb_statfs,
5833 .sb_mount = selinux_mount,
5834 .sb_umount = selinux_umount,
Eric Parisc9180a52007-11-30 13:00:35 -05005835 .sb_set_mnt_opts = selinux_set_mnt_opts,
Eric Paris828dfe12008-04-17 13:17:49 -04005836 .sb_clone_mnt_opts = selinux_sb_clone_mnt_opts,
Eric Parise0007522008-03-05 10:31:54 -05005837 .sb_parse_opts_str = selinux_parse_opts_str,
5838
David Quigleyd47be3d2013-05-22 12:50:34 -04005839 .dentry_init_security = selinux_dentry_init_security,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005840
5841 .inode_alloc_security = selinux_inode_alloc_security,
5842 .inode_free_security = selinux_inode_free_security,
Stephen Smalley5e41ff92005-09-09 13:01:35 -07005843 .inode_init_security = selinux_inode_init_security,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005844 .inode_create = selinux_inode_create,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005845 .inode_link = selinux_inode_link,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005846 .inode_unlink = selinux_inode_unlink,
5847 .inode_symlink = selinux_inode_symlink,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005848 .inode_mkdir = selinux_inode_mkdir,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005849 .inode_rmdir = selinux_inode_rmdir,
5850 .inode_mknod = selinux_inode_mknod,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005851 .inode_rename = selinux_inode_rename,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005852 .inode_readlink = selinux_inode_readlink,
5853 .inode_follow_link = selinux_inode_follow_link,
5854 .inode_permission = selinux_inode_permission,
5855 .inode_setattr = selinux_inode_setattr,
5856 .inode_getattr = selinux_inode_getattr,
5857 .inode_setxattr = selinux_inode_setxattr,
5858 .inode_post_setxattr = selinux_inode_post_setxattr,
5859 .inode_getxattr = selinux_inode_getxattr,
5860 .inode_listxattr = selinux_inode_listxattr,
5861 .inode_removexattr = selinux_inode_removexattr,
Eric Paris828dfe12008-04-17 13:17:49 -04005862 .inode_getsecurity = selinux_inode_getsecurity,
5863 .inode_setsecurity = selinux_inode_setsecurity,
5864 .inode_listsecurity = selinux_inode_listsecurity,
Eric Parisf5269712008-05-14 11:27:45 -04005865 .inode_getsecid = selinux_inode_getsecid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005866
5867 .file_permission = selinux_file_permission,
5868 .file_alloc_security = selinux_file_alloc_security,
5869 .file_free_security = selinux_file_free_security,
5870 .file_ioctl = selinux_file_ioctl,
Al Viroe5467852012-05-30 13:30:51 -04005871 .mmap_file = selinux_mmap_file,
5872 .mmap_addr = selinux_mmap_addr,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005873 .file_mprotect = selinux_file_mprotect,
5874 .file_lock = selinux_file_lock,
5875 .file_fcntl = selinux_file_fcntl,
5876 .file_set_fowner = selinux_file_set_fowner,
5877 .file_send_sigiotask = selinux_file_send_sigiotask,
5878 .file_receive = selinux_file_receive,
5879
Eric Paris83d49852012-04-04 13:45:40 -04005880 .file_open = selinux_file_open,
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09005881
Linus Torvalds1da177e2005-04-16 15:20:36 -07005882 .task_create = selinux_task_create,
David Howellsee18d642009-09-02 09:14:21 +01005883 .cred_alloc_blank = selinux_cred_alloc_blank,
David Howellsf1752ee2008-11-14 10:39:17 +11005884 .cred_free = selinux_cred_free,
David Howellsd84f4f92008-11-14 10:39:23 +11005885 .cred_prepare = selinux_cred_prepare,
David Howellsee18d642009-09-02 09:14:21 +01005886 .cred_transfer = selinux_cred_transfer,
David Howells3a3b7ce2008-11-14 10:39:28 +11005887 .kernel_act_as = selinux_kernel_act_as,
5888 .kernel_create_files_as = selinux_kernel_create_files_as,
Eric Paris25354c42009-08-13 09:45:03 -04005889 .kernel_module_request = selinux_kernel_module_request,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005890 .task_setpgid = selinux_task_setpgid,
5891 .task_getpgid = selinux_task_getpgid,
Eric Paris828dfe12008-04-17 13:17:49 -04005892 .task_getsid = selinux_task_getsid,
David Quigleyf9008e4c2006-06-30 01:55:46 -07005893 .task_getsecid = selinux_task_getsecid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005894 .task_setnice = selinux_task_setnice,
James Morris03e68062006-06-23 02:03:58 -07005895 .task_setioprio = selinux_task_setioprio,
David Quigleya1836a42006-06-30 01:55:49 -07005896 .task_getioprio = selinux_task_getioprio,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005897 .task_setrlimit = selinux_task_setrlimit,
5898 .task_setscheduler = selinux_task_setscheduler,
5899 .task_getscheduler = selinux_task_getscheduler,
David Quigley35601542006-06-23 02:04:01 -07005900 .task_movememory = selinux_task_movememory,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005901 .task_kill = selinux_task_kill,
5902 .task_wait = selinux_task_wait,
Eric Paris828dfe12008-04-17 13:17:49 -04005903 .task_to_inode = selinux_task_to_inode,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005904
5905 .ipc_permission = selinux_ipc_permission,
Eric Parisf5269712008-05-14 11:27:45 -04005906 .ipc_getsecid = selinux_ipc_getsecid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005907
5908 .msg_msg_alloc_security = selinux_msg_msg_alloc_security,
5909 .msg_msg_free_security = selinux_msg_msg_free_security,
5910
5911 .msg_queue_alloc_security = selinux_msg_queue_alloc_security,
5912 .msg_queue_free_security = selinux_msg_queue_free_security,
5913 .msg_queue_associate = selinux_msg_queue_associate,
5914 .msg_queue_msgctl = selinux_msg_queue_msgctl,
5915 .msg_queue_msgsnd = selinux_msg_queue_msgsnd,
5916 .msg_queue_msgrcv = selinux_msg_queue_msgrcv,
5917
5918 .shm_alloc_security = selinux_shm_alloc_security,
5919 .shm_free_security = selinux_shm_free_security,
5920 .shm_associate = selinux_shm_associate,
5921 .shm_shmctl = selinux_shm_shmctl,
5922 .shm_shmat = selinux_shm_shmat,
5923
Eric Paris828dfe12008-04-17 13:17:49 -04005924 .sem_alloc_security = selinux_sem_alloc_security,
5925 .sem_free_security = selinux_sem_free_security,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005926 .sem_associate = selinux_sem_associate,
5927 .sem_semctl = selinux_sem_semctl,
5928 .sem_semop = selinux_sem_semop,
5929
Eric Paris828dfe12008-04-17 13:17:49 -04005930 .d_instantiate = selinux_d_instantiate,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005931
Eric Paris828dfe12008-04-17 13:17:49 -04005932 .getprocattr = selinux_getprocattr,
5933 .setprocattr = selinux_setprocattr,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005934
David Quigley746df9b2013-05-22 12:50:35 -04005935 .ismaclabel = selinux_ismaclabel,
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005936 .secid_to_secctx = selinux_secid_to_secctx,
David Howells63cb3442008-01-15 23:47:35 +00005937 .secctx_to_secid = selinux_secctx_to_secid,
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005938 .release_secctx = selinux_release_secctx,
David P. Quigley1ee65e32009-09-03 14:25:57 -04005939 .inode_notifysecctx = selinux_inode_notifysecctx,
5940 .inode_setsecctx = selinux_inode_setsecctx,
5941 .inode_getsecctx = selinux_inode_getsecctx,
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005942
Eric Paris828dfe12008-04-17 13:17:49 -04005943 .unix_stream_connect = selinux_socket_unix_stream_connect,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005944 .unix_may_send = selinux_socket_unix_may_send,
5945
5946 .socket_create = selinux_socket_create,
5947 .socket_post_create = selinux_socket_post_create,
5948 .socket_bind = selinux_socket_bind,
5949 .socket_connect = selinux_socket_connect,
5950 .socket_listen = selinux_socket_listen,
5951 .socket_accept = selinux_socket_accept,
5952 .socket_sendmsg = selinux_socket_sendmsg,
5953 .socket_recvmsg = selinux_socket_recvmsg,
5954 .socket_getsockname = selinux_socket_getsockname,
5955 .socket_getpeername = selinux_socket_getpeername,
5956 .socket_getsockopt = selinux_socket_getsockopt,
5957 .socket_setsockopt = selinux_socket_setsockopt,
5958 .socket_shutdown = selinux_socket_shutdown,
5959 .socket_sock_rcv_skb = selinux_socket_sock_rcv_skb,
Catherine Zhang2c7946a2006-03-20 22:41:23 -08005960 .socket_getpeersec_stream = selinux_socket_getpeersec_stream,
5961 .socket_getpeersec_dgram = selinux_socket_getpeersec_dgram,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005962 .sk_alloc_security = selinux_sk_alloc_security,
5963 .sk_free_security = selinux_sk_free_security,
Venkat Yekkirala892c1412006-08-04 23:08:56 -07005964 .sk_clone_security = selinux_sk_clone_security,
Eric Paris828dfe12008-04-17 13:17:49 -04005965 .sk_getsecid = selinux_sk_getsecid,
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005966 .sock_graft = selinux_sock_graft,
5967 .inet_conn_request = selinux_inet_conn_request,
5968 .inet_csk_clone = selinux_inet_csk_clone,
Venkat Yekkirala6b877692006-11-08 17:04:09 -06005969 .inet_conn_established = selinux_inet_conn_established,
Eric Paris2606fd12010-10-13 16:24:41 -04005970 .secmark_relabel_packet = selinux_secmark_relabel_packet,
5971 .secmark_refcount_inc = selinux_secmark_refcount_inc,
5972 .secmark_refcount_dec = selinux_secmark_refcount_dec,
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005973 .req_classify_flow = selinux_req_classify_flow,
Paul Moore5dbbaf22013-01-14 07:12:19 +00005974 .tun_dev_alloc_security = selinux_tun_dev_alloc_security,
5975 .tun_dev_free_security = selinux_tun_dev_free_security,
Paul Mooreed6d76e2009-08-28 18:12:49 -04005976 .tun_dev_create = selinux_tun_dev_create,
Paul Moore5dbbaf22013-01-14 07:12:19 +00005977 .tun_dev_attach_queue = selinux_tun_dev_attach_queue,
Paul Mooreed6d76e2009-08-28 18:12:49 -04005978 .tun_dev_attach = selinux_tun_dev_attach,
Paul Moore5dbbaf22013-01-14 07:12:19 +00005979 .tun_dev_open = selinux_tun_dev_open,
Eric Dumazetca10b9e2013-04-08 17:58:11 +00005980 .skb_owned_by = selinux_skb_owned_by,
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005981
5982#ifdef CONFIG_SECURITY_NETWORK_XFRM
5983 .xfrm_policy_alloc_security = selinux_xfrm_policy_alloc,
5984 .xfrm_policy_clone_security = selinux_xfrm_policy_clone,
5985 .xfrm_policy_free_security = selinux_xfrm_policy_free,
Catherine Zhangc8c05a82006-06-08 23:39:49 -07005986 .xfrm_policy_delete_security = selinux_xfrm_policy_delete,
Paul Moore2e5aa862013-07-23 17:38:38 -04005987 .xfrm_state_alloc = selinux_xfrm_state_alloc,
5988 .xfrm_state_alloc_acquire = selinux_xfrm_state_alloc_acquire,
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005989 .xfrm_state_free_security = selinux_xfrm_state_free,
Catherine Zhangc8c05a82006-06-08 23:39:49 -07005990 .xfrm_state_delete_security = selinux_xfrm_state_delete,
Eric Paris828dfe12008-04-17 13:17:49 -04005991 .xfrm_policy_lookup = selinux_xfrm_policy_lookup,
Venkat Yekkiralae0d1caa2006-07-24 23:29:07 -07005992 .xfrm_state_pol_flow_match = selinux_xfrm_state_pol_flow_match,
Venkat Yekkiralae0d1caa2006-07-24 23:29:07 -07005993 .xfrm_decode_session = selinux_xfrm_decode_session,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005994#endif
Michael LeMayd7200242006-06-22 14:47:17 -07005995
5996#ifdef CONFIG_KEYS
Eric Paris828dfe12008-04-17 13:17:49 -04005997 .key_alloc = selinux_key_alloc,
5998 .key_free = selinux_key_free,
5999 .key_permission = selinux_key_permission,
David Howells70a5bb72008-04-29 01:01:26 -07006000 .key_getsecurity = selinux_key_getsecurity,
Michael LeMayd7200242006-06-22 14:47:17 -07006001#endif
Ahmed S. Darwish9d57a7f2008-03-01 22:03:14 +02006002
6003#ifdef CONFIG_AUDIT
6004 .audit_rule_init = selinux_audit_rule_init,
6005 .audit_rule_known = selinux_audit_rule_known,
6006 .audit_rule_match = selinux_audit_rule_match,
6007 .audit_rule_free = selinux_audit_rule_free,
6008#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07006009};
6010
6011static __init int selinux_init(void)
6012{
Ahmed S. Darwish076c54c2008-03-06 18:09:10 +02006013 if (!security_module_enable(&selinux_ops)) {
6014 selinux_enabled = 0;
6015 return 0;
6016 }
6017
Linus Torvalds1da177e2005-04-16 15:20:36 -07006018 if (!selinux_enabled) {
6019 printk(KERN_INFO "SELinux: Disabled at boot.\n");
6020 return 0;
6021 }
6022
6023 printk(KERN_INFO "SELinux: Initializing.\n");
6024
6025 /* Set the security state for the initial task. */
David Howellsd84f4f92008-11-14 10:39:23 +11006026 cred_init_security();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006027
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04006028 default_noexec = !(VM_DATA_DEFAULT_FLAGS & VM_EXEC);
6029
James Morris7cae7e22006-03-22 00:09:22 -08006030 sel_inode_cache = kmem_cache_create("selinux_inode_security",
6031 sizeof(struct inode_security_struct),
Paul Mundt20c2df82007-07-20 10:11:58 +09006032 0, SLAB_PANIC, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006033 avc_init();
6034
Eric Paris828dfe12008-04-17 13:17:49 -04006035 if (register_security(&selinux_ops))
Linus Torvalds1da177e2005-04-16 15:20:36 -07006036 panic("SELinux: Unable to register with kernel.\n");
6037
Paul Moore615e51f2014-06-26 14:33:56 -04006038 if (avc_add_callback(selinux_netcache_avc_callback, AVC_CALLBACK_RESET))
6039 panic("SELinux: Unable to register AVC netcache callback\n");
6040
Eric Paris828dfe12008-04-17 13:17:49 -04006041 if (selinux_enforcing)
Eric Parisfadcdb42007-02-22 18:11:31 -05006042 printk(KERN_DEBUG "SELinux: Starting in enforcing mode\n");
Eric Paris828dfe12008-04-17 13:17:49 -04006043 else
Eric Parisfadcdb42007-02-22 18:11:31 -05006044 printk(KERN_DEBUG "SELinux: Starting in permissive mode\n");
Michael LeMayd7200242006-06-22 14:47:17 -07006045
Linus Torvalds1da177e2005-04-16 15:20:36 -07006046 return 0;
6047}
6048
Al Viroe8c26252010-03-23 06:36:54 -04006049static void delayed_superblock_init(struct super_block *sb, void *unused)
6050{
6051 superblock_doinit(sb, NULL);
6052}
6053
Linus Torvalds1da177e2005-04-16 15:20:36 -07006054void selinux_complete_init(void)
6055{
Eric Parisfadcdb42007-02-22 18:11:31 -05006056 printk(KERN_DEBUG "SELinux: Completing initialization.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07006057
6058 /* Set up any superblocks initialized prior to the policy load. */
Eric Parisfadcdb42007-02-22 18:11:31 -05006059 printk(KERN_DEBUG "SELinux: Setting up existing superblocks.\n");
Al Viroe8c26252010-03-23 06:36:54 -04006060 iterate_supers(delayed_superblock_init, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006061}
6062
6063/* SELinux requires early initialization in order to label
6064 all processes and objects when they are created. */
6065security_initcall(selinux_init);
6066
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08006067#if defined(CONFIG_NETFILTER)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006068
Jiri Pirko25db6be2014-09-03 17:42:13 +02006069static struct nf_hook_ops selinux_nf_ops[] = {
Paul Mooreeffad8d2008-01-29 08:49:27 -05006070 {
6071 .hook = selinux_ipv4_postroute,
6072 .owner = THIS_MODULE,
Alban Crequy2597a832012-05-14 03:56:39 +00006073 .pf = NFPROTO_IPV4,
Paul Mooreeffad8d2008-01-29 08:49:27 -05006074 .hooknum = NF_INET_POST_ROUTING,
6075 .priority = NF_IP_PRI_SELINUX_LAST,
6076 },
6077 {
6078 .hook = selinux_ipv4_forward,
6079 .owner = THIS_MODULE,
Alban Crequy2597a832012-05-14 03:56:39 +00006080 .pf = NFPROTO_IPV4,
Paul Mooreeffad8d2008-01-29 08:49:27 -05006081 .hooknum = NF_INET_FORWARD,
6082 .priority = NF_IP_PRI_SELINUX_FIRST,
Paul Moore948bf852008-10-10 10:16:32 -04006083 },
6084 {
6085 .hook = selinux_ipv4_output,
6086 .owner = THIS_MODULE,
Alban Crequy2597a832012-05-14 03:56:39 +00006087 .pf = NFPROTO_IPV4,
Paul Moore948bf852008-10-10 10:16:32 -04006088 .hooknum = NF_INET_LOCAL_OUT,
6089 .priority = NF_IP_PRI_SELINUX_FIRST,
Jiri Pirko25db6be2014-09-03 17:42:13 +02006090 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07006091#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Paul Mooreeffad8d2008-01-29 08:49:27 -05006092 {
6093 .hook = selinux_ipv6_postroute,
6094 .owner = THIS_MODULE,
Alban Crequy2597a832012-05-14 03:56:39 +00006095 .pf = NFPROTO_IPV6,
Paul Mooreeffad8d2008-01-29 08:49:27 -05006096 .hooknum = NF_INET_POST_ROUTING,
6097 .priority = NF_IP6_PRI_SELINUX_LAST,
6098 },
6099 {
6100 .hook = selinux_ipv6_forward,
6101 .owner = THIS_MODULE,
Alban Crequy2597a832012-05-14 03:56:39 +00006102 .pf = NFPROTO_IPV6,
Paul Mooreeffad8d2008-01-29 08:49:27 -05006103 .hooknum = NF_INET_FORWARD,
6104 .priority = NF_IP6_PRI_SELINUX_FIRST,
Jiri Pirko25db6be2014-09-03 17:42:13 +02006105 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07006106#endif /* IPV6 */
Jiri Pirko25db6be2014-09-03 17:42:13 +02006107};
Linus Torvalds1da177e2005-04-16 15:20:36 -07006108
6109static int __init selinux_nf_ip_init(void)
6110{
Jiri Pirko25db6be2014-09-03 17:42:13 +02006111 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006112
6113 if (!selinux_enabled)
Jiri Pirko25db6be2014-09-03 17:42:13 +02006114 return 0;
Eric Parisfadcdb42007-02-22 18:11:31 -05006115
6116 printk(KERN_DEBUG "SELinux: Registering netfilter hooks\n");
6117
Jiri Pirko25db6be2014-09-03 17:42:13 +02006118 err = nf_register_hooks(selinux_nf_ops, ARRAY_SIZE(selinux_nf_ops));
Alexey Dobriyan6c5a9d22008-07-26 17:48:15 -07006119 if (err)
Jiri Pirko25db6be2014-09-03 17:42:13 +02006120 panic("SELinux: nf_register_hooks: error %d\n", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006121
Jiri Pirko25db6be2014-09-03 17:42:13 +02006122 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006123}
6124
6125__initcall(selinux_nf_ip_init);
6126
6127#ifdef CONFIG_SECURITY_SELINUX_DISABLE
6128static void selinux_nf_ip_exit(void)
6129{
Eric Parisfadcdb42007-02-22 18:11:31 -05006130 printk(KERN_DEBUG "SELinux: Unregistering netfilter hooks\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07006131
Jiri Pirko25db6be2014-09-03 17:42:13 +02006132 nf_unregister_hooks(selinux_nf_ops, ARRAY_SIZE(selinux_nf_ops));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006133}
6134#endif
6135
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08006136#else /* CONFIG_NETFILTER */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006137
6138#ifdef CONFIG_SECURITY_SELINUX_DISABLE
6139#define selinux_nf_ip_exit()
6140#endif
6141
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08006142#endif /* CONFIG_NETFILTER */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006143
6144#ifdef CONFIG_SECURITY_SELINUX_DISABLE
Eric Paris828dfe12008-04-17 13:17:49 -04006145static int selinux_disabled;
6146
Linus Torvalds1da177e2005-04-16 15:20:36 -07006147int selinux_disable(void)
6148{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006149 if (ss_initialized) {
6150 /* Not permitted after initial policy load. */
6151 return -EINVAL;
6152 }
6153
6154 if (selinux_disabled) {
6155 /* Only do this once. */
6156 return -EINVAL;
6157 }
6158
6159 printk(KERN_INFO "SELinux: Disabled at runtime.\n");
6160
6161 selinux_disabled = 1;
Stephen Smalley30d55282006-05-03 10:52:36 -04006162 selinux_enabled = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006163
wzt.wzt@gmail.com189b3b12010-02-23 23:15:28 +08006164 reset_security_ops();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006165
Eric Parisaf8ff042009-09-20 21:23:01 -04006166 /* Try to destroy the avc node cache */
6167 avc_disable();
6168
Linus Torvalds1da177e2005-04-16 15:20:36 -07006169 /* Unregister netfilter hooks. */
6170 selinux_nf_ip_exit();
6171
6172 /* Unregister selinuxfs. */
6173 exit_sel_fs();
6174
6175 return 0;
6176}
6177#endif