blob: ef3bd9d61c38cd0f2fd927786ede1199bba82fd6 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * NSA Security-Enhanced Linux (SELinux) security module
3 *
4 * This file contains the SELinux hook function implementations.
5 *
6 * Authors: Stephen Smalley, <sds@epoch.ncsc.mil>
Eric Paris828dfe12008-04-17 13:17:49 -04007 * Chris Vance, <cvance@nai.com>
8 * Wayne Salamon, <wsalamon@nai.com>
9 * James Morris <jmorris@redhat.com>
Linus Torvalds1da177e2005-04-16 15:20:36 -070010 *
11 * Copyright (C) 2001,2002 Networks Associates Technology, Inc.
Eric Paris2069f452008-07-04 09:47:13 +100012 * Copyright (C) 2003-2008 Red Hat, Inc., James Morris <jmorris@redhat.com>
13 * Eric Paris <eparis@redhat.com>
Linus Torvalds1da177e2005-04-16 15:20:36 -070014 * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
Eric Paris828dfe12008-04-17 13:17:49 -040015 * <dgoeddel@trustedcs.com>
Paul Mooreed6d76e2009-08-28 18:12:49 -040016 * Copyright (C) 2006, 2007, 2009 Hewlett-Packard Development Company, L.P.
Paul Moore82c21bf2011-08-01 11:10:33 +000017 * Paul Moore <paul@paul-moore.com>
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +090018 * Copyright (C) 2007 Hitachi Software Engineering Co., Ltd.
Eric Paris828dfe12008-04-17 13:17:49 -040019 * Yuichi Nakamura <ynakam@hitachisoft.jp>
Linus Torvalds1da177e2005-04-16 15:20:36 -070020 *
21 * This program is free software; you can redistribute it and/or modify
22 * it under the terms of the GNU General Public License version 2,
Eric Paris828dfe12008-04-17 13:17:49 -040023 * as published by the Free Software Foundation.
Linus Torvalds1da177e2005-04-16 15:20:36 -070024 */
25
Linus Torvalds1da177e2005-04-16 15:20:36 -070026#include <linux/init.h>
Eric Paris0b24dcb2011-02-25 15:39:20 -050027#include <linux/kd.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070028#include <linux/kernel.h>
Roland McGrath0d094ef2008-07-25 19:45:49 -070029#include <linux/tracehook.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070030#include <linux/errno.h>
31#include <linux/sched.h>
Casey Schaufler3c4ed7b2015-05-02 15:10:46 -070032#include <linux/lsm_hooks.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070033#include <linux/xattr.h>
34#include <linux/capability.h>
35#include <linux/unistd.h>
36#include <linux/mm.h>
37#include <linux/mman.h>
38#include <linux/slab.h>
39#include <linux/pagemap.h>
Eric Paris0b24dcb2011-02-25 15:39:20 -050040#include <linux/proc_fs.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070041#include <linux/swap.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070042#include <linux/spinlock.h>
43#include <linux/syscalls.h>
Eric Paris2a7dba32011-02-01 11:05:39 -050044#include <linux/dcache.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070045#include <linux/file.h>
Al Viro9f3acc32008-04-24 07:44:08 -040046#include <linux/fdtable.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070047#include <linux/namei.h>
48#include <linux/mount.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070049#include <linux/netfilter_ipv4.h>
50#include <linux/netfilter_ipv6.h>
51#include <linux/tty.h>
52#include <net/icmp.h>
Stephen Hemminger227b60f2007-10-10 17:30:46 -070053#include <net/ip.h> /* for local_port_range[] */
Linus Torvalds1da177e2005-04-16 15:20:36 -070054#include <net/tcp.h> /* struct or_callable used in sock_rcv_skb */
Paul Moore47180062013-12-04 16:10:45 -050055#include <net/inet_connection_sock.h>
Paul Moore220deb92008-01-29 08:38:23 -050056#include <net/net_namespace.h>
Paul Moored621d352008-01-29 08:43:36 -050057#include <net/netlabel.h>
Eric Parisf5269712008-05-14 11:27:45 -040058#include <linux/uaccess.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070059#include <asm/ioctls.h>
Arun Sharma600634972011-07-26 16:09:06 -070060#include <linux/atomic.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070061#include <linux/bitops.h>
62#include <linux/interrupt.h>
63#include <linux/netdevice.h> /* for network interface checks */
Hong zhi guo77954982013-03-27 06:49:35 +000064#include <net/netlink.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070065#include <linux/tcp.h>
66#include <linux/udp.h>
James Morris2ee92d42006-11-13 16:09:01 -080067#include <linux/dccp.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070068#include <linux/quota.h>
69#include <linux/un.h> /* for Unix socket types */
70#include <net/af_unix.h> /* for Unix socket types */
71#include <linux/parser.h>
72#include <linux/nfs_mount.h>
73#include <net/ipv6.h>
74#include <linux/hugetlb.h>
75#include <linux/personality.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070076#include <linux/audit.h>
Eric Paris6931dfc2005-06-30 02:58:51 -070077#include <linux/string.h>
Catherine Zhang877ce7c2006-06-29 12:27:47 -070078#include <linux/selinux.h>
Eric Paris23970742006-09-25 23:32:01 -070079#include <linux/mutex.h>
Frank Mayharf06febc2008-09-12 09:54:39 -070080#include <linux/posix-timers.h>
Kees Cook00234592010-02-03 15:36:43 -080081#include <linux/syslog.h>
Serge E. Hallyn34867402011-03-23 16:43:17 -070082#include <linux/user_namespace.h>
Paul Gortmaker44fc7ea2011-05-26 20:52:10 -040083#include <linux/export.h>
Al Viro40401532012-02-13 03:58:52 +000084#include <linux/msg.h>
85#include <linux/shm.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070086
87#include "avc.h"
88#include "objsec.h"
89#include "netif.h"
Paul Moore224dfbd2008-01-29 08:38:13 -050090#include "netnode.h"
Paul Moore3e112172008-04-10 10:48:14 -040091#include "netport.h"
Trent Jaegerd28d1e02005-12-13 23:12:40 -080092#include "xfrm.h"
Paul Moorec60475b2007-02-28 15:14:23 -050093#include "netlabel.h"
Ahmed S. Darwish9d57a7f2008-03-01 22:03:14 +020094#include "audit.h"
James Morris7b98a582011-08-30 12:52:32 +100095#include "avc_ss.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070096
Paul Moored621d352008-01-29 08:43:36 -050097/* SECMARK reference count */
James Morris56a4ca92011-08-17 11:08:43 +100098static atomic_t selinux_secmark_refcount = ATOMIC_INIT(0);
Paul Moored621d352008-01-29 08:43:36 -050099
Linus Torvalds1da177e2005-04-16 15:20:36 -0700100#ifdef CONFIG_SECURITY_SELINUX_DEVELOP
Eric Paris828dfe12008-04-17 13:17:49 -0400101int selinux_enforcing;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700102
103static int __init enforcing_setup(char *str)
104{
Eric Parisf5269712008-05-14 11:27:45 -0400105 unsigned long enforcing;
Jingoo Han29707b22014-02-05 15:13:14 +0900106 if (!kstrtoul(str, 0, &enforcing))
Eric Parisf5269712008-05-14 11:27:45 -0400107 selinux_enforcing = enforcing ? 1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108 return 1;
109}
110__setup("enforcing=", enforcing_setup);
111#endif
112
113#ifdef CONFIG_SECURITY_SELINUX_BOOTPARAM
114int selinux_enabled = CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE;
115
116static int __init selinux_enabled_setup(char *str)
117{
Eric Parisf5269712008-05-14 11:27:45 -0400118 unsigned long enabled;
Jingoo Han29707b22014-02-05 15:13:14 +0900119 if (!kstrtoul(str, 0, &enabled))
Eric Parisf5269712008-05-14 11:27:45 -0400120 selinux_enabled = enabled ? 1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700121 return 1;
122}
123__setup("selinux=", selinux_enabled_setup);
Stephen Smalley30d55282006-05-03 10:52:36 -0400124#else
125int selinux_enabled = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126#endif
127
Christoph Lametere18b8902006-12-06 20:33:20 -0800128static struct kmem_cache *sel_inode_cache;
Sangwoo63205652015-10-21 17:44:30 -0400129static struct kmem_cache *file_security_cache;
James Morris7cae7e22006-03-22 00:09:22 -0800130
Paul Moored621d352008-01-29 08:43:36 -0500131/**
132 * selinux_secmark_enabled - Check to see if SECMARK is currently enabled
133 *
134 * Description:
135 * This function checks the SECMARK reference counter to see if any SECMARK
136 * targets are currently configured, if the reference counter is greater than
137 * zero SECMARK is considered to be enabled. Returns true (1) if SECMARK is
Chris PeBenito2be4d742013-05-03 09:05:39 -0400138 * enabled, false (0) if SECMARK is disabled. If the always_check_network
139 * policy capability is enabled, SECMARK is always considered enabled.
Paul Moored621d352008-01-29 08:43:36 -0500140 *
141 */
142static int selinux_secmark_enabled(void)
143{
Chris PeBenito2be4d742013-05-03 09:05:39 -0400144 return (selinux_policycap_alwaysnetwork || atomic_read(&selinux_secmark_refcount));
145}
146
147/**
148 * selinux_peerlbl_enabled - Check to see if peer labeling is currently enabled
149 *
150 * Description:
151 * This function checks if NetLabel or labeled IPSEC is enabled. Returns true
152 * (1) if any are enabled or false (0) if neither are enabled. If the
153 * always_check_network policy capability is enabled, peer labeling
154 * is always considered enabled.
155 *
156 */
157static int selinux_peerlbl_enabled(void)
158{
159 return (selinux_policycap_alwaysnetwork || netlbl_enabled() || selinux_xfrm_enabled());
Paul Moored621d352008-01-29 08:43:36 -0500160}
161
Paul Moore615e51f2014-06-26 14:33:56 -0400162static int selinux_netcache_avc_callback(u32 event)
163{
164 if (event == AVC_CALLBACK_RESET) {
165 sel_netif_flush();
166 sel_netnode_flush();
167 sel_netport_flush();
168 synchronize_net();
169 }
170 return 0;
171}
172
David Howellsd84f4f92008-11-14 10:39:23 +1100173/*
174 * initialise the security for the init task
175 */
176static void cred_init_security(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700177{
David Howells3b11a1d2008-11-14 10:39:26 +1100178 struct cred *cred = (struct cred *) current->real_cred;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700179 struct task_security_struct *tsec;
180
James Morris89d155e2005-10-30 14:59:21 -0800181 tsec = kzalloc(sizeof(struct task_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700182 if (!tsec)
David Howellsd84f4f92008-11-14 10:39:23 +1100183 panic("SELinux: Failed to initialize initial task.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700184
David Howellsd84f4f92008-11-14 10:39:23 +1100185 tsec->osid = tsec->sid = SECINITSID_KERNEL;
David Howellsf1752ee2008-11-14 10:39:17 +1100186 cred->security = tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700187}
188
David Howells275bb412008-11-14 10:39:19 +1100189/*
David Howells88e67f32008-11-14 10:39:21 +1100190 * get the security ID of a set of credentials
191 */
192static inline u32 cred_sid(const struct cred *cred)
193{
194 const struct task_security_struct *tsec;
195
196 tsec = cred->security;
197 return tsec->sid;
198}
199
200/*
David Howells3b11a1d2008-11-14 10:39:26 +1100201 * get the objective security ID of a task
David Howells275bb412008-11-14 10:39:19 +1100202 */
203static inline u32 task_sid(const struct task_struct *task)
204{
David Howells275bb412008-11-14 10:39:19 +1100205 u32 sid;
206
207 rcu_read_lock();
David Howells88e67f32008-11-14 10:39:21 +1100208 sid = cred_sid(__task_cred(task));
David Howells275bb412008-11-14 10:39:19 +1100209 rcu_read_unlock();
210 return sid;
211}
212
213/*
David Howells3b11a1d2008-11-14 10:39:26 +1100214 * get the subjective security ID of the current task
David Howells275bb412008-11-14 10:39:19 +1100215 */
216static inline u32 current_sid(void)
217{
Paul Moore5fb49872010-04-22 14:46:19 -0400218 const struct task_security_struct *tsec = current_security();
David Howells275bb412008-11-14 10:39:19 +1100219
220 return tsec->sid;
221}
222
David Howells88e67f32008-11-14 10:39:21 +1100223/* Allocate and free functions for each kind of security blob. */
224
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225static int inode_alloc_security(struct inode *inode)
226{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700227 struct inode_security_struct *isec;
David Howells275bb412008-11-14 10:39:19 +1100228 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700229
Josef Bacika02fe132008-04-04 09:35:05 +1100230 isec = kmem_cache_zalloc(sel_inode_cache, GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700231 if (!isec)
232 return -ENOMEM;
233
Eric Paris23970742006-09-25 23:32:01 -0700234 mutex_init(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700235 INIT_LIST_HEAD(&isec->list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700236 isec->inode = inode;
237 isec->sid = SECINITSID_UNLABELED;
238 isec->sclass = SECCLASS_FILE;
David Howells275bb412008-11-14 10:39:19 +1100239 isec->task_sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700240 inode->i_security = isec;
241
242 return 0;
243}
244
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500245/*
246 * Get the security label of an inode.
247 */
248static struct inode_security_struct *inode_security(struct inode *inode)
249{
250 return inode->i_security;
251}
252
253/*
254 * Get the security label of a dentry's backing inode.
255 */
256static struct inode_security_struct *backing_inode_security(struct dentry *dentry)
257{
258 struct inode *inode = d_backing_inode(dentry);
259
260 return inode->i_security;
261}
262
Steven Rostedt3dc91d42014-01-09 21:46:34 -0500263static void inode_free_rcu(struct rcu_head *head)
264{
265 struct inode_security_struct *isec;
266
267 isec = container_of(head, struct inode_security_struct, rcu);
268 kmem_cache_free(sel_inode_cache, isec);
269}
270
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271static void inode_free_security(struct inode *inode)
272{
273 struct inode_security_struct *isec = inode->i_security;
274 struct superblock_security_struct *sbsec = inode->i_sb->s_security;
275
Waiman Long9629d042015-07-10 17:19:56 -0400276 /*
277 * As not all inode security structures are in a list, we check for
278 * empty list outside of the lock to make sure that we won't waste
279 * time taking a lock doing nothing.
280 *
281 * The list_del_init() function can be safely called more than once.
282 * It should not be possible for this function to be called with
283 * concurrent list_add(), but for better safety against future changes
284 * in the code, we use list_empty_careful() here.
285 */
286 if (!list_empty_careful(&isec->list)) {
287 spin_lock(&sbsec->isec_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288 list_del_init(&isec->list);
Waiman Long9629d042015-07-10 17:19:56 -0400289 spin_unlock(&sbsec->isec_lock);
290 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291
Steven Rostedt3dc91d42014-01-09 21:46:34 -0500292 /*
293 * The inode may still be referenced in a path walk and
294 * a call to selinux_inode_permission() can be made
295 * after inode_free_security() is called. Ideally, the VFS
296 * wouldn't do this, but fixing that is a much harder
297 * job. For now, simply free the i_security via RCU, and
298 * leave the current inode->i_security pointer intact.
299 * The inode will be freed after the RCU grace period too.
300 */
301 call_rcu(&isec->rcu, inode_free_rcu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700302}
303
304static int file_alloc_security(struct file *file)
305{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700306 struct file_security_struct *fsec;
David Howells275bb412008-11-14 10:39:19 +1100307 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700308
Sangwoo63205652015-10-21 17:44:30 -0400309 fsec = kmem_cache_zalloc(file_security_cache, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700310 if (!fsec)
311 return -ENOMEM;
312
David Howells275bb412008-11-14 10:39:19 +1100313 fsec->sid = sid;
314 fsec->fown_sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700315 file->f_security = fsec;
316
317 return 0;
318}
319
320static void file_free_security(struct file *file)
321{
322 struct file_security_struct *fsec = file->f_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700323 file->f_security = NULL;
Sangwoo63205652015-10-21 17:44:30 -0400324 kmem_cache_free(file_security_cache, fsec);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700325}
326
327static int superblock_alloc_security(struct super_block *sb)
328{
329 struct superblock_security_struct *sbsec;
330
James Morris89d155e2005-10-30 14:59:21 -0800331 sbsec = kzalloc(sizeof(struct superblock_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700332 if (!sbsec)
333 return -ENOMEM;
334
Eric Parisbc7e9822006-09-25 23:32:02 -0700335 mutex_init(&sbsec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700336 INIT_LIST_HEAD(&sbsec->isec_head);
337 spin_lock_init(&sbsec->isec_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700338 sbsec->sb = sb;
339 sbsec->sid = SECINITSID_UNLABELED;
340 sbsec->def_sid = SECINITSID_FILE;
Eric Parisc312feb2006-07-10 04:43:53 -0700341 sbsec->mntpoint_sid = SECINITSID_UNLABELED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700342 sb->s_security = sbsec;
343
344 return 0;
345}
346
347static void superblock_free_security(struct super_block *sb)
348{
349 struct superblock_security_struct *sbsec = sb->s_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350 sb->s_security = NULL;
351 kfree(sbsec);
352}
353
Linus Torvalds1da177e2005-04-16 15:20:36 -0700354/* The file system's label must be initialized prior to use. */
355
David Quigleyeb9ae682013-05-22 12:50:37 -0400356static const char *labeling_behaviors[7] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357 "uses xattr",
358 "uses transition SIDs",
359 "uses task SIDs",
360 "uses genfs_contexts",
361 "not configured for labeling",
362 "uses mountpoint labeling",
David Quigleyeb9ae682013-05-22 12:50:37 -0400363 "uses native labeling",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700364};
365
366static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry);
367
368static inline int inode_doinit(struct inode *inode)
369{
370 return inode_doinit_with_dentry(inode, NULL);
371}
372
373enum {
Eric Paris31e87932007-09-19 17:19:12 -0400374 Opt_error = -1,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375 Opt_context = 1,
376 Opt_fscontext = 2,
Eric Parisc9180a52007-11-30 13:00:35 -0500377 Opt_defcontext = 3,
378 Opt_rootcontext = 4,
David P. Quigley11689d42009-01-16 09:22:03 -0500379 Opt_labelsupport = 5,
Eric Parisd355987f2012-08-24 15:58:53 -0400380 Opt_nextmntopt = 6,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381};
382
Eric Parisd355987f2012-08-24 15:58:53 -0400383#define NUM_SEL_MNT_OPTS (Opt_nextmntopt - 1)
384
Steven Whitehousea447c092008-10-13 10:46:57 +0100385static const match_table_t tokens = {
Eric Paris832cbd92008-04-01 13:24:09 -0400386 {Opt_context, CONTEXT_STR "%s"},
387 {Opt_fscontext, FSCONTEXT_STR "%s"},
388 {Opt_defcontext, DEFCONTEXT_STR "%s"},
389 {Opt_rootcontext, ROOTCONTEXT_STR "%s"},
David P. Quigley11689d42009-01-16 09:22:03 -0500390 {Opt_labelsupport, LABELSUPP_STR},
Eric Paris31e87932007-09-19 17:19:12 -0400391 {Opt_error, NULL},
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392};
393
394#define SEL_MOUNT_FAIL_MSG "SELinux: duplicate or incompatible mount options\n"
395
Eric Parisc312feb2006-07-10 04:43:53 -0700396static int may_context_mount_sb_relabel(u32 sid,
397 struct superblock_security_struct *sbsec,
David Howells275bb412008-11-14 10:39:19 +1100398 const struct cred *cred)
Eric Parisc312feb2006-07-10 04:43:53 -0700399{
David Howells275bb412008-11-14 10:39:19 +1100400 const struct task_security_struct *tsec = cred->security;
Eric Parisc312feb2006-07-10 04:43:53 -0700401 int rc;
402
403 rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
404 FILESYSTEM__RELABELFROM, NULL);
405 if (rc)
406 return rc;
407
408 rc = avc_has_perm(tsec->sid, sid, SECCLASS_FILESYSTEM,
409 FILESYSTEM__RELABELTO, NULL);
410 return rc;
411}
412
Eric Paris08089252006-07-10 04:43:55 -0700413static int may_context_mount_inode_relabel(u32 sid,
414 struct superblock_security_struct *sbsec,
David Howells275bb412008-11-14 10:39:19 +1100415 const struct cred *cred)
Eric Paris08089252006-07-10 04:43:55 -0700416{
David Howells275bb412008-11-14 10:39:19 +1100417 const struct task_security_struct *tsec = cred->security;
Eric Paris08089252006-07-10 04:43:55 -0700418 int rc;
419 rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
420 FILESYSTEM__RELABELFROM, NULL);
421 if (rc)
422 return rc;
423
424 rc = avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM,
425 FILESYSTEM__ASSOCIATE, NULL);
426 return rc;
427}
428
Eric Parisb43e7252012-10-10 14:27:35 -0400429static int selinux_is_sblabel_mnt(struct super_block *sb)
430{
431 struct superblock_security_struct *sbsec = sb->s_security;
432
Mark Salyzynd5f3a5f2015-02-04 11:34:30 -0500433 return sbsec->behavior == SECURITY_FS_USE_XATTR ||
434 sbsec->behavior == SECURITY_FS_USE_TRANS ||
435 sbsec->behavior == SECURITY_FS_USE_TASK ||
J. Bruce Fields9fc2b4b2015-06-04 15:57:25 -0400436 sbsec->behavior == SECURITY_FS_USE_NATIVE ||
Mark Salyzynd5f3a5f2015-02-04 11:34:30 -0500437 /* Special handling. Genfs but also in-core setxattr handler */
438 !strcmp(sb->s_type->name, "sysfs") ||
439 !strcmp(sb->s_type->name, "pstore") ||
440 !strcmp(sb->s_type->name, "debugfs") ||
441 !strcmp(sb->s_type->name, "rootfs");
Eric Parisb43e7252012-10-10 14:27:35 -0400442}
443
Eric Parisc9180a52007-11-30 13:00:35 -0500444static int sb_finish_set_opts(struct super_block *sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700445{
446 struct superblock_security_struct *sbsec = sb->s_security;
447 struct dentry *root = sb->s_root;
David Howellsc6f493d2015-03-17 22:26:22 +0000448 struct inode *root_inode = d_backing_inode(root);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449 int rc = 0;
450
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451 if (sbsec->behavior == SECURITY_FS_USE_XATTR) {
452 /* Make sure that the xattr handler exists and that no
453 error other than -ENODATA is returned by getxattr on
454 the root directory. -ENODATA is ok, as this may be
455 the first boot of the SELinux kernel before we have
456 assigned xattr values to the filesystem. */
Eric Parisc9180a52007-11-30 13:00:35 -0500457 if (!root_inode->i_op->getxattr) {
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800458 printk(KERN_WARNING "SELinux: (dev %s, type %s) has no "
459 "xattr support\n", sb->s_id, sb->s_type->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460 rc = -EOPNOTSUPP;
461 goto out;
462 }
Eric Parisc9180a52007-11-30 13:00:35 -0500463 rc = root_inode->i_op->getxattr(root, XATTR_NAME_SELINUX, NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700464 if (rc < 0 && rc != -ENODATA) {
465 if (rc == -EOPNOTSUPP)
466 printk(KERN_WARNING "SELinux: (dev %s, type "
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800467 "%s) has no security xattr handler\n",
468 sb->s_id, sb->s_type->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469 else
470 printk(KERN_WARNING "SELinux: (dev %s, type "
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800471 "%s) getxattr errno %d\n", sb->s_id,
472 sb->s_type->name, -rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700473 goto out;
474 }
475 }
476
Eric Parisc9180a52007-11-30 13:00:35 -0500477 if (sbsec->behavior > ARRAY_SIZE(labeling_behaviors))
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800478 printk(KERN_ERR "SELinux: initialized (dev %s, type %s), unknown behavior\n",
479 sb->s_id, sb->s_type->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700480
Eric Pariseadcabc2012-08-24 15:59:14 -0400481 sbsec->flags |= SE_SBINITIALIZED;
Eric Parisb43e7252012-10-10 14:27:35 -0400482 if (selinux_is_sblabel_mnt(sb))
Eric Paris12f348b2012-10-09 10:56:25 -0400483 sbsec->flags |= SBLABEL_MNT;
David P. Quigleyddd29ec2009-09-09 14:25:37 -0400484
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485 /* Initialize the root inode. */
Eric Parisc9180a52007-11-30 13:00:35 -0500486 rc = inode_doinit_with_dentry(root_inode, root);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700487
488 /* Initialize any other inodes associated with the superblock, e.g.
489 inodes created prior to initial policy load or inodes created
490 during get_sb by a pseudo filesystem that directly
491 populates itself. */
492 spin_lock(&sbsec->isec_lock);
493next_inode:
494 if (!list_empty(&sbsec->isec_head)) {
495 struct inode_security_struct *isec =
496 list_entry(sbsec->isec_head.next,
Eric Parisc9180a52007-11-30 13:00:35 -0500497 struct inode_security_struct, list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498 struct inode *inode = isec->inode;
Stephen Smalley923190d2014-10-06 16:32:52 -0400499 list_del_init(&isec->list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700500 spin_unlock(&sbsec->isec_lock);
501 inode = igrab(inode);
502 if (inode) {
Eric Parisc9180a52007-11-30 13:00:35 -0500503 if (!IS_PRIVATE(inode))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700504 inode_doinit(inode);
505 iput(inode);
506 }
507 spin_lock(&sbsec->isec_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700508 goto next_inode;
509 }
510 spin_unlock(&sbsec->isec_lock);
511out:
Eric Parisc9180a52007-11-30 13:00:35 -0500512 return rc;
513}
514
515/*
516 * This function should allow an FS to ask what it's mount security
517 * options were so it can use those later for submounts, displaying
518 * mount options, or whatever.
519 */
520static int selinux_get_mnt_opts(const struct super_block *sb,
Eric Parise0007522008-03-05 10:31:54 -0500521 struct security_mnt_opts *opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500522{
523 int rc = 0, i;
524 struct superblock_security_struct *sbsec = sb->s_security;
525 char *context = NULL;
526 u32 len;
527 char tmp;
528
Eric Parise0007522008-03-05 10:31:54 -0500529 security_init_mnt_opts(opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500530
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500531 if (!(sbsec->flags & SE_SBINITIALIZED))
Eric Parisc9180a52007-11-30 13:00:35 -0500532 return -EINVAL;
533
534 if (!ss_initialized)
535 return -EINVAL;
536
Eric Parisaf8e50c2012-08-24 15:59:00 -0400537 /* make sure we always check enough bits to cover the mask */
538 BUILD_BUG_ON(SE_MNTMASK >= (1 << NUM_SEL_MNT_OPTS));
539
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500540 tmp = sbsec->flags & SE_MNTMASK;
Eric Parisc9180a52007-11-30 13:00:35 -0500541 /* count the number of mount options for this sb */
Eric Parisaf8e50c2012-08-24 15:59:00 -0400542 for (i = 0; i < NUM_SEL_MNT_OPTS; i++) {
Eric Parisc9180a52007-11-30 13:00:35 -0500543 if (tmp & 0x01)
Eric Parise0007522008-03-05 10:31:54 -0500544 opts->num_mnt_opts++;
Eric Parisc9180a52007-11-30 13:00:35 -0500545 tmp >>= 1;
546 }
David P. Quigley11689d42009-01-16 09:22:03 -0500547 /* Check if the Label support flag is set */
Eric Paris0b4bdb32013-08-28 13:32:42 -0400548 if (sbsec->flags & SBLABEL_MNT)
David P. Quigley11689d42009-01-16 09:22:03 -0500549 opts->num_mnt_opts++;
Eric Parisc9180a52007-11-30 13:00:35 -0500550
Eric Parise0007522008-03-05 10:31:54 -0500551 opts->mnt_opts = kcalloc(opts->num_mnt_opts, sizeof(char *), GFP_ATOMIC);
552 if (!opts->mnt_opts) {
Eric Parisc9180a52007-11-30 13:00:35 -0500553 rc = -ENOMEM;
554 goto out_free;
555 }
556
Eric Parise0007522008-03-05 10:31:54 -0500557 opts->mnt_opts_flags = kcalloc(opts->num_mnt_opts, sizeof(int), GFP_ATOMIC);
558 if (!opts->mnt_opts_flags) {
Eric Parisc9180a52007-11-30 13:00:35 -0500559 rc = -ENOMEM;
560 goto out_free;
561 }
562
563 i = 0;
564 if (sbsec->flags & FSCONTEXT_MNT) {
565 rc = security_sid_to_context(sbsec->sid, &context, &len);
566 if (rc)
567 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500568 opts->mnt_opts[i] = context;
569 opts->mnt_opts_flags[i++] = FSCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500570 }
571 if (sbsec->flags & CONTEXT_MNT) {
572 rc = security_sid_to_context(sbsec->mntpoint_sid, &context, &len);
573 if (rc)
574 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500575 opts->mnt_opts[i] = context;
576 opts->mnt_opts_flags[i++] = CONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500577 }
578 if (sbsec->flags & DEFCONTEXT_MNT) {
579 rc = security_sid_to_context(sbsec->def_sid, &context, &len);
580 if (rc)
581 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500582 opts->mnt_opts[i] = context;
583 opts->mnt_opts_flags[i++] = DEFCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500584 }
585 if (sbsec->flags & ROOTCONTEXT_MNT) {
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500586 struct dentry *root = sbsec->sb->s_root;
587 struct inode_security_struct *isec = backing_inode_security(root);
Eric Parisc9180a52007-11-30 13:00:35 -0500588
589 rc = security_sid_to_context(isec->sid, &context, &len);
590 if (rc)
591 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500592 opts->mnt_opts[i] = context;
593 opts->mnt_opts_flags[i++] = ROOTCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500594 }
Eric Paris12f348b2012-10-09 10:56:25 -0400595 if (sbsec->flags & SBLABEL_MNT) {
David P. Quigley11689d42009-01-16 09:22:03 -0500596 opts->mnt_opts[i] = NULL;
Eric Paris12f348b2012-10-09 10:56:25 -0400597 opts->mnt_opts_flags[i++] = SBLABEL_MNT;
David P. Quigley11689d42009-01-16 09:22:03 -0500598 }
Eric Parisc9180a52007-11-30 13:00:35 -0500599
Eric Parise0007522008-03-05 10:31:54 -0500600 BUG_ON(i != opts->num_mnt_opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500601
602 return 0;
603
604out_free:
Eric Parise0007522008-03-05 10:31:54 -0500605 security_free_mnt_opts(opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500606 return rc;
607}
608
609static int bad_option(struct superblock_security_struct *sbsec, char flag,
610 u32 old_sid, u32 new_sid)
611{
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500612 char mnt_flags = sbsec->flags & SE_MNTMASK;
613
Eric Parisc9180a52007-11-30 13:00:35 -0500614 /* check if the old mount command had the same options */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500615 if (sbsec->flags & SE_SBINITIALIZED)
Eric Parisc9180a52007-11-30 13:00:35 -0500616 if (!(sbsec->flags & flag) ||
617 (old_sid != new_sid))
618 return 1;
619
620 /* check if we were passed the same options twice,
621 * aka someone passed context=a,context=b
622 */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500623 if (!(sbsec->flags & SE_SBINITIALIZED))
624 if (mnt_flags & flag)
Eric Parisc9180a52007-11-30 13:00:35 -0500625 return 1;
626 return 0;
627}
Eric Parise0007522008-03-05 10:31:54 -0500628
Eric Parisc9180a52007-11-30 13:00:35 -0500629/*
630 * Allow filesystems with binary mount data to explicitly set mount point
631 * labeling information.
632 */
Eric Parise0007522008-03-05 10:31:54 -0500633static int selinux_set_mnt_opts(struct super_block *sb,
David Quigley649f6e72013-05-22 12:50:36 -0400634 struct security_mnt_opts *opts,
635 unsigned long kern_flags,
636 unsigned long *set_kern_flags)
Eric Parisc9180a52007-11-30 13:00:35 -0500637{
David Howells275bb412008-11-14 10:39:19 +1100638 const struct cred *cred = current_cred();
Eric Parisc9180a52007-11-30 13:00:35 -0500639 int rc = 0, i;
Eric Parisc9180a52007-11-30 13:00:35 -0500640 struct superblock_security_struct *sbsec = sb->s_security;
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800641 const char *name = sb->s_type->name;
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500642 struct dentry *root = sbsec->sb->s_root;
643 struct inode_security_struct *root_isec = backing_inode_security(root);
Eric Parisc9180a52007-11-30 13:00:35 -0500644 u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0;
645 u32 defcontext_sid = 0;
Eric Parise0007522008-03-05 10:31:54 -0500646 char **mount_options = opts->mnt_opts;
647 int *flags = opts->mnt_opts_flags;
648 int num_opts = opts->num_mnt_opts;
Eric Parisc9180a52007-11-30 13:00:35 -0500649
650 mutex_lock(&sbsec->lock);
651
652 if (!ss_initialized) {
653 if (!num_opts) {
654 /* Defer initialization until selinux_complete_init,
655 after the initial policy is loaded and the security
656 server is ready to handle calls. */
Eric Parisc9180a52007-11-30 13:00:35 -0500657 goto out;
658 }
659 rc = -EINVAL;
Eric Paris744ba352008-04-17 11:52:44 -0400660 printk(KERN_WARNING "SELinux: Unable to set superblock options "
661 "before the security server is initialized\n");
Eric Parisc9180a52007-11-30 13:00:35 -0500662 goto out;
663 }
David Quigley649f6e72013-05-22 12:50:36 -0400664 if (kern_flags && !set_kern_flags) {
665 /* Specifying internal flags without providing a place to
666 * place the results is not allowed */
667 rc = -EINVAL;
668 goto out;
669 }
Eric Parisc9180a52007-11-30 13:00:35 -0500670
671 /*
Eric Parise0007522008-03-05 10:31:54 -0500672 * Binary mount data FS will come through this function twice. Once
673 * from an explicit call and once from the generic calls from the vfs.
674 * Since the generic VFS calls will not contain any security mount data
675 * we need to skip the double mount verification.
676 *
677 * This does open a hole in which we will not notice if the first
678 * mount using this sb set explict options and a second mount using
679 * this sb does not set any security options. (The first options
680 * will be used for both mounts)
681 */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500682 if ((sbsec->flags & SE_SBINITIALIZED) && (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)
Eric Parise0007522008-03-05 10:31:54 -0500683 && (num_opts == 0))
Eric Parisf5269712008-05-14 11:27:45 -0400684 goto out;
Eric Parise0007522008-03-05 10:31:54 -0500685
686 /*
Eric Parisc9180a52007-11-30 13:00:35 -0500687 * parse the mount options, check if they are valid sids.
688 * also check if someone is trying to mount the same sb more
689 * than once with different security options.
690 */
691 for (i = 0; i < num_opts; i++) {
692 u32 sid;
David P. Quigley11689d42009-01-16 09:22:03 -0500693
Eric Paris12f348b2012-10-09 10:56:25 -0400694 if (flags[i] == SBLABEL_MNT)
David P. Quigley11689d42009-01-16 09:22:03 -0500695 continue;
Rasmus Villemoes44be2f62015-10-21 17:44:25 -0400696 rc = security_context_str_to_sid(mount_options[i], &sid, GFP_KERNEL);
Eric Parisc9180a52007-11-30 13:00:35 -0500697 if (rc) {
Rasmus Villemoes44be2f62015-10-21 17:44:25 -0400698 printk(KERN_WARNING "SELinux: security_context_str_to_sid"
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800699 "(%s) failed for (dev %s, type %s) errno=%d\n",
700 mount_options[i], sb->s_id, name, rc);
Eric Parisc9180a52007-11-30 13:00:35 -0500701 goto out;
702 }
703 switch (flags[i]) {
704 case FSCONTEXT_MNT:
705 fscontext_sid = sid;
706
707 if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid,
708 fscontext_sid))
709 goto out_double_mount;
710
711 sbsec->flags |= FSCONTEXT_MNT;
712 break;
713 case CONTEXT_MNT:
714 context_sid = sid;
715
716 if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid,
717 context_sid))
718 goto out_double_mount;
719
720 sbsec->flags |= CONTEXT_MNT;
721 break;
722 case ROOTCONTEXT_MNT:
723 rootcontext_sid = sid;
724
725 if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid,
726 rootcontext_sid))
727 goto out_double_mount;
728
729 sbsec->flags |= ROOTCONTEXT_MNT;
730
731 break;
732 case DEFCONTEXT_MNT:
733 defcontext_sid = sid;
734
735 if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid,
736 defcontext_sid))
737 goto out_double_mount;
738
739 sbsec->flags |= DEFCONTEXT_MNT;
740
741 break;
742 default:
743 rc = -EINVAL;
744 goto out;
745 }
746 }
747
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500748 if (sbsec->flags & SE_SBINITIALIZED) {
Eric Parisc9180a52007-11-30 13:00:35 -0500749 /* previously mounted with options, but not on this attempt? */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500750 if ((sbsec->flags & SE_MNTMASK) && !num_opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500751 goto out_double_mount;
752 rc = 0;
753 goto out;
754 }
755
James Morris089be432008-07-15 18:32:49 +1000756 if (strcmp(sb->s_type->name, "proc") == 0)
Stephen Smalley134509d2015-06-04 16:22:17 -0400757 sbsec->flags |= SE_SBPROC | SE_SBGENFS;
758
Stephen Smalley8e014722015-06-04 16:22:17 -0400759 if (!strcmp(sb->s_type->name, "debugfs") ||
760 !strcmp(sb->s_type->name, "sysfs") ||
761 !strcmp(sb->s_type->name, "pstore"))
Stephen Smalley134509d2015-06-04 16:22:17 -0400762 sbsec->flags |= SE_SBGENFS;
Eric Parisc9180a52007-11-30 13:00:35 -0500763
David Quigleyeb9ae682013-05-22 12:50:37 -0400764 if (!sbsec->behavior) {
765 /*
766 * Determine the labeling behavior to use for this
767 * filesystem type.
768 */
Paul Moore98f700f2013-09-18 13:52:20 -0400769 rc = security_fs_use(sb);
David Quigleyeb9ae682013-05-22 12:50:37 -0400770 if (rc) {
771 printk(KERN_WARNING
772 "%s: security_fs_use(%s) returned %d\n",
773 __func__, sb->s_type->name, rc);
774 goto out;
775 }
Eric Parisc9180a52007-11-30 13:00:35 -0500776 }
Eric Parisc9180a52007-11-30 13:00:35 -0500777 /* sets the context of the superblock for the fs being mounted. */
778 if (fscontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100779 rc = may_context_mount_sb_relabel(fscontext_sid, sbsec, cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500780 if (rc)
781 goto out;
782
783 sbsec->sid = fscontext_sid;
784 }
785
786 /*
787 * Switch to using mount point labeling behavior.
788 * sets the label used on all file below the mountpoint, and will set
789 * the superblock context if not already set.
790 */
David Quigleyeb9ae682013-05-22 12:50:37 -0400791 if (kern_flags & SECURITY_LSM_NATIVE_LABELS && !context_sid) {
792 sbsec->behavior = SECURITY_FS_USE_NATIVE;
793 *set_kern_flags |= SECURITY_LSM_NATIVE_LABELS;
794 }
795
Eric Parisc9180a52007-11-30 13:00:35 -0500796 if (context_sid) {
797 if (!fscontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100798 rc = may_context_mount_sb_relabel(context_sid, sbsec,
799 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500800 if (rc)
801 goto out;
802 sbsec->sid = context_sid;
803 } else {
David Howells275bb412008-11-14 10:39:19 +1100804 rc = may_context_mount_inode_relabel(context_sid, sbsec,
805 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500806 if (rc)
807 goto out;
808 }
809 if (!rootcontext_sid)
810 rootcontext_sid = context_sid;
811
812 sbsec->mntpoint_sid = context_sid;
813 sbsec->behavior = SECURITY_FS_USE_MNTPOINT;
814 }
815
816 if (rootcontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100817 rc = may_context_mount_inode_relabel(rootcontext_sid, sbsec,
818 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500819 if (rc)
820 goto out;
821
822 root_isec->sid = rootcontext_sid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -0500823 root_isec->initialized = LABEL_INITIALIZED;
Eric Parisc9180a52007-11-30 13:00:35 -0500824 }
825
826 if (defcontext_sid) {
David Quigleyeb9ae682013-05-22 12:50:37 -0400827 if (sbsec->behavior != SECURITY_FS_USE_XATTR &&
828 sbsec->behavior != SECURITY_FS_USE_NATIVE) {
Eric Parisc9180a52007-11-30 13:00:35 -0500829 rc = -EINVAL;
830 printk(KERN_WARNING "SELinux: defcontext option is "
831 "invalid for this filesystem type\n");
832 goto out;
833 }
834
835 if (defcontext_sid != sbsec->def_sid) {
836 rc = may_context_mount_inode_relabel(defcontext_sid,
David Howells275bb412008-11-14 10:39:19 +1100837 sbsec, cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500838 if (rc)
839 goto out;
840 }
841
842 sbsec->def_sid = defcontext_sid;
843 }
844
845 rc = sb_finish_set_opts(sb);
846out:
Eric Parisbc7e9822006-09-25 23:32:02 -0700847 mutex_unlock(&sbsec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700848 return rc;
Eric Parisc9180a52007-11-30 13:00:35 -0500849out_double_mount:
850 rc = -EINVAL;
851 printk(KERN_WARNING "SELinux: mount invalid. Same superblock, different "
Linus Torvalds29b1deb2013-12-15 11:17:45 -0800852 "security settings for (dev %s, type %s)\n", sb->s_id, name);
Eric Parisc9180a52007-11-30 13:00:35 -0500853 goto out;
854}
855
Jeff Layton094f7b62013-04-01 08:14:24 -0400856static int selinux_cmp_sb_context(const struct super_block *oldsb,
857 const struct super_block *newsb)
858{
859 struct superblock_security_struct *old = oldsb->s_security;
860 struct superblock_security_struct *new = newsb->s_security;
861 char oldflags = old->flags & SE_MNTMASK;
862 char newflags = new->flags & SE_MNTMASK;
863
864 if (oldflags != newflags)
865 goto mismatch;
866 if ((oldflags & FSCONTEXT_MNT) && old->sid != new->sid)
867 goto mismatch;
868 if ((oldflags & CONTEXT_MNT) && old->mntpoint_sid != new->mntpoint_sid)
869 goto mismatch;
870 if ((oldflags & DEFCONTEXT_MNT) && old->def_sid != new->def_sid)
871 goto mismatch;
872 if (oldflags & ROOTCONTEXT_MNT) {
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500873 struct inode_security_struct *oldroot = backing_inode_security(oldsb->s_root);
874 struct inode_security_struct *newroot = backing_inode_security(newsb->s_root);
Jeff Layton094f7b62013-04-01 08:14:24 -0400875 if (oldroot->sid != newroot->sid)
876 goto mismatch;
877 }
878 return 0;
879mismatch:
880 printk(KERN_WARNING "SELinux: mount invalid. Same superblock, "
881 "different security settings for (dev %s, "
882 "type %s)\n", newsb->s_id, newsb->s_type->name);
883 return -EBUSY;
884}
885
886static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
Eric Parisc9180a52007-11-30 13:00:35 -0500887 struct super_block *newsb)
888{
889 const struct superblock_security_struct *oldsbsec = oldsb->s_security;
890 struct superblock_security_struct *newsbsec = newsb->s_security;
891
892 int set_fscontext = (oldsbsec->flags & FSCONTEXT_MNT);
893 int set_context = (oldsbsec->flags & CONTEXT_MNT);
894 int set_rootcontext = (oldsbsec->flags & ROOTCONTEXT_MNT);
895
Eric Paris0f5e6422008-04-21 16:24:11 -0400896 /*
897 * if the parent was able to be mounted it clearly had no special lsm
Al Viroe8c26252010-03-23 06:36:54 -0400898 * mount options. thus we can safely deal with this superblock later
Eric Paris0f5e6422008-04-21 16:24:11 -0400899 */
Al Viroe8c26252010-03-23 06:36:54 -0400900 if (!ss_initialized)
Jeff Layton094f7b62013-04-01 08:14:24 -0400901 return 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500902
Eric Parisc9180a52007-11-30 13:00:35 -0500903 /* how can we clone if the old one wasn't set up?? */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500904 BUG_ON(!(oldsbsec->flags & SE_SBINITIALIZED));
Eric Parisc9180a52007-11-30 13:00:35 -0500905
Jeff Layton094f7b62013-04-01 08:14:24 -0400906 /* if fs is reusing a sb, make sure that the contexts match */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500907 if (newsbsec->flags & SE_SBINITIALIZED)
Jeff Layton094f7b62013-04-01 08:14:24 -0400908 return selinux_cmp_sb_context(oldsb, newsb);
Eric Paris5a552612008-04-09 14:08:35 -0400909
Eric Parisc9180a52007-11-30 13:00:35 -0500910 mutex_lock(&newsbsec->lock);
911
912 newsbsec->flags = oldsbsec->flags;
913
914 newsbsec->sid = oldsbsec->sid;
915 newsbsec->def_sid = oldsbsec->def_sid;
916 newsbsec->behavior = oldsbsec->behavior;
917
918 if (set_context) {
919 u32 sid = oldsbsec->mntpoint_sid;
920
921 if (!set_fscontext)
922 newsbsec->sid = sid;
923 if (!set_rootcontext) {
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500924 struct inode_security_struct *newisec = backing_inode_security(newsb->s_root);
Eric Parisc9180a52007-11-30 13:00:35 -0500925 newisec->sid = sid;
926 }
927 newsbsec->mntpoint_sid = sid;
928 }
929 if (set_rootcontext) {
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -0500930 const struct inode_security_struct *oldisec = backing_inode_security(oldsb->s_root);
931 struct inode_security_struct *newisec = backing_inode_security(newsb->s_root);
Eric Parisc9180a52007-11-30 13:00:35 -0500932
933 newisec->sid = oldisec->sid;
934 }
935
936 sb_finish_set_opts(newsb);
937 mutex_unlock(&newsbsec->lock);
Jeff Layton094f7b62013-04-01 08:14:24 -0400938 return 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500939}
940
Adrian Bunk2e1479d2008-03-17 22:29:23 +0200941static int selinux_parse_opts_str(char *options,
942 struct security_mnt_opts *opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500943{
Eric Parise0007522008-03-05 10:31:54 -0500944 char *p;
Eric Parisc9180a52007-11-30 13:00:35 -0500945 char *context = NULL, *defcontext = NULL;
946 char *fscontext = NULL, *rootcontext = NULL;
Eric Parise0007522008-03-05 10:31:54 -0500947 int rc, num_mnt_opts = 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500948
Eric Parise0007522008-03-05 10:31:54 -0500949 opts->num_mnt_opts = 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500950
951 /* Standard string-based options. */
952 while ((p = strsep(&options, "|")) != NULL) {
953 int token;
954 substring_t args[MAX_OPT_ARGS];
955
956 if (!*p)
957 continue;
958
959 token = match_token(p, tokens, args);
960
961 switch (token) {
962 case Opt_context:
963 if (context || defcontext) {
964 rc = -EINVAL;
965 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
966 goto out_err;
967 }
968 context = match_strdup(&args[0]);
969 if (!context) {
970 rc = -ENOMEM;
971 goto out_err;
972 }
973 break;
974
975 case Opt_fscontext:
976 if (fscontext) {
977 rc = -EINVAL;
978 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
979 goto out_err;
980 }
981 fscontext = match_strdup(&args[0]);
982 if (!fscontext) {
983 rc = -ENOMEM;
984 goto out_err;
985 }
986 break;
987
988 case Opt_rootcontext:
989 if (rootcontext) {
990 rc = -EINVAL;
991 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
992 goto out_err;
993 }
994 rootcontext = match_strdup(&args[0]);
995 if (!rootcontext) {
996 rc = -ENOMEM;
997 goto out_err;
998 }
999 break;
1000
1001 case Opt_defcontext:
1002 if (context || defcontext) {
1003 rc = -EINVAL;
1004 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
1005 goto out_err;
1006 }
1007 defcontext = match_strdup(&args[0]);
1008 if (!defcontext) {
1009 rc = -ENOMEM;
1010 goto out_err;
1011 }
1012 break;
David P. Quigley11689d42009-01-16 09:22:03 -05001013 case Opt_labelsupport:
1014 break;
Eric Parisc9180a52007-11-30 13:00:35 -05001015 default:
1016 rc = -EINVAL;
1017 printk(KERN_WARNING "SELinux: unknown mount option\n");
1018 goto out_err;
1019
1020 }
1021 }
1022
Eric Parise0007522008-03-05 10:31:54 -05001023 rc = -ENOMEM;
1024 opts->mnt_opts = kcalloc(NUM_SEL_MNT_OPTS, sizeof(char *), GFP_ATOMIC);
1025 if (!opts->mnt_opts)
1026 goto out_err;
1027
1028 opts->mnt_opts_flags = kcalloc(NUM_SEL_MNT_OPTS, sizeof(int), GFP_ATOMIC);
1029 if (!opts->mnt_opts_flags) {
1030 kfree(opts->mnt_opts);
1031 goto out_err;
Eric Parisc9180a52007-11-30 13:00:35 -05001032 }
1033
Eric Parise0007522008-03-05 10:31:54 -05001034 if (fscontext) {
1035 opts->mnt_opts[num_mnt_opts] = fscontext;
1036 opts->mnt_opts_flags[num_mnt_opts++] = FSCONTEXT_MNT;
1037 }
1038 if (context) {
1039 opts->mnt_opts[num_mnt_opts] = context;
1040 opts->mnt_opts_flags[num_mnt_opts++] = CONTEXT_MNT;
1041 }
1042 if (rootcontext) {
1043 opts->mnt_opts[num_mnt_opts] = rootcontext;
1044 opts->mnt_opts_flags[num_mnt_opts++] = ROOTCONTEXT_MNT;
1045 }
1046 if (defcontext) {
1047 opts->mnt_opts[num_mnt_opts] = defcontext;
1048 opts->mnt_opts_flags[num_mnt_opts++] = DEFCONTEXT_MNT;
1049 }
1050
1051 opts->num_mnt_opts = num_mnt_opts;
1052 return 0;
1053
Eric Parisc9180a52007-11-30 13:00:35 -05001054out_err:
1055 kfree(context);
1056 kfree(defcontext);
1057 kfree(fscontext);
1058 kfree(rootcontext);
1059 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001060}
Eric Parise0007522008-03-05 10:31:54 -05001061/*
1062 * string mount options parsing and call set the sbsec
1063 */
1064static int superblock_doinit(struct super_block *sb, void *data)
1065{
1066 int rc = 0;
1067 char *options = data;
1068 struct security_mnt_opts opts;
1069
1070 security_init_mnt_opts(&opts);
1071
1072 if (!data)
1073 goto out;
1074
1075 BUG_ON(sb->s_type->fs_flags & FS_BINARY_MOUNTDATA);
1076
1077 rc = selinux_parse_opts_str(options, &opts);
1078 if (rc)
1079 goto out_err;
1080
1081out:
David Quigley649f6e72013-05-22 12:50:36 -04001082 rc = selinux_set_mnt_opts(sb, &opts, 0, NULL);
Eric Parise0007522008-03-05 10:31:54 -05001083
1084out_err:
1085 security_free_mnt_opts(&opts);
1086 return rc;
1087}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001088
Adrian Bunk3583a712008-07-22 20:21:23 +03001089static void selinux_write_opts(struct seq_file *m,
1090 struct security_mnt_opts *opts)
Eric Paris2069f452008-07-04 09:47:13 +10001091{
1092 int i;
1093 char *prefix;
1094
1095 for (i = 0; i < opts->num_mnt_opts; i++) {
David P. Quigley11689d42009-01-16 09:22:03 -05001096 char *has_comma;
1097
1098 if (opts->mnt_opts[i])
1099 has_comma = strchr(opts->mnt_opts[i], ',');
1100 else
1101 has_comma = NULL;
Eric Paris2069f452008-07-04 09:47:13 +10001102
1103 switch (opts->mnt_opts_flags[i]) {
1104 case CONTEXT_MNT:
1105 prefix = CONTEXT_STR;
1106 break;
1107 case FSCONTEXT_MNT:
1108 prefix = FSCONTEXT_STR;
1109 break;
1110 case ROOTCONTEXT_MNT:
1111 prefix = ROOTCONTEXT_STR;
1112 break;
1113 case DEFCONTEXT_MNT:
1114 prefix = DEFCONTEXT_STR;
1115 break;
Eric Paris12f348b2012-10-09 10:56:25 -04001116 case SBLABEL_MNT:
David P. Quigley11689d42009-01-16 09:22:03 -05001117 seq_putc(m, ',');
1118 seq_puts(m, LABELSUPP_STR);
1119 continue;
Eric Paris2069f452008-07-04 09:47:13 +10001120 default:
1121 BUG();
Eric Parisa35c6c832011-04-20 10:21:28 -04001122 return;
Eric Paris2069f452008-07-04 09:47:13 +10001123 };
1124 /* we need a comma before each option */
1125 seq_putc(m, ',');
1126 seq_puts(m, prefix);
1127 if (has_comma)
1128 seq_putc(m, '\"');
Kees Cooka068acf2015-09-04 15:44:57 -07001129 seq_escape(m, opts->mnt_opts[i], "\"\n\\");
Eric Paris2069f452008-07-04 09:47:13 +10001130 if (has_comma)
1131 seq_putc(m, '\"');
1132 }
1133}
1134
1135static int selinux_sb_show_options(struct seq_file *m, struct super_block *sb)
1136{
1137 struct security_mnt_opts opts;
1138 int rc;
1139
1140 rc = selinux_get_mnt_opts(sb, &opts);
Eric Paris383795c2008-07-29 17:07:26 -04001141 if (rc) {
1142 /* before policy load we may get EINVAL, don't show anything */
1143 if (rc == -EINVAL)
1144 rc = 0;
Eric Paris2069f452008-07-04 09:47:13 +10001145 return rc;
Eric Paris383795c2008-07-29 17:07:26 -04001146 }
Eric Paris2069f452008-07-04 09:47:13 +10001147
1148 selinux_write_opts(m, &opts);
1149
1150 security_free_mnt_opts(&opts);
1151
1152 return rc;
1153}
1154
Linus Torvalds1da177e2005-04-16 15:20:36 -07001155static inline u16 inode_mode_to_security_class(umode_t mode)
1156{
1157 switch (mode & S_IFMT) {
1158 case S_IFSOCK:
1159 return SECCLASS_SOCK_FILE;
1160 case S_IFLNK:
1161 return SECCLASS_LNK_FILE;
1162 case S_IFREG:
1163 return SECCLASS_FILE;
1164 case S_IFBLK:
1165 return SECCLASS_BLK_FILE;
1166 case S_IFDIR:
1167 return SECCLASS_DIR;
1168 case S_IFCHR:
1169 return SECCLASS_CHR_FILE;
1170 case S_IFIFO:
1171 return SECCLASS_FIFO_FILE;
1172
1173 }
1174
1175 return SECCLASS_FILE;
1176}
1177
James Morris13402582005-09-30 14:24:34 -04001178static inline int default_protocol_stream(int protocol)
1179{
1180 return (protocol == IPPROTO_IP || protocol == IPPROTO_TCP);
1181}
1182
1183static inline int default_protocol_dgram(int protocol)
1184{
1185 return (protocol == IPPROTO_IP || protocol == IPPROTO_UDP);
1186}
1187
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188static inline u16 socket_type_to_security_class(int family, int type, int protocol)
1189{
1190 switch (family) {
1191 case PF_UNIX:
1192 switch (type) {
1193 case SOCK_STREAM:
1194 case SOCK_SEQPACKET:
1195 return SECCLASS_UNIX_STREAM_SOCKET;
1196 case SOCK_DGRAM:
1197 return SECCLASS_UNIX_DGRAM_SOCKET;
1198 }
1199 break;
1200 case PF_INET:
1201 case PF_INET6:
1202 switch (type) {
1203 case SOCK_STREAM:
James Morris13402582005-09-30 14:24:34 -04001204 if (default_protocol_stream(protocol))
1205 return SECCLASS_TCP_SOCKET;
1206 else
1207 return SECCLASS_RAWIP_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208 case SOCK_DGRAM:
James Morris13402582005-09-30 14:24:34 -04001209 if (default_protocol_dgram(protocol))
1210 return SECCLASS_UDP_SOCKET;
1211 else
1212 return SECCLASS_RAWIP_SOCKET;
James Morris2ee92d42006-11-13 16:09:01 -08001213 case SOCK_DCCP:
1214 return SECCLASS_DCCP_SOCKET;
James Morris13402582005-09-30 14:24:34 -04001215 default:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001216 return SECCLASS_RAWIP_SOCKET;
1217 }
1218 break;
1219 case PF_NETLINK:
1220 switch (protocol) {
1221 case NETLINK_ROUTE:
1222 return SECCLASS_NETLINK_ROUTE_SOCKET;
Pavel Emelyanov7f1fb602011-12-06 07:56:43 +00001223 case NETLINK_SOCK_DIAG:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001224 return SECCLASS_NETLINK_TCPDIAG_SOCKET;
1225 case NETLINK_NFLOG:
1226 return SECCLASS_NETLINK_NFLOG_SOCKET;
1227 case NETLINK_XFRM:
1228 return SECCLASS_NETLINK_XFRM_SOCKET;
1229 case NETLINK_SELINUX:
1230 return SECCLASS_NETLINK_SELINUX_SOCKET;
Stephen Smalley6c6d2e92015-06-04 16:22:16 -04001231 case NETLINK_ISCSI:
1232 return SECCLASS_NETLINK_ISCSI_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001233 case NETLINK_AUDIT:
1234 return SECCLASS_NETLINK_AUDIT_SOCKET;
Stephen Smalley6c6d2e92015-06-04 16:22:16 -04001235 case NETLINK_FIB_LOOKUP:
1236 return SECCLASS_NETLINK_FIB_LOOKUP_SOCKET;
1237 case NETLINK_CONNECTOR:
1238 return SECCLASS_NETLINK_CONNECTOR_SOCKET;
1239 case NETLINK_NETFILTER:
1240 return SECCLASS_NETLINK_NETFILTER_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001241 case NETLINK_DNRTMSG:
1242 return SECCLASS_NETLINK_DNRT_SOCKET;
James Morris0c9b7942005-04-16 15:24:13 -07001243 case NETLINK_KOBJECT_UEVENT:
1244 return SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET;
Stephen Smalley6c6d2e92015-06-04 16:22:16 -04001245 case NETLINK_GENERIC:
1246 return SECCLASS_NETLINK_GENERIC_SOCKET;
1247 case NETLINK_SCSITRANSPORT:
1248 return SECCLASS_NETLINK_SCSITRANSPORT_SOCKET;
1249 case NETLINK_RDMA:
1250 return SECCLASS_NETLINK_RDMA_SOCKET;
1251 case NETLINK_CRYPTO:
1252 return SECCLASS_NETLINK_CRYPTO_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001253 default:
1254 return SECCLASS_NETLINK_SOCKET;
1255 }
1256 case PF_PACKET:
1257 return SECCLASS_PACKET_SOCKET;
1258 case PF_KEY:
1259 return SECCLASS_KEY_SOCKET;
Christopher J. PeBenito3e3ff152006-06-09 00:25:03 -07001260 case PF_APPLETALK:
1261 return SECCLASS_APPLETALK_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001262 }
1263
1264 return SECCLASS_SOCKET;
1265}
1266
Stephen Smalley134509d2015-06-04 16:22:17 -04001267static int selinux_genfs_get_sid(struct dentry *dentry,
1268 u16 tclass,
1269 u16 flags,
1270 u32 *sid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001271{
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001272 int rc;
Stephen Smalley134509d2015-06-04 16:22:17 -04001273 struct super_block *sb = dentry->d_inode->i_sb;
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001274 char *buffer, *path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001275
Eric Paris828dfe12008-04-17 13:17:49 -04001276 buffer = (char *)__get_free_page(GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001277 if (!buffer)
1278 return -ENOMEM;
1279
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001280 path = dentry_path_raw(dentry, buffer, PAGE_SIZE);
1281 if (IS_ERR(path))
1282 rc = PTR_ERR(path);
1283 else {
Stephen Smalley134509d2015-06-04 16:22:17 -04001284 if (flags & SE_SBPROC) {
1285 /* each process gets a /proc/PID/ entry. Strip off the
1286 * PID part to get a valid selinux labeling.
1287 * e.g. /proc/1/net/rpc/nfs -> /net/rpc/nfs */
1288 while (path[1] >= '0' && path[1] <= '9') {
1289 path[1] = '/';
1290 path++;
1291 }
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001292 }
Stephen Smalley134509d2015-06-04 16:22:17 -04001293 rc = security_genfs_sid(sb->s_type->name, path, tclass, sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001294 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001295 free_page((unsigned long)buffer);
1296 return rc;
1297}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001298
1299/* The inode's security attributes must be initialized before first use. */
1300static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry)
1301{
1302 struct superblock_security_struct *sbsec = NULL;
1303 struct inode_security_struct *isec = inode->i_security;
1304 u32 sid;
1305 struct dentry *dentry;
1306#define INITCONTEXTLEN 255
1307 char *context = NULL;
1308 unsigned len = 0;
1309 int rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001310
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05001311 if (isec->initialized == LABEL_INITIALIZED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001312 goto out;
1313
Eric Paris23970742006-09-25 23:32:01 -07001314 mutex_lock(&isec->lock);
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05001315 if (isec->initialized == LABEL_INITIALIZED)
Eric Paris23970742006-09-25 23:32:01 -07001316 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001317
1318 sbsec = inode->i_sb->s_security;
David P. Quigley0d90a7e2009-01-16 09:22:02 -05001319 if (!(sbsec->flags & SE_SBINITIALIZED)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001320 /* Defer initialization until selinux_complete_init,
1321 after the initial policy is loaded and the security
1322 server is ready to handle calls. */
1323 spin_lock(&sbsec->isec_lock);
1324 if (list_empty(&isec->list))
1325 list_add(&isec->list, &sbsec->isec_head);
1326 spin_unlock(&sbsec->isec_lock);
Eric Paris23970742006-09-25 23:32:01 -07001327 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001328 }
1329
1330 switch (sbsec->behavior) {
David Quigleyeb9ae682013-05-22 12:50:37 -04001331 case SECURITY_FS_USE_NATIVE:
1332 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001333 case SECURITY_FS_USE_XATTR:
1334 if (!inode->i_op->getxattr) {
1335 isec->sid = sbsec->def_sid;
1336 break;
1337 }
1338
1339 /* Need a dentry, since the xattr API requires one.
1340 Life would be simpler if we could just pass the inode. */
1341 if (opt_dentry) {
1342 /* Called from d_instantiate or d_splice_alias. */
1343 dentry = dget(opt_dentry);
1344 } else {
1345 /* Called from selinux_complete_init, try to find a dentry. */
1346 dentry = d_find_alias(inode);
1347 }
1348 if (!dentry) {
Eric Parisdf7f54c2009-03-09 14:35:58 -04001349 /*
1350 * this is can be hit on boot when a file is accessed
1351 * before the policy is loaded. When we load policy we
1352 * may find inodes that have no dentry on the
1353 * sbsec->isec_head list. No reason to complain as these
1354 * will get fixed up the next time we go through
1355 * inode_doinit with a dentry, before these inodes could
1356 * be used again by userspace.
1357 */
Eric Paris23970742006-09-25 23:32:01 -07001358 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001359 }
1360
1361 len = INITCONTEXTLEN;
Eric Paris4cb912f2009-02-12 14:50:05 -05001362 context = kmalloc(len+1, GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001363 if (!context) {
1364 rc = -ENOMEM;
1365 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001366 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001367 }
Eric Paris4cb912f2009-02-12 14:50:05 -05001368 context[len] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001369 rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX,
1370 context, len);
1371 if (rc == -ERANGE) {
James Morris314dabb2009-08-10 22:00:13 +10001372 kfree(context);
1373
Linus Torvalds1da177e2005-04-16 15:20:36 -07001374 /* Need a larger buffer. Query for the right size. */
1375 rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX,
1376 NULL, 0);
1377 if (rc < 0) {
1378 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001379 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001380 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001381 len = rc;
Eric Paris4cb912f2009-02-12 14:50:05 -05001382 context = kmalloc(len+1, GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001383 if (!context) {
1384 rc = -ENOMEM;
1385 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001386 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001387 }
Eric Paris4cb912f2009-02-12 14:50:05 -05001388 context[len] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001389 rc = inode->i_op->getxattr(dentry,
1390 XATTR_NAME_SELINUX,
1391 context, len);
1392 }
1393 dput(dentry);
1394 if (rc < 0) {
1395 if (rc != -ENODATA) {
Eric Paris744ba352008-04-17 11:52:44 -04001396 printk(KERN_WARNING "SELinux: %s: getxattr returned "
Harvey Harrisondd6f9532008-03-06 10:03:59 +11001397 "%d for dev=%s ino=%ld\n", __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001398 -rc, inode->i_sb->s_id, inode->i_ino);
1399 kfree(context);
Eric Paris23970742006-09-25 23:32:01 -07001400 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001401 }
1402 /* Map ENODATA to the default file SID */
1403 sid = sbsec->def_sid;
1404 rc = 0;
1405 } else {
James Morrisf5c1d5b2005-07-28 01:07:37 -07001406 rc = security_context_to_sid_default(context, rc, &sid,
Stephen Smalley869ab512008-04-04 08:46:05 -04001407 sbsec->def_sid,
1408 GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001409 if (rc) {
Eric Paris4ba0a8a2009-02-12 15:01:10 -05001410 char *dev = inode->i_sb->s_id;
1411 unsigned long ino = inode->i_ino;
1412
1413 if (rc == -EINVAL) {
1414 if (printk_ratelimit())
1415 printk(KERN_NOTICE "SELinux: inode=%lu on dev=%s was found to have an invalid "
1416 "context=%s. This indicates you may need to relabel the inode or the "
1417 "filesystem in question.\n", ino, dev, context);
1418 } else {
1419 printk(KERN_WARNING "SELinux: %s: context_to_sid(%s) "
1420 "returned %d for dev=%s ino=%ld\n",
1421 __func__, context, -rc, dev, ino);
1422 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001423 kfree(context);
1424 /* Leave with the unlabeled SID */
1425 rc = 0;
1426 break;
1427 }
1428 }
1429 kfree(context);
1430 isec->sid = sid;
1431 break;
1432 case SECURITY_FS_USE_TASK:
1433 isec->sid = isec->task_sid;
1434 break;
1435 case SECURITY_FS_USE_TRANS:
1436 /* Default to the fs SID. */
1437 isec->sid = sbsec->sid;
1438
1439 /* Try to obtain a transition SID. */
1440 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Eric Paris652bb9b2011-02-01 11:05:40 -05001441 rc = security_transition_sid(isec->task_sid, sbsec->sid,
1442 isec->sclass, NULL, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001443 if (rc)
Eric Paris23970742006-09-25 23:32:01 -07001444 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001445 isec->sid = sid;
1446 break;
Eric Parisc312feb2006-07-10 04:43:53 -07001447 case SECURITY_FS_USE_MNTPOINT:
1448 isec->sid = sbsec->mntpoint_sid;
1449 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001450 default:
Eric Parisc312feb2006-07-10 04:43:53 -07001451 /* Default to the fs superblock SID. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001452 isec->sid = sbsec->sid;
1453
Stephen Smalley134509d2015-06-04 16:22:17 -04001454 if ((sbsec->flags & SE_SBGENFS) && !S_ISLNK(inode->i_mode)) {
Paul Mooref64410e2014-03-19 16:46:18 -04001455 /* We must have a dentry to determine the label on
1456 * procfs inodes */
1457 if (opt_dentry)
1458 /* Called from d_instantiate or
1459 * d_splice_alias. */
1460 dentry = dget(opt_dentry);
1461 else
1462 /* Called from selinux_complete_init, try to
1463 * find a dentry. */
1464 dentry = d_find_alias(inode);
1465 /*
1466 * This can be hit on boot when a file is accessed
1467 * before the policy is loaded. When we load policy we
1468 * may find inodes that have no dentry on the
1469 * sbsec->isec_head list. No reason to complain as
1470 * these will get fixed up the next time we go through
1471 * inode_doinit() with a dentry, before these inodes
1472 * could be used again by userspace.
1473 */
1474 if (!dentry)
1475 goto out_unlock;
1476 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Stephen Smalley134509d2015-06-04 16:22:17 -04001477 rc = selinux_genfs_get_sid(dentry, isec->sclass,
1478 sbsec->flags, &sid);
Paul Mooref64410e2014-03-19 16:46:18 -04001479 dput(dentry);
1480 if (rc)
1481 goto out_unlock;
1482 isec->sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001483 }
1484 break;
1485 }
1486
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05001487 isec->initialized = LABEL_INITIALIZED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001488
Eric Paris23970742006-09-25 23:32:01 -07001489out_unlock:
1490 mutex_unlock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001491out:
1492 if (isec->sclass == SECCLASS_FILE)
1493 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001494 return rc;
1495}
1496
1497/* Convert a Linux signal to an access vector. */
1498static inline u32 signal_to_av(int sig)
1499{
1500 u32 perm = 0;
1501
1502 switch (sig) {
1503 case SIGCHLD:
1504 /* Commonly granted from child to parent. */
1505 perm = PROCESS__SIGCHLD;
1506 break;
1507 case SIGKILL:
1508 /* Cannot be caught or ignored */
1509 perm = PROCESS__SIGKILL;
1510 break;
1511 case SIGSTOP:
1512 /* Cannot be caught or ignored */
1513 perm = PROCESS__SIGSTOP;
1514 break;
1515 default:
1516 /* All other signals. */
1517 perm = PROCESS__SIGNAL;
1518 break;
1519 }
1520
1521 return perm;
1522}
1523
David Howells275bb412008-11-14 10:39:19 +11001524/*
David Howellsd84f4f92008-11-14 10:39:23 +11001525 * Check permission between a pair of credentials
1526 * fork check, ptrace check, etc.
1527 */
1528static int cred_has_perm(const struct cred *actor,
1529 const struct cred *target,
1530 u32 perms)
1531{
1532 u32 asid = cred_sid(actor), tsid = cred_sid(target);
1533
1534 return avc_has_perm(asid, tsid, SECCLASS_PROCESS, perms, NULL);
1535}
1536
1537/*
David Howells88e67f32008-11-14 10:39:21 +11001538 * Check permission between a pair of tasks, e.g. signal checks,
David Howells275bb412008-11-14 10:39:19 +11001539 * fork check, ptrace check, etc.
1540 * tsk1 is the actor and tsk2 is the target
David Howells3b11a1d2008-11-14 10:39:26 +11001541 * - this uses the default subjective creds of tsk1
David Howells275bb412008-11-14 10:39:19 +11001542 */
1543static int task_has_perm(const struct task_struct *tsk1,
1544 const struct task_struct *tsk2,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001545 u32 perms)
1546{
David Howells275bb412008-11-14 10:39:19 +11001547 const struct task_security_struct *__tsec1, *__tsec2;
1548 u32 sid1, sid2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001549
David Howells275bb412008-11-14 10:39:19 +11001550 rcu_read_lock();
1551 __tsec1 = __task_cred(tsk1)->security; sid1 = __tsec1->sid;
1552 __tsec2 = __task_cred(tsk2)->security; sid2 = __tsec2->sid;
1553 rcu_read_unlock();
1554 return avc_has_perm(sid1, sid2, SECCLASS_PROCESS, perms, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001555}
1556
David Howells3b11a1d2008-11-14 10:39:26 +11001557/*
1558 * Check permission between current and another task, e.g. signal checks,
1559 * fork check, ptrace check, etc.
1560 * current is the actor and tsk2 is the target
1561 * - this uses current's subjective creds
1562 */
1563static int current_has_perm(const struct task_struct *tsk,
1564 u32 perms)
1565{
1566 u32 sid, tsid;
1567
1568 sid = current_sid();
1569 tsid = task_sid(tsk);
1570 return avc_has_perm(sid, tsid, SECCLASS_PROCESS, perms, NULL);
1571}
1572
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001573#if CAP_LAST_CAP > 63
1574#error Fix SELinux to handle capabilities > 63.
1575#endif
1576
Linus Torvalds1da177e2005-04-16 15:20:36 -07001577/* Check whether a task is allowed to use a capability. */
Eric Paris6a9de492012-01-03 12:25:14 -05001578static int cred_has_capability(const struct cred *cred,
Eric Paris06112162008-11-11 22:02:50 +11001579 int cap, int audit)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001580{
Thomas Liu2bf49692009-07-14 12:14:09 -04001581 struct common_audit_data ad;
Eric Paris06112162008-11-11 22:02:50 +11001582 struct av_decision avd;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001583 u16 sclass;
David Howells3699c532009-01-06 22:27:01 +00001584 u32 sid = cred_sid(cred);
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001585 u32 av = CAP_TO_MASK(cap);
Eric Paris06112162008-11-11 22:02:50 +11001586 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001587
Eric Paris50c205f2012-04-04 15:01:43 -04001588 ad.type = LSM_AUDIT_DATA_CAP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001589 ad.u.cap = cap;
1590
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001591 switch (CAP_TO_INDEX(cap)) {
1592 case 0:
1593 sclass = SECCLASS_CAPABILITY;
1594 break;
1595 case 1:
1596 sclass = SECCLASS_CAPABILITY2;
1597 break;
1598 default:
1599 printk(KERN_ERR
1600 "SELinux: out of range capability %d\n", cap);
1601 BUG();
Eric Parisa35c6c832011-04-20 10:21:28 -04001602 return -EINVAL;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001603 }
Eric Paris06112162008-11-11 22:02:50 +11001604
David Howells275bb412008-11-14 10:39:19 +11001605 rc = avc_has_perm_noaudit(sid, sid, sclass, av, 0, &avd);
Eric Paris9ade0cf2011-04-25 16:26:29 -04001606 if (audit == SECURITY_CAP_AUDIT) {
NeilBrown7b20ea22015-03-23 13:37:39 +11001607 int rc2 = avc_audit(sid, sid, sclass, av, &avd, rc, &ad, 0);
Eric Paris9ade0cf2011-04-25 16:26:29 -04001608 if (rc2)
1609 return rc2;
1610 }
Eric Paris06112162008-11-11 22:02:50 +11001611 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001612}
1613
1614/* Check whether a task is allowed to use a system operation. */
1615static int task_has_system(struct task_struct *tsk,
1616 u32 perms)
1617{
David Howells275bb412008-11-14 10:39:19 +11001618 u32 sid = task_sid(tsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001619
David Howells275bb412008-11-14 10:39:19 +11001620 return avc_has_perm(sid, SECINITSID_KERNEL,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001621 SECCLASS_SYSTEM, perms, NULL);
1622}
1623
1624/* Check whether a task has a particular permission to an inode.
1625 The 'adp' parameter is optional and allows other audit
1626 data to be passed (e.g. the dentry). */
David Howells88e67f32008-11-14 10:39:21 +11001627static int inode_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001628 struct inode *inode,
1629 u32 perms,
Linus Torvalds19e49832013-10-04 12:54:11 -07001630 struct common_audit_data *adp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001631{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001632 struct inode_security_struct *isec;
David Howells275bb412008-11-14 10:39:19 +11001633 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001634
David Howellse0e81732009-09-02 09:13:40 +01001635 validate_creds(cred);
1636
Eric Paris828dfe12008-04-17 13:17:49 -04001637 if (unlikely(IS_PRIVATE(inode)))
Stephen Smalleybbaca6c2007-02-14 00:34:16 -08001638 return 0;
1639
David Howells88e67f32008-11-14 10:39:21 +11001640 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001641 isec = inode->i_security;
1642
Linus Torvalds19e49832013-10-04 12:54:11 -07001643 return avc_has_perm(sid, isec->sid, isec->sclass, perms, adp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001644}
1645
1646/* Same as inode_has_perm, but pass explicit audit data containing
1647 the dentry to help the auditing code to more easily generate the
1648 pathname if needed. */
David Howells88e67f32008-11-14 10:39:21 +11001649static inline int dentry_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001650 struct dentry *dentry,
1651 u32 av)
1652{
David Howellsc6f493d2015-03-17 22:26:22 +00001653 struct inode *inode = d_backing_inode(dentry);
Thomas Liu2bf49692009-07-14 12:14:09 -04001654 struct common_audit_data ad;
David Howells88e67f32008-11-14 10:39:21 +11001655
Eric Paris50c205f2012-04-04 15:01:43 -04001656 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Paris2875fa02011-04-28 16:04:24 -04001657 ad.u.dentry = dentry;
Linus Torvalds19e49832013-10-04 12:54:11 -07001658 return inode_has_perm(cred, inode, av, &ad);
Eric Paris2875fa02011-04-28 16:04:24 -04001659}
1660
1661/* Same as inode_has_perm, but pass explicit audit data containing
1662 the path to help the auditing code to more easily generate the
1663 pathname if needed. */
1664static inline int path_has_perm(const struct cred *cred,
Al Viro3f7036a2015-03-08 19:28:30 -04001665 const struct path *path,
Eric Paris2875fa02011-04-28 16:04:24 -04001666 u32 av)
1667{
David Howellsc6f493d2015-03-17 22:26:22 +00001668 struct inode *inode = d_backing_inode(path->dentry);
Eric Paris2875fa02011-04-28 16:04:24 -04001669 struct common_audit_data ad;
1670
Eric Paris50c205f2012-04-04 15:01:43 -04001671 ad.type = LSM_AUDIT_DATA_PATH;
Eric Paris2875fa02011-04-28 16:04:24 -04001672 ad.u.path = *path;
Linus Torvalds19e49832013-10-04 12:54:11 -07001673 return inode_has_perm(cred, inode, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001674}
1675
David Howells13f8e982013-06-13 23:37:55 +01001676/* Same as path_has_perm, but uses the inode from the file struct. */
1677static inline int file_path_has_perm(const struct cred *cred,
1678 struct file *file,
1679 u32 av)
1680{
1681 struct common_audit_data ad;
1682
1683 ad.type = LSM_AUDIT_DATA_PATH;
1684 ad.u.path = file->f_path;
Linus Torvalds19e49832013-10-04 12:54:11 -07001685 return inode_has_perm(cred, file_inode(file), av, &ad);
David Howells13f8e982013-06-13 23:37:55 +01001686}
1687
Linus Torvalds1da177e2005-04-16 15:20:36 -07001688/* Check whether a task can use an open file descriptor to
1689 access an inode in a given way. Check access to the
1690 descriptor itself, and then use dentry_has_perm to
1691 check a particular permission to the file.
1692 Access to the descriptor is implicitly granted if it
1693 has the same SID as the process. If av is zero, then
1694 access to the file is not checked, e.g. for cases
1695 where only the descriptor is affected like seek. */
David Howells88e67f32008-11-14 10:39:21 +11001696static int file_has_perm(const struct cred *cred,
1697 struct file *file,
1698 u32 av)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001699{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001700 struct file_security_struct *fsec = file->f_security;
Al Viro496ad9a2013-01-23 17:07:38 -05001701 struct inode *inode = file_inode(file);
Thomas Liu2bf49692009-07-14 12:14:09 -04001702 struct common_audit_data ad;
David Howells88e67f32008-11-14 10:39:21 +11001703 u32 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001704 int rc;
1705
Eric Paris50c205f2012-04-04 15:01:43 -04001706 ad.type = LSM_AUDIT_DATA_PATH;
Eric Parisf48b7392011-04-25 12:54:27 -04001707 ad.u.path = file->f_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001708
David Howells275bb412008-11-14 10:39:19 +11001709 if (sid != fsec->sid) {
1710 rc = avc_has_perm(sid, fsec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001711 SECCLASS_FD,
1712 FD__USE,
1713 &ad);
1714 if (rc)
David Howells88e67f32008-11-14 10:39:21 +11001715 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001716 }
1717
1718 /* av is zero if only checking access to the descriptor. */
David Howells88e67f32008-11-14 10:39:21 +11001719 rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001720 if (av)
Linus Torvalds19e49832013-10-04 12:54:11 -07001721 rc = inode_has_perm(cred, inode, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001722
David Howells88e67f32008-11-14 10:39:21 +11001723out:
1724 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001725}
1726
David Howellsc3c188b2015-07-10 17:19:58 -04001727/*
1728 * Determine the label for an inode that might be unioned.
1729 */
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05001730static int selinux_determine_inode_label(struct inode *dir,
David Howellsc3c188b2015-07-10 17:19:58 -04001731 const struct qstr *name,
1732 u16 tclass,
1733 u32 *_new_isid)
1734{
1735 const struct superblock_security_struct *sbsec = dir->i_sb->s_security;
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05001736 const struct inode_security_struct *dsec = inode_security(dir);
David Howellsc3c188b2015-07-10 17:19:58 -04001737 const struct task_security_struct *tsec = current_security();
1738
1739 if ((sbsec->flags & SE_SBINITIALIZED) &&
1740 (sbsec->behavior == SECURITY_FS_USE_MNTPOINT)) {
1741 *_new_isid = sbsec->mntpoint_sid;
1742 } else if ((sbsec->flags & SBLABEL_MNT) &&
1743 tsec->create_sid) {
1744 *_new_isid = tsec->create_sid;
1745 } else {
1746 return security_transition_sid(tsec->sid, dsec->sid, tclass,
1747 name, _new_isid);
1748 }
1749
1750 return 0;
1751}
1752
Linus Torvalds1da177e2005-04-16 15:20:36 -07001753/* Check whether a task can create a file. */
1754static int may_create(struct inode *dir,
1755 struct dentry *dentry,
1756 u16 tclass)
1757{
Paul Moore5fb49872010-04-22 14:46:19 -04001758 const struct task_security_struct *tsec = current_security();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001759 struct inode_security_struct *dsec;
1760 struct superblock_security_struct *sbsec;
David Howells275bb412008-11-14 10:39:19 +11001761 u32 sid, newsid;
Thomas Liu2bf49692009-07-14 12:14:09 -04001762 struct common_audit_data ad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001763 int rc;
1764
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05001765 dsec = inode_security(dir);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001766 sbsec = dir->i_sb->s_security;
1767
David Howells275bb412008-11-14 10:39:19 +11001768 sid = tsec->sid;
David Howells275bb412008-11-14 10:39:19 +11001769
Eric Paris50c205f2012-04-04 15:01:43 -04001770 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04001771 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001772
David Howells275bb412008-11-14 10:39:19 +11001773 rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001774 DIR__ADD_NAME | DIR__SEARCH,
1775 &ad);
1776 if (rc)
1777 return rc;
1778
David Howellsc3c188b2015-07-10 17:19:58 -04001779 rc = selinux_determine_inode_label(dir, &dentry->d_name, tclass,
1780 &newsid);
1781 if (rc)
1782 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001783
David Howells275bb412008-11-14 10:39:19 +11001784 rc = avc_has_perm(sid, newsid, tclass, FILE__CREATE, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001785 if (rc)
1786 return rc;
1787
1788 return avc_has_perm(newsid, sbsec->sid,
1789 SECCLASS_FILESYSTEM,
1790 FILESYSTEM__ASSOCIATE, &ad);
1791}
1792
Michael LeMay4eb582c2006-06-26 00:24:57 -07001793/* Check whether a task can create a key. */
1794static int may_create_key(u32 ksid,
1795 struct task_struct *ctx)
1796{
David Howells275bb412008-11-14 10:39:19 +11001797 u32 sid = task_sid(ctx);
Michael LeMay4eb582c2006-06-26 00:24:57 -07001798
David Howells275bb412008-11-14 10:39:19 +11001799 return avc_has_perm(sid, ksid, SECCLASS_KEY, KEY__CREATE, NULL);
Michael LeMay4eb582c2006-06-26 00:24:57 -07001800}
1801
Eric Paris828dfe12008-04-17 13:17:49 -04001802#define MAY_LINK 0
1803#define MAY_UNLINK 1
1804#define MAY_RMDIR 2
Linus Torvalds1da177e2005-04-16 15:20:36 -07001805
1806/* Check whether a task can link, unlink, or rmdir a file/directory. */
1807static int may_link(struct inode *dir,
1808 struct dentry *dentry,
1809 int kind)
1810
1811{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001812 struct inode_security_struct *dsec, *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04001813 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11001814 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001815 u32 av;
1816 int rc;
1817
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05001818 dsec = inode_security(dir);
1819 isec = backing_inode_security(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001820
Eric Paris50c205f2012-04-04 15:01:43 -04001821 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04001822 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001823
1824 av = DIR__SEARCH;
1825 av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME);
David Howells275bb412008-11-14 10:39:19 +11001826 rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001827 if (rc)
1828 return rc;
1829
1830 switch (kind) {
1831 case MAY_LINK:
1832 av = FILE__LINK;
1833 break;
1834 case MAY_UNLINK:
1835 av = FILE__UNLINK;
1836 break;
1837 case MAY_RMDIR:
1838 av = DIR__RMDIR;
1839 break;
1840 default:
Eric Paris744ba352008-04-17 11:52:44 -04001841 printk(KERN_WARNING "SELinux: %s: unrecognized kind %d\n",
1842 __func__, kind);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001843 return 0;
1844 }
1845
David Howells275bb412008-11-14 10:39:19 +11001846 rc = avc_has_perm(sid, isec->sid, isec->sclass, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001847 return rc;
1848}
1849
1850static inline int may_rename(struct inode *old_dir,
1851 struct dentry *old_dentry,
1852 struct inode *new_dir,
1853 struct dentry *new_dentry)
1854{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001855 struct inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04001856 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11001857 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001858 u32 av;
1859 int old_is_dir, new_is_dir;
1860 int rc;
1861
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05001862 old_dsec = inode_security(old_dir);
1863 old_isec = backing_inode_security(old_dentry);
David Howellse36cb0b2015-01-29 12:02:35 +00001864 old_is_dir = d_is_dir(old_dentry);
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05001865 new_dsec = inode_security(new_dir);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001866
Eric Paris50c205f2012-04-04 15:01:43 -04001867 ad.type = LSM_AUDIT_DATA_DENTRY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001868
Eric Parisa2694342011-04-25 13:10:27 -04001869 ad.u.dentry = old_dentry;
David Howells275bb412008-11-14 10:39:19 +11001870 rc = avc_has_perm(sid, old_dsec->sid, SECCLASS_DIR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001871 DIR__REMOVE_NAME | DIR__SEARCH, &ad);
1872 if (rc)
1873 return rc;
David Howells275bb412008-11-14 10:39:19 +11001874 rc = avc_has_perm(sid, old_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001875 old_isec->sclass, FILE__RENAME, &ad);
1876 if (rc)
1877 return rc;
1878 if (old_is_dir && new_dir != old_dir) {
David Howells275bb412008-11-14 10:39:19 +11001879 rc = avc_has_perm(sid, old_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001880 old_isec->sclass, DIR__REPARENT, &ad);
1881 if (rc)
1882 return rc;
1883 }
1884
Eric Parisa2694342011-04-25 13:10:27 -04001885 ad.u.dentry = new_dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001886 av = DIR__ADD_NAME | DIR__SEARCH;
David Howells2c616d42015-01-29 12:02:33 +00001887 if (d_is_positive(new_dentry))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001888 av |= DIR__REMOVE_NAME;
David Howells275bb412008-11-14 10:39:19 +11001889 rc = avc_has_perm(sid, new_dsec->sid, SECCLASS_DIR, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001890 if (rc)
1891 return rc;
David Howells2c616d42015-01-29 12:02:33 +00001892 if (d_is_positive(new_dentry)) {
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05001893 new_isec = backing_inode_security(new_dentry);
David Howellse36cb0b2015-01-29 12:02:35 +00001894 new_is_dir = d_is_dir(new_dentry);
David Howells275bb412008-11-14 10:39:19 +11001895 rc = avc_has_perm(sid, new_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001896 new_isec->sclass,
1897 (new_is_dir ? DIR__RMDIR : FILE__UNLINK), &ad);
1898 if (rc)
1899 return rc;
1900 }
1901
1902 return 0;
1903}
1904
1905/* Check whether a task can perform a filesystem operation. */
David Howells88e67f32008-11-14 10:39:21 +11001906static int superblock_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001907 struct super_block *sb,
1908 u32 perms,
Thomas Liu2bf49692009-07-14 12:14:09 -04001909 struct common_audit_data *ad)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001910{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001911 struct superblock_security_struct *sbsec;
David Howells88e67f32008-11-14 10:39:21 +11001912 u32 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001913
Linus Torvalds1da177e2005-04-16 15:20:36 -07001914 sbsec = sb->s_security;
David Howells275bb412008-11-14 10:39:19 +11001915 return avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM, perms, ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001916}
1917
1918/* Convert a Linux mode and permission mask to an access vector. */
1919static inline u32 file_mask_to_av(int mode, int mask)
1920{
1921 u32 av = 0;
1922
Al Virodba19c62011-07-25 20:49:29 -04001923 if (!S_ISDIR(mode)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001924 if (mask & MAY_EXEC)
1925 av |= FILE__EXECUTE;
1926 if (mask & MAY_READ)
1927 av |= FILE__READ;
1928
1929 if (mask & MAY_APPEND)
1930 av |= FILE__APPEND;
1931 else if (mask & MAY_WRITE)
1932 av |= FILE__WRITE;
1933
1934 } else {
1935 if (mask & MAY_EXEC)
1936 av |= DIR__SEARCH;
1937 if (mask & MAY_WRITE)
1938 av |= DIR__WRITE;
1939 if (mask & MAY_READ)
1940 av |= DIR__READ;
1941 }
1942
1943 return av;
1944}
1945
1946/* Convert a Linux file to an access vector. */
1947static inline u32 file_to_av(struct file *file)
1948{
1949 u32 av = 0;
1950
1951 if (file->f_mode & FMODE_READ)
1952 av |= FILE__READ;
1953 if (file->f_mode & FMODE_WRITE) {
1954 if (file->f_flags & O_APPEND)
1955 av |= FILE__APPEND;
1956 else
1957 av |= FILE__WRITE;
1958 }
Stephen Smalley0794c662008-03-17 08:55:18 -04001959 if (!av) {
1960 /*
1961 * Special file opened with flags 3 for ioctl-only use.
1962 */
1963 av = FILE__IOCTL;
1964 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001965
1966 return av;
1967}
1968
Eric Paris8b6a5a32008-10-29 17:06:46 -04001969/*
1970 * Convert a file to an access vector and include the correct open
1971 * open permission.
1972 */
1973static inline u32 open_file_to_av(struct file *file)
1974{
1975 u32 av = file_to_av(file);
1976
Eric Paris49b7b8d2010-07-23 11:44:09 -04001977 if (selinux_policycap_openperm)
1978 av |= FILE__OPEN;
1979
Eric Paris8b6a5a32008-10-29 17:06:46 -04001980 return av;
1981}
1982
Linus Torvalds1da177e2005-04-16 15:20:36 -07001983/* Hook functions begin here. */
1984
Stephen Smalley79af7302015-01-21 10:54:10 -05001985static int selinux_binder_set_context_mgr(struct task_struct *mgr)
1986{
1987 u32 mysid = current_sid();
1988 u32 mgrsid = task_sid(mgr);
1989
1990 return avc_has_perm(mysid, mgrsid, SECCLASS_BINDER,
1991 BINDER__SET_CONTEXT_MGR, NULL);
1992}
1993
1994static int selinux_binder_transaction(struct task_struct *from,
1995 struct task_struct *to)
1996{
1997 u32 mysid = current_sid();
1998 u32 fromsid = task_sid(from);
1999 u32 tosid = task_sid(to);
2000 int rc;
2001
2002 if (mysid != fromsid) {
2003 rc = avc_has_perm(mysid, fromsid, SECCLASS_BINDER,
2004 BINDER__IMPERSONATE, NULL);
2005 if (rc)
2006 return rc;
2007 }
2008
2009 return avc_has_perm(fromsid, tosid, SECCLASS_BINDER, BINDER__CALL,
2010 NULL);
2011}
2012
2013static int selinux_binder_transfer_binder(struct task_struct *from,
2014 struct task_struct *to)
2015{
2016 u32 fromsid = task_sid(from);
2017 u32 tosid = task_sid(to);
2018
2019 return avc_has_perm(fromsid, tosid, SECCLASS_BINDER, BINDER__TRANSFER,
2020 NULL);
2021}
2022
2023static int selinux_binder_transfer_file(struct task_struct *from,
2024 struct task_struct *to,
2025 struct file *file)
2026{
2027 u32 sid = task_sid(to);
2028 struct file_security_struct *fsec = file->f_security;
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05002029 struct dentry *dentry = file->f_path.dentry;
2030 struct inode_security_struct *isec = backing_inode_security(dentry);
Stephen Smalley79af7302015-01-21 10:54:10 -05002031 struct common_audit_data ad;
2032 int rc;
2033
2034 ad.type = LSM_AUDIT_DATA_PATH;
2035 ad.u.path = file->f_path;
2036
2037 if (sid != fsec->sid) {
2038 rc = avc_has_perm(sid, fsec->sid,
2039 SECCLASS_FD,
2040 FD__USE,
2041 &ad);
2042 if (rc)
2043 return rc;
2044 }
2045
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05002046 if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
Stephen Smalley79af7302015-01-21 10:54:10 -05002047 return 0;
2048
2049 return avc_has_perm(sid, isec->sid, isec->sclass, file_to_av(file),
2050 &ad);
2051}
2052
Ingo Molnar9e488582009-05-07 19:26:19 +10002053static int selinux_ptrace_access_check(struct task_struct *child,
David Howells5cd9c582008-08-14 11:37:28 +01002054 unsigned int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002055{
Eric Paris69f594a2012-01-03 12:25:15 -05002056 if (mode & PTRACE_MODE_READ) {
David Howells275bb412008-11-14 10:39:19 +11002057 u32 sid = current_sid();
2058 u32 csid = task_sid(child);
2059 return avc_has_perm(sid, csid, SECCLASS_FILE, FILE__READ, NULL);
Stephen Smalley006ebb42008-05-19 08:32:49 -04002060 }
2061
David Howells3b11a1d2008-11-14 10:39:26 +11002062 return current_has_perm(child, PROCESS__PTRACE);
David Howells5cd9c582008-08-14 11:37:28 +01002063}
2064
2065static int selinux_ptrace_traceme(struct task_struct *parent)
2066{
David Howells5cd9c582008-08-14 11:37:28 +01002067 return task_has_perm(parent, current, PROCESS__PTRACE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002068}
2069
2070static int selinux_capget(struct task_struct *target, kernel_cap_t *effective,
Eric Paris828dfe12008-04-17 13:17:49 -04002071 kernel_cap_t *inheritable, kernel_cap_t *permitted)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002072{
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07002073 return current_has_perm(target, PROCESS__GETCAP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002074}
2075
David Howellsd84f4f92008-11-14 10:39:23 +11002076static int selinux_capset(struct cred *new, const struct cred *old,
2077 const kernel_cap_t *effective,
2078 const kernel_cap_t *inheritable,
2079 const kernel_cap_t *permitted)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002080{
David Howellsd84f4f92008-11-14 10:39:23 +11002081 return cred_has_perm(old, new, PROCESS__SETCAP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002082}
2083
James Morris5626d3e2009-01-30 10:05:06 +11002084/*
2085 * (This comment used to live with the selinux_task_setuid hook,
2086 * which was removed).
2087 *
2088 * Since setuid only affects the current process, and since the SELinux
2089 * controls are not based on the Linux identity attributes, SELinux does not
2090 * need to control this operation. However, SELinux does control the use of
2091 * the CAP_SETUID and CAP_SETGID capabilities using the capable hook.
2092 */
2093
Eric Paris6a9de492012-01-03 12:25:14 -05002094static int selinux_capable(const struct cred *cred, struct user_namespace *ns,
2095 int cap, int audit)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002096{
Eric Paris6a9de492012-01-03 12:25:14 -05002097 return cred_has_capability(cred, cap, audit);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002098}
2099
Linus Torvalds1da177e2005-04-16 15:20:36 -07002100static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb)
2101{
David Howells88e67f32008-11-14 10:39:21 +11002102 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002103 int rc = 0;
2104
2105 if (!sb)
2106 return 0;
2107
2108 switch (cmds) {
Eric Paris828dfe12008-04-17 13:17:49 -04002109 case Q_SYNC:
2110 case Q_QUOTAON:
2111 case Q_QUOTAOFF:
2112 case Q_SETINFO:
2113 case Q_SETQUOTA:
David Howells88e67f32008-11-14 10:39:21 +11002114 rc = superblock_has_perm(cred, sb, FILESYSTEM__QUOTAMOD, NULL);
Eric Paris828dfe12008-04-17 13:17:49 -04002115 break;
2116 case Q_GETFMT:
2117 case Q_GETINFO:
2118 case Q_GETQUOTA:
David Howells88e67f32008-11-14 10:39:21 +11002119 rc = superblock_has_perm(cred, sb, FILESYSTEM__QUOTAGET, NULL);
Eric Paris828dfe12008-04-17 13:17:49 -04002120 break;
2121 default:
2122 rc = 0; /* let the kernel handle invalid cmds */
2123 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002124 }
2125 return rc;
2126}
2127
2128static int selinux_quota_on(struct dentry *dentry)
2129{
David Howells88e67f32008-11-14 10:39:21 +11002130 const struct cred *cred = current_cred();
2131
Eric Paris2875fa02011-04-28 16:04:24 -04002132 return dentry_has_perm(cred, dentry, FILE__QUOTAON);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002133}
2134
Eric Paris12b30522010-11-15 18:36:29 -05002135static int selinux_syslog(int type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002136{
2137 int rc;
2138
Linus Torvalds1da177e2005-04-16 15:20:36 -07002139 switch (type) {
Kees Cookd78ca3c2010-02-03 15:37:13 -08002140 case SYSLOG_ACTION_READ_ALL: /* Read last kernel messages */
2141 case SYSLOG_ACTION_SIZE_BUFFER: /* Return size of the log buffer */
Eric Paris828dfe12008-04-17 13:17:49 -04002142 rc = task_has_system(current, SYSTEM__SYSLOG_READ);
2143 break;
Kees Cookd78ca3c2010-02-03 15:37:13 -08002144 case SYSLOG_ACTION_CONSOLE_OFF: /* Disable logging to console */
2145 case SYSLOG_ACTION_CONSOLE_ON: /* Enable logging to console */
2146 /* Set level of messages printed to console */
2147 case SYSLOG_ACTION_CONSOLE_LEVEL:
Eric Paris828dfe12008-04-17 13:17:49 -04002148 rc = task_has_system(current, SYSTEM__SYSLOG_CONSOLE);
2149 break;
Kees Cookd78ca3c2010-02-03 15:37:13 -08002150 case SYSLOG_ACTION_CLOSE: /* Close log */
2151 case SYSLOG_ACTION_OPEN: /* Open log */
2152 case SYSLOG_ACTION_READ: /* Read from log */
2153 case SYSLOG_ACTION_READ_CLEAR: /* Read/clear last kernel messages */
2154 case SYSLOG_ACTION_CLEAR: /* Clear ring buffer */
Eric Paris828dfe12008-04-17 13:17:49 -04002155 default:
2156 rc = task_has_system(current, SYSTEM__SYSLOG_MOD);
2157 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002158 }
2159 return rc;
2160}
2161
2162/*
2163 * Check that a process has enough memory to allocate a new virtual
2164 * mapping. 0 means there is enough memory for the allocation to
2165 * succeed and -ENOMEM implies there is not.
2166 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07002167 * Do not audit the selinux permission check, as this is applied to all
2168 * processes that allocate mappings.
2169 */
Alan Cox34b4e4a2007-08-22 14:01:28 -07002170static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002171{
2172 int rc, cap_sys_admin = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002173
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07002174 rc = cred_has_capability(current_cred(), CAP_SYS_ADMIN,
2175 SECURITY_CAP_NOAUDIT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002176 if (rc == 0)
2177 cap_sys_admin = 1;
2178
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07002179 return cap_sys_admin;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002180}
2181
2182/* binprm security operations */
2183
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002184static int check_nnp_nosuid(const struct linux_binprm *bprm,
2185 const struct task_security_struct *old_tsec,
2186 const struct task_security_struct *new_tsec)
2187{
2188 int nnp = (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS);
2189 int nosuid = (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID);
2190 int rc;
2191
2192 if (!nnp && !nosuid)
2193 return 0; /* neither NNP nor nosuid */
2194
2195 if (new_tsec->sid == old_tsec->sid)
2196 return 0; /* No change in credentials */
2197
2198 /*
2199 * The only transitions we permit under NNP or nosuid
2200 * are transitions to bounded SIDs, i.e. SIDs that are
2201 * guaranteed to only be allowed a subset of the permissions
2202 * of the current SID.
2203 */
2204 rc = security_bounded_transition(old_tsec->sid, new_tsec->sid);
2205 if (rc) {
2206 /*
2207 * On failure, preserve the errno values for NNP vs nosuid.
2208 * NNP: Operation not permitted for caller.
2209 * nosuid: Permission denied to file.
2210 */
2211 if (nnp)
2212 return -EPERM;
2213 else
2214 return -EACCES;
2215 }
2216 return 0;
2217}
2218
David Howellsa6f76f22008-11-14 10:39:24 +11002219static int selinux_bprm_set_creds(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002220{
David Howellsa6f76f22008-11-14 10:39:24 +11002221 const struct task_security_struct *old_tsec;
2222 struct task_security_struct *new_tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002223 struct inode_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04002224 struct common_audit_data ad;
Al Viro496ad9a2013-01-23 17:07:38 -05002225 struct inode *inode = file_inode(bprm->file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002226 int rc;
2227
David Howellsa6f76f22008-11-14 10:39:24 +11002228 /* SELinux context only depends on initial program or script and not
2229 * the script interpreter */
2230 if (bprm->cred_prepared)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002231 return 0;
2232
David Howellsa6f76f22008-11-14 10:39:24 +11002233 old_tsec = current_security();
2234 new_tsec = bprm->cred->security;
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05002235 isec = inode_security(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002236
2237 /* Default to the current task SID. */
David Howellsa6f76f22008-11-14 10:39:24 +11002238 new_tsec->sid = old_tsec->sid;
2239 new_tsec->osid = old_tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002240
Michael LeMay28eba5b2006-06-27 02:53:42 -07002241 /* Reset fs, key, and sock SIDs on execve. */
David Howellsa6f76f22008-11-14 10:39:24 +11002242 new_tsec->create_sid = 0;
2243 new_tsec->keycreate_sid = 0;
2244 new_tsec->sockcreate_sid = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002245
David Howellsa6f76f22008-11-14 10:39:24 +11002246 if (old_tsec->exec_sid) {
2247 new_tsec->sid = old_tsec->exec_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002248 /* Reset exec SID on execve. */
David Howellsa6f76f22008-11-14 10:39:24 +11002249 new_tsec->exec_sid = 0;
Andy Lutomirski259e5e62012-04-12 16:47:50 -05002250
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002251 /* Fail on NNP or nosuid if not an allowed transition. */
2252 rc = check_nnp_nosuid(bprm, old_tsec, new_tsec);
2253 if (rc)
2254 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002255 } else {
2256 /* Check for a default transition on this program. */
David Howellsa6f76f22008-11-14 10:39:24 +11002257 rc = security_transition_sid(old_tsec->sid, isec->sid,
Eric Paris652bb9b2011-02-01 11:05:40 -05002258 SECCLASS_PROCESS, NULL,
2259 &new_tsec->sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002260 if (rc)
2261 return rc;
Stephen Smalley7b0d0b42014-08-04 13:36:49 -04002262
2263 /*
2264 * Fallback to old SID on NNP or nosuid if not an allowed
2265 * transition.
2266 */
2267 rc = check_nnp_nosuid(bprm, old_tsec, new_tsec);
2268 if (rc)
2269 new_tsec->sid = old_tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002270 }
2271
Eric Paris50c205f2012-04-04 15:01:43 -04002272 ad.type = LSM_AUDIT_DATA_PATH;
Eric Parisf48b7392011-04-25 12:54:27 -04002273 ad.u.path = bprm->file->f_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002274
David Howellsa6f76f22008-11-14 10:39:24 +11002275 if (new_tsec->sid == old_tsec->sid) {
2276 rc = avc_has_perm(old_tsec->sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002277 SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, &ad);
2278 if (rc)
2279 return rc;
2280 } else {
2281 /* Check permissions for the transition. */
David Howellsa6f76f22008-11-14 10:39:24 +11002282 rc = avc_has_perm(old_tsec->sid, new_tsec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002283 SECCLASS_PROCESS, PROCESS__TRANSITION, &ad);
2284 if (rc)
2285 return rc;
2286
David Howellsa6f76f22008-11-14 10:39:24 +11002287 rc = avc_has_perm(new_tsec->sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002288 SECCLASS_FILE, FILE__ENTRYPOINT, &ad);
2289 if (rc)
2290 return rc;
2291
David Howellsa6f76f22008-11-14 10:39:24 +11002292 /* Check for shared state */
2293 if (bprm->unsafe & LSM_UNSAFE_SHARE) {
2294 rc = avc_has_perm(old_tsec->sid, new_tsec->sid,
2295 SECCLASS_PROCESS, PROCESS__SHARE,
2296 NULL);
2297 if (rc)
2298 return -EPERM;
2299 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002300
David Howellsa6f76f22008-11-14 10:39:24 +11002301 /* Make sure that anyone attempting to ptrace over a task that
2302 * changes its SID has the appropriate permit */
2303 if (bprm->unsafe &
2304 (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) {
2305 struct task_struct *tracer;
2306 struct task_security_struct *sec;
2307 u32 ptsid = 0;
2308
2309 rcu_read_lock();
Tejun Heo06d98472011-06-17 16:50:40 +02002310 tracer = ptrace_parent(current);
David Howellsa6f76f22008-11-14 10:39:24 +11002311 if (likely(tracer != NULL)) {
2312 sec = __task_cred(tracer)->security;
2313 ptsid = sec->sid;
2314 }
2315 rcu_read_unlock();
2316
2317 if (ptsid != 0) {
2318 rc = avc_has_perm(ptsid, new_tsec->sid,
2319 SECCLASS_PROCESS,
2320 PROCESS__PTRACE, NULL);
2321 if (rc)
2322 return -EPERM;
2323 }
2324 }
2325
2326 /* Clear any possibly unsafe personality bits on exec: */
2327 bprm->per_clear |= PER_CLEAR_ON_SETID;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002328 }
2329
Linus Torvalds1da177e2005-04-16 15:20:36 -07002330 return 0;
2331}
2332
Eric Paris828dfe12008-04-17 13:17:49 -04002333static int selinux_bprm_secureexec(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002334{
Paul Moore5fb49872010-04-22 14:46:19 -04002335 const struct task_security_struct *tsec = current_security();
David Howells275bb412008-11-14 10:39:19 +11002336 u32 sid, osid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002337 int atsecure = 0;
2338
David Howells275bb412008-11-14 10:39:19 +11002339 sid = tsec->sid;
2340 osid = tsec->osid;
2341
2342 if (osid != sid) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002343 /* Enable secure mode for SIDs transitions unless
2344 the noatsecure permission is granted between
2345 the two SIDs, i.e. ahp returns 0. */
David Howells275bb412008-11-14 10:39:19 +11002346 atsecure = avc_has_perm(osid, sid,
David Howellsa6f76f22008-11-14 10:39:24 +11002347 SECCLASS_PROCESS,
2348 PROCESS__NOATSECURE, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002349 }
2350
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07002351 return !!atsecure;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002352}
2353
Al Viroc3c073f2012-08-21 22:32:06 -04002354static int match_file(const void *p, struct file *file, unsigned fd)
2355{
2356 return file_has_perm(p, file, file_to_av(file)) ? fd + 1 : 0;
2357}
2358
Linus Torvalds1da177e2005-04-16 15:20:36 -07002359/* Derived from fs/exec.c:flush_old_files. */
David Howells745ca242008-11-14 10:39:22 +11002360static inline void flush_unauthorized_files(const struct cred *cred,
2361 struct files_struct *files)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002362{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002363 struct file *file, *devnull = NULL;
Stephen Smalleyb20c8122006-09-25 23:32:03 -07002364 struct tty_struct *tty;
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002365 int drop_tty = 0;
Al Viroc3c073f2012-08-21 22:32:06 -04002366 unsigned n;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002367
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002368 tty = get_current_tty();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002369 if (tty) {
Nick Pigginee2ffa02010-08-18 04:37:35 +10002370 spin_lock(&tty_files_lock);
Eric Paris37dd0bd2008-10-31 17:40:00 -04002371 if (!list_empty(&tty->tty_files)) {
Nick Piggind996b622010-08-18 04:37:36 +10002372 struct tty_file_private *file_priv;
Eric Paris37dd0bd2008-10-31 17:40:00 -04002373
Linus Torvalds1da177e2005-04-16 15:20:36 -07002374 /* Revalidate access to controlling tty.
David Howells13f8e982013-06-13 23:37:55 +01002375 Use file_path_has_perm on the tty path directly
2376 rather than using file_has_perm, as this particular
2377 open file may belong to another process and we are
2378 only interested in the inode-based check here. */
Nick Piggind996b622010-08-18 04:37:36 +10002379 file_priv = list_first_entry(&tty->tty_files,
2380 struct tty_file_private, list);
2381 file = file_priv->file;
David Howells13f8e982013-06-13 23:37:55 +01002382 if (file_path_has_perm(cred, file, FILE__READ | FILE__WRITE))
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002383 drop_tty = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002384 }
Nick Pigginee2ffa02010-08-18 04:37:35 +10002385 spin_unlock(&tty_files_lock);
Alan Cox452a00d2008-10-13 10:39:13 +01002386 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002387 }
Eric W. Biederman98a27ba2007-05-08 00:26:56 -07002388 /* Reset controlling tty. */
2389 if (drop_tty)
2390 no_tty();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002391
2392 /* Revalidate access to inherited open files. */
Al Viroc3c073f2012-08-21 22:32:06 -04002393 n = iterate_fd(files, 0, match_file, cred);
2394 if (!n) /* none found? */
2395 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002396
Al Viroc3c073f2012-08-21 22:32:06 -04002397 devnull = dentry_open(&selinux_null, O_RDWR, cred);
Al Viro45525b22012-10-16 13:30:07 -04002398 if (IS_ERR(devnull))
2399 devnull = NULL;
2400 /* replace all the matching ones with this */
2401 do {
2402 replace_fd(n - 1, devnull, 0);
2403 } while ((n = iterate_fd(files, n, match_file, cred)) != 0);
2404 if (devnull)
Al Viroc3c073f2012-08-21 22:32:06 -04002405 fput(devnull);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002406}
2407
Linus Torvalds1da177e2005-04-16 15:20:36 -07002408/*
David Howellsa6f76f22008-11-14 10:39:24 +11002409 * Prepare a process for imminent new credential changes due to exec
Linus Torvalds1da177e2005-04-16 15:20:36 -07002410 */
David Howellsa6f76f22008-11-14 10:39:24 +11002411static void selinux_bprm_committing_creds(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002412{
David Howellsa6f76f22008-11-14 10:39:24 +11002413 struct task_security_struct *new_tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002414 struct rlimit *rlim, *initrlim;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002415 int rc, i;
2416
David Howellsa6f76f22008-11-14 10:39:24 +11002417 new_tsec = bprm->cred->security;
2418 if (new_tsec->sid == new_tsec->osid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002419 return;
2420
2421 /* Close files for which the new task SID is not authorized. */
David Howellsa6f76f22008-11-14 10:39:24 +11002422 flush_unauthorized_files(bprm->cred, current->files);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002423
David Howellsa6f76f22008-11-14 10:39:24 +11002424 /* Always clear parent death signal on SID transitions. */
2425 current->pdeath_signal = 0;
2426
2427 /* Check whether the new SID can inherit resource limits from the old
2428 * SID. If not, reset all soft limits to the lower of the current
2429 * task's hard limit and the init task's soft limit.
2430 *
2431 * Note that the setting of hard limits (even to lower them) can be
2432 * controlled by the setrlimit check. The inclusion of the init task's
2433 * soft limit into the computation is to avoid resetting soft limits
2434 * higher than the default soft limit for cases where the default is
2435 * lower than the hard limit, e.g. RLIMIT_CORE or RLIMIT_STACK.
2436 */
2437 rc = avc_has_perm(new_tsec->osid, new_tsec->sid, SECCLASS_PROCESS,
2438 PROCESS__RLIMITINH, NULL);
2439 if (rc) {
Oleg Nesteroveb2d55a2010-06-23 22:43:32 +02002440 /* protect against do_prlimit() */
2441 task_lock(current);
David Howellsa6f76f22008-11-14 10:39:24 +11002442 for (i = 0; i < RLIM_NLIMITS; i++) {
2443 rlim = current->signal->rlim + i;
2444 initrlim = init_task.signal->rlim + i;
2445 rlim->rlim_cur = min(rlim->rlim_max, initrlim->rlim_cur);
2446 }
Oleg Nesteroveb2d55a2010-06-23 22:43:32 +02002447 task_unlock(current);
2448 update_rlimit_cpu(current, rlimit(RLIMIT_CPU));
David Howellsa6f76f22008-11-14 10:39:24 +11002449 }
2450}
2451
2452/*
2453 * Clean up the process immediately after the installation of new credentials
2454 * due to exec
2455 */
2456static void selinux_bprm_committed_creds(struct linux_binprm *bprm)
2457{
2458 const struct task_security_struct *tsec = current_security();
2459 struct itimerval itimer;
David Howellsa6f76f22008-11-14 10:39:24 +11002460 u32 osid, sid;
2461 int rc, i;
David Howellsa6f76f22008-11-14 10:39:24 +11002462
David Howellsa6f76f22008-11-14 10:39:24 +11002463 osid = tsec->osid;
2464 sid = tsec->sid;
2465
2466 if (sid == osid)
2467 return;
2468
2469 /* Check whether the new SID can inherit signal state from the old SID.
2470 * If not, clear itimers to avoid subsequent signal generation and
2471 * flush and unblock signals.
2472 *
2473 * This must occur _after_ the task SID has been updated so that any
2474 * kill done after the flush will be checked against the new SID.
2475 */
2476 rc = avc_has_perm(osid, sid, SECCLASS_PROCESS, PROCESS__SIGINH, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002477 if (rc) {
2478 memset(&itimer, 0, sizeof itimer);
2479 for (i = 0; i < 3; i++)
2480 do_setitimer(i, &itimer, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002481 spin_lock_irq(&current->sighand->siglock);
Oleg Nesterov9e7c8f82015-06-04 16:22:16 -04002482 if (!fatal_signal_pending(current)) {
2483 flush_sigqueue(&current->pending);
2484 flush_sigqueue(&current->signal->shared_pending);
David Howells3bcac022009-04-29 13:45:05 +01002485 flush_signal_handlers(current, 1);
2486 sigemptyset(&current->blocked);
Oleg Nesterov9e7c8f82015-06-04 16:22:16 -04002487 recalc_sigpending();
David Howells3bcac022009-04-29 13:45:05 +01002488 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002489 spin_unlock_irq(&current->sighand->siglock);
2490 }
2491
David Howellsa6f76f22008-11-14 10:39:24 +11002492 /* Wake up the parent if it is waiting so that it can recheck
2493 * wait permission to the new task SID. */
Oleg Nesterovecd6de32009-04-29 16:02:24 +02002494 read_lock(&tasklist_lock);
Oleg Nesterov0b7570e2009-09-23 15:56:46 -07002495 __wake_up_parent(current, current->real_parent);
Oleg Nesterovecd6de32009-04-29 16:02:24 +02002496 read_unlock(&tasklist_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002497}
2498
2499/* superblock security operations */
2500
2501static int selinux_sb_alloc_security(struct super_block *sb)
2502{
2503 return superblock_alloc_security(sb);
2504}
2505
2506static void selinux_sb_free_security(struct super_block *sb)
2507{
2508 superblock_free_security(sb);
2509}
2510
2511static inline int match_prefix(char *prefix, int plen, char *option, int olen)
2512{
2513 if (plen > olen)
2514 return 0;
2515
2516 return !memcmp(prefix, option, plen);
2517}
2518
2519static inline int selinux_option(char *option, int len)
2520{
Eric Paris832cbd92008-04-01 13:24:09 -04002521 return (match_prefix(CONTEXT_STR, sizeof(CONTEXT_STR)-1, option, len) ||
2522 match_prefix(FSCONTEXT_STR, sizeof(FSCONTEXT_STR)-1, option, len) ||
2523 match_prefix(DEFCONTEXT_STR, sizeof(DEFCONTEXT_STR)-1, option, len) ||
David P. Quigley11689d42009-01-16 09:22:03 -05002524 match_prefix(ROOTCONTEXT_STR, sizeof(ROOTCONTEXT_STR)-1, option, len) ||
2525 match_prefix(LABELSUPP_STR, sizeof(LABELSUPP_STR)-1, option, len));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002526}
2527
2528static inline void take_option(char **to, char *from, int *first, int len)
2529{
2530 if (!*first) {
2531 **to = ',';
2532 *to += 1;
Cory Olmo3528a952006-09-29 01:58:44 -07002533 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002534 *first = 0;
2535 memcpy(*to, from, len);
2536 *to += len;
2537}
2538
Eric Paris828dfe12008-04-17 13:17:49 -04002539static inline void take_selinux_option(char **to, char *from, int *first,
2540 int len)
Cory Olmo3528a952006-09-29 01:58:44 -07002541{
2542 int current_size = 0;
2543
2544 if (!*first) {
2545 **to = '|';
2546 *to += 1;
Eric Paris828dfe12008-04-17 13:17:49 -04002547 } else
Cory Olmo3528a952006-09-29 01:58:44 -07002548 *first = 0;
2549
2550 while (current_size < len) {
2551 if (*from != '"') {
2552 **to = *from;
2553 *to += 1;
2554 }
2555 from += 1;
2556 current_size += 1;
2557 }
2558}
2559
Eric Parise0007522008-03-05 10:31:54 -05002560static int selinux_sb_copy_data(char *orig, char *copy)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002561{
2562 int fnosec, fsec, rc = 0;
2563 char *in_save, *in_curr, *in_end;
2564 char *sec_curr, *nosec_save, *nosec;
Cory Olmo3528a952006-09-29 01:58:44 -07002565 int open_quote = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002566
2567 in_curr = orig;
2568 sec_curr = copy;
2569
Linus Torvalds1da177e2005-04-16 15:20:36 -07002570 nosec = (char *)get_zeroed_page(GFP_KERNEL);
2571 if (!nosec) {
2572 rc = -ENOMEM;
2573 goto out;
2574 }
2575
2576 nosec_save = nosec;
2577 fnosec = fsec = 1;
2578 in_save = in_end = orig;
2579
2580 do {
Cory Olmo3528a952006-09-29 01:58:44 -07002581 if (*in_end == '"')
2582 open_quote = !open_quote;
2583 if ((*in_end == ',' && open_quote == 0) ||
2584 *in_end == '\0') {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002585 int len = in_end - in_curr;
2586
2587 if (selinux_option(in_curr, len))
Cory Olmo3528a952006-09-29 01:58:44 -07002588 take_selinux_option(&sec_curr, in_curr, &fsec, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002589 else
2590 take_option(&nosec, in_curr, &fnosec, len);
2591
2592 in_curr = in_end + 1;
2593 }
2594 } while (*in_end++);
2595
Eric Paris6931dfc2005-06-30 02:58:51 -07002596 strcpy(in_save, nosec_save);
Gerald Schaeferda3caa22005-06-21 17:15:18 -07002597 free_page((unsigned long)nosec_save);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002598out:
2599 return rc;
2600}
2601
Eric Paris026eb162011-03-03 16:09:14 -05002602static int selinux_sb_remount(struct super_block *sb, void *data)
2603{
2604 int rc, i, *flags;
2605 struct security_mnt_opts opts;
2606 char *secdata, **mount_options;
2607 struct superblock_security_struct *sbsec = sb->s_security;
2608
2609 if (!(sbsec->flags & SE_SBINITIALIZED))
2610 return 0;
2611
2612 if (!data)
2613 return 0;
2614
2615 if (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)
2616 return 0;
2617
2618 security_init_mnt_opts(&opts);
2619 secdata = alloc_secdata();
2620 if (!secdata)
2621 return -ENOMEM;
2622 rc = selinux_sb_copy_data(data, secdata);
2623 if (rc)
2624 goto out_free_secdata;
2625
2626 rc = selinux_parse_opts_str(secdata, &opts);
2627 if (rc)
2628 goto out_free_secdata;
2629
2630 mount_options = opts.mnt_opts;
2631 flags = opts.mnt_opts_flags;
2632
2633 for (i = 0; i < opts.num_mnt_opts; i++) {
2634 u32 sid;
Eric Paris026eb162011-03-03 16:09:14 -05002635
Eric Paris12f348b2012-10-09 10:56:25 -04002636 if (flags[i] == SBLABEL_MNT)
Eric Paris026eb162011-03-03 16:09:14 -05002637 continue;
Rasmus Villemoes44be2f62015-10-21 17:44:25 -04002638 rc = security_context_str_to_sid(mount_options[i], &sid, GFP_KERNEL);
Eric Paris026eb162011-03-03 16:09:14 -05002639 if (rc) {
Rasmus Villemoes44be2f62015-10-21 17:44:25 -04002640 printk(KERN_WARNING "SELinux: security_context_str_to_sid"
Linus Torvalds29b1deb2013-12-15 11:17:45 -08002641 "(%s) failed for (dev %s, type %s) errno=%d\n",
2642 mount_options[i], sb->s_id, sb->s_type->name, rc);
Eric Paris026eb162011-03-03 16:09:14 -05002643 goto out_free_opts;
2644 }
2645 rc = -EINVAL;
2646 switch (flags[i]) {
2647 case FSCONTEXT_MNT:
2648 if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid, sid))
2649 goto out_bad_option;
2650 break;
2651 case CONTEXT_MNT:
2652 if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid, sid))
2653 goto out_bad_option;
2654 break;
2655 case ROOTCONTEXT_MNT: {
2656 struct inode_security_struct *root_isec;
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05002657 root_isec = backing_inode_security(sb->s_root);
Eric Paris026eb162011-03-03 16:09:14 -05002658
2659 if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid, sid))
2660 goto out_bad_option;
2661 break;
2662 }
2663 case DEFCONTEXT_MNT:
2664 if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid, sid))
2665 goto out_bad_option;
2666 break;
2667 default:
2668 goto out_free_opts;
2669 }
2670 }
2671
2672 rc = 0;
2673out_free_opts:
2674 security_free_mnt_opts(&opts);
2675out_free_secdata:
2676 free_secdata(secdata);
2677 return rc;
2678out_bad_option:
2679 printk(KERN_WARNING "SELinux: unable to change security options "
Linus Torvalds29b1deb2013-12-15 11:17:45 -08002680 "during remount (dev %s, type=%s)\n", sb->s_id,
2681 sb->s_type->name);
Eric Paris026eb162011-03-03 16:09:14 -05002682 goto out_free_opts;
2683}
2684
James Morris12204e22008-12-19 10:44:42 +11002685static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002686{
David Howells88e67f32008-11-14 10:39:21 +11002687 const struct cred *cred = current_cred();
Thomas Liu2bf49692009-07-14 12:14:09 -04002688 struct common_audit_data ad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002689 int rc;
2690
2691 rc = superblock_doinit(sb, data);
2692 if (rc)
2693 return rc;
2694
James Morris74192242008-12-19 11:41:10 +11002695 /* Allow all mounts performed by the kernel */
2696 if (flags & MS_KERNMOUNT)
2697 return 0;
2698
Eric Paris50c205f2012-04-04 15:01:43 -04002699 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04002700 ad.u.dentry = sb->s_root;
David Howells88e67f32008-11-14 10:39:21 +11002701 return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002702}
2703
David Howells726c3342006-06-23 02:02:58 -07002704static int selinux_sb_statfs(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002705{
David Howells88e67f32008-11-14 10:39:21 +11002706 const struct cred *cred = current_cred();
Thomas Liu2bf49692009-07-14 12:14:09 -04002707 struct common_audit_data ad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002708
Eric Paris50c205f2012-04-04 15:01:43 -04002709 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04002710 ad.u.dentry = dentry->d_sb->s_root;
David Howells88e67f32008-11-14 10:39:21 +11002711 return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002712}
2713
Al Viro808d4e32012-10-11 11:42:01 -04002714static int selinux_mount(const char *dev_name,
Al Virob5266eb2008-03-22 17:48:24 -04002715 struct path *path,
Al Viro808d4e32012-10-11 11:42:01 -04002716 const char *type,
Eric Paris828dfe12008-04-17 13:17:49 -04002717 unsigned long flags,
2718 void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002719{
David Howells88e67f32008-11-14 10:39:21 +11002720 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002721
2722 if (flags & MS_REMOUNT)
Al Virod8c95842011-12-07 18:16:57 -05002723 return superblock_has_perm(cred, path->dentry->d_sb,
Eric Paris828dfe12008-04-17 13:17:49 -04002724 FILESYSTEM__REMOUNT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002725 else
Eric Paris2875fa02011-04-28 16:04:24 -04002726 return path_has_perm(cred, path, FILE__MOUNTON);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002727}
2728
2729static int selinux_umount(struct vfsmount *mnt, int flags)
2730{
David Howells88e67f32008-11-14 10:39:21 +11002731 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002732
David Howells88e67f32008-11-14 10:39:21 +11002733 return superblock_has_perm(cred, mnt->mnt_sb,
Eric Paris828dfe12008-04-17 13:17:49 -04002734 FILESYSTEM__UNMOUNT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002735}
2736
2737/* inode security operations */
2738
2739static int selinux_inode_alloc_security(struct inode *inode)
2740{
2741 return inode_alloc_security(inode);
2742}
2743
2744static void selinux_inode_free_security(struct inode *inode)
2745{
2746 inode_free_security(inode);
2747}
2748
David Quigleyd47be3d2013-05-22 12:50:34 -04002749static int selinux_dentry_init_security(struct dentry *dentry, int mode,
2750 struct qstr *name, void **ctx,
2751 u32 *ctxlen)
2752{
David Quigleyd47be3d2013-05-22 12:50:34 -04002753 u32 newsid;
2754 int rc;
2755
David Howellsc3c188b2015-07-10 17:19:58 -04002756 rc = selinux_determine_inode_label(d_inode(dentry->d_parent), name,
2757 inode_mode_to_security_class(mode),
2758 &newsid);
2759 if (rc)
2760 return rc;
David Quigleyd47be3d2013-05-22 12:50:34 -04002761
2762 return security_sid_to_context(newsid, (char **)ctx, ctxlen);
2763}
2764
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002765static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
Tetsuo Handa95489062013-07-25 05:44:02 +09002766 const struct qstr *qstr,
2767 const char **name,
Eric Paris2a7dba32011-02-01 11:05:39 -05002768 void **value, size_t *len)
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002769{
Paul Moore5fb49872010-04-22 14:46:19 -04002770 const struct task_security_struct *tsec = current_security();
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002771 struct superblock_security_struct *sbsec;
David Howells275bb412008-11-14 10:39:19 +11002772 u32 sid, newsid, clen;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002773 int rc;
Tetsuo Handa95489062013-07-25 05:44:02 +09002774 char *context;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002775
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002776 sbsec = dir->i_sb->s_security;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002777
David Howells275bb412008-11-14 10:39:19 +11002778 sid = tsec->sid;
2779 newsid = tsec->create_sid;
2780
David Howellsc3c188b2015-07-10 17:19:58 -04002781 rc = selinux_determine_inode_label(
2782 dir, qstr,
2783 inode_mode_to_security_class(inode->i_mode),
2784 &newsid);
2785 if (rc)
2786 return rc;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002787
Eric Paris296fddf2006-09-25 23:32:00 -07002788 /* Possibly defer initialization to selinux_complete_init. */
David P. Quigley0d90a7e2009-01-16 09:22:02 -05002789 if (sbsec->flags & SE_SBINITIALIZED) {
Eric Paris296fddf2006-09-25 23:32:00 -07002790 struct inode_security_struct *isec = inode->i_security;
2791 isec->sclass = inode_mode_to_security_class(inode->i_mode);
2792 isec->sid = newsid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05002793 isec->initialized = LABEL_INITIALIZED;
Eric Paris296fddf2006-09-25 23:32:00 -07002794 }
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002795
Eric Paris12f348b2012-10-09 10:56:25 -04002796 if (!ss_initialized || !(sbsec->flags & SBLABEL_MNT))
Stephen Smalley25a74f32005-11-08 21:34:33 -08002797 return -EOPNOTSUPP;
2798
Tetsuo Handa95489062013-07-25 05:44:02 +09002799 if (name)
2800 *name = XATTR_SELINUX_SUFFIX;
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002801
2802 if (value && len) {
Stephen Smalley12b29f32008-05-07 13:03:20 -04002803 rc = security_sid_to_context_force(newsid, &context, &clen);
Tetsuo Handa95489062013-07-25 05:44:02 +09002804 if (rc)
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002805 return rc;
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002806 *value = context;
2807 *len = clen;
2808 }
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002809
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002810 return 0;
2811}
2812
Al Viro4acdaf22011-07-26 01:42:34 -04002813static int selinux_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002814{
2815 return may_create(dir, dentry, SECCLASS_FILE);
2816}
2817
Linus Torvalds1da177e2005-04-16 15:20:36 -07002818static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
2819{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002820 return may_link(dir, old_dentry, MAY_LINK);
2821}
2822
Linus Torvalds1da177e2005-04-16 15:20:36 -07002823static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry)
2824{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002825 return may_link(dir, dentry, MAY_UNLINK);
2826}
2827
2828static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry, const char *name)
2829{
2830 return may_create(dir, dentry, SECCLASS_LNK_FILE);
2831}
2832
Al Viro18bb1db2011-07-26 01:41:39 -04002833static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry, umode_t mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002834{
2835 return may_create(dir, dentry, SECCLASS_DIR);
2836}
2837
Linus Torvalds1da177e2005-04-16 15:20:36 -07002838static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry)
2839{
2840 return may_link(dir, dentry, MAY_RMDIR);
2841}
2842
Al Viro1a67aaf2011-07-26 01:52:52 -04002843static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002844{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002845 return may_create(dir, dentry, inode_mode_to_security_class(mode));
2846}
2847
Linus Torvalds1da177e2005-04-16 15:20:36 -07002848static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
Eric Paris828dfe12008-04-17 13:17:49 -04002849 struct inode *new_inode, struct dentry *new_dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002850{
2851 return may_rename(old_inode, old_dentry, new_inode, new_dentry);
2852}
2853
Linus Torvalds1da177e2005-04-16 15:20:36 -07002854static int selinux_inode_readlink(struct dentry *dentry)
2855{
David Howells88e67f32008-11-14 10:39:21 +11002856 const struct cred *cred = current_cred();
2857
Eric Paris2875fa02011-04-28 16:04:24 -04002858 return dentry_has_perm(cred, dentry, FILE__READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002859}
2860
NeilBrownbda0be72015-03-23 13:37:39 +11002861static int selinux_inode_follow_link(struct dentry *dentry, struct inode *inode,
2862 bool rcu)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002863{
David Howells88e67f32008-11-14 10:39:21 +11002864 const struct cred *cred = current_cred();
NeilBrownbda0be72015-03-23 13:37:39 +11002865 struct common_audit_data ad;
2866 struct inode_security_struct *isec;
2867 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002868
NeilBrownbda0be72015-03-23 13:37:39 +11002869 validate_creds(cred);
2870
2871 ad.type = LSM_AUDIT_DATA_DENTRY;
2872 ad.u.dentry = dentry;
2873 sid = cred_sid(cred);
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05002874 isec = inode_security(inode);
NeilBrownbda0be72015-03-23 13:37:39 +11002875
2876 return avc_has_perm_flags(sid, isec->sid, isec->sclass, FILE__READ, &ad,
2877 rcu ? MAY_NOT_BLOCK : 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002878}
2879
Eric Parisd4cf970d2012-04-04 15:01:42 -04002880static noinline int audit_inode_permission(struct inode *inode,
2881 u32 perms, u32 audited, u32 denied,
Stephen Smalley626b9742014-04-29 11:29:04 -07002882 int result,
Eric Parisd4cf970d2012-04-04 15:01:42 -04002883 unsigned flags)
2884{
2885 struct common_audit_data ad;
Eric Parisd4cf970d2012-04-04 15:01:42 -04002886 struct inode_security_struct *isec = inode->i_security;
2887 int rc;
2888
Eric Paris50c205f2012-04-04 15:01:43 -04002889 ad.type = LSM_AUDIT_DATA_INODE;
Eric Parisd4cf970d2012-04-04 15:01:42 -04002890 ad.u.inode = inode;
2891
2892 rc = slow_avc_audit(current_sid(), isec->sid, isec->sclass, perms,
Stephen Smalley626b9742014-04-29 11:29:04 -07002893 audited, denied, result, &ad, flags);
Eric Parisd4cf970d2012-04-04 15:01:42 -04002894 if (rc)
2895 return rc;
2896 return 0;
2897}
2898
Al Viroe74f71e2011-06-20 19:38:15 -04002899static int selinux_inode_permission(struct inode *inode, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002900{
David Howells88e67f32008-11-14 10:39:21 +11002901 const struct cred *cred = current_cred();
Eric Parisb782e0a2010-07-23 11:44:03 -04002902 u32 perms;
2903 bool from_access;
Al Virocf1dd1d2011-06-20 19:44:08 -04002904 unsigned flags = mask & MAY_NOT_BLOCK;
Eric Paris2e334052012-04-04 15:01:42 -04002905 struct inode_security_struct *isec;
2906 u32 sid;
2907 struct av_decision avd;
2908 int rc, rc2;
2909 u32 audited, denied;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002910
Eric Parisb782e0a2010-07-23 11:44:03 -04002911 from_access = mask & MAY_ACCESS;
Eric Parisd09ca732010-07-23 11:43:57 -04002912 mask &= (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND);
2913
Eric Parisb782e0a2010-07-23 11:44:03 -04002914 /* No permission to check. Existence test. */
2915 if (!mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002916 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002917
Eric Paris2e334052012-04-04 15:01:42 -04002918 validate_creds(cred);
Eric Parisb782e0a2010-07-23 11:44:03 -04002919
Eric Paris2e334052012-04-04 15:01:42 -04002920 if (unlikely(IS_PRIVATE(inode)))
2921 return 0;
Eric Parisb782e0a2010-07-23 11:44:03 -04002922
2923 perms = file_mask_to_av(inode->i_mode, mask);
2924
Eric Paris2e334052012-04-04 15:01:42 -04002925 sid = cred_sid(cred);
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05002926 isec = inode_security(inode);
Eric Paris2e334052012-04-04 15:01:42 -04002927
2928 rc = avc_has_perm_noaudit(sid, isec->sid, isec->sclass, perms, 0, &avd);
2929 audited = avc_audit_required(perms, &avd, rc,
2930 from_access ? FILE__AUDIT_ACCESS : 0,
2931 &denied);
2932 if (likely(!audited))
2933 return rc;
2934
Stephen Smalley626b9742014-04-29 11:29:04 -07002935 rc2 = audit_inode_permission(inode, perms, audited, denied, rc, flags);
Eric Paris2e334052012-04-04 15:01:42 -04002936 if (rc2)
2937 return rc2;
2938 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002939}
2940
2941static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
2942{
David Howells88e67f32008-11-14 10:39:21 +11002943 const struct cred *cred = current_cred();
Amerigo Wangbc6a6002009-08-20 19:29:02 -07002944 unsigned int ia_valid = iattr->ia_valid;
Eric Paris95dbf732012-04-04 13:45:34 -04002945 __u32 av = FILE__WRITE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002946
Amerigo Wangbc6a6002009-08-20 19:29:02 -07002947 /* ATTR_FORCE is just used for ATTR_KILL_S[UG]ID. */
2948 if (ia_valid & ATTR_FORCE) {
2949 ia_valid &= ~(ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_MODE |
2950 ATTR_FORCE);
2951 if (!ia_valid)
2952 return 0;
2953 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002954
Amerigo Wangbc6a6002009-08-20 19:29:02 -07002955 if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID |
2956 ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_TIMES_SET))
Eric Paris2875fa02011-04-28 16:04:24 -04002957 return dentry_has_perm(cred, dentry, FILE__SETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002958
Jeff Vander Stoep44d37ad2015-10-21 17:44:25 -04002959 if (selinux_policycap_openperm && (ia_valid & ATTR_SIZE)
2960 && !(ia_valid & ATTR_FILE))
Eric Paris95dbf732012-04-04 13:45:34 -04002961 av |= FILE__OPEN;
2962
2963 return dentry_has_perm(cred, dentry, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002964}
2965
Al Viro3f7036a2015-03-08 19:28:30 -04002966static int selinux_inode_getattr(const struct path *path)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002967{
Al Viro3f7036a2015-03-08 19:28:30 -04002968 return path_has_perm(current_cred(), path, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002969}
2970
David Howells8f0cfa52008-04-29 00:59:41 -07002971static int selinux_inode_setotherxattr(struct dentry *dentry, const char *name)
Serge E. Hallynb5376772007-10-16 23:31:36 -07002972{
David Howells88e67f32008-11-14 10:39:21 +11002973 const struct cred *cred = current_cred();
2974
Serge E. Hallynb5376772007-10-16 23:31:36 -07002975 if (!strncmp(name, XATTR_SECURITY_PREFIX,
2976 sizeof XATTR_SECURITY_PREFIX - 1)) {
2977 if (!strcmp(name, XATTR_NAME_CAPS)) {
2978 if (!capable(CAP_SETFCAP))
2979 return -EPERM;
2980 } else if (!capable(CAP_SYS_ADMIN)) {
2981 /* A different attribute in the security namespace.
2982 Restrict to administrator. */
2983 return -EPERM;
2984 }
2985 }
2986
2987 /* Not an attribute we recognize, so just check the
2988 ordinary setattr permission. */
Eric Paris2875fa02011-04-28 16:04:24 -04002989 return dentry_has_perm(cred, dentry, FILE__SETATTR);
Serge E. Hallynb5376772007-10-16 23:31:36 -07002990}
2991
David Howells8f0cfa52008-04-29 00:59:41 -07002992static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
2993 const void *value, size_t size, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002994{
David Howellsc6f493d2015-03-17 22:26:22 +00002995 struct inode *inode = d_backing_inode(dentry);
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05002996 struct inode_security_struct *isec = backing_inode_security(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002997 struct superblock_security_struct *sbsec;
Thomas Liu2bf49692009-07-14 12:14:09 -04002998 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11002999 u32 newsid, sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003000 int rc = 0;
3001
Serge E. Hallynb5376772007-10-16 23:31:36 -07003002 if (strcmp(name, XATTR_NAME_SELINUX))
3003 return selinux_inode_setotherxattr(dentry, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003004
3005 sbsec = inode->i_sb->s_security;
Eric Paris12f348b2012-10-09 10:56:25 -04003006 if (!(sbsec->flags & SBLABEL_MNT))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003007 return -EOPNOTSUPP;
3008
Serge E. Hallyn2e149672011-03-23 16:43:26 -07003009 if (!inode_owner_or_capable(inode))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003010 return -EPERM;
3011
Eric Paris50c205f2012-04-04 15:01:43 -04003012 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04003013 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003014
David Howells275bb412008-11-14 10:39:19 +11003015 rc = avc_has_perm(sid, isec->sid, isec->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003016 FILE__RELABELFROM, &ad);
3017 if (rc)
3018 return rc;
3019
Nikolay Aleksandrov52a4c642014-03-07 12:44:19 +01003020 rc = security_context_to_sid(value, size, &newsid, GFP_KERNEL);
Stephen Smalley12b29f32008-05-07 13:03:20 -04003021 if (rc == -EINVAL) {
Eric Parisd6ea83e2012-04-04 13:45:49 -04003022 if (!capable(CAP_MAC_ADMIN)) {
3023 struct audit_buffer *ab;
3024 size_t audit_size;
3025 const char *str;
3026
3027 /* We strip a nul only if it is at the end, otherwise the
3028 * context contains a nul and we should audit that */
Al Viroe3fea3f2012-06-09 08:15:16 +01003029 if (value) {
3030 str = value;
3031 if (str[size - 1] == '\0')
3032 audit_size = size - 1;
3033 else
3034 audit_size = size;
3035 } else {
3036 str = "";
3037 audit_size = 0;
3038 }
Eric Parisd6ea83e2012-04-04 13:45:49 -04003039 ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR);
3040 audit_log_format(ab, "op=setxattr invalid_context=");
3041 audit_log_n_untrustedstring(ab, value, audit_size);
3042 audit_log_end(ab);
3043
Stephen Smalley12b29f32008-05-07 13:03:20 -04003044 return rc;
Eric Parisd6ea83e2012-04-04 13:45:49 -04003045 }
Stephen Smalley12b29f32008-05-07 13:03:20 -04003046 rc = security_context_to_sid_force(value, size, &newsid);
3047 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003048 if (rc)
3049 return rc;
3050
David Howells275bb412008-11-14 10:39:19 +11003051 rc = avc_has_perm(sid, newsid, isec->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003052 FILE__RELABELTO, &ad);
3053 if (rc)
3054 return rc;
3055
David Howells275bb412008-11-14 10:39:19 +11003056 rc = security_validate_transition(isec->sid, newsid, sid,
Eric Paris828dfe12008-04-17 13:17:49 -04003057 isec->sclass);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003058 if (rc)
3059 return rc;
3060
3061 return avc_has_perm(newsid,
3062 sbsec->sid,
3063 SECCLASS_FILESYSTEM,
3064 FILESYSTEM__ASSOCIATE,
3065 &ad);
3066}
3067
David Howells8f0cfa52008-04-29 00:59:41 -07003068static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
Eric Parisf5269712008-05-14 11:27:45 -04003069 const void *value, size_t size,
David Howells8f0cfa52008-04-29 00:59:41 -07003070 int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003071{
David Howellsc6f493d2015-03-17 22:26:22 +00003072 struct inode *inode = d_backing_inode(dentry);
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05003073 struct inode_security_struct *isec = backing_inode_security(dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003074 u32 newsid;
3075 int rc;
3076
3077 if (strcmp(name, XATTR_NAME_SELINUX)) {
3078 /* Not an attribute we recognize, so nothing to do. */
3079 return;
3080 }
3081
Stephen Smalley12b29f32008-05-07 13:03:20 -04003082 rc = security_context_to_sid_force(value, size, &newsid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003083 if (rc) {
Stephen Smalley12b29f32008-05-07 13:03:20 -04003084 printk(KERN_ERR "SELinux: unable to map context to SID"
3085 "for (%s, %lu), rc=%d\n",
3086 inode->i_sb->s_id, inode->i_ino, -rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003087 return;
3088 }
3089
David Quigleyaa9c2662013-05-22 12:50:44 -04003090 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003091 isec->sid = newsid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05003092 isec->initialized = LABEL_INITIALIZED;
David Quigleyaa9c2662013-05-22 12:50:44 -04003093
Linus Torvalds1da177e2005-04-16 15:20:36 -07003094 return;
3095}
3096
David Howells8f0cfa52008-04-29 00:59:41 -07003097static int selinux_inode_getxattr(struct dentry *dentry, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003098{
David Howells88e67f32008-11-14 10:39:21 +11003099 const struct cred *cred = current_cred();
3100
Eric Paris2875fa02011-04-28 16:04:24 -04003101 return dentry_has_perm(cred, dentry, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003102}
3103
Eric Paris828dfe12008-04-17 13:17:49 -04003104static int selinux_inode_listxattr(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003105{
David Howells88e67f32008-11-14 10:39:21 +11003106 const struct cred *cred = current_cred();
3107
Eric Paris2875fa02011-04-28 16:04:24 -04003108 return dentry_has_perm(cred, dentry, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003109}
3110
David Howells8f0cfa52008-04-29 00:59:41 -07003111static int selinux_inode_removexattr(struct dentry *dentry, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003112{
Serge E. Hallynb5376772007-10-16 23:31:36 -07003113 if (strcmp(name, XATTR_NAME_SELINUX))
3114 return selinux_inode_setotherxattr(dentry, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003115
3116 /* No one is allowed to remove a SELinux security label.
3117 You can change the label, but all data must be labeled. */
3118 return -EACCES;
3119}
3120
James Morrisd381d8a2005-10-30 14:59:22 -08003121/*
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04003122 * Copy the inode security context value to the user.
James Morrisd381d8a2005-10-30 14:59:22 -08003123 *
3124 * Permission check is handled by selinux_inode_getxattr hook.
3125 */
Andreas Gruenbacherea861df2015-12-24 11:09:39 -05003126static int selinux_inode_getsecurity(struct inode *inode, const char *name, void **buffer, bool alloc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003127{
David P. Quigley42492592008-02-04 22:29:39 -08003128 u32 size;
3129 int error;
3130 char *context = NULL;
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05003131 struct inode_security_struct *isec = inode_security(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003132
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00003133 if (strcmp(name, XATTR_SELINUX_SUFFIX))
3134 return -EOPNOTSUPP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003135
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04003136 /*
3137 * If the caller has CAP_MAC_ADMIN, then get the raw context
3138 * value even if it is not defined by current policy; otherwise,
3139 * use the in-core value under current policy.
3140 * Use the non-auditing forms of the permission checks since
3141 * getxattr may be called by unprivileged processes commonly
3142 * and lack of permission just means that we fall back to the
3143 * in-core context value, not a denial.
3144 */
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07003145 error = cap_capable(current_cred(), &init_user_ns, CAP_MAC_ADMIN,
3146 SECURITY_CAP_NOAUDIT);
3147 if (!error)
3148 error = cred_has_capability(current_cred(), CAP_MAC_ADMIN,
3149 SECURITY_CAP_NOAUDIT);
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04003150 if (!error)
3151 error = security_sid_to_context_force(isec->sid, &context,
3152 &size);
3153 else
3154 error = security_sid_to_context(isec->sid, &context, &size);
David P. Quigley42492592008-02-04 22:29:39 -08003155 if (error)
3156 return error;
3157 error = size;
3158 if (alloc) {
3159 *buffer = context;
3160 goto out_nofree;
3161 }
3162 kfree(context);
3163out_nofree:
3164 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003165}
3166
3167static int selinux_inode_setsecurity(struct inode *inode, const char *name,
Eric Paris828dfe12008-04-17 13:17:49 -04003168 const void *value, size_t size, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003169{
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05003170 struct inode_security_struct *isec = inode_security(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003171 u32 newsid;
3172 int rc;
3173
3174 if (strcmp(name, XATTR_SELINUX_SUFFIX))
3175 return -EOPNOTSUPP;
3176
3177 if (!value || !size)
3178 return -EACCES;
3179
Rasmus Villemoes20ba96a2015-10-21 17:44:26 -04003180 rc = security_context_to_sid(value, size, &newsid, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003181 if (rc)
3182 return rc;
3183
David Quigleyaa9c2662013-05-22 12:50:44 -04003184 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003185 isec->sid = newsid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05003186 isec->initialized = LABEL_INITIALIZED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003187 return 0;
3188}
3189
3190static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size)
3191{
3192 const int len = sizeof(XATTR_NAME_SELINUX);
3193 if (buffer && len <= buffer_size)
3194 memcpy(buffer, XATTR_NAME_SELINUX, len);
3195 return len;
3196}
3197
Andreas Gruenbacherd6335d72015-12-24 11:09:39 -05003198static void selinux_inode_getsecid(struct inode *inode, u32 *secid)
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02003199{
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05003200 struct inode_security_struct *isec = inode_security(inode);
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02003201 *secid = isec->sid;
3202}
3203
Linus Torvalds1da177e2005-04-16 15:20:36 -07003204/* file security operations */
3205
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003206static int selinux_revalidate_file_permission(struct file *file, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003207{
David Howells88e67f32008-11-14 10:39:21 +11003208 const struct cred *cred = current_cred();
Al Viro496ad9a2013-01-23 17:07:38 -05003209 struct inode *inode = file_inode(file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003210
Linus Torvalds1da177e2005-04-16 15:20:36 -07003211 /* file_mask_to_av won't add FILE__WRITE if MAY_APPEND is set */
3212 if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE))
3213 mask |= MAY_APPEND;
3214
Paul Moore389fb8002009-03-27 17:10:34 -04003215 return file_has_perm(cred, file,
3216 file_mask_to_av(inode->i_mode, mask));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003217}
3218
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003219static int selinux_file_permission(struct file *file, int mask)
3220{
Al Viro496ad9a2013-01-23 17:07:38 -05003221 struct inode *inode = file_inode(file);
Stephen Smalley20dda182009-06-22 14:54:53 -04003222 struct file_security_struct *fsec = file->f_security;
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05003223 struct inode_security_struct *isec = inode_security(inode);
Stephen Smalley20dda182009-06-22 14:54:53 -04003224 u32 sid = current_sid();
3225
Paul Moore389fb8002009-03-27 17:10:34 -04003226 if (!mask)
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003227 /* No permission to check. Existence test. */
3228 return 0;
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003229
Stephen Smalley20dda182009-06-22 14:54:53 -04003230 if (sid == fsec->sid && fsec->isid == isec->sid &&
3231 fsec->pseqno == avc_policy_seqno())
Eric Paris83d49852012-04-04 13:45:40 -04003232 /* No change since file_open check. */
Stephen Smalley20dda182009-06-22 14:54:53 -04003233 return 0;
3234
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003235 return selinux_revalidate_file_permission(file, mask);
3236}
3237
Linus Torvalds1da177e2005-04-16 15:20:36 -07003238static int selinux_file_alloc_security(struct file *file)
3239{
3240 return file_alloc_security(file);
3241}
3242
3243static void selinux_file_free_security(struct file *file)
3244{
3245 file_free_security(file);
3246}
3247
Jeff Vander Stoepfa1aa142015-07-10 17:19:56 -04003248/*
3249 * Check whether a task has the ioctl permission and cmd
3250 * operation to an inode.
3251 */
Geliang Tang1d2a1682015-10-21 17:44:27 -04003252static int ioctl_has_perm(const struct cred *cred, struct file *file,
Jeff Vander Stoepfa1aa142015-07-10 17:19:56 -04003253 u32 requested, u16 cmd)
3254{
3255 struct common_audit_data ad;
3256 struct file_security_struct *fsec = file->f_security;
3257 struct inode *inode = file_inode(file);
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05003258 struct inode_security_struct *isec = inode_security(inode);
Jeff Vander Stoepfa1aa142015-07-10 17:19:56 -04003259 struct lsm_ioctlop_audit ioctl;
3260 u32 ssid = cred_sid(cred);
3261 int rc;
3262 u8 driver = cmd >> 8;
3263 u8 xperm = cmd & 0xff;
3264
3265 ad.type = LSM_AUDIT_DATA_IOCTL_OP;
3266 ad.u.op = &ioctl;
3267 ad.u.op->cmd = cmd;
3268 ad.u.op->path = file->f_path;
3269
3270 if (ssid != fsec->sid) {
3271 rc = avc_has_perm(ssid, fsec->sid,
3272 SECCLASS_FD,
3273 FD__USE,
3274 &ad);
3275 if (rc)
3276 goto out;
3277 }
3278
3279 if (unlikely(IS_PRIVATE(inode)))
3280 return 0;
3281
3282 rc = avc_has_extended_perms(ssid, isec->sid, isec->sclass,
3283 requested, driver, xperm, &ad);
3284out:
3285 return rc;
3286}
3287
Linus Torvalds1da177e2005-04-16 15:20:36 -07003288static int selinux_file_ioctl(struct file *file, unsigned int cmd,
3289 unsigned long arg)
3290{
David Howells88e67f32008-11-14 10:39:21 +11003291 const struct cred *cred = current_cred();
Eric Paris0b24dcb2011-02-25 15:39:20 -05003292 int error = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003293
Eric Paris0b24dcb2011-02-25 15:39:20 -05003294 switch (cmd) {
3295 case FIONREAD:
3296 /* fall through */
3297 case FIBMAP:
3298 /* fall through */
3299 case FIGETBSZ:
3300 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003301 case FS_IOC_GETFLAGS:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003302 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003303 case FS_IOC_GETVERSION:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003304 error = file_has_perm(cred, file, FILE__GETATTR);
3305 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003306
Al Viro2f99c362012-03-23 16:04:05 -04003307 case FS_IOC_SETFLAGS:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003308 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003309 case FS_IOC_SETVERSION:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003310 error = file_has_perm(cred, file, FILE__SETATTR);
3311 break;
3312
3313 /* sys_ioctl() checks */
3314 case FIONBIO:
3315 /* fall through */
3316 case FIOASYNC:
3317 error = file_has_perm(cred, file, 0);
3318 break;
3319
3320 case KDSKBENT:
3321 case KDSKBSENT:
Eric Paris6a9de492012-01-03 12:25:14 -05003322 error = cred_has_capability(cred, CAP_SYS_TTY_CONFIG,
3323 SECURITY_CAP_AUDIT);
Eric Paris0b24dcb2011-02-25 15:39:20 -05003324 break;
3325
3326 /* default case assumes that the command will go
3327 * to the file's ioctl() function.
3328 */
3329 default:
Jeff Vander Stoepfa1aa142015-07-10 17:19:56 -04003330 error = ioctl_has_perm(cred, file, FILE__IOCTL, (u16) cmd);
Eric Paris0b24dcb2011-02-25 15:39:20 -05003331 }
3332 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003333}
3334
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003335static int default_noexec;
3336
Linus Torvalds1da177e2005-04-16 15:20:36 -07003337static int file_map_prot_check(struct file *file, unsigned long prot, int shared)
3338{
David Howells88e67f32008-11-14 10:39:21 +11003339 const struct cred *cred = current_cred();
David Howellsd84f4f92008-11-14 10:39:23 +11003340 int rc = 0;
David Howells88e67f32008-11-14 10:39:21 +11003341
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003342 if (default_noexec &&
Stephen Smalley892e8ca2015-07-10 09:40:59 -04003343 (prot & PROT_EXEC) && (!file || IS_PRIVATE(file_inode(file)) ||
3344 (!shared && (prot & PROT_WRITE)))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003345 /*
3346 * We are making executable an anonymous mapping or a
3347 * private file mapping that will also be writable.
3348 * This has an additional check.
3349 */
David Howellsd84f4f92008-11-14 10:39:23 +11003350 rc = cred_has_perm(cred, cred, PROCESS__EXECMEM);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003351 if (rc)
David Howellsd84f4f92008-11-14 10:39:23 +11003352 goto error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003353 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003354
3355 if (file) {
3356 /* read access is always possible with a mapping */
3357 u32 av = FILE__READ;
3358
3359 /* write access only matters if the mapping is shared */
3360 if (shared && (prot & PROT_WRITE))
3361 av |= FILE__WRITE;
3362
3363 if (prot & PROT_EXEC)
3364 av |= FILE__EXECUTE;
3365
David Howells88e67f32008-11-14 10:39:21 +11003366 return file_has_perm(cred, file, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003367 }
David Howellsd84f4f92008-11-14 10:39:23 +11003368
3369error:
3370 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003371}
3372
Al Viroe5467852012-05-30 13:30:51 -04003373static int selinux_mmap_addr(unsigned long addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003374{
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07003375 int rc = 0;
Paul Moore98883bf2014-03-19 16:46:11 -04003376
3377 if (addr < CONFIG_LSM_MMAP_MIN_ADDR) {
3378 u32 sid = current_sid();
3379 rc = avc_has_perm(sid, sid, SECCLASS_MEMPROTECT,
3380 MEMPROTECT__MMAP_ZERO, NULL);
3381 }
3382
3383 return rc;
Al Viroe5467852012-05-30 13:30:51 -04003384}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003385
Al Viroe5467852012-05-30 13:30:51 -04003386static int selinux_mmap_file(struct file *file, unsigned long reqprot,
3387 unsigned long prot, unsigned long flags)
3388{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003389 if (selinux_checkreqprot)
3390 prot = reqprot;
3391
3392 return file_map_prot_check(file, prot,
3393 (flags & MAP_TYPE) == MAP_SHARED);
3394}
3395
3396static int selinux_file_mprotect(struct vm_area_struct *vma,
3397 unsigned long reqprot,
3398 unsigned long prot)
3399{
David Howells88e67f32008-11-14 10:39:21 +11003400 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003401
3402 if (selinux_checkreqprot)
3403 prot = reqprot;
3404
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003405 if (default_noexec &&
3406 (prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) {
James Morrisd541bbe2009-01-29 12:19:51 +11003407 int rc = 0;
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003408 if (vma->vm_start >= vma->vm_mm->start_brk &&
3409 vma->vm_end <= vma->vm_mm->brk) {
David Howellsd84f4f92008-11-14 10:39:23 +11003410 rc = cred_has_perm(cred, cred, PROCESS__EXECHEAP);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003411 } else if (!vma->vm_file &&
3412 vma->vm_start <= vma->vm_mm->start_stack &&
3413 vma->vm_end >= vma->vm_mm->start_stack) {
David Howells3b11a1d2008-11-14 10:39:26 +11003414 rc = current_has_perm(current, PROCESS__EXECSTACK);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003415 } else if (vma->vm_file && vma->anon_vma) {
3416 /*
3417 * We are making executable a file mapping that has
3418 * had some COW done. Since pages might have been
3419 * written, check ability to execute the possibly
3420 * modified content. This typically should only
3421 * occur for text relocations.
3422 */
David Howellsd84f4f92008-11-14 10:39:23 +11003423 rc = file_has_perm(cred, vma->vm_file, FILE__EXECMOD);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003424 }
Lorenzo Hernandez García-Hierro6b992192005-06-25 14:54:34 -07003425 if (rc)
3426 return rc;
3427 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003428
3429 return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED);
3430}
3431
3432static int selinux_file_lock(struct file *file, unsigned int cmd)
3433{
David Howells88e67f32008-11-14 10:39:21 +11003434 const struct cred *cred = current_cred();
3435
3436 return file_has_perm(cred, file, FILE__LOCK);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003437}
3438
3439static int selinux_file_fcntl(struct file *file, unsigned int cmd,
3440 unsigned long arg)
3441{
David Howells88e67f32008-11-14 10:39:21 +11003442 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003443 int err = 0;
3444
3445 switch (cmd) {
Eric Paris828dfe12008-04-17 13:17:49 -04003446 case F_SETFL:
Eric Paris828dfe12008-04-17 13:17:49 -04003447 if ((file->f_flags & O_APPEND) && !(arg & O_APPEND)) {
David Howells88e67f32008-11-14 10:39:21 +11003448 err = file_has_perm(cred, file, FILE__WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003449 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003450 }
3451 /* fall through */
3452 case F_SETOWN:
3453 case F_SETSIG:
3454 case F_GETFL:
3455 case F_GETOWN:
3456 case F_GETSIG:
Cyrill Gorcunov1d151c32012-07-30 14:43:00 -07003457 case F_GETOWNER_UIDS:
Eric Paris828dfe12008-04-17 13:17:49 -04003458 /* Just check FD__USE permission */
David Howells88e67f32008-11-14 10:39:21 +11003459 err = file_has_perm(cred, file, 0);
Eric Paris828dfe12008-04-17 13:17:49 -04003460 break;
3461 case F_GETLK:
3462 case F_SETLK:
3463 case F_SETLKW:
Jeff Layton0d3f7a22014-04-22 08:23:58 -04003464 case F_OFD_GETLK:
3465 case F_OFD_SETLK:
3466 case F_OFD_SETLKW:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003467#if BITS_PER_LONG == 32
Eric Paris828dfe12008-04-17 13:17:49 -04003468 case F_GETLK64:
3469 case F_SETLK64:
3470 case F_SETLKW64:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003471#endif
David Howells88e67f32008-11-14 10:39:21 +11003472 err = file_has_perm(cred, file, FILE__LOCK);
Eric Paris828dfe12008-04-17 13:17:49 -04003473 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003474 }
3475
3476 return err;
3477}
3478
Jeff Laytone0b93ed2014-08-22 11:27:32 -04003479static void selinux_file_set_fowner(struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003480{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003481 struct file_security_struct *fsec;
3482
Linus Torvalds1da177e2005-04-16 15:20:36 -07003483 fsec = file->f_security;
David Howells275bb412008-11-14 10:39:19 +11003484 fsec->fown_sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003485}
3486
3487static int selinux_file_send_sigiotask(struct task_struct *tsk,
3488 struct fown_struct *fown, int signum)
3489{
Eric Paris828dfe12008-04-17 13:17:49 -04003490 struct file *file;
Stephen Smalley65c90bc2009-05-04 15:43:18 -04003491 u32 sid = task_sid(tsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003492 u32 perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003493 struct file_security_struct *fsec;
3494
3495 /* struct fown_struct is never outside the context of a struct file */
Eric Paris828dfe12008-04-17 13:17:49 -04003496 file = container_of(fown, struct file, f_owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003497
Linus Torvalds1da177e2005-04-16 15:20:36 -07003498 fsec = file->f_security;
3499
3500 if (!signum)
3501 perm = signal_to_av(SIGIO); /* as per send_sigio_to_task */
3502 else
3503 perm = signal_to_av(signum);
3504
David Howells275bb412008-11-14 10:39:19 +11003505 return avc_has_perm(fsec->fown_sid, sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003506 SECCLASS_PROCESS, perm, NULL);
3507}
3508
3509static int selinux_file_receive(struct file *file)
3510{
David Howells88e67f32008-11-14 10:39:21 +11003511 const struct cred *cred = current_cred();
3512
3513 return file_has_perm(cred, file, file_to_av(file));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003514}
3515
Eric Paris83d49852012-04-04 13:45:40 -04003516static int selinux_file_open(struct file *file, const struct cred *cred)
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003517{
3518 struct file_security_struct *fsec;
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003519 struct inode_security_struct *isec;
David Howellsd84f4f92008-11-14 10:39:23 +11003520
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003521 fsec = file->f_security;
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05003522 isec = inode_security(file_inode(file));
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003523 /*
3524 * Save inode label and policy sequence number
3525 * at open-time so that selinux_file_permission
3526 * can determine whether revalidation is necessary.
3527 * Task label is already saved in the file security
3528 * struct as its SID.
3529 */
3530 fsec->isid = isec->sid;
3531 fsec->pseqno = avc_policy_seqno();
3532 /*
3533 * Since the inode label or policy seqno may have changed
3534 * between the selinux_inode_permission check and the saving
3535 * of state above, recheck that access is still permitted.
3536 * Otherwise, access might never be revalidated against the
3537 * new inode label or new policy.
3538 * This check is not redundant - do not remove.
3539 */
David Howells13f8e982013-06-13 23:37:55 +01003540 return file_path_has_perm(cred, file, open_file_to_av(file));
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003541}
3542
Linus Torvalds1da177e2005-04-16 15:20:36 -07003543/* task security operations */
3544
3545static int selinux_task_create(unsigned long clone_flags)
3546{
David Howells3b11a1d2008-11-14 10:39:26 +11003547 return current_has_perm(current, PROCESS__FORK);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003548}
3549
David Howellsf1752ee2008-11-14 10:39:17 +11003550/*
David Howellsee18d642009-09-02 09:14:21 +01003551 * allocate the SELinux part of blank credentials
3552 */
3553static int selinux_cred_alloc_blank(struct cred *cred, gfp_t gfp)
3554{
3555 struct task_security_struct *tsec;
3556
3557 tsec = kzalloc(sizeof(struct task_security_struct), gfp);
3558 if (!tsec)
3559 return -ENOMEM;
3560
3561 cred->security = tsec;
3562 return 0;
3563}
3564
3565/*
David Howellsf1752ee2008-11-14 10:39:17 +11003566 * detach and free the LSM part of a set of credentials
3567 */
3568static void selinux_cred_free(struct cred *cred)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003569{
David Howellsf1752ee2008-11-14 10:39:17 +11003570 struct task_security_struct *tsec = cred->security;
David Howellse0e81732009-09-02 09:13:40 +01003571
Tetsuo Handa2edeaa32011-02-07 13:36:10 +00003572 /*
3573 * cred->security == NULL if security_cred_alloc_blank() or
3574 * security_prepare_creds() returned an error.
3575 */
3576 BUG_ON(cred->security && (unsigned long) cred->security < PAGE_SIZE);
David Howellse0e81732009-09-02 09:13:40 +01003577 cred->security = (void *) 0x7UL;
David Howellsf1752ee2008-11-14 10:39:17 +11003578 kfree(tsec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003579}
3580
David Howellsd84f4f92008-11-14 10:39:23 +11003581/*
3582 * prepare a new set of credentials for modification
3583 */
3584static int selinux_cred_prepare(struct cred *new, const struct cred *old,
3585 gfp_t gfp)
3586{
3587 const struct task_security_struct *old_tsec;
3588 struct task_security_struct *tsec;
3589
3590 old_tsec = old->security;
3591
3592 tsec = kmemdup(old_tsec, sizeof(struct task_security_struct), gfp);
3593 if (!tsec)
3594 return -ENOMEM;
3595
3596 new->security = tsec;
3597 return 0;
3598}
3599
3600/*
David Howellsee18d642009-09-02 09:14:21 +01003601 * transfer the SELinux data to a blank set of creds
3602 */
3603static void selinux_cred_transfer(struct cred *new, const struct cred *old)
3604{
3605 const struct task_security_struct *old_tsec = old->security;
3606 struct task_security_struct *tsec = new->security;
3607
3608 *tsec = *old_tsec;
3609}
3610
3611/*
David Howells3a3b7ce2008-11-14 10:39:28 +11003612 * set the security data for a kernel service
3613 * - all the creation contexts are set to unlabelled
3614 */
3615static int selinux_kernel_act_as(struct cred *new, u32 secid)
3616{
3617 struct task_security_struct *tsec = new->security;
3618 u32 sid = current_sid();
3619 int ret;
3620
3621 ret = avc_has_perm(sid, secid,
3622 SECCLASS_KERNEL_SERVICE,
3623 KERNEL_SERVICE__USE_AS_OVERRIDE,
3624 NULL);
3625 if (ret == 0) {
3626 tsec->sid = secid;
3627 tsec->create_sid = 0;
3628 tsec->keycreate_sid = 0;
3629 tsec->sockcreate_sid = 0;
3630 }
3631 return ret;
3632}
3633
3634/*
3635 * set the file creation context in a security record to the same as the
3636 * objective context of the specified inode
3637 */
3638static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode)
3639{
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05003640 struct inode_security_struct *isec = inode_security(inode);
David Howells3a3b7ce2008-11-14 10:39:28 +11003641 struct task_security_struct *tsec = new->security;
3642 u32 sid = current_sid();
3643 int ret;
3644
3645 ret = avc_has_perm(sid, isec->sid,
3646 SECCLASS_KERNEL_SERVICE,
3647 KERNEL_SERVICE__CREATE_FILES_AS,
3648 NULL);
3649
3650 if (ret == 0)
3651 tsec->create_sid = isec->sid;
David Howellsef574712010-02-26 01:56:16 +00003652 return ret;
David Howells3a3b7ce2008-11-14 10:39:28 +11003653}
3654
Eric Parisdd8dbf22009-11-03 16:35:32 +11003655static int selinux_kernel_module_request(char *kmod_name)
Eric Paris25354c42009-08-13 09:45:03 -04003656{
Eric Parisdd8dbf22009-11-03 16:35:32 +11003657 u32 sid;
3658 struct common_audit_data ad;
3659
3660 sid = task_sid(current);
3661
Eric Paris50c205f2012-04-04 15:01:43 -04003662 ad.type = LSM_AUDIT_DATA_KMOD;
Eric Parisdd8dbf22009-11-03 16:35:32 +11003663 ad.u.kmod_name = kmod_name;
3664
3665 return avc_has_perm(sid, SECINITSID_KERNEL, SECCLASS_SYSTEM,
3666 SYSTEM__MODULE_REQUEST, &ad);
Eric Paris25354c42009-08-13 09:45:03 -04003667}
3668
Linus Torvalds1da177e2005-04-16 15:20:36 -07003669static int selinux_task_setpgid(struct task_struct *p, pid_t pgid)
3670{
David Howells3b11a1d2008-11-14 10:39:26 +11003671 return current_has_perm(p, PROCESS__SETPGID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003672}
3673
3674static int selinux_task_getpgid(struct task_struct *p)
3675{
David Howells3b11a1d2008-11-14 10:39:26 +11003676 return current_has_perm(p, PROCESS__GETPGID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003677}
3678
3679static int selinux_task_getsid(struct task_struct *p)
3680{
David Howells3b11a1d2008-11-14 10:39:26 +11003681 return current_has_perm(p, PROCESS__GETSESSION);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003682}
3683
David Quigleyf9008e4c2006-06-30 01:55:46 -07003684static void selinux_task_getsecid(struct task_struct *p, u32 *secid)
3685{
David Howells275bb412008-11-14 10:39:19 +11003686 *secid = task_sid(p);
David Quigleyf9008e4c2006-06-30 01:55:46 -07003687}
3688
Linus Torvalds1da177e2005-04-16 15:20:36 -07003689static int selinux_task_setnice(struct task_struct *p, int nice)
3690{
David Howells3b11a1d2008-11-14 10:39:26 +11003691 return current_has_perm(p, PROCESS__SETSCHED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003692}
3693
James Morris03e68062006-06-23 02:03:58 -07003694static int selinux_task_setioprio(struct task_struct *p, int ioprio)
3695{
David Howells3b11a1d2008-11-14 10:39:26 +11003696 return current_has_perm(p, PROCESS__SETSCHED);
James Morris03e68062006-06-23 02:03:58 -07003697}
3698
David Quigleya1836a42006-06-30 01:55:49 -07003699static int selinux_task_getioprio(struct task_struct *p)
3700{
David Howells3b11a1d2008-11-14 10:39:26 +11003701 return current_has_perm(p, PROCESS__GETSCHED);
David Quigleya1836a42006-06-30 01:55:49 -07003702}
3703
Jiri Slaby8fd00b42009-08-26 18:41:16 +02003704static int selinux_task_setrlimit(struct task_struct *p, unsigned int resource,
3705 struct rlimit *new_rlim)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003706{
Jiri Slaby8fd00b42009-08-26 18:41:16 +02003707 struct rlimit *old_rlim = p->signal->rlim + resource;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003708
3709 /* Control the ability to change the hard limit (whether
3710 lowering or raising it), so that the hard limit can
3711 later be used as a safe reset point for the soft limit
David Howellsd84f4f92008-11-14 10:39:23 +11003712 upon context transitions. See selinux_bprm_committing_creds. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003713 if (old_rlim->rlim_max != new_rlim->rlim_max)
Jiri Slaby8fd00b42009-08-26 18:41:16 +02003714 return current_has_perm(p, PROCESS__SETRLIMIT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003715
3716 return 0;
3717}
3718
KOSAKI Motohirob0ae1982010-10-15 04:21:18 +09003719static int selinux_task_setscheduler(struct task_struct *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003720{
David Howells3b11a1d2008-11-14 10:39:26 +11003721 return current_has_perm(p, PROCESS__SETSCHED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003722}
3723
3724static int selinux_task_getscheduler(struct task_struct *p)
3725{
David Howells3b11a1d2008-11-14 10:39:26 +11003726 return current_has_perm(p, PROCESS__GETSCHED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003727}
3728
David Quigley35601542006-06-23 02:04:01 -07003729static int selinux_task_movememory(struct task_struct *p)
3730{
David Howells3b11a1d2008-11-14 10:39:26 +11003731 return current_has_perm(p, PROCESS__SETSCHED);
David Quigley35601542006-06-23 02:04:01 -07003732}
3733
David Quigleyf9008e4c2006-06-30 01:55:46 -07003734static int selinux_task_kill(struct task_struct *p, struct siginfo *info,
3735 int sig, u32 secid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003736{
3737 u32 perm;
3738 int rc;
3739
Linus Torvalds1da177e2005-04-16 15:20:36 -07003740 if (!sig)
3741 perm = PROCESS__SIGNULL; /* null signal; existence test */
3742 else
3743 perm = signal_to_av(sig);
David Quigleyf9008e4c2006-06-30 01:55:46 -07003744 if (secid)
David Howells275bb412008-11-14 10:39:19 +11003745 rc = avc_has_perm(secid, task_sid(p),
3746 SECCLASS_PROCESS, perm, NULL);
David Quigleyf9008e4c2006-06-30 01:55:46 -07003747 else
David Howells3b11a1d2008-11-14 10:39:26 +11003748 rc = current_has_perm(p, perm);
David Quigleyf9008e4c2006-06-30 01:55:46 -07003749 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003750}
3751
Linus Torvalds1da177e2005-04-16 15:20:36 -07003752static int selinux_task_wait(struct task_struct *p)
3753{
Eric Paris8a535142007-10-22 16:10:31 -04003754 return task_has_perm(p, current, PROCESS__SIGCHLD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003755}
3756
Linus Torvalds1da177e2005-04-16 15:20:36 -07003757static void selinux_task_to_inode(struct task_struct *p,
3758 struct inode *inode)
3759{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003760 struct inode_security_struct *isec = inode->i_security;
David Howells275bb412008-11-14 10:39:19 +11003761 u32 sid = task_sid(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003762
David Howells275bb412008-11-14 10:39:19 +11003763 isec->sid = sid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05003764 isec->initialized = LABEL_INITIALIZED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003765}
3766
Linus Torvalds1da177e2005-04-16 15:20:36 -07003767/* Returns error only if unable to parse addresses */
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003768static int selinux_parse_skb_ipv4(struct sk_buff *skb,
Thomas Liu2bf49692009-07-14 12:14:09 -04003769 struct common_audit_data *ad, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003770{
3771 int offset, ihlen, ret = -EINVAL;
3772 struct iphdr _iph, *ih;
3773
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03003774 offset = skb_network_offset(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003775 ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph);
3776 if (ih == NULL)
3777 goto out;
3778
3779 ihlen = ih->ihl * 4;
3780 if (ihlen < sizeof(_iph))
3781 goto out;
3782
Eric Paris48c62af2012-04-02 13:15:44 -04003783 ad->u.net->v4info.saddr = ih->saddr;
3784 ad->u.net->v4info.daddr = ih->daddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003785 ret = 0;
3786
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003787 if (proto)
3788 *proto = ih->protocol;
3789
Linus Torvalds1da177e2005-04-16 15:20:36 -07003790 switch (ih->protocol) {
Eric Paris828dfe12008-04-17 13:17:49 -04003791 case IPPROTO_TCP: {
3792 struct tcphdr _tcph, *th;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003793
Eric Paris828dfe12008-04-17 13:17:49 -04003794 if (ntohs(ih->frag_off) & IP_OFFSET)
3795 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003796
3797 offset += ihlen;
3798 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
3799 if (th == NULL)
3800 break;
3801
Eric Paris48c62af2012-04-02 13:15:44 -04003802 ad->u.net->sport = th->source;
3803 ad->u.net->dport = th->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003804 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003805 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003806
Eric Paris828dfe12008-04-17 13:17:49 -04003807 case IPPROTO_UDP: {
3808 struct udphdr _udph, *uh;
3809
3810 if (ntohs(ih->frag_off) & IP_OFFSET)
3811 break;
3812
3813 offset += ihlen;
3814 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
3815 if (uh == NULL)
3816 break;
3817
Eric Paris48c62af2012-04-02 13:15:44 -04003818 ad->u.net->sport = uh->source;
3819 ad->u.net->dport = uh->dest;
Eric Paris828dfe12008-04-17 13:17:49 -04003820 break;
3821 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003822
James Morris2ee92d42006-11-13 16:09:01 -08003823 case IPPROTO_DCCP: {
3824 struct dccp_hdr _dccph, *dh;
3825
3826 if (ntohs(ih->frag_off) & IP_OFFSET)
3827 break;
3828
3829 offset += ihlen;
3830 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
3831 if (dh == NULL)
3832 break;
3833
Eric Paris48c62af2012-04-02 13:15:44 -04003834 ad->u.net->sport = dh->dccph_sport;
3835 ad->u.net->dport = dh->dccph_dport;
James Morris2ee92d42006-11-13 16:09:01 -08003836 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003837 }
James Morris2ee92d42006-11-13 16:09:01 -08003838
Eric Paris828dfe12008-04-17 13:17:49 -04003839 default:
3840 break;
3841 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003842out:
3843 return ret;
3844}
3845
3846#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
3847
3848/* Returns error only if unable to parse addresses */
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003849static int selinux_parse_skb_ipv6(struct sk_buff *skb,
Thomas Liu2bf49692009-07-14 12:14:09 -04003850 struct common_audit_data *ad, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003851{
3852 u8 nexthdr;
3853 int ret = -EINVAL, offset;
3854 struct ipv6hdr _ipv6h, *ip6;
Jesse Gross75f28112011-11-30 17:05:51 -08003855 __be16 frag_off;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003856
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03003857 offset = skb_network_offset(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003858 ip6 = skb_header_pointer(skb, offset, sizeof(_ipv6h), &_ipv6h);
3859 if (ip6 == NULL)
3860 goto out;
3861
Eric Paris48c62af2012-04-02 13:15:44 -04003862 ad->u.net->v6info.saddr = ip6->saddr;
3863 ad->u.net->v6info.daddr = ip6->daddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003864 ret = 0;
3865
3866 nexthdr = ip6->nexthdr;
3867 offset += sizeof(_ipv6h);
Jesse Gross75f28112011-11-30 17:05:51 -08003868 offset = ipv6_skip_exthdr(skb, offset, &nexthdr, &frag_off);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003869 if (offset < 0)
3870 goto out;
3871
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003872 if (proto)
3873 *proto = nexthdr;
3874
Linus Torvalds1da177e2005-04-16 15:20:36 -07003875 switch (nexthdr) {
3876 case IPPROTO_TCP: {
Eric Paris828dfe12008-04-17 13:17:49 -04003877 struct tcphdr _tcph, *th;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003878
3879 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
3880 if (th == NULL)
3881 break;
3882
Eric Paris48c62af2012-04-02 13:15:44 -04003883 ad->u.net->sport = th->source;
3884 ad->u.net->dport = th->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003885 break;
3886 }
3887
3888 case IPPROTO_UDP: {
3889 struct udphdr _udph, *uh;
3890
3891 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
3892 if (uh == NULL)
3893 break;
3894
Eric Paris48c62af2012-04-02 13:15:44 -04003895 ad->u.net->sport = uh->source;
3896 ad->u.net->dport = uh->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003897 break;
3898 }
3899
James Morris2ee92d42006-11-13 16:09:01 -08003900 case IPPROTO_DCCP: {
3901 struct dccp_hdr _dccph, *dh;
3902
3903 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
3904 if (dh == NULL)
3905 break;
3906
Eric Paris48c62af2012-04-02 13:15:44 -04003907 ad->u.net->sport = dh->dccph_sport;
3908 ad->u.net->dport = dh->dccph_dport;
James Morris2ee92d42006-11-13 16:09:01 -08003909 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003910 }
James Morris2ee92d42006-11-13 16:09:01 -08003911
Linus Torvalds1da177e2005-04-16 15:20:36 -07003912 /* includes fragments */
3913 default:
3914 break;
3915 }
3916out:
3917 return ret;
3918}
3919
3920#endif /* IPV6 */
3921
Thomas Liu2bf49692009-07-14 12:14:09 -04003922static int selinux_parse_skb(struct sk_buff *skb, struct common_audit_data *ad,
David Howellscf9481e2008-07-27 21:31:07 +10003923 char **_addrp, int src, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003924{
David Howellscf9481e2008-07-27 21:31:07 +10003925 char *addrp;
3926 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003927
Eric Paris48c62af2012-04-02 13:15:44 -04003928 switch (ad->u.net->family) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003929 case PF_INET:
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003930 ret = selinux_parse_skb_ipv4(skb, ad, proto);
David Howellscf9481e2008-07-27 21:31:07 +10003931 if (ret)
3932 goto parse_error;
Eric Paris48c62af2012-04-02 13:15:44 -04003933 addrp = (char *)(src ? &ad->u.net->v4info.saddr :
3934 &ad->u.net->v4info.daddr);
David Howellscf9481e2008-07-27 21:31:07 +10003935 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003936
3937#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
3938 case PF_INET6:
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003939 ret = selinux_parse_skb_ipv6(skb, ad, proto);
David Howellscf9481e2008-07-27 21:31:07 +10003940 if (ret)
3941 goto parse_error;
Eric Paris48c62af2012-04-02 13:15:44 -04003942 addrp = (char *)(src ? &ad->u.net->v6info.saddr :
3943 &ad->u.net->v6info.daddr);
David Howellscf9481e2008-07-27 21:31:07 +10003944 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003945#endif /* IPV6 */
3946 default:
David Howellscf9481e2008-07-27 21:31:07 +10003947 addrp = NULL;
3948 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003949 }
3950
David Howellscf9481e2008-07-27 21:31:07 +10003951parse_error:
3952 printk(KERN_WARNING
3953 "SELinux: failure in selinux_parse_skb(),"
3954 " unable to parse packet\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003955 return ret;
David Howellscf9481e2008-07-27 21:31:07 +10003956
3957okay:
3958 if (_addrp)
3959 *_addrp = addrp;
3960 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003961}
3962
Paul Moore4f6a9932007-03-01 14:35:22 -05003963/**
Paul Moore220deb92008-01-29 08:38:23 -05003964 * selinux_skb_peerlbl_sid - Determine the peer label of a packet
Paul Moore4f6a9932007-03-01 14:35:22 -05003965 * @skb: the packet
Paul Moore75e22912008-01-29 08:38:04 -05003966 * @family: protocol family
Paul Moore220deb92008-01-29 08:38:23 -05003967 * @sid: the packet's peer label SID
Paul Moore4f6a9932007-03-01 14:35:22 -05003968 *
3969 * Description:
Paul Moore220deb92008-01-29 08:38:23 -05003970 * Check the various different forms of network peer labeling and determine
3971 * the peer label/SID for the packet; most of the magic actually occurs in
3972 * the security server function security_net_peersid_cmp(). The function
3973 * returns zero if the value in @sid is valid (although it may be SECSID_NULL)
3974 * or -EACCES if @sid is invalid due to inconsistencies with the different
3975 * peer labels.
Paul Moore4f6a9932007-03-01 14:35:22 -05003976 *
3977 */
Paul Moore220deb92008-01-29 08:38:23 -05003978static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)
Paul Moore4f6a9932007-03-01 14:35:22 -05003979{
Paul Moore71f1cb02008-01-29 08:51:16 -05003980 int err;
Paul Moore4f6a9932007-03-01 14:35:22 -05003981 u32 xfrm_sid;
3982 u32 nlbl_sid;
Paul Moore220deb92008-01-29 08:38:23 -05003983 u32 nlbl_type;
Paul Moore4f6a9932007-03-01 14:35:22 -05003984
Paul Moore817eff72013-12-10 14:57:54 -05003985 err = selinux_xfrm_skb_sid(skb, &xfrm_sid);
Paul Moorebed4d7e2013-07-23 17:38:40 -04003986 if (unlikely(err))
3987 return -EACCES;
3988 err = selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid);
3989 if (unlikely(err))
3990 return -EACCES;
Paul Moore220deb92008-01-29 08:38:23 -05003991
Paul Moore71f1cb02008-01-29 08:51:16 -05003992 err = security_net_peersid_resolve(nlbl_sid, nlbl_type, xfrm_sid, sid);
3993 if (unlikely(err)) {
3994 printk(KERN_WARNING
3995 "SELinux: failure in selinux_skb_peerlbl_sid(),"
3996 " unable to determine packet's peer label\n");
Paul Moore220deb92008-01-29 08:38:23 -05003997 return -EACCES;
Paul Moore71f1cb02008-01-29 08:51:16 -05003998 }
Paul Moore220deb92008-01-29 08:38:23 -05003999
4000 return 0;
Paul Moore4f6a9932007-03-01 14:35:22 -05004001}
4002
Paul Moore446b8022013-12-04 16:10:51 -05004003/**
4004 * selinux_conn_sid - Determine the child socket label for a connection
4005 * @sk_sid: the parent socket's SID
4006 * @skb_sid: the packet's SID
4007 * @conn_sid: the resulting connection SID
4008 *
4009 * If @skb_sid is valid then the user:role:type information from @sk_sid is
4010 * combined with the MLS information from @skb_sid in order to create
4011 * @conn_sid. If @skb_sid is not valid then then @conn_sid is simply a copy
4012 * of @sk_sid. Returns zero on success, negative values on failure.
4013 *
4014 */
4015static int selinux_conn_sid(u32 sk_sid, u32 skb_sid, u32 *conn_sid)
4016{
4017 int err = 0;
4018
4019 if (skb_sid != SECSID_NULL)
4020 err = security_sid_mls_copy(sk_sid, skb_sid, conn_sid);
4021 else
4022 *conn_sid = sk_sid;
4023
4024 return err;
4025}
4026
Linus Torvalds1da177e2005-04-16 15:20:36 -07004027/* socket security operations */
Paul Moored4f2d972010-04-22 14:46:18 -04004028
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004029static int socket_sockcreate_sid(const struct task_security_struct *tsec,
4030 u16 secclass, u32 *socksid)
Paul Moored4f2d972010-04-22 14:46:18 -04004031{
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004032 if (tsec->sockcreate_sid > SECSID_NULL) {
4033 *socksid = tsec->sockcreate_sid;
4034 return 0;
4035 }
4036
4037 return security_transition_sid(tsec->sid, tsec->sid, secclass, NULL,
4038 socksid);
Paul Moored4f2d972010-04-22 14:46:18 -04004039}
4040
Paul Moore253bfae2010-04-22 14:46:19 -04004041static int sock_has_perm(struct task_struct *task, struct sock *sk, u32 perms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004042{
Paul Moore253bfae2010-04-22 14:46:19 -04004043 struct sk_security_struct *sksec = sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004044 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004045 struct lsm_network_audit net = {0,};
Paul Moore253bfae2010-04-22 14:46:19 -04004046 u32 tsid = task_sid(task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004047
Paul Moore253bfae2010-04-22 14:46:19 -04004048 if (sksec->sid == SECINITSID_KERNEL)
4049 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004050
Eric Paris50c205f2012-04-04 15:01:43 -04004051 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004052 ad.u.net = &net;
4053 ad.u.net->sk = sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004054
Paul Moore253bfae2010-04-22 14:46:19 -04004055 return avc_has_perm(tsid, sksec->sid, sksec->sclass, perms, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004056}
4057
4058static int selinux_socket_create(int family, int type,
4059 int protocol, int kern)
4060{
Paul Moore5fb49872010-04-22 14:46:19 -04004061 const struct task_security_struct *tsec = current_security();
Paul Moored4f2d972010-04-22 14:46:18 -04004062 u32 newsid;
David Howells275bb412008-11-14 10:39:19 +11004063 u16 secclass;
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004064 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004065
4066 if (kern)
Paul Moored4f2d972010-04-22 14:46:18 -04004067 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004068
David Howells275bb412008-11-14 10:39:19 +11004069 secclass = socket_type_to_security_class(family, type, protocol);
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004070 rc = socket_sockcreate_sid(tsec, secclass, &newsid);
4071 if (rc)
4072 return rc;
4073
Paul Moored4f2d972010-04-22 14:46:18 -04004074 return avc_has_perm(tsec->sid, newsid, secclass, SOCKET__CREATE, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004075}
4076
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07004077static int selinux_socket_post_create(struct socket *sock, int family,
4078 int type, int protocol, int kern)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004079{
Paul Moore5fb49872010-04-22 14:46:19 -04004080 const struct task_security_struct *tsec = current_security();
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05004081 struct inode_security_struct *isec = inode_security(SOCK_INODE(sock));
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004082 struct sk_security_struct *sksec;
David Howells275bb412008-11-14 10:39:19 +11004083 int err = 0;
4084
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004085 isec->sclass = socket_type_to_security_class(family, type, protocol);
4086
David Howells275bb412008-11-14 10:39:19 +11004087 if (kern)
4088 isec->sid = SECINITSID_KERNEL;
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004089 else {
4090 err = socket_sockcreate_sid(tsec, isec->sclass, &(isec->sid));
4091 if (err)
4092 return err;
4093 }
David Howells275bb412008-11-14 10:39:19 +11004094
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05004095 isec->initialized = LABEL_INITIALIZED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004096
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004097 if (sock->sk) {
4098 sksec = sock->sk->sk_security;
4099 sksec->sid = isec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05004100 sksec->sclass = isec->sclass;
Paul Moore389fb8002009-03-27 17:10:34 -04004101 err = selinux_netlbl_socket_post_create(sock->sk, family);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004102 }
4103
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07004104 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004105}
4106
4107/* Range of port numbers used to automatically bind.
4108 Need to determine whether we should perform a name_bind
4109 permission check between the socket and the port number. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004110
4111static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen)
4112{
Paul Moore253bfae2010-04-22 14:46:19 -04004113 struct sock *sk = sock->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004114 u16 family;
4115 int err;
4116
Paul Moore253bfae2010-04-22 14:46:19 -04004117 err = sock_has_perm(current, sk, SOCKET__BIND);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004118 if (err)
4119 goto out;
4120
4121 /*
4122 * If PF_INET or PF_INET6, check name_bind permission for the port.
James Morris13402582005-09-30 14:24:34 -04004123 * Multiple address binding for SCTP is not supported yet: we just
4124 * check the first address now.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004125 */
Paul Moore253bfae2010-04-22 14:46:19 -04004126 family = sk->sk_family;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004127 if (family == PF_INET || family == PF_INET6) {
4128 char *addrp;
Paul Moore253bfae2010-04-22 14:46:19 -04004129 struct sk_security_struct *sksec = sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004130 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004131 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004132 struct sockaddr_in *addr4 = NULL;
4133 struct sockaddr_in6 *addr6 = NULL;
4134 unsigned short snum;
James Morrise399f982008-06-12 01:39:58 +10004135 u32 sid, node_perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004136
Linus Torvalds1da177e2005-04-16 15:20:36 -07004137 if (family == PF_INET) {
4138 addr4 = (struct sockaddr_in *)address;
4139 snum = ntohs(addr4->sin_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004140 addrp = (char *)&addr4->sin_addr.s_addr;
4141 } else {
4142 addr6 = (struct sockaddr_in6 *)address;
4143 snum = ntohs(addr6->sin6_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004144 addrp = (char *)&addr6->sin6_addr.s6_addr;
4145 }
4146
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004147 if (snum) {
4148 int low, high;
4149
Eric W. Biederman0bbf87d2013-09-28 14:10:59 -07004150 inet_get_local_port_range(sock_net(sk), &low, &high);
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004151
4152 if (snum < max(PROT_SOCK, low) || snum > high) {
Paul Moore3e112172008-04-10 10:48:14 -04004153 err = sel_netport_sid(sk->sk_protocol,
4154 snum, &sid);
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004155 if (err)
4156 goto out;
Eric Paris50c205f2012-04-04 15:01:43 -04004157 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004158 ad.u.net = &net;
4159 ad.u.net->sport = htons(snum);
4160 ad.u.net->family = family;
Paul Moore253bfae2010-04-22 14:46:19 -04004161 err = avc_has_perm(sksec->sid, sid,
4162 sksec->sclass,
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004163 SOCKET__NAME_BIND, &ad);
4164 if (err)
4165 goto out;
4166 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004167 }
Eric Paris828dfe12008-04-17 13:17:49 -04004168
Paul Moore253bfae2010-04-22 14:46:19 -04004169 switch (sksec->sclass) {
James Morris13402582005-09-30 14:24:34 -04004170 case SECCLASS_TCP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004171 node_perm = TCP_SOCKET__NODE_BIND;
4172 break;
Eric Paris828dfe12008-04-17 13:17:49 -04004173
James Morris13402582005-09-30 14:24:34 -04004174 case SECCLASS_UDP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004175 node_perm = UDP_SOCKET__NODE_BIND;
4176 break;
James Morris2ee92d42006-11-13 16:09:01 -08004177
4178 case SECCLASS_DCCP_SOCKET:
4179 node_perm = DCCP_SOCKET__NODE_BIND;
4180 break;
4181
Linus Torvalds1da177e2005-04-16 15:20:36 -07004182 default:
4183 node_perm = RAWIP_SOCKET__NODE_BIND;
4184 break;
4185 }
Eric Paris828dfe12008-04-17 13:17:49 -04004186
Paul Moore224dfbd2008-01-29 08:38:13 -05004187 err = sel_netnode_sid(addrp, family, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004188 if (err)
4189 goto out;
Eric Paris828dfe12008-04-17 13:17:49 -04004190
Eric Paris50c205f2012-04-04 15:01:43 -04004191 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004192 ad.u.net = &net;
4193 ad.u.net->sport = htons(snum);
4194 ad.u.net->family = family;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004195
4196 if (family == PF_INET)
Eric Paris48c62af2012-04-02 13:15:44 -04004197 ad.u.net->v4info.saddr = addr4->sin_addr.s_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004198 else
Eric Paris48c62af2012-04-02 13:15:44 -04004199 ad.u.net->v6info.saddr = addr6->sin6_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004200
Paul Moore253bfae2010-04-22 14:46:19 -04004201 err = avc_has_perm(sksec->sid, sid,
4202 sksec->sclass, node_perm, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004203 if (err)
4204 goto out;
4205 }
4206out:
4207 return err;
4208}
4209
4210static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen)
4211{
Paul Moore014ab192008-10-10 10:16:33 -04004212 struct sock *sk = sock->sk;
Paul Moore253bfae2010-04-22 14:46:19 -04004213 struct sk_security_struct *sksec = sk->sk_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004214 int err;
4215
Paul Moore253bfae2010-04-22 14:46:19 -04004216 err = sock_has_perm(current, sk, SOCKET__CONNECT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004217 if (err)
4218 return err;
4219
4220 /*
James Morris2ee92d42006-11-13 16:09:01 -08004221 * If a TCP or DCCP socket, check name_connect permission for the port.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004222 */
Paul Moore253bfae2010-04-22 14:46:19 -04004223 if (sksec->sclass == SECCLASS_TCP_SOCKET ||
4224 sksec->sclass == SECCLASS_DCCP_SOCKET) {
Thomas Liu2bf49692009-07-14 12:14:09 -04004225 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004226 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004227 struct sockaddr_in *addr4 = NULL;
4228 struct sockaddr_in6 *addr6 = NULL;
4229 unsigned short snum;
James Morris2ee92d42006-11-13 16:09:01 -08004230 u32 sid, perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004231
4232 if (sk->sk_family == PF_INET) {
4233 addr4 = (struct sockaddr_in *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07004234 if (addrlen < sizeof(struct sockaddr_in))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004235 return -EINVAL;
4236 snum = ntohs(addr4->sin_port);
4237 } else {
4238 addr6 = (struct sockaddr_in6 *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07004239 if (addrlen < SIN6_LEN_RFC2133)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004240 return -EINVAL;
4241 snum = ntohs(addr6->sin6_port);
4242 }
4243
Paul Moore3e112172008-04-10 10:48:14 -04004244 err = sel_netport_sid(sk->sk_protocol, snum, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004245 if (err)
4246 goto out;
4247
Paul Moore253bfae2010-04-22 14:46:19 -04004248 perm = (sksec->sclass == SECCLASS_TCP_SOCKET) ?
James Morris2ee92d42006-11-13 16:09:01 -08004249 TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT;
4250
Eric Paris50c205f2012-04-04 15:01:43 -04004251 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004252 ad.u.net = &net;
4253 ad.u.net->dport = htons(snum);
4254 ad.u.net->family = sk->sk_family;
Paul Moore253bfae2010-04-22 14:46:19 -04004255 err = avc_has_perm(sksec->sid, sid, sksec->sclass, perm, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004256 if (err)
4257 goto out;
4258 }
4259
Paul Moore014ab192008-10-10 10:16:33 -04004260 err = selinux_netlbl_socket_connect(sk, address);
4261
Linus Torvalds1da177e2005-04-16 15:20:36 -07004262out:
4263 return err;
4264}
4265
4266static int selinux_socket_listen(struct socket *sock, int backlog)
4267{
Paul Moore253bfae2010-04-22 14:46:19 -04004268 return sock_has_perm(current, sock->sk, SOCKET__LISTEN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004269}
4270
4271static int selinux_socket_accept(struct socket *sock, struct socket *newsock)
4272{
4273 int err;
4274 struct inode_security_struct *isec;
4275 struct inode_security_struct *newisec;
4276
Paul Moore253bfae2010-04-22 14:46:19 -04004277 err = sock_has_perm(current, sock->sk, SOCKET__ACCEPT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004278 if (err)
4279 return err;
4280
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05004281 newisec = inode_security(SOCK_INODE(newsock));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004282
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05004283 isec = inode_security(SOCK_INODE(sock));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004284 newisec->sclass = isec->sclass;
4285 newisec->sid = isec->sid;
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05004286 newisec->initialized = LABEL_INITIALIZED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004287
4288 return 0;
4289}
4290
4291static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg,
Eric Paris828dfe12008-04-17 13:17:49 -04004292 int size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004293{
Paul Moore253bfae2010-04-22 14:46:19 -04004294 return sock_has_perm(current, sock->sk, SOCKET__WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004295}
4296
4297static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg,
4298 int size, int flags)
4299{
Paul Moore253bfae2010-04-22 14:46:19 -04004300 return sock_has_perm(current, sock->sk, SOCKET__READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004301}
4302
4303static int selinux_socket_getsockname(struct socket *sock)
4304{
Paul Moore253bfae2010-04-22 14:46:19 -04004305 return sock_has_perm(current, sock->sk, SOCKET__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004306}
4307
4308static int selinux_socket_getpeername(struct socket *sock)
4309{
Paul Moore253bfae2010-04-22 14:46:19 -04004310 return sock_has_perm(current, sock->sk, SOCKET__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004311}
4312
Eric Paris828dfe12008-04-17 13:17:49 -04004313static int selinux_socket_setsockopt(struct socket *sock, int level, int optname)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004314{
Paul Mooref8687af2006-10-30 15:22:15 -08004315 int err;
4316
Paul Moore253bfae2010-04-22 14:46:19 -04004317 err = sock_has_perm(current, sock->sk, SOCKET__SETOPT);
Paul Mooref8687af2006-10-30 15:22:15 -08004318 if (err)
4319 return err;
4320
4321 return selinux_netlbl_socket_setsockopt(sock, level, optname);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004322}
4323
4324static int selinux_socket_getsockopt(struct socket *sock, int level,
4325 int optname)
4326{
Paul Moore253bfae2010-04-22 14:46:19 -04004327 return sock_has_perm(current, sock->sk, SOCKET__GETOPT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004328}
4329
4330static int selinux_socket_shutdown(struct socket *sock, int how)
4331{
Paul Moore253bfae2010-04-22 14:46:19 -04004332 return sock_has_perm(current, sock->sk, SOCKET__SHUTDOWN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004333}
4334
David S. Miller3610cda2011-01-05 15:38:53 -08004335static int selinux_socket_unix_stream_connect(struct sock *sock,
4336 struct sock *other,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004337 struct sock *newsk)
4338{
David S. Miller3610cda2011-01-05 15:38:53 -08004339 struct sk_security_struct *sksec_sock = sock->sk_security;
4340 struct sk_security_struct *sksec_other = other->sk_security;
Paul Moore4d1e2452010-04-22 14:46:18 -04004341 struct sk_security_struct *sksec_new = newsk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004342 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004343 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004344 int err;
4345
Eric Paris50c205f2012-04-04 15:01:43 -04004346 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004347 ad.u.net = &net;
4348 ad.u.net->sk = other;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004349
Paul Moore4d1e2452010-04-22 14:46:18 -04004350 err = avc_has_perm(sksec_sock->sid, sksec_other->sid,
4351 sksec_other->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004352 UNIX_STREAM_SOCKET__CONNECTTO, &ad);
4353 if (err)
4354 return err;
4355
Linus Torvalds1da177e2005-04-16 15:20:36 -07004356 /* server child socket */
Paul Moore4d1e2452010-04-22 14:46:18 -04004357 sksec_new->peer_sid = sksec_sock->sid;
4358 err = security_sid_mls_copy(sksec_other->sid, sksec_sock->sid,
4359 &sksec_new->sid);
4360 if (err)
4361 return err;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004362
Paul Moore4d1e2452010-04-22 14:46:18 -04004363 /* connecting socket */
4364 sksec_sock->peer_sid = sksec_new->sid;
4365
4366 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004367}
4368
4369static int selinux_socket_unix_may_send(struct socket *sock,
4370 struct socket *other)
4371{
Paul Moore253bfae2010-04-22 14:46:19 -04004372 struct sk_security_struct *ssec = sock->sk->sk_security;
4373 struct sk_security_struct *osec = other->sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004374 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004375 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004376
Eric Paris50c205f2012-04-04 15:01:43 -04004377 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004378 ad.u.net = &net;
4379 ad.u.net->sk = other->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004380
Paul Moore253bfae2010-04-22 14:46:19 -04004381 return avc_has_perm(ssec->sid, osec->sid, osec->sclass, SOCKET__SENDTO,
4382 &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004383}
4384
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004385static int selinux_inet_sys_rcv_skb(struct net *ns, int ifindex,
4386 char *addrp, u16 family, u32 peer_sid,
Thomas Liu2bf49692009-07-14 12:14:09 -04004387 struct common_audit_data *ad)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004388{
4389 int err;
4390 u32 if_sid;
4391 u32 node_sid;
4392
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004393 err = sel_netif_sid(ns, ifindex, &if_sid);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004394 if (err)
4395 return err;
4396 err = avc_has_perm(peer_sid, if_sid,
4397 SECCLASS_NETIF, NETIF__INGRESS, ad);
4398 if (err)
4399 return err;
4400
4401 err = sel_netnode_sid(addrp, family, &node_sid);
4402 if (err)
4403 return err;
4404 return avc_has_perm(peer_sid, node_sid,
4405 SECCLASS_NODE, NODE__RECVFROM, ad);
4406}
4407
Paul Moore220deb92008-01-29 08:38:23 -05004408static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
Paul Moored8395c82008-10-10 10:16:30 -04004409 u16 family)
Paul Moore220deb92008-01-29 08:38:23 -05004410{
Paul Moore277d3422008-12-31 12:54:11 -05004411 int err = 0;
Paul Moore220deb92008-01-29 08:38:23 -05004412 struct sk_security_struct *sksec = sk->sk_security;
Paul Moore220deb92008-01-29 08:38:23 -05004413 u32 sk_sid = sksec->sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04004414 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004415 struct lsm_network_audit net = {0,};
Paul Moored8395c82008-10-10 10:16:30 -04004416 char *addrp;
4417
Eric Paris50c205f2012-04-04 15:01:43 -04004418 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004419 ad.u.net = &net;
4420 ad.u.net->netif = skb->skb_iif;
4421 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04004422 err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
4423 if (err)
4424 return err;
Paul Moore220deb92008-01-29 08:38:23 -05004425
Paul Moore58bfbb52009-03-27 17:10:41 -04004426 if (selinux_secmark_enabled()) {
Paul Moore220deb92008-01-29 08:38:23 -05004427 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
Paul Moored8395c82008-10-10 10:16:30 -04004428 PACKET__RECV, &ad);
Paul Moore58bfbb52009-03-27 17:10:41 -04004429 if (err)
4430 return err;
4431 }
Paul Moore220deb92008-01-29 08:38:23 -05004432
Steffen Klassertb9679a72011-02-23 12:55:21 +01004433 err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, &ad);
4434 if (err)
4435 return err;
4436 err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, &ad);
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004437
James Morris4e5ab4c2006-06-09 00:33:33 -07004438 return err;
4439}
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004440
James Morris4e5ab4c2006-06-09 00:33:33 -07004441static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
4442{
Paul Moore220deb92008-01-29 08:38:23 -05004443 int err;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004444 struct sk_security_struct *sksec = sk->sk_security;
Paul Moore220deb92008-01-29 08:38:23 -05004445 u16 family = sk->sk_family;
4446 u32 sk_sid = sksec->sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04004447 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004448 struct lsm_network_audit net = {0,};
Paul Moore220deb92008-01-29 08:38:23 -05004449 char *addrp;
Paul Moored8395c82008-10-10 10:16:30 -04004450 u8 secmark_active;
4451 u8 peerlbl_active;
James Morris4e5ab4c2006-06-09 00:33:33 -07004452
James Morris4e5ab4c2006-06-09 00:33:33 -07004453 if (family != PF_INET && family != PF_INET6)
Paul Moore220deb92008-01-29 08:38:23 -05004454 return 0;
James Morris4e5ab4c2006-06-09 00:33:33 -07004455
4456 /* Handle mapped IPv4 packets arriving via IPv6 sockets */
Al Viro87fcd702006-12-04 22:00:55 +00004457 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
James Morris4e5ab4c2006-06-09 00:33:33 -07004458 family = PF_INET;
4459
Paul Moored8395c82008-10-10 10:16:30 -04004460 /* If any sort of compatibility mode is enabled then handoff processing
4461 * to the selinux_sock_rcv_skb_compat() function to deal with the
4462 * special handling. We do this in an attempt to keep this function
4463 * as fast and as clean as possible. */
Paul Moore58bfbb52009-03-27 17:10:41 -04004464 if (!selinux_policycap_netpeer)
Paul Moored8395c82008-10-10 10:16:30 -04004465 return selinux_sock_rcv_skb_compat(sk, skb, family);
4466
4467 secmark_active = selinux_secmark_enabled();
Chris PeBenito2be4d742013-05-03 09:05:39 -04004468 peerlbl_active = selinux_peerlbl_enabled();
Paul Moored8395c82008-10-10 10:16:30 -04004469 if (!secmark_active && !peerlbl_active)
4470 return 0;
4471
Eric Paris50c205f2012-04-04 15:01:43 -04004472 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004473 ad.u.net = &net;
4474 ad.u.net->netif = skb->skb_iif;
4475 ad.u.net->family = family;
Paul Moore224dfbd2008-01-29 08:38:13 -05004476 err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
James Morris4e5ab4c2006-06-09 00:33:33 -07004477 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05004478 return err;
James Morris4e5ab4c2006-06-09 00:33:33 -07004479
Paul Moored8395c82008-10-10 10:16:30 -04004480 if (peerlbl_active) {
Paul Moored621d352008-01-29 08:43:36 -05004481 u32 peer_sid;
4482
4483 err = selinux_skb_peerlbl_sid(skb, family, &peer_sid);
4484 if (err)
4485 return err;
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004486 err = selinux_inet_sys_rcv_skb(sock_net(sk), skb->skb_iif,
4487 addrp, family, peer_sid, &ad);
Paul Mooredfaebe92008-10-10 10:16:31 -04004488 if (err) {
4489 selinux_netlbl_err(skb, err, 0);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004490 return err;
Paul Mooredfaebe92008-10-10 10:16:31 -04004491 }
Paul Moored621d352008-01-29 08:43:36 -05004492 err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER,
4493 PEER__RECV, &ad);
Chad Hanson46d01d62013-12-23 17:45:01 -05004494 if (err) {
Paul Mooredfaebe92008-10-10 10:16:31 -04004495 selinux_netlbl_err(skb, err, 0);
Chad Hanson46d01d62013-12-23 17:45:01 -05004496 return err;
4497 }
Paul Moored621d352008-01-29 08:43:36 -05004498 }
4499
Paul Moored8395c82008-10-10 10:16:30 -04004500 if (secmark_active) {
Paul Mooreeffad8d2008-01-29 08:49:27 -05004501 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
4502 PACKET__RECV, &ad);
4503 if (err)
4504 return err;
4505 }
4506
Paul Moored621d352008-01-29 08:43:36 -05004507 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004508}
4509
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004510static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *optval,
4511 int __user *optlen, unsigned len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004512{
4513 int err = 0;
4514 char *scontext;
4515 u32 scontext_len;
Paul Moore253bfae2010-04-22 14:46:19 -04004516 struct sk_security_struct *sksec = sock->sk->sk_security;
Paul Moore3de4bab2006-11-17 17:38:54 -05004517 u32 peer_sid = SECSID_NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004518
Paul Moore253bfae2010-04-22 14:46:19 -04004519 if (sksec->sclass == SECCLASS_UNIX_STREAM_SOCKET ||
4520 sksec->sclass == SECCLASS_TCP_SOCKET)
Eric Parisdd3e7832010-04-07 15:08:46 -04004521 peer_sid = sksec->peer_sid;
Paul Moore253bfae2010-04-22 14:46:19 -04004522 if (peer_sid == SECSID_NULL)
4523 return -ENOPROTOOPT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004524
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004525 err = security_sid_to_context(peer_sid, &scontext, &scontext_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004526 if (err)
Paul Moore253bfae2010-04-22 14:46:19 -04004527 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004528
4529 if (scontext_len > len) {
4530 err = -ERANGE;
4531 goto out_len;
4532 }
4533
4534 if (copy_to_user(optval, scontext, scontext_len))
4535 err = -EFAULT;
4536
4537out_len:
4538 if (put_user(scontext_len, optlen))
4539 err = -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004540 kfree(scontext);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004541 return err;
4542}
4543
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004544static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid)
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004545{
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004546 u32 peer_secid = SECSID_NULL;
Paul Moore75e22912008-01-29 08:38:04 -05004547 u16 family;
Catherine Zhang877ce7c2006-06-29 12:27:47 -07004548
Paul Mooreaa862902008-10-10 10:16:29 -04004549 if (skb && skb->protocol == htons(ETH_P_IP))
4550 family = PF_INET;
4551 else if (skb && skb->protocol == htons(ETH_P_IPV6))
4552 family = PF_INET6;
4553 else if (sock)
Paul Moore75e22912008-01-29 08:38:04 -05004554 family = sock->sk->sk_family;
Paul Moore75e22912008-01-29 08:38:04 -05004555 else
4556 goto out;
4557
4558 if (sock && family == PF_UNIX)
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02004559 selinux_inode_getsecid(SOCK_INODE(sock), &peer_secid);
Paul Moore3de4bab2006-11-17 17:38:54 -05004560 else if (skb)
Paul Moore220deb92008-01-29 08:38:23 -05004561 selinux_skb_peerlbl_sid(skb, family, &peer_secid);
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004562
Paul Moore75e22912008-01-29 08:38:04 -05004563out:
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004564 *secid = peer_secid;
Paul Moore75e22912008-01-29 08:38:04 -05004565 if (peer_secid == SECSID_NULL)
4566 return -EINVAL;
4567 return 0;
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004568}
4569
Al Viro7d877f32005-10-21 03:20:43 -04004570static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004571{
Paul Moore84914b72010-04-22 14:46:18 -04004572 struct sk_security_struct *sksec;
4573
4574 sksec = kzalloc(sizeof(*sksec), priority);
4575 if (!sksec)
4576 return -ENOMEM;
4577
4578 sksec->peer_sid = SECINITSID_UNLABELED;
4579 sksec->sid = SECINITSID_UNLABELED;
Stephen Smalley5dee25d2015-07-10 17:19:57 -04004580 sksec->sclass = SECCLASS_SOCKET;
Paul Moore84914b72010-04-22 14:46:18 -04004581 selinux_netlbl_sk_security_reset(sksec);
4582 sk->sk_security = sksec;
4583
4584 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004585}
4586
4587static void selinux_sk_free_security(struct sock *sk)
4588{
Paul Moore84914b72010-04-22 14:46:18 -04004589 struct sk_security_struct *sksec = sk->sk_security;
4590
4591 sk->sk_security = NULL;
4592 selinux_netlbl_sk_security_free(sksec);
4593 kfree(sksec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004594}
4595
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004596static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk)
4597{
Eric Parisdd3e7832010-04-07 15:08:46 -04004598 struct sk_security_struct *sksec = sk->sk_security;
4599 struct sk_security_struct *newsksec = newsk->sk_security;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004600
Eric Parisdd3e7832010-04-07 15:08:46 -04004601 newsksec->sid = sksec->sid;
4602 newsksec->peer_sid = sksec->peer_sid;
4603 newsksec->sclass = sksec->sclass;
Paul Moore99f59ed2006-08-29 17:53:48 -07004604
Eric Parisdd3e7832010-04-07 15:08:46 -04004605 selinux_netlbl_sk_security_reset(newsksec);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004606}
4607
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004608static void selinux_sk_getsecid(struct sock *sk, u32 *secid)
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004609{
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004610 if (!sk)
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004611 *secid = SECINITSID_ANY_SOCKET;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004612 else {
4613 struct sk_security_struct *sksec = sk->sk_security;
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004614
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004615 *secid = sksec->sid;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004616 }
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004617}
4618
Eric Paris828dfe12008-04-17 13:17:49 -04004619static void selinux_sock_graft(struct sock *sk, struct socket *parent)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004620{
Andreas Gruenbacher83da53c52015-12-24 11:09:39 -05004621 struct inode_security_struct *isec = inode_security(SOCK_INODE(parent));
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004622 struct sk_security_struct *sksec = sk->sk_security;
4623
Paul Moore2873ead2014-07-28 10:42:48 -04004624 if (sk->sk_family == PF_INET || sk->sk_family == PF_INET6 ||
4625 sk->sk_family == PF_UNIX)
David Woodhouse2148ccc2006-09-29 15:50:25 -07004626 isec->sid = sksec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05004627 sksec->sclass = isec->sclass;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004628}
4629
Adrian Bunk9a673e52006-08-15 00:03:53 -07004630static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
4631 struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004632{
4633 struct sk_security_struct *sksec = sk->sk_security;
4634 int err;
Paul Moore0b1f24e2013-12-03 11:39:13 -05004635 u16 family = req->rsk_ops->family;
Paul Moore446b8022013-12-04 16:10:51 -05004636 u32 connsid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004637 u32 peersid;
4638
Paul Mooreaa862902008-10-10 10:16:29 -04004639 err = selinux_skb_peerlbl_sid(skb, family, &peersid);
Paul Moore220deb92008-01-29 08:38:23 -05004640 if (err)
4641 return err;
Paul Moore446b8022013-12-04 16:10:51 -05004642 err = selinux_conn_sid(sksec->sid, peersid, &connsid);
4643 if (err)
4644 return err;
4645 req->secid = connsid;
4646 req->peer_secid = peersid;
Venkat Yekkiralaa51c64f2006-07-27 22:01:34 -07004647
Paul Moore389fb8002009-03-27 17:10:34 -04004648 return selinux_netlbl_inet_conn_request(req, family);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004649}
4650
Adrian Bunk9a673e52006-08-15 00:03:53 -07004651static void selinux_inet_csk_clone(struct sock *newsk,
4652 const struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004653{
4654 struct sk_security_struct *newsksec = newsk->sk_security;
4655
4656 newsksec->sid = req->secid;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004657 newsksec->peer_sid = req->peer_secid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004658 /* NOTE: Ideally, we should also get the isec->sid for the
4659 new socket in sync, but we don't have the isec available yet.
4660 So we will wait until sock_graft to do it, by which
4661 time it will have been created and available. */
Paul Moore99f59ed2006-08-29 17:53:48 -07004662
Paul Moore9f2ad662006-11-17 17:38:53 -05004663 /* We don't need to take any sort of lock here as we are the only
4664 * thread with access to newsksec */
Paul Moore389fb8002009-03-27 17:10:34 -04004665 selinux_netlbl_inet_csk_clone(newsk, req->rsk_ops->family);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004666}
4667
Paul Moore014ab192008-10-10 10:16:33 -04004668static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb)
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004669{
Paul Mooreaa862902008-10-10 10:16:29 -04004670 u16 family = sk->sk_family;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004671 struct sk_security_struct *sksec = sk->sk_security;
4672
Paul Mooreaa862902008-10-10 10:16:29 -04004673 /* handle mapped IPv4 packets arriving via IPv6 sockets */
4674 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
4675 family = PF_INET;
4676
4677 selinux_skb_peerlbl_sid(skb, family, &sksec->peer_sid);
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004678}
4679
Eric Paris2606fd12010-10-13 16:24:41 -04004680static int selinux_secmark_relabel_packet(u32 sid)
4681{
4682 const struct task_security_struct *__tsec;
4683 u32 tsid;
4684
4685 __tsec = current_security();
4686 tsid = __tsec->sid;
4687
4688 return avc_has_perm(tsid, sid, SECCLASS_PACKET, PACKET__RELABELTO, NULL);
4689}
4690
4691static void selinux_secmark_refcount_inc(void)
4692{
4693 atomic_inc(&selinux_secmark_refcount);
4694}
4695
4696static void selinux_secmark_refcount_dec(void)
4697{
4698 atomic_dec(&selinux_secmark_refcount);
4699}
4700
Adrian Bunk9a673e52006-08-15 00:03:53 -07004701static void selinux_req_classify_flow(const struct request_sock *req,
4702 struct flowi *fl)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004703{
David S. Miller1d28f422011-03-12 00:29:39 -05004704 fl->flowi_secid = req->secid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004705}
4706
Paul Moore5dbbaf22013-01-14 07:12:19 +00004707static int selinux_tun_dev_alloc_security(void **security)
4708{
4709 struct tun_security_struct *tunsec;
4710
4711 tunsec = kzalloc(sizeof(*tunsec), GFP_KERNEL);
4712 if (!tunsec)
4713 return -ENOMEM;
4714 tunsec->sid = current_sid();
4715
4716 *security = tunsec;
4717 return 0;
4718}
4719
4720static void selinux_tun_dev_free_security(void *security)
4721{
4722 kfree(security);
4723}
4724
Paul Mooreed6d76e2009-08-28 18:12:49 -04004725static int selinux_tun_dev_create(void)
4726{
4727 u32 sid = current_sid();
4728
4729 /* we aren't taking into account the "sockcreate" SID since the socket
4730 * that is being created here is not a socket in the traditional sense,
4731 * instead it is a private sock, accessible only to the kernel, and
4732 * representing a wide range of network traffic spanning multiple
4733 * connections unlike traditional sockets - check the TUN driver to
4734 * get a better understanding of why this socket is special */
4735
4736 return avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET, TUN_SOCKET__CREATE,
4737 NULL);
4738}
4739
Paul Moore5dbbaf22013-01-14 07:12:19 +00004740static int selinux_tun_dev_attach_queue(void *security)
Paul Mooreed6d76e2009-08-28 18:12:49 -04004741{
Paul Moore5dbbaf22013-01-14 07:12:19 +00004742 struct tun_security_struct *tunsec = security;
4743
4744 return avc_has_perm(current_sid(), tunsec->sid, SECCLASS_TUN_SOCKET,
4745 TUN_SOCKET__ATTACH_QUEUE, NULL);
4746}
4747
4748static int selinux_tun_dev_attach(struct sock *sk, void *security)
4749{
4750 struct tun_security_struct *tunsec = security;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004751 struct sk_security_struct *sksec = sk->sk_security;
4752
4753 /* we don't currently perform any NetLabel based labeling here and it
4754 * isn't clear that we would want to do so anyway; while we could apply
4755 * labeling without the support of the TUN user the resulting labeled
4756 * traffic from the other end of the connection would almost certainly
4757 * cause confusion to the TUN user that had no idea network labeling
4758 * protocols were being used */
4759
Paul Moore5dbbaf22013-01-14 07:12:19 +00004760 sksec->sid = tunsec->sid;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004761 sksec->sclass = SECCLASS_TUN_SOCKET;
Paul Moore5dbbaf22013-01-14 07:12:19 +00004762
4763 return 0;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004764}
4765
Paul Moore5dbbaf22013-01-14 07:12:19 +00004766static int selinux_tun_dev_open(void *security)
Paul Mooreed6d76e2009-08-28 18:12:49 -04004767{
Paul Moore5dbbaf22013-01-14 07:12:19 +00004768 struct tun_security_struct *tunsec = security;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004769 u32 sid = current_sid();
4770 int err;
4771
Paul Moore5dbbaf22013-01-14 07:12:19 +00004772 err = avc_has_perm(sid, tunsec->sid, SECCLASS_TUN_SOCKET,
Paul Mooreed6d76e2009-08-28 18:12:49 -04004773 TUN_SOCKET__RELABELFROM, NULL);
4774 if (err)
4775 return err;
4776 err = avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET,
4777 TUN_SOCKET__RELABELTO, NULL);
4778 if (err)
4779 return err;
Paul Moore5dbbaf22013-01-14 07:12:19 +00004780 tunsec->sid = sid;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004781
4782 return 0;
4783}
4784
Linus Torvalds1da177e2005-04-16 15:20:36 -07004785static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
4786{
4787 int err = 0;
4788 u32 perm;
4789 struct nlmsghdr *nlh;
Paul Moore253bfae2010-04-22 14:46:19 -04004790 struct sk_security_struct *sksec = sk->sk_security;
Eric Paris828dfe12008-04-17 13:17:49 -04004791
Hong zhi guo77954982013-03-27 06:49:35 +00004792 if (skb->len < NLMSG_HDRLEN) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004793 err = -EINVAL;
4794 goto out;
4795 }
Arnaldo Carvalho de Melob529ccf2007-04-25 19:08:35 -07004796 nlh = nlmsg_hdr(skb);
Eric Paris828dfe12008-04-17 13:17:49 -04004797
Paul Moore253bfae2010-04-22 14:46:19 -04004798 err = selinux_nlmsg_lookup(sksec->sclass, nlh->nlmsg_type, &perm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004799 if (err) {
4800 if (err == -EINVAL) {
Richard Guy Briggsd950f842014-11-12 14:01:34 -05004801 printk(KERN_WARNING
4802 "SELinux: unrecognized netlink message:"
Marek Milkoviccded3ff2015-06-04 16:22:16 -04004803 " protocol=%hu nlmsg_type=%hu sclass=%s\n",
4804 sk->sk_protocol, nlh->nlmsg_type,
4805 secclass_map[sksec->sclass - 1].name);
Eric Paris39c9aed2008-11-05 09:34:42 -05004806 if (!selinux_enforcing || security_get_allow_unknown())
Linus Torvalds1da177e2005-04-16 15:20:36 -07004807 err = 0;
4808 }
4809
4810 /* Ignore */
4811 if (err == -ENOENT)
4812 err = 0;
4813 goto out;
4814 }
4815
Paul Moore253bfae2010-04-22 14:46:19 -04004816 err = sock_has_perm(current, sk, perm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004817out:
4818 return err;
4819}
4820
4821#ifdef CONFIG_NETFILTER
4822
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004823static unsigned int selinux_ip_forward(struct sk_buff *skb,
4824 const struct net_device *indev,
Paul Mooreeffad8d2008-01-29 08:49:27 -05004825 u16 family)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004826{
Paul Mooredfaebe92008-10-10 10:16:31 -04004827 int err;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004828 char *addrp;
4829 u32 peer_sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04004830 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004831 struct lsm_network_audit net = {0,};
Paul Mooreeffad8d2008-01-29 08:49:27 -05004832 u8 secmark_active;
Paul Moore948bf852008-10-10 10:16:32 -04004833 u8 netlbl_active;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004834 u8 peerlbl_active;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004835
Paul Mooreeffad8d2008-01-29 08:49:27 -05004836 if (!selinux_policycap_netpeer)
4837 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004838
Paul Mooreeffad8d2008-01-29 08:49:27 -05004839 secmark_active = selinux_secmark_enabled();
Paul Moore948bf852008-10-10 10:16:32 -04004840 netlbl_active = netlbl_enabled();
Chris PeBenito2be4d742013-05-03 09:05:39 -04004841 peerlbl_active = selinux_peerlbl_enabled();
Paul Mooreeffad8d2008-01-29 08:49:27 -05004842 if (!secmark_active && !peerlbl_active)
4843 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004844
Paul Moored8395c82008-10-10 10:16:30 -04004845 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0)
4846 return NF_DROP;
4847
Eric Paris50c205f2012-04-04 15:01:43 -04004848 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004849 ad.u.net = &net;
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004850 ad.u.net->netif = indev->ifindex;
Eric Paris48c62af2012-04-02 13:15:44 -04004851 ad.u.net->family = family;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004852 if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0)
4853 return NF_DROP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004854
Paul Mooredfaebe92008-10-10 10:16:31 -04004855 if (peerlbl_active) {
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004856 err = selinux_inet_sys_rcv_skb(dev_net(indev), indev->ifindex,
4857 addrp, family, peer_sid, &ad);
Paul Mooredfaebe92008-10-10 10:16:31 -04004858 if (err) {
4859 selinux_netlbl_err(skb, err, 1);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004860 return NF_DROP;
Paul Mooredfaebe92008-10-10 10:16:31 -04004861 }
4862 }
Paul Mooreeffad8d2008-01-29 08:49:27 -05004863
4864 if (secmark_active)
4865 if (avc_has_perm(peer_sid, skb->secmark,
4866 SECCLASS_PACKET, PACKET__FORWARD_IN, &ad))
4867 return NF_DROP;
4868
Paul Moore948bf852008-10-10 10:16:32 -04004869 if (netlbl_active)
4870 /* we do this in the FORWARD path and not the POST_ROUTING
4871 * path because we want to make sure we apply the necessary
4872 * labeling before IPsec is applied so we can leverage AH
4873 * protection */
4874 if (selinux_netlbl_skbuff_setsid(skb, family, peer_sid) != 0)
4875 return NF_DROP;
4876
Paul Mooreeffad8d2008-01-29 08:49:27 -05004877 return NF_ACCEPT;
4878}
4879
Eric W. Biederman06198b32015-09-18 14:33:06 -05004880static unsigned int selinux_ipv4_forward(void *priv,
Paul Mooreeffad8d2008-01-29 08:49:27 -05004881 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04004882 const struct nf_hook_state *state)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004883{
David S. Miller238e54c2015-04-03 20:32:56 -04004884 return selinux_ip_forward(skb, state->in, PF_INET);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004885}
4886
4887#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Eric W. Biederman06198b32015-09-18 14:33:06 -05004888static unsigned int selinux_ipv6_forward(void *priv,
Paul Mooreeffad8d2008-01-29 08:49:27 -05004889 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04004890 const struct nf_hook_state *state)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004891{
David S. Miller238e54c2015-04-03 20:32:56 -04004892 return selinux_ip_forward(skb, state->in, PF_INET6);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004893}
4894#endif /* IPV6 */
4895
Paul Moore948bf852008-10-10 10:16:32 -04004896static unsigned int selinux_ip_output(struct sk_buff *skb,
4897 u16 family)
4898{
Paul Moore47180062013-12-04 16:10:45 -05004899 struct sock *sk;
Paul Moore948bf852008-10-10 10:16:32 -04004900 u32 sid;
4901
4902 if (!netlbl_enabled())
4903 return NF_ACCEPT;
4904
4905 /* we do this in the LOCAL_OUT path and not the POST_ROUTING path
4906 * because we want to make sure we apply the necessary labeling
4907 * before IPsec is applied so we can leverage AH protection */
Paul Moore47180062013-12-04 16:10:45 -05004908 sk = skb->sk;
4909 if (sk) {
4910 struct sk_security_struct *sksec;
4911
Eric Dumazete446f9d2015-10-08 05:01:55 -07004912 if (sk_listener(sk))
Paul Moore47180062013-12-04 16:10:45 -05004913 /* if the socket is the listening state then this
4914 * packet is a SYN-ACK packet which means it needs to
4915 * be labeled based on the connection/request_sock and
4916 * not the parent socket. unfortunately, we can't
4917 * lookup the request_sock yet as it isn't queued on
4918 * the parent socket until after the SYN-ACK is sent.
4919 * the "solution" is to simply pass the packet as-is
4920 * as any IP option based labeling should be copied
4921 * from the initial connection request (in the IP
4922 * layer). it is far from ideal, but until we get a
4923 * security label in the packet itself this is the
4924 * best we can do. */
4925 return NF_ACCEPT;
4926
4927 /* standard practice, label using the parent socket */
4928 sksec = sk->sk_security;
Paul Moore948bf852008-10-10 10:16:32 -04004929 sid = sksec->sid;
4930 } else
4931 sid = SECINITSID_KERNEL;
4932 if (selinux_netlbl_skbuff_setsid(skb, family, sid) != 0)
4933 return NF_DROP;
4934
4935 return NF_ACCEPT;
4936}
4937
Eric W. Biederman06198b32015-09-18 14:33:06 -05004938static unsigned int selinux_ipv4_output(void *priv,
Paul Moore948bf852008-10-10 10:16:32 -04004939 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04004940 const struct nf_hook_state *state)
Paul Moore948bf852008-10-10 10:16:32 -04004941{
4942 return selinux_ip_output(skb, PF_INET);
4943}
4944
Paul Mooreeffad8d2008-01-29 08:49:27 -05004945static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
4946 int ifindex,
Paul Moored8395c82008-10-10 10:16:30 -04004947 u16 family)
James Morris4e5ab4c2006-06-09 00:33:33 -07004948{
Eric Dumazet54abc682015-11-08 10:54:07 -08004949 struct sock *sk = skb_to_full_sk(skb);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004950 struct sk_security_struct *sksec;
Thomas Liu2bf49692009-07-14 12:14:09 -04004951 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004952 struct lsm_network_audit net = {0,};
Paul Moored8395c82008-10-10 10:16:30 -04004953 char *addrp;
4954 u8 proto;
James Morris4e5ab4c2006-06-09 00:33:33 -07004955
Paul Mooreeffad8d2008-01-29 08:49:27 -05004956 if (sk == NULL)
4957 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004958 sksec = sk->sk_security;
James Morris4e5ab4c2006-06-09 00:33:33 -07004959
Eric Paris50c205f2012-04-04 15:01:43 -04004960 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004961 ad.u.net = &net;
4962 ad.u.net->netif = ifindex;
4963 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04004964 if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto))
4965 return NF_DROP;
4966
Paul Moore58bfbb52009-03-27 17:10:41 -04004967 if (selinux_secmark_enabled())
Paul Mooreeffad8d2008-01-29 08:49:27 -05004968 if (avc_has_perm(sksec->sid, skb->secmark,
Paul Moored8395c82008-10-10 10:16:30 -04004969 SECCLASS_PACKET, PACKET__SEND, &ad))
Eric Paris2fe66ec2010-11-23 06:28:08 +00004970 return NF_DROP_ERR(-ECONNREFUSED);
James Morris4e5ab4c2006-06-09 00:33:33 -07004971
Steffen Klassertb9679a72011-02-23 12:55:21 +01004972 if (selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto))
4973 return NF_DROP_ERR(-ECONNREFUSED);
James Morris4e5ab4c2006-06-09 00:33:33 -07004974
Paul Mooreeffad8d2008-01-29 08:49:27 -05004975 return NF_ACCEPT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004976}
4977
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004978static unsigned int selinux_ip_postroute(struct sk_buff *skb,
4979 const struct net_device *outdev,
Paul Mooreeffad8d2008-01-29 08:49:27 -05004980 u16 family)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004981{
Paul Mooreeffad8d2008-01-29 08:49:27 -05004982 u32 secmark_perm;
4983 u32 peer_sid;
Paul Moorecbe0d6e2014-09-10 17:09:57 -04004984 int ifindex = outdev->ifindex;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004985 struct sock *sk;
Thomas Liu2bf49692009-07-14 12:14:09 -04004986 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004987 struct lsm_network_audit net = {0,};
Paul Mooreeffad8d2008-01-29 08:49:27 -05004988 char *addrp;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004989 u8 secmark_active;
4990 u8 peerlbl_active;
4991
Paul Mooreeffad8d2008-01-29 08:49:27 -05004992 /* If any sort of compatibility mode is enabled then handoff processing
4993 * to the selinux_ip_postroute_compat() function to deal with the
4994 * special handling. We do this in an attempt to keep this function
4995 * as fast and as clean as possible. */
Paul Moore58bfbb52009-03-27 17:10:41 -04004996 if (!selinux_policycap_netpeer)
Paul Moored8395c82008-10-10 10:16:30 -04004997 return selinux_ip_postroute_compat(skb, ifindex, family);
Paul Moorec0828e52013-12-10 14:58:01 -05004998
Paul Mooreeffad8d2008-01-29 08:49:27 -05004999 secmark_active = selinux_secmark_enabled();
Chris PeBenito2be4d742013-05-03 09:05:39 -04005000 peerlbl_active = selinux_peerlbl_enabled();
Paul Mooreeffad8d2008-01-29 08:49:27 -05005001 if (!secmark_active && !peerlbl_active)
5002 return NF_ACCEPT;
5003
Eric Dumazet54abc682015-11-08 10:54:07 -08005004 sk = skb_to_full_sk(skb);
Paul Moorec0828e52013-12-10 14:58:01 -05005005
Paul Mooreeffad8d2008-01-29 08:49:27 -05005006#ifdef CONFIG_XFRM
5007 /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec
5008 * packet transformation so allow the packet to pass without any checks
5009 * since we'll have another chance to perform access control checks
5010 * when the packet is on it's final way out.
5011 * NOTE: there appear to be some IPv6 multicast cases where skb->dst
Paul Moorec0828e52013-12-10 14:58:01 -05005012 * is NULL, in this case go ahead and apply access control.
5013 * NOTE: if this is a local socket (skb->sk != NULL) that is in the
5014 * TCP listening state we cannot wait until the XFRM processing
5015 * is done as we will miss out on the SA label if we do;
5016 * unfortunately, this means more work, but it is only once per
5017 * connection. */
5018 if (skb_dst(skb) != NULL && skb_dst(skb)->xfrm != NULL &&
Eric Dumazete446f9d2015-10-08 05:01:55 -07005019 !(sk && sk_listener(sk)))
Paul Mooreeffad8d2008-01-29 08:49:27 -05005020 return NF_ACCEPT;
5021#endif
Paul Mooreeffad8d2008-01-29 08:49:27 -05005022
Paul Moored8395c82008-10-10 10:16:30 -04005023 if (sk == NULL) {
Paul Moore446b8022013-12-04 16:10:51 -05005024 /* Without an associated socket the packet is either coming
5025 * from the kernel or it is being forwarded; check the packet
5026 * to determine which and if the packet is being forwarded
5027 * query the packet directly to determine the security label. */
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01005028 if (skb->skb_iif) {
5029 secmark_perm = PACKET__FORWARD_OUT;
Paul Moored8395c82008-10-10 10:16:30 -04005030 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00005031 return NF_DROP;
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01005032 } else {
5033 secmark_perm = PACKET__SEND;
Paul Moored8395c82008-10-10 10:16:30 -04005034 peer_sid = SECINITSID_KERNEL;
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01005035 }
Eric Dumazete446f9d2015-10-08 05:01:55 -07005036 } else if (sk_listener(sk)) {
Paul Moore446b8022013-12-04 16:10:51 -05005037 /* Locally generated packet but the associated socket is in the
5038 * listening state which means this is a SYN-ACK packet. In
5039 * this particular case the correct security label is assigned
5040 * to the connection/request_sock but unfortunately we can't
5041 * query the request_sock as it isn't queued on the parent
5042 * socket until after the SYN-ACK packet is sent; the only
5043 * viable choice is to regenerate the label like we do in
5044 * selinux_inet_conn_request(). See also selinux_ip_output()
5045 * for similar problems. */
5046 u32 skb_sid;
Eric Dumazete446f9d2015-10-08 05:01:55 -07005047 struct sk_security_struct *sksec;
5048
Eric Dumazete446f9d2015-10-08 05:01:55 -07005049 sksec = sk->sk_security;
Paul Moore446b8022013-12-04 16:10:51 -05005050 if (selinux_skb_peerlbl_sid(skb, family, &skb_sid))
5051 return NF_DROP;
Paul Moorec0828e52013-12-10 14:58:01 -05005052 /* At this point, if the returned skb peerlbl is SECSID_NULL
5053 * and the packet has been through at least one XFRM
5054 * transformation then we must be dealing with the "final"
5055 * form of labeled IPsec packet; since we've already applied
5056 * all of our access controls on this packet we can safely
5057 * pass the packet. */
5058 if (skb_sid == SECSID_NULL) {
5059 switch (family) {
5060 case PF_INET:
5061 if (IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED)
5062 return NF_ACCEPT;
5063 break;
5064 case PF_INET6:
5065 if (IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED)
5066 return NF_ACCEPT;
Paul Moorea7a91a12014-09-03 10:51:59 -04005067 break;
Paul Moorec0828e52013-12-10 14:58:01 -05005068 default:
5069 return NF_DROP_ERR(-ECONNREFUSED);
5070 }
5071 }
Paul Moore446b8022013-12-04 16:10:51 -05005072 if (selinux_conn_sid(sksec->sid, skb_sid, &peer_sid))
5073 return NF_DROP;
5074 secmark_perm = PACKET__SEND;
Paul Moored8395c82008-10-10 10:16:30 -04005075 } else {
Paul Moore446b8022013-12-04 16:10:51 -05005076 /* Locally generated packet, fetch the security label from the
5077 * associated socket. */
Paul Mooreeffad8d2008-01-29 08:49:27 -05005078 struct sk_security_struct *sksec = sk->sk_security;
5079 peer_sid = sksec->sid;
5080 secmark_perm = PACKET__SEND;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005081 }
5082
Eric Paris50c205f2012-04-04 15:01:43 -04005083 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04005084 ad.u.net = &net;
5085 ad.u.net->netif = ifindex;
5086 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04005087 if (selinux_parse_skb(skb, &ad, &addrp, 0, NULL))
Eric Paris04f6d702010-11-23 06:28:02 +00005088 return NF_DROP;
Paul Moored8395c82008-10-10 10:16:30 -04005089
Paul Mooreeffad8d2008-01-29 08:49:27 -05005090 if (secmark_active)
5091 if (avc_has_perm(peer_sid, skb->secmark,
5092 SECCLASS_PACKET, secmark_perm, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00005093 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005094
5095 if (peerlbl_active) {
5096 u32 if_sid;
5097 u32 node_sid;
5098
Paul Moorecbe0d6e2014-09-10 17:09:57 -04005099 if (sel_netif_sid(dev_net(outdev), ifindex, &if_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00005100 return NF_DROP;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005101 if (avc_has_perm(peer_sid, if_sid,
5102 SECCLASS_NETIF, NETIF__EGRESS, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00005103 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005104
5105 if (sel_netnode_sid(addrp, family, &node_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00005106 return NF_DROP;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005107 if (avc_has_perm(peer_sid, node_sid,
5108 SECCLASS_NODE, NODE__SENDTO, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00005109 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005110 }
5111
5112 return NF_ACCEPT;
5113}
5114
Eric W. Biederman06198b32015-09-18 14:33:06 -05005115static unsigned int selinux_ipv4_postroute(void *priv,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005116 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04005117 const struct nf_hook_state *state)
Paul Mooreeffad8d2008-01-29 08:49:27 -05005118{
David S. Miller238e54c2015-04-03 20:32:56 -04005119 return selinux_ip_postroute(skb, state->out, PF_INET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005120}
5121
5122#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Eric W. Biederman06198b32015-09-18 14:33:06 -05005123static unsigned int selinux_ipv6_postroute(void *priv,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005124 struct sk_buff *skb,
David S. Miller238e54c2015-04-03 20:32:56 -04005125 const struct nf_hook_state *state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005126{
David S. Miller238e54c2015-04-03 20:32:56 -04005127 return selinux_ip_postroute(skb, state->out, PF_INET6);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005128}
Linus Torvalds1da177e2005-04-16 15:20:36 -07005129#endif /* IPV6 */
5130
5131#endif /* CONFIG_NETFILTER */
5132
Linus Torvalds1da177e2005-04-16 15:20:36 -07005133static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb)
5134{
Stephen Smalley941fc5b2009-10-01 14:48:23 -04005135 return selinux_nlmsg_perm(sk, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005136}
5137
Linus Torvalds1da177e2005-04-16 15:20:36 -07005138static int ipc_alloc_security(struct task_struct *task,
5139 struct kern_ipc_perm *perm,
5140 u16 sclass)
5141{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005142 struct ipc_security_struct *isec;
David Howells275bb412008-11-14 10:39:19 +11005143 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005144
James Morris89d155e2005-10-30 14:59:21 -08005145 isec = kzalloc(sizeof(struct ipc_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005146 if (!isec)
5147 return -ENOMEM;
5148
David Howells275bb412008-11-14 10:39:19 +11005149 sid = task_sid(task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005150 isec->sclass = sclass;
David Howells275bb412008-11-14 10:39:19 +11005151 isec->sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005152 perm->security = isec;
5153
5154 return 0;
5155}
5156
5157static void ipc_free_security(struct kern_ipc_perm *perm)
5158{
5159 struct ipc_security_struct *isec = perm->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005160 perm->security = NULL;
5161 kfree(isec);
5162}
5163
5164static int msg_msg_alloc_security(struct msg_msg *msg)
5165{
5166 struct msg_security_struct *msec;
5167
James Morris89d155e2005-10-30 14:59:21 -08005168 msec = kzalloc(sizeof(struct msg_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005169 if (!msec)
5170 return -ENOMEM;
5171
Linus Torvalds1da177e2005-04-16 15:20:36 -07005172 msec->sid = SECINITSID_UNLABELED;
5173 msg->security = msec;
5174
5175 return 0;
5176}
5177
5178static void msg_msg_free_security(struct msg_msg *msg)
5179{
5180 struct msg_security_struct *msec = msg->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005181
5182 msg->security = NULL;
5183 kfree(msec);
5184}
5185
5186static int ipc_has_perm(struct kern_ipc_perm *ipc_perms,
Stephen Smalley6af963f2005-05-01 08:58:39 -07005187 u32 perms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005188{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005189 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005190 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005191 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005192
Linus Torvalds1da177e2005-04-16 15:20:36 -07005193 isec = ipc_perms->security;
5194
Eric Paris50c205f2012-04-04 15:01:43 -04005195 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005196 ad.u.ipc_id = ipc_perms->key;
5197
David Howells275bb412008-11-14 10:39:19 +11005198 return avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005199}
5200
5201static int selinux_msg_msg_alloc_security(struct msg_msg *msg)
5202{
5203 return msg_msg_alloc_security(msg);
5204}
5205
5206static void selinux_msg_msg_free_security(struct msg_msg *msg)
5207{
5208 msg_msg_free_security(msg);
5209}
5210
5211/* message queue security operations */
5212static int selinux_msg_queue_alloc_security(struct msg_queue *msq)
5213{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005214 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005215 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005216 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005217 int rc;
5218
5219 rc = ipc_alloc_security(current, &msq->q_perm, SECCLASS_MSGQ);
5220 if (rc)
5221 return rc;
5222
Linus Torvalds1da177e2005-04-16 15:20:36 -07005223 isec = msq->q_perm.security;
5224
Eric Paris50c205f2012-04-04 15:01:43 -04005225 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04005226 ad.u.ipc_id = msq->q_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005227
David Howells275bb412008-11-14 10:39:19 +11005228 rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005229 MSGQ__CREATE, &ad);
5230 if (rc) {
5231 ipc_free_security(&msq->q_perm);
5232 return rc;
5233 }
5234 return 0;
5235}
5236
5237static void selinux_msg_queue_free_security(struct msg_queue *msq)
5238{
5239 ipc_free_security(&msq->q_perm);
5240}
5241
5242static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg)
5243{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005244 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005245 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005246 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005247
Linus Torvalds1da177e2005-04-16 15:20:36 -07005248 isec = msq->q_perm.security;
5249
Eric Paris50c205f2012-04-04 15:01:43 -04005250 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005251 ad.u.ipc_id = msq->q_perm.key;
5252
David Howells275bb412008-11-14 10:39:19 +11005253 return avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005254 MSGQ__ASSOCIATE, &ad);
5255}
5256
5257static int selinux_msg_queue_msgctl(struct msg_queue *msq, int cmd)
5258{
5259 int err;
5260 int perms;
5261
Eric Paris828dfe12008-04-17 13:17:49 -04005262 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005263 case IPC_INFO:
5264 case MSG_INFO:
5265 /* No specific object, just general system-wide information. */
5266 return task_has_system(current, SYSTEM__IPC_INFO);
5267 case IPC_STAT:
5268 case MSG_STAT:
5269 perms = MSGQ__GETATTR | MSGQ__ASSOCIATE;
5270 break;
5271 case IPC_SET:
5272 perms = MSGQ__SETATTR;
5273 break;
5274 case IPC_RMID:
5275 perms = MSGQ__DESTROY;
5276 break;
5277 default:
5278 return 0;
5279 }
5280
Stephen Smalley6af963f2005-05-01 08:58:39 -07005281 err = ipc_has_perm(&msq->q_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005282 return err;
5283}
5284
5285static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, int msqflg)
5286{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005287 struct ipc_security_struct *isec;
5288 struct msg_security_struct *msec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005289 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005290 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005291 int rc;
5292
Linus Torvalds1da177e2005-04-16 15:20:36 -07005293 isec = msq->q_perm.security;
5294 msec = msg->security;
5295
5296 /*
5297 * First time through, need to assign label to the message
5298 */
5299 if (msec->sid == SECINITSID_UNLABELED) {
5300 /*
5301 * Compute new sid based on current process and
5302 * message queue this message will be stored in
5303 */
David Howells275bb412008-11-14 10:39:19 +11005304 rc = security_transition_sid(sid, isec->sid, SECCLASS_MSG,
Eric Paris652bb9b2011-02-01 11:05:40 -05005305 NULL, &msec->sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005306 if (rc)
5307 return rc;
5308 }
5309
Eric Paris50c205f2012-04-04 15:01:43 -04005310 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005311 ad.u.ipc_id = msq->q_perm.key;
5312
5313 /* Can this process write to the queue? */
David Howells275bb412008-11-14 10:39:19 +11005314 rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005315 MSGQ__WRITE, &ad);
5316 if (!rc)
5317 /* Can this process send the message */
David Howells275bb412008-11-14 10:39:19 +11005318 rc = avc_has_perm(sid, msec->sid, SECCLASS_MSG,
5319 MSG__SEND, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005320 if (!rc)
5321 /* Can the message be put in the queue? */
David Howells275bb412008-11-14 10:39:19 +11005322 rc = avc_has_perm(msec->sid, isec->sid, SECCLASS_MSGQ,
5323 MSGQ__ENQUEUE, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005324
5325 return rc;
5326}
5327
5328static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
5329 struct task_struct *target,
5330 long type, int mode)
5331{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005332 struct ipc_security_struct *isec;
5333 struct msg_security_struct *msec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005334 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005335 u32 sid = task_sid(target);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005336 int rc;
5337
Linus Torvalds1da177e2005-04-16 15:20:36 -07005338 isec = msq->q_perm.security;
5339 msec = msg->security;
5340
Eric Paris50c205f2012-04-04 15:01:43 -04005341 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04005342 ad.u.ipc_id = msq->q_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005343
David Howells275bb412008-11-14 10:39:19 +11005344 rc = avc_has_perm(sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005345 SECCLASS_MSGQ, MSGQ__READ, &ad);
5346 if (!rc)
David Howells275bb412008-11-14 10:39:19 +11005347 rc = avc_has_perm(sid, msec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005348 SECCLASS_MSG, MSG__RECEIVE, &ad);
5349 return rc;
5350}
5351
5352/* Shared Memory security operations */
5353static int selinux_shm_alloc_security(struct shmid_kernel *shp)
5354{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005355 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005356 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005357 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005358 int rc;
5359
5360 rc = ipc_alloc_security(current, &shp->shm_perm, SECCLASS_SHM);
5361 if (rc)
5362 return rc;
5363
Linus Torvalds1da177e2005-04-16 15:20:36 -07005364 isec = shp->shm_perm.security;
5365
Eric Paris50c205f2012-04-04 15:01:43 -04005366 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04005367 ad.u.ipc_id = shp->shm_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005368
David Howells275bb412008-11-14 10:39:19 +11005369 rc = avc_has_perm(sid, isec->sid, SECCLASS_SHM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005370 SHM__CREATE, &ad);
5371 if (rc) {
5372 ipc_free_security(&shp->shm_perm);
5373 return rc;
5374 }
5375 return 0;
5376}
5377
5378static void selinux_shm_free_security(struct shmid_kernel *shp)
5379{
5380 ipc_free_security(&shp->shm_perm);
5381}
5382
5383static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg)
5384{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005385 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005386 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005387 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005388
Linus Torvalds1da177e2005-04-16 15:20:36 -07005389 isec = shp->shm_perm.security;
5390
Eric Paris50c205f2012-04-04 15:01:43 -04005391 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005392 ad.u.ipc_id = shp->shm_perm.key;
5393
David Howells275bb412008-11-14 10:39:19 +11005394 return avc_has_perm(sid, isec->sid, SECCLASS_SHM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005395 SHM__ASSOCIATE, &ad);
5396}
5397
5398/* Note, at this point, shp is locked down */
5399static int selinux_shm_shmctl(struct shmid_kernel *shp, int cmd)
5400{
5401 int perms;
5402 int err;
5403
Eric Paris828dfe12008-04-17 13:17:49 -04005404 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005405 case IPC_INFO:
5406 case SHM_INFO:
5407 /* No specific object, just general system-wide information. */
5408 return task_has_system(current, SYSTEM__IPC_INFO);
5409 case IPC_STAT:
5410 case SHM_STAT:
5411 perms = SHM__GETATTR | SHM__ASSOCIATE;
5412 break;
5413 case IPC_SET:
5414 perms = SHM__SETATTR;
5415 break;
5416 case SHM_LOCK:
5417 case SHM_UNLOCK:
5418 perms = SHM__LOCK;
5419 break;
5420 case IPC_RMID:
5421 perms = SHM__DESTROY;
5422 break;
5423 default:
5424 return 0;
5425 }
5426
Stephen Smalley6af963f2005-05-01 08:58:39 -07005427 err = ipc_has_perm(&shp->shm_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005428 return err;
5429}
5430
5431static int selinux_shm_shmat(struct shmid_kernel *shp,
5432 char __user *shmaddr, int shmflg)
5433{
5434 u32 perms;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005435
5436 if (shmflg & SHM_RDONLY)
5437 perms = SHM__READ;
5438 else
5439 perms = SHM__READ | SHM__WRITE;
5440
Stephen Smalley6af963f2005-05-01 08:58:39 -07005441 return ipc_has_perm(&shp->shm_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005442}
5443
5444/* Semaphore security operations */
5445static int selinux_sem_alloc_security(struct sem_array *sma)
5446{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005447 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005448 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005449 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005450 int rc;
5451
5452 rc = ipc_alloc_security(current, &sma->sem_perm, SECCLASS_SEM);
5453 if (rc)
5454 return rc;
5455
Linus Torvalds1da177e2005-04-16 15:20:36 -07005456 isec = sma->sem_perm.security;
5457
Eric Paris50c205f2012-04-04 15:01:43 -04005458 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04005459 ad.u.ipc_id = sma->sem_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005460
David Howells275bb412008-11-14 10:39:19 +11005461 rc = avc_has_perm(sid, isec->sid, SECCLASS_SEM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005462 SEM__CREATE, &ad);
5463 if (rc) {
5464 ipc_free_security(&sma->sem_perm);
5465 return rc;
5466 }
5467 return 0;
5468}
5469
5470static void selinux_sem_free_security(struct sem_array *sma)
5471{
5472 ipc_free_security(&sma->sem_perm);
5473}
5474
5475static int selinux_sem_associate(struct sem_array *sma, int semflg)
5476{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005477 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005478 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005479 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005480
Linus Torvalds1da177e2005-04-16 15:20:36 -07005481 isec = sma->sem_perm.security;
5482
Eric Paris50c205f2012-04-04 15:01:43 -04005483 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005484 ad.u.ipc_id = sma->sem_perm.key;
5485
David Howells275bb412008-11-14 10:39:19 +11005486 return avc_has_perm(sid, isec->sid, SECCLASS_SEM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005487 SEM__ASSOCIATE, &ad);
5488}
5489
5490/* Note, at this point, sma is locked down */
5491static int selinux_sem_semctl(struct sem_array *sma, int cmd)
5492{
5493 int err;
5494 u32 perms;
5495
Eric Paris828dfe12008-04-17 13:17:49 -04005496 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005497 case IPC_INFO:
5498 case SEM_INFO:
5499 /* No specific object, just general system-wide information. */
5500 return task_has_system(current, SYSTEM__IPC_INFO);
5501 case GETPID:
5502 case GETNCNT:
5503 case GETZCNT:
5504 perms = SEM__GETATTR;
5505 break;
5506 case GETVAL:
5507 case GETALL:
5508 perms = SEM__READ;
5509 break;
5510 case SETVAL:
5511 case SETALL:
5512 perms = SEM__WRITE;
5513 break;
5514 case IPC_RMID:
5515 perms = SEM__DESTROY;
5516 break;
5517 case IPC_SET:
5518 perms = SEM__SETATTR;
5519 break;
5520 case IPC_STAT:
5521 case SEM_STAT:
5522 perms = SEM__GETATTR | SEM__ASSOCIATE;
5523 break;
5524 default:
5525 return 0;
5526 }
5527
Stephen Smalley6af963f2005-05-01 08:58:39 -07005528 err = ipc_has_perm(&sma->sem_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005529 return err;
5530}
5531
5532static int selinux_sem_semop(struct sem_array *sma,
5533 struct sembuf *sops, unsigned nsops, int alter)
5534{
5535 u32 perms;
5536
5537 if (alter)
5538 perms = SEM__READ | SEM__WRITE;
5539 else
5540 perms = SEM__READ;
5541
Stephen Smalley6af963f2005-05-01 08:58:39 -07005542 return ipc_has_perm(&sma->sem_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005543}
5544
5545static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
5546{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005547 u32 av = 0;
5548
Linus Torvalds1da177e2005-04-16 15:20:36 -07005549 av = 0;
5550 if (flag & S_IRUGO)
5551 av |= IPC__UNIX_READ;
5552 if (flag & S_IWUGO)
5553 av |= IPC__UNIX_WRITE;
5554
5555 if (av == 0)
5556 return 0;
5557
Stephen Smalley6af963f2005-05-01 08:58:39 -07005558 return ipc_has_perm(ipcp, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005559}
5560
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02005561static void selinux_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
5562{
5563 struct ipc_security_struct *isec = ipcp->security;
5564 *secid = isec->sid;
5565}
5566
Eric Paris828dfe12008-04-17 13:17:49 -04005567static void selinux_d_instantiate(struct dentry *dentry, struct inode *inode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005568{
5569 if (inode)
5570 inode_doinit_with_dentry(inode, dentry);
5571}
5572
5573static int selinux_getprocattr(struct task_struct *p,
Al Viro04ff9702007-03-12 16:17:58 +00005574 char *name, char **value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005575{
David Howells275bb412008-11-14 10:39:19 +11005576 const struct task_security_struct *__tsec;
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00005577 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005578 int error;
Al Viro04ff9702007-03-12 16:17:58 +00005579 unsigned len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005580
5581 if (current != p) {
David Howells3b11a1d2008-11-14 10:39:26 +11005582 error = current_has_perm(p, PROCESS__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005583 if (error)
5584 return error;
5585 }
5586
David Howells275bb412008-11-14 10:39:19 +11005587 rcu_read_lock();
5588 __tsec = __task_cred(p)->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005589
5590 if (!strcmp(name, "current"))
David Howells275bb412008-11-14 10:39:19 +11005591 sid = __tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005592 else if (!strcmp(name, "prev"))
David Howells275bb412008-11-14 10:39:19 +11005593 sid = __tsec->osid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005594 else if (!strcmp(name, "exec"))
David Howells275bb412008-11-14 10:39:19 +11005595 sid = __tsec->exec_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005596 else if (!strcmp(name, "fscreate"))
David Howells275bb412008-11-14 10:39:19 +11005597 sid = __tsec->create_sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005598 else if (!strcmp(name, "keycreate"))
David Howells275bb412008-11-14 10:39:19 +11005599 sid = __tsec->keycreate_sid;
Eric Paris42c3e032006-06-26 00:26:03 -07005600 else if (!strcmp(name, "sockcreate"))
David Howells275bb412008-11-14 10:39:19 +11005601 sid = __tsec->sockcreate_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005602 else
David Howells275bb412008-11-14 10:39:19 +11005603 goto invalid;
5604 rcu_read_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005605
5606 if (!sid)
5607 return 0;
5608
Al Viro04ff9702007-03-12 16:17:58 +00005609 error = security_sid_to_context(sid, value, &len);
5610 if (error)
5611 return error;
5612 return len;
David Howells275bb412008-11-14 10:39:19 +11005613
5614invalid:
5615 rcu_read_unlock();
5616 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005617}
5618
5619static int selinux_setprocattr(struct task_struct *p,
5620 char *name, void *value, size_t size)
5621{
5622 struct task_security_struct *tsec;
Roland McGrath03563572008-03-26 15:46:39 -07005623 struct task_struct *tracer;
David Howellsd84f4f92008-11-14 10:39:23 +11005624 struct cred *new;
5625 u32 sid = 0, ptsid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005626 int error;
5627 char *str = value;
5628
5629 if (current != p) {
5630 /* SELinux only allows a process to change its own
5631 security attributes. */
5632 return -EACCES;
5633 }
5634
5635 /*
5636 * Basic control over ability to set these attributes at all.
5637 * current == p, but we'll pass them separately in case the
5638 * above restriction is ever removed.
5639 */
5640 if (!strcmp(name, "exec"))
David Howells3b11a1d2008-11-14 10:39:26 +11005641 error = current_has_perm(p, PROCESS__SETEXEC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005642 else if (!strcmp(name, "fscreate"))
David Howells3b11a1d2008-11-14 10:39:26 +11005643 error = current_has_perm(p, PROCESS__SETFSCREATE);
Michael LeMay4eb582c2006-06-26 00:24:57 -07005644 else if (!strcmp(name, "keycreate"))
David Howells3b11a1d2008-11-14 10:39:26 +11005645 error = current_has_perm(p, PROCESS__SETKEYCREATE);
Eric Paris42c3e032006-06-26 00:26:03 -07005646 else if (!strcmp(name, "sockcreate"))
David Howells3b11a1d2008-11-14 10:39:26 +11005647 error = current_has_perm(p, PROCESS__SETSOCKCREATE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005648 else if (!strcmp(name, "current"))
David Howells3b11a1d2008-11-14 10:39:26 +11005649 error = current_has_perm(p, PROCESS__SETCURRENT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005650 else
5651 error = -EINVAL;
5652 if (error)
5653 return error;
5654
5655 /* Obtain a SID for the context, if one was specified. */
5656 if (size && str[1] && str[1] != '\n') {
5657 if (str[size-1] == '\n') {
5658 str[size-1] = 0;
5659 size--;
5660 }
Nikolay Aleksandrov52a4c642014-03-07 12:44:19 +01005661 error = security_context_to_sid(value, size, &sid, GFP_KERNEL);
Stephen Smalley12b29f32008-05-07 13:03:20 -04005662 if (error == -EINVAL && !strcmp(name, "fscreate")) {
Eric Parisd6ea83e2012-04-04 13:45:49 -04005663 if (!capable(CAP_MAC_ADMIN)) {
5664 struct audit_buffer *ab;
5665 size_t audit_size;
5666
5667 /* We strip a nul only if it is at the end, otherwise the
5668 * context contains a nul and we should audit that */
5669 if (str[size - 1] == '\0')
5670 audit_size = size - 1;
5671 else
5672 audit_size = size;
5673 ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR);
5674 audit_log_format(ab, "op=fscreate invalid_context=");
5675 audit_log_n_untrustedstring(ab, value, audit_size);
5676 audit_log_end(ab);
5677
Stephen Smalley12b29f32008-05-07 13:03:20 -04005678 return error;
Eric Parisd6ea83e2012-04-04 13:45:49 -04005679 }
Stephen Smalley12b29f32008-05-07 13:03:20 -04005680 error = security_context_to_sid_force(value, size,
5681 &sid);
5682 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005683 if (error)
5684 return error;
5685 }
5686
David Howellsd84f4f92008-11-14 10:39:23 +11005687 new = prepare_creds();
5688 if (!new)
5689 return -ENOMEM;
5690
Linus Torvalds1da177e2005-04-16 15:20:36 -07005691 /* Permission checking based on the specified context is
5692 performed during the actual operation (execve,
5693 open/mkdir/...), when we know the full context of the
David Howellsd84f4f92008-11-14 10:39:23 +11005694 operation. See selinux_bprm_set_creds for the execve
Linus Torvalds1da177e2005-04-16 15:20:36 -07005695 checks and may_create for the file creation checks. The
5696 operation will then fail if the context is not permitted. */
David Howellsd84f4f92008-11-14 10:39:23 +11005697 tsec = new->security;
5698 if (!strcmp(name, "exec")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005699 tsec->exec_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005700 } else if (!strcmp(name, "fscreate")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005701 tsec->create_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005702 } else if (!strcmp(name, "keycreate")) {
Michael LeMay4eb582c2006-06-26 00:24:57 -07005703 error = may_create_key(sid, p);
5704 if (error)
David Howellsd84f4f92008-11-14 10:39:23 +11005705 goto abort_change;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005706 tsec->keycreate_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005707 } else if (!strcmp(name, "sockcreate")) {
Eric Paris42c3e032006-06-26 00:26:03 -07005708 tsec->sockcreate_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005709 } else if (!strcmp(name, "current")) {
5710 error = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005711 if (sid == 0)
David Howellsd84f4f92008-11-14 10:39:23 +11005712 goto abort_change;
KaiGai Koheid9250de2008-08-28 16:35:57 +09005713
David Howellsd84f4f92008-11-14 10:39:23 +11005714 /* Only allow single threaded processes to change context */
5715 error = -EPERM;
Oleg Nesterov5bb459b2009-07-10 03:48:23 +02005716 if (!current_is_single_threaded()) {
David Howellsd84f4f92008-11-14 10:39:23 +11005717 error = security_bounded_transition(tsec->sid, sid);
5718 if (error)
5719 goto abort_change;
Eric Paris828dfe12008-04-17 13:17:49 -04005720 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005721
5722 /* Check permissions for the transition. */
5723 error = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS,
Eric Paris828dfe12008-04-17 13:17:49 -04005724 PROCESS__DYNTRANSITION, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005725 if (error)
David Howellsd84f4f92008-11-14 10:39:23 +11005726 goto abort_change;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005727
5728 /* Check for ptracing, and update the task SID if ok.
5729 Otherwise, leave SID unchanged and fail. */
David Howellsd84f4f92008-11-14 10:39:23 +11005730 ptsid = 0;
Oleg Nesterovc0c14392013-12-23 17:45:01 -05005731 rcu_read_lock();
Tejun Heo06d98472011-06-17 16:50:40 +02005732 tracer = ptrace_parent(p);
David Howellsd84f4f92008-11-14 10:39:23 +11005733 if (tracer)
5734 ptsid = task_sid(tracer);
Oleg Nesterovc0c14392013-12-23 17:45:01 -05005735 rcu_read_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005736
David Howellsd84f4f92008-11-14 10:39:23 +11005737 if (tracer) {
5738 error = avc_has_perm(ptsid, sid, SECCLASS_PROCESS,
5739 PROCESS__PTRACE, NULL);
5740 if (error)
5741 goto abort_change;
5742 }
5743
5744 tsec->sid = sid;
5745 } else {
5746 error = -EINVAL;
5747 goto abort_change;
5748 }
5749
5750 commit_creds(new);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005751 return size;
David Howellsd84f4f92008-11-14 10:39:23 +11005752
5753abort_change:
5754 abort_creds(new);
5755 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005756}
5757
David Quigley746df9b2013-05-22 12:50:35 -04005758static int selinux_ismaclabel(const char *name)
5759{
5760 return (strcmp(name, XATTR_SELINUX_SUFFIX) == 0);
5761}
5762
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005763static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
5764{
5765 return security_sid_to_context(secid, secdata, seclen);
5766}
5767
David Howells7bf570d2008-04-29 20:52:51 +01005768static int selinux_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
David Howells63cb3442008-01-15 23:47:35 +00005769{
Nikolay Aleksandrov52a4c642014-03-07 12:44:19 +01005770 return security_context_to_sid(secdata, seclen, secid, GFP_KERNEL);
David Howells63cb3442008-01-15 23:47:35 +00005771}
5772
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005773static void selinux_release_secctx(char *secdata, u32 seclen)
5774{
Paul Moore088999e2007-08-01 11:12:58 -04005775 kfree(secdata);
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005776}
5777
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05005778static void selinux_inode_invalidate_secctx(struct inode *inode)
5779{
5780 struct inode_security_struct *isec = inode->i_security;
5781
5782 mutex_lock(&isec->lock);
5783 isec->initialized = LABEL_INVALID;
5784 mutex_unlock(&isec->lock);
5785}
5786
David P. Quigley1ee65e32009-09-03 14:25:57 -04005787/*
5788 * called with inode->i_mutex locked
5789 */
5790static int selinux_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen)
5791{
5792 return selinux_inode_setsecurity(inode, XATTR_SELINUX_SUFFIX, ctx, ctxlen, 0);
5793}
5794
5795/*
5796 * called with inode->i_mutex locked
5797 */
5798static int selinux_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen)
5799{
5800 return __vfs_setxattr_noperm(dentry, XATTR_NAME_SELINUX, ctx, ctxlen, 0);
5801}
5802
5803static int selinux_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen)
5804{
5805 int len = 0;
5806 len = selinux_inode_getsecurity(inode, XATTR_SELINUX_SUFFIX,
5807 ctx, true);
5808 if (len < 0)
5809 return len;
5810 *ctxlen = len;
5811 return 0;
5812}
Michael LeMayd7200242006-06-22 14:47:17 -07005813#ifdef CONFIG_KEYS
5814
David Howellsd84f4f92008-11-14 10:39:23 +11005815static int selinux_key_alloc(struct key *k, const struct cred *cred,
David Howells7e047ef2006-06-26 00:24:50 -07005816 unsigned long flags)
Michael LeMayd7200242006-06-22 14:47:17 -07005817{
David Howellsd84f4f92008-11-14 10:39:23 +11005818 const struct task_security_struct *tsec;
Michael LeMayd7200242006-06-22 14:47:17 -07005819 struct key_security_struct *ksec;
5820
5821 ksec = kzalloc(sizeof(struct key_security_struct), GFP_KERNEL);
5822 if (!ksec)
5823 return -ENOMEM;
5824
David Howellsd84f4f92008-11-14 10:39:23 +11005825 tsec = cred->security;
5826 if (tsec->keycreate_sid)
5827 ksec->sid = tsec->keycreate_sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005828 else
David Howellsd84f4f92008-11-14 10:39:23 +11005829 ksec->sid = tsec->sid;
Michael LeMayd7200242006-06-22 14:47:17 -07005830
David Howells275bb412008-11-14 10:39:19 +11005831 k->security = ksec;
Michael LeMayd7200242006-06-22 14:47:17 -07005832 return 0;
5833}
5834
5835static void selinux_key_free(struct key *k)
5836{
5837 struct key_security_struct *ksec = k->security;
5838
5839 k->security = NULL;
5840 kfree(ksec);
5841}
5842
5843static int selinux_key_permission(key_ref_t key_ref,
David Howellsd84f4f92008-11-14 10:39:23 +11005844 const struct cred *cred,
David Howellsf5895942014-03-14 17:44:49 +00005845 unsigned perm)
Michael LeMayd7200242006-06-22 14:47:17 -07005846{
5847 struct key *key;
Michael LeMayd7200242006-06-22 14:47:17 -07005848 struct key_security_struct *ksec;
David Howells275bb412008-11-14 10:39:19 +11005849 u32 sid;
Michael LeMayd7200242006-06-22 14:47:17 -07005850
5851 /* if no specific permissions are requested, we skip the
5852 permission check. No serious, additional covert channels
5853 appear to be created. */
5854 if (perm == 0)
5855 return 0;
5856
David Howellsd84f4f92008-11-14 10:39:23 +11005857 sid = cred_sid(cred);
David Howells275bb412008-11-14 10:39:19 +11005858
5859 key = key_ref_to_ptr(key_ref);
5860 ksec = key->security;
5861
5862 return avc_has_perm(sid, ksec->sid, SECCLASS_KEY, perm, NULL);
Michael LeMayd7200242006-06-22 14:47:17 -07005863}
5864
David Howells70a5bb72008-04-29 01:01:26 -07005865static int selinux_key_getsecurity(struct key *key, char **_buffer)
5866{
5867 struct key_security_struct *ksec = key->security;
5868 char *context = NULL;
5869 unsigned len;
5870 int rc;
5871
5872 rc = security_sid_to_context(ksec->sid, &context, &len);
5873 if (!rc)
5874 rc = len;
5875 *_buffer = context;
5876 return rc;
5877}
5878
Michael LeMayd7200242006-06-22 14:47:17 -07005879#endif
5880
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07005881static struct security_hook_list selinux_hooks[] = {
Casey Schauflere20b0432015-05-02 15:11:36 -07005882 LSM_HOOK_INIT(binder_set_context_mgr, selinux_binder_set_context_mgr),
5883 LSM_HOOK_INIT(binder_transaction, selinux_binder_transaction),
5884 LSM_HOOK_INIT(binder_transfer_binder, selinux_binder_transfer_binder),
5885 LSM_HOOK_INIT(binder_transfer_file, selinux_binder_transfer_file),
Ahmed S. Darwish076c54c2008-03-06 18:09:10 +02005886
Casey Schauflere20b0432015-05-02 15:11:36 -07005887 LSM_HOOK_INIT(ptrace_access_check, selinux_ptrace_access_check),
5888 LSM_HOOK_INIT(ptrace_traceme, selinux_ptrace_traceme),
5889 LSM_HOOK_INIT(capget, selinux_capget),
5890 LSM_HOOK_INIT(capset, selinux_capset),
5891 LSM_HOOK_INIT(capable, selinux_capable),
5892 LSM_HOOK_INIT(quotactl, selinux_quotactl),
5893 LSM_HOOK_INIT(quota_on, selinux_quota_on),
5894 LSM_HOOK_INIT(syslog, selinux_syslog),
5895 LSM_HOOK_INIT(vm_enough_memory, selinux_vm_enough_memory),
Stephen Smalley79af7302015-01-21 10:54:10 -05005896
Casey Schauflere20b0432015-05-02 15:11:36 -07005897 LSM_HOOK_INIT(netlink_send, selinux_netlink_send),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005898
Casey Schauflere20b0432015-05-02 15:11:36 -07005899 LSM_HOOK_INIT(bprm_set_creds, selinux_bprm_set_creds),
5900 LSM_HOOK_INIT(bprm_committing_creds, selinux_bprm_committing_creds),
5901 LSM_HOOK_INIT(bprm_committed_creds, selinux_bprm_committed_creds),
5902 LSM_HOOK_INIT(bprm_secureexec, selinux_bprm_secureexec),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005903
Casey Schauflere20b0432015-05-02 15:11:36 -07005904 LSM_HOOK_INIT(sb_alloc_security, selinux_sb_alloc_security),
5905 LSM_HOOK_INIT(sb_free_security, selinux_sb_free_security),
5906 LSM_HOOK_INIT(sb_copy_data, selinux_sb_copy_data),
5907 LSM_HOOK_INIT(sb_remount, selinux_sb_remount),
5908 LSM_HOOK_INIT(sb_kern_mount, selinux_sb_kern_mount),
5909 LSM_HOOK_INIT(sb_show_options, selinux_sb_show_options),
5910 LSM_HOOK_INIT(sb_statfs, selinux_sb_statfs),
5911 LSM_HOOK_INIT(sb_mount, selinux_mount),
5912 LSM_HOOK_INIT(sb_umount, selinux_umount),
5913 LSM_HOOK_INIT(sb_set_mnt_opts, selinux_set_mnt_opts),
5914 LSM_HOOK_INIT(sb_clone_mnt_opts, selinux_sb_clone_mnt_opts),
5915 LSM_HOOK_INIT(sb_parse_opts_str, selinux_parse_opts_str),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005916
Casey Schauflere20b0432015-05-02 15:11:36 -07005917 LSM_HOOK_INIT(dentry_init_security, selinux_dentry_init_security),
Eric Parise0007522008-03-05 10:31:54 -05005918
Casey Schauflere20b0432015-05-02 15:11:36 -07005919 LSM_HOOK_INIT(inode_alloc_security, selinux_inode_alloc_security),
5920 LSM_HOOK_INIT(inode_free_security, selinux_inode_free_security),
5921 LSM_HOOK_INIT(inode_init_security, selinux_inode_init_security),
5922 LSM_HOOK_INIT(inode_create, selinux_inode_create),
5923 LSM_HOOK_INIT(inode_link, selinux_inode_link),
5924 LSM_HOOK_INIT(inode_unlink, selinux_inode_unlink),
5925 LSM_HOOK_INIT(inode_symlink, selinux_inode_symlink),
5926 LSM_HOOK_INIT(inode_mkdir, selinux_inode_mkdir),
5927 LSM_HOOK_INIT(inode_rmdir, selinux_inode_rmdir),
5928 LSM_HOOK_INIT(inode_mknod, selinux_inode_mknod),
5929 LSM_HOOK_INIT(inode_rename, selinux_inode_rename),
5930 LSM_HOOK_INIT(inode_readlink, selinux_inode_readlink),
5931 LSM_HOOK_INIT(inode_follow_link, selinux_inode_follow_link),
5932 LSM_HOOK_INIT(inode_permission, selinux_inode_permission),
5933 LSM_HOOK_INIT(inode_setattr, selinux_inode_setattr),
5934 LSM_HOOK_INIT(inode_getattr, selinux_inode_getattr),
5935 LSM_HOOK_INIT(inode_setxattr, selinux_inode_setxattr),
5936 LSM_HOOK_INIT(inode_post_setxattr, selinux_inode_post_setxattr),
5937 LSM_HOOK_INIT(inode_getxattr, selinux_inode_getxattr),
5938 LSM_HOOK_INIT(inode_listxattr, selinux_inode_listxattr),
5939 LSM_HOOK_INIT(inode_removexattr, selinux_inode_removexattr),
5940 LSM_HOOK_INIT(inode_getsecurity, selinux_inode_getsecurity),
5941 LSM_HOOK_INIT(inode_setsecurity, selinux_inode_setsecurity),
5942 LSM_HOOK_INIT(inode_listsecurity, selinux_inode_listsecurity),
5943 LSM_HOOK_INIT(inode_getsecid, selinux_inode_getsecid),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005944
Casey Schauflere20b0432015-05-02 15:11:36 -07005945 LSM_HOOK_INIT(file_permission, selinux_file_permission),
5946 LSM_HOOK_INIT(file_alloc_security, selinux_file_alloc_security),
5947 LSM_HOOK_INIT(file_free_security, selinux_file_free_security),
5948 LSM_HOOK_INIT(file_ioctl, selinux_file_ioctl),
5949 LSM_HOOK_INIT(mmap_file, selinux_mmap_file),
5950 LSM_HOOK_INIT(mmap_addr, selinux_mmap_addr),
5951 LSM_HOOK_INIT(file_mprotect, selinux_file_mprotect),
5952 LSM_HOOK_INIT(file_lock, selinux_file_lock),
5953 LSM_HOOK_INIT(file_fcntl, selinux_file_fcntl),
5954 LSM_HOOK_INIT(file_set_fowner, selinux_file_set_fowner),
5955 LSM_HOOK_INIT(file_send_sigiotask, selinux_file_send_sigiotask),
5956 LSM_HOOK_INIT(file_receive, selinux_file_receive),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005957
Casey Schauflere20b0432015-05-02 15:11:36 -07005958 LSM_HOOK_INIT(file_open, selinux_file_open),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005959
Casey Schauflere20b0432015-05-02 15:11:36 -07005960 LSM_HOOK_INIT(task_create, selinux_task_create),
5961 LSM_HOOK_INIT(cred_alloc_blank, selinux_cred_alloc_blank),
5962 LSM_HOOK_INIT(cred_free, selinux_cred_free),
5963 LSM_HOOK_INIT(cred_prepare, selinux_cred_prepare),
5964 LSM_HOOK_INIT(cred_transfer, selinux_cred_transfer),
5965 LSM_HOOK_INIT(kernel_act_as, selinux_kernel_act_as),
5966 LSM_HOOK_INIT(kernel_create_files_as, selinux_kernel_create_files_as),
5967 LSM_HOOK_INIT(kernel_module_request, selinux_kernel_module_request),
5968 LSM_HOOK_INIT(task_setpgid, selinux_task_setpgid),
5969 LSM_HOOK_INIT(task_getpgid, selinux_task_getpgid),
5970 LSM_HOOK_INIT(task_getsid, selinux_task_getsid),
5971 LSM_HOOK_INIT(task_getsecid, selinux_task_getsecid),
5972 LSM_HOOK_INIT(task_setnice, selinux_task_setnice),
5973 LSM_HOOK_INIT(task_setioprio, selinux_task_setioprio),
5974 LSM_HOOK_INIT(task_getioprio, selinux_task_getioprio),
5975 LSM_HOOK_INIT(task_setrlimit, selinux_task_setrlimit),
5976 LSM_HOOK_INIT(task_setscheduler, selinux_task_setscheduler),
5977 LSM_HOOK_INIT(task_getscheduler, selinux_task_getscheduler),
5978 LSM_HOOK_INIT(task_movememory, selinux_task_movememory),
5979 LSM_HOOK_INIT(task_kill, selinux_task_kill),
5980 LSM_HOOK_INIT(task_wait, selinux_task_wait),
5981 LSM_HOOK_INIT(task_to_inode, selinux_task_to_inode),
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09005982
Casey Schauflere20b0432015-05-02 15:11:36 -07005983 LSM_HOOK_INIT(ipc_permission, selinux_ipc_permission),
5984 LSM_HOOK_INIT(ipc_getsecid, selinux_ipc_getsecid),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005985
Casey Schauflere20b0432015-05-02 15:11:36 -07005986 LSM_HOOK_INIT(msg_msg_alloc_security, selinux_msg_msg_alloc_security),
5987 LSM_HOOK_INIT(msg_msg_free_security, selinux_msg_msg_free_security),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005988
Casey Schauflere20b0432015-05-02 15:11:36 -07005989 LSM_HOOK_INIT(msg_queue_alloc_security,
5990 selinux_msg_queue_alloc_security),
5991 LSM_HOOK_INIT(msg_queue_free_security, selinux_msg_queue_free_security),
5992 LSM_HOOK_INIT(msg_queue_associate, selinux_msg_queue_associate),
5993 LSM_HOOK_INIT(msg_queue_msgctl, selinux_msg_queue_msgctl),
5994 LSM_HOOK_INIT(msg_queue_msgsnd, selinux_msg_queue_msgsnd),
5995 LSM_HOOK_INIT(msg_queue_msgrcv, selinux_msg_queue_msgrcv),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005996
Casey Schauflere20b0432015-05-02 15:11:36 -07005997 LSM_HOOK_INIT(shm_alloc_security, selinux_shm_alloc_security),
5998 LSM_HOOK_INIT(shm_free_security, selinux_shm_free_security),
5999 LSM_HOOK_INIT(shm_associate, selinux_shm_associate),
6000 LSM_HOOK_INIT(shm_shmctl, selinux_shm_shmctl),
6001 LSM_HOOK_INIT(shm_shmat, selinux_shm_shmat),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006002
Casey Schauflere20b0432015-05-02 15:11:36 -07006003 LSM_HOOK_INIT(sem_alloc_security, selinux_sem_alloc_security),
6004 LSM_HOOK_INIT(sem_free_security, selinux_sem_free_security),
6005 LSM_HOOK_INIT(sem_associate, selinux_sem_associate),
6006 LSM_HOOK_INIT(sem_semctl, selinux_sem_semctl),
6007 LSM_HOOK_INIT(sem_semop, selinux_sem_semop),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006008
Casey Schauflere20b0432015-05-02 15:11:36 -07006009 LSM_HOOK_INIT(d_instantiate, selinux_d_instantiate),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006010
Casey Schauflere20b0432015-05-02 15:11:36 -07006011 LSM_HOOK_INIT(getprocattr, selinux_getprocattr),
6012 LSM_HOOK_INIT(setprocattr, selinux_setprocattr),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006013
Casey Schauflere20b0432015-05-02 15:11:36 -07006014 LSM_HOOK_INIT(ismaclabel, selinux_ismaclabel),
6015 LSM_HOOK_INIT(secid_to_secctx, selinux_secid_to_secctx),
6016 LSM_HOOK_INIT(secctx_to_secid, selinux_secctx_to_secid),
6017 LSM_HOOK_INIT(release_secctx, selinux_release_secctx),
Andreas Gruenbacher6f3be9f2015-12-24 11:09:40 -05006018 LSM_HOOK_INIT(inode_invalidate_secctx, selinux_inode_invalidate_secctx),
Casey Schauflere20b0432015-05-02 15:11:36 -07006019 LSM_HOOK_INIT(inode_notifysecctx, selinux_inode_notifysecctx),
6020 LSM_HOOK_INIT(inode_setsecctx, selinux_inode_setsecctx),
6021 LSM_HOOK_INIT(inode_getsecctx, selinux_inode_getsecctx),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006022
Casey Schauflere20b0432015-05-02 15:11:36 -07006023 LSM_HOOK_INIT(unix_stream_connect, selinux_socket_unix_stream_connect),
6024 LSM_HOOK_INIT(unix_may_send, selinux_socket_unix_may_send),
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07006025
Casey Schauflere20b0432015-05-02 15:11:36 -07006026 LSM_HOOK_INIT(socket_create, selinux_socket_create),
6027 LSM_HOOK_INIT(socket_post_create, selinux_socket_post_create),
6028 LSM_HOOK_INIT(socket_bind, selinux_socket_bind),
6029 LSM_HOOK_INIT(socket_connect, selinux_socket_connect),
6030 LSM_HOOK_INIT(socket_listen, selinux_socket_listen),
6031 LSM_HOOK_INIT(socket_accept, selinux_socket_accept),
6032 LSM_HOOK_INIT(socket_sendmsg, selinux_socket_sendmsg),
6033 LSM_HOOK_INIT(socket_recvmsg, selinux_socket_recvmsg),
6034 LSM_HOOK_INIT(socket_getsockname, selinux_socket_getsockname),
6035 LSM_HOOK_INIT(socket_getpeername, selinux_socket_getpeername),
6036 LSM_HOOK_INIT(socket_getsockopt, selinux_socket_getsockopt),
6037 LSM_HOOK_INIT(socket_setsockopt, selinux_socket_setsockopt),
6038 LSM_HOOK_INIT(socket_shutdown, selinux_socket_shutdown),
6039 LSM_HOOK_INIT(socket_sock_rcv_skb, selinux_socket_sock_rcv_skb),
6040 LSM_HOOK_INIT(socket_getpeersec_stream,
6041 selinux_socket_getpeersec_stream),
6042 LSM_HOOK_INIT(socket_getpeersec_dgram, selinux_socket_getpeersec_dgram),
6043 LSM_HOOK_INIT(sk_alloc_security, selinux_sk_alloc_security),
6044 LSM_HOOK_INIT(sk_free_security, selinux_sk_free_security),
6045 LSM_HOOK_INIT(sk_clone_security, selinux_sk_clone_security),
6046 LSM_HOOK_INIT(sk_getsecid, selinux_sk_getsecid),
6047 LSM_HOOK_INIT(sock_graft, selinux_sock_graft),
6048 LSM_HOOK_INIT(inet_conn_request, selinux_inet_conn_request),
6049 LSM_HOOK_INIT(inet_csk_clone, selinux_inet_csk_clone),
6050 LSM_HOOK_INIT(inet_conn_established, selinux_inet_conn_established),
6051 LSM_HOOK_INIT(secmark_relabel_packet, selinux_secmark_relabel_packet),
6052 LSM_HOOK_INIT(secmark_refcount_inc, selinux_secmark_refcount_inc),
6053 LSM_HOOK_INIT(secmark_refcount_dec, selinux_secmark_refcount_dec),
6054 LSM_HOOK_INIT(req_classify_flow, selinux_req_classify_flow),
6055 LSM_HOOK_INIT(tun_dev_alloc_security, selinux_tun_dev_alloc_security),
6056 LSM_HOOK_INIT(tun_dev_free_security, selinux_tun_dev_free_security),
6057 LSM_HOOK_INIT(tun_dev_create, selinux_tun_dev_create),
6058 LSM_HOOK_INIT(tun_dev_attach_queue, selinux_tun_dev_attach_queue),
6059 LSM_HOOK_INIT(tun_dev_attach, selinux_tun_dev_attach),
6060 LSM_HOOK_INIT(tun_dev_open, selinux_tun_dev_open),
Trent Jaegerd28d1e02005-12-13 23:12:40 -08006061
6062#ifdef CONFIG_SECURITY_NETWORK_XFRM
Casey Schauflere20b0432015-05-02 15:11:36 -07006063 LSM_HOOK_INIT(xfrm_policy_alloc_security, selinux_xfrm_policy_alloc),
6064 LSM_HOOK_INIT(xfrm_policy_clone_security, selinux_xfrm_policy_clone),
6065 LSM_HOOK_INIT(xfrm_policy_free_security, selinux_xfrm_policy_free),
6066 LSM_HOOK_INIT(xfrm_policy_delete_security, selinux_xfrm_policy_delete),
6067 LSM_HOOK_INIT(xfrm_state_alloc, selinux_xfrm_state_alloc),
6068 LSM_HOOK_INIT(xfrm_state_alloc_acquire,
6069 selinux_xfrm_state_alloc_acquire),
6070 LSM_HOOK_INIT(xfrm_state_free_security, selinux_xfrm_state_free),
6071 LSM_HOOK_INIT(xfrm_state_delete_security, selinux_xfrm_state_delete),
6072 LSM_HOOK_INIT(xfrm_policy_lookup, selinux_xfrm_policy_lookup),
6073 LSM_HOOK_INIT(xfrm_state_pol_flow_match,
6074 selinux_xfrm_state_pol_flow_match),
6075 LSM_HOOK_INIT(xfrm_decode_session, selinux_xfrm_decode_session),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006076#endif
Michael LeMayd7200242006-06-22 14:47:17 -07006077
6078#ifdef CONFIG_KEYS
Casey Schauflere20b0432015-05-02 15:11:36 -07006079 LSM_HOOK_INIT(key_alloc, selinux_key_alloc),
6080 LSM_HOOK_INIT(key_free, selinux_key_free),
6081 LSM_HOOK_INIT(key_permission, selinux_key_permission),
6082 LSM_HOOK_INIT(key_getsecurity, selinux_key_getsecurity),
Michael LeMayd7200242006-06-22 14:47:17 -07006083#endif
Ahmed S. Darwish9d57a7f2008-03-01 22:03:14 +02006084
6085#ifdef CONFIG_AUDIT
Casey Schauflere20b0432015-05-02 15:11:36 -07006086 LSM_HOOK_INIT(audit_rule_init, selinux_audit_rule_init),
6087 LSM_HOOK_INIT(audit_rule_known, selinux_audit_rule_known),
6088 LSM_HOOK_INIT(audit_rule_match, selinux_audit_rule_match),
6089 LSM_HOOK_INIT(audit_rule_free, selinux_audit_rule_free),
Ahmed S. Darwish9d57a7f2008-03-01 22:03:14 +02006090#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07006091};
6092
6093static __init int selinux_init(void)
6094{
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07006095 if (!security_module_enable("selinux")) {
Ahmed S. Darwish076c54c2008-03-06 18:09:10 +02006096 selinux_enabled = 0;
6097 return 0;
6098 }
6099
Linus Torvalds1da177e2005-04-16 15:20:36 -07006100 if (!selinux_enabled) {
6101 printk(KERN_INFO "SELinux: Disabled at boot.\n");
6102 return 0;
6103 }
6104
6105 printk(KERN_INFO "SELinux: Initializing.\n");
6106
6107 /* Set the security state for the initial task. */
David Howellsd84f4f92008-11-14 10:39:23 +11006108 cred_init_security();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006109
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04006110 default_noexec = !(VM_DATA_DEFAULT_FLAGS & VM_EXEC);
6111
James Morris7cae7e22006-03-22 00:09:22 -08006112 sel_inode_cache = kmem_cache_create("selinux_inode_security",
6113 sizeof(struct inode_security_struct),
Paul Mundt20c2df82007-07-20 10:11:58 +09006114 0, SLAB_PANIC, NULL);
Sangwoo63205652015-10-21 17:44:30 -04006115 file_security_cache = kmem_cache_create("selinux_file_security",
6116 sizeof(struct file_security_struct),
6117 0, SLAB_PANIC, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006118 avc_init();
6119
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07006120 security_add_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006121
Paul Moore615e51f2014-06-26 14:33:56 -04006122 if (avc_add_callback(selinux_netcache_avc_callback, AVC_CALLBACK_RESET))
6123 panic("SELinux: Unable to register AVC netcache callback\n");
6124
Eric Paris828dfe12008-04-17 13:17:49 -04006125 if (selinux_enforcing)
Eric Parisfadcdb42007-02-22 18:11:31 -05006126 printk(KERN_DEBUG "SELinux: Starting in enforcing mode\n");
Eric Paris828dfe12008-04-17 13:17:49 -04006127 else
Eric Parisfadcdb42007-02-22 18:11:31 -05006128 printk(KERN_DEBUG "SELinux: Starting in permissive mode\n");
Michael LeMayd7200242006-06-22 14:47:17 -07006129
Linus Torvalds1da177e2005-04-16 15:20:36 -07006130 return 0;
6131}
6132
Al Viroe8c26252010-03-23 06:36:54 -04006133static void delayed_superblock_init(struct super_block *sb, void *unused)
6134{
6135 superblock_doinit(sb, NULL);
6136}
6137
Linus Torvalds1da177e2005-04-16 15:20:36 -07006138void selinux_complete_init(void)
6139{
Eric Parisfadcdb42007-02-22 18:11:31 -05006140 printk(KERN_DEBUG "SELinux: Completing initialization.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07006141
6142 /* Set up any superblocks initialized prior to the policy load. */
Eric Parisfadcdb42007-02-22 18:11:31 -05006143 printk(KERN_DEBUG "SELinux: Setting up existing superblocks.\n");
Al Viroe8c26252010-03-23 06:36:54 -04006144 iterate_supers(delayed_superblock_init, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006145}
6146
6147/* SELinux requires early initialization in order to label
6148 all processes and objects when they are created. */
6149security_initcall(selinux_init);
6150
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08006151#if defined(CONFIG_NETFILTER)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006152
Jiri Pirko25db6be2014-09-03 17:42:13 +02006153static struct nf_hook_ops selinux_nf_ops[] = {
Paul Mooreeffad8d2008-01-29 08:49:27 -05006154 {
6155 .hook = selinux_ipv4_postroute,
Alban Crequy2597a832012-05-14 03:56:39 +00006156 .pf = NFPROTO_IPV4,
Paul Mooreeffad8d2008-01-29 08:49:27 -05006157 .hooknum = NF_INET_POST_ROUTING,
6158 .priority = NF_IP_PRI_SELINUX_LAST,
6159 },
6160 {
6161 .hook = selinux_ipv4_forward,
Alban Crequy2597a832012-05-14 03:56:39 +00006162 .pf = NFPROTO_IPV4,
Paul Mooreeffad8d2008-01-29 08:49:27 -05006163 .hooknum = NF_INET_FORWARD,
6164 .priority = NF_IP_PRI_SELINUX_FIRST,
Paul Moore948bf852008-10-10 10:16:32 -04006165 },
6166 {
6167 .hook = selinux_ipv4_output,
Alban Crequy2597a832012-05-14 03:56:39 +00006168 .pf = NFPROTO_IPV4,
Paul Moore948bf852008-10-10 10:16:32 -04006169 .hooknum = NF_INET_LOCAL_OUT,
6170 .priority = NF_IP_PRI_SELINUX_FIRST,
Jiri Pirko25db6be2014-09-03 17:42:13 +02006171 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07006172#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Paul Mooreeffad8d2008-01-29 08:49:27 -05006173 {
6174 .hook = selinux_ipv6_postroute,
Alban Crequy2597a832012-05-14 03:56:39 +00006175 .pf = NFPROTO_IPV6,
Paul Mooreeffad8d2008-01-29 08:49:27 -05006176 .hooknum = NF_INET_POST_ROUTING,
6177 .priority = NF_IP6_PRI_SELINUX_LAST,
6178 },
6179 {
6180 .hook = selinux_ipv6_forward,
Alban Crequy2597a832012-05-14 03:56:39 +00006181 .pf = NFPROTO_IPV6,
Paul Mooreeffad8d2008-01-29 08:49:27 -05006182 .hooknum = NF_INET_FORWARD,
6183 .priority = NF_IP6_PRI_SELINUX_FIRST,
Jiri Pirko25db6be2014-09-03 17:42:13 +02006184 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07006185#endif /* IPV6 */
Jiri Pirko25db6be2014-09-03 17:42:13 +02006186};
Linus Torvalds1da177e2005-04-16 15:20:36 -07006187
6188static int __init selinux_nf_ip_init(void)
6189{
Jiri Pirko25db6be2014-09-03 17:42:13 +02006190 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006191
6192 if (!selinux_enabled)
Jiri Pirko25db6be2014-09-03 17:42:13 +02006193 return 0;
Eric Parisfadcdb42007-02-22 18:11:31 -05006194
6195 printk(KERN_DEBUG "SELinux: Registering netfilter hooks\n");
6196
Jiri Pirko25db6be2014-09-03 17:42:13 +02006197 err = nf_register_hooks(selinux_nf_ops, ARRAY_SIZE(selinux_nf_ops));
Alexey Dobriyan6c5a9d22008-07-26 17:48:15 -07006198 if (err)
Jiri Pirko25db6be2014-09-03 17:42:13 +02006199 panic("SELinux: nf_register_hooks: error %d\n", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006200
Jiri Pirko25db6be2014-09-03 17:42:13 +02006201 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006202}
6203
6204__initcall(selinux_nf_ip_init);
6205
6206#ifdef CONFIG_SECURITY_SELINUX_DISABLE
6207static void selinux_nf_ip_exit(void)
6208{
Eric Parisfadcdb42007-02-22 18:11:31 -05006209 printk(KERN_DEBUG "SELinux: Unregistering netfilter hooks\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07006210
Jiri Pirko25db6be2014-09-03 17:42:13 +02006211 nf_unregister_hooks(selinux_nf_ops, ARRAY_SIZE(selinux_nf_ops));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006212}
6213#endif
6214
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08006215#else /* CONFIG_NETFILTER */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006216
6217#ifdef CONFIG_SECURITY_SELINUX_DISABLE
6218#define selinux_nf_ip_exit()
6219#endif
6220
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08006221#endif /* CONFIG_NETFILTER */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006222
6223#ifdef CONFIG_SECURITY_SELINUX_DISABLE
Eric Paris828dfe12008-04-17 13:17:49 -04006224static int selinux_disabled;
6225
Linus Torvalds1da177e2005-04-16 15:20:36 -07006226int selinux_disable(void)
6227{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006228 if (ss_initialized) {
6229 /* Not permitted after initial policy load. */
6230 return -EINVAL;
6231 }
6232
6233 if (selinux_disabled) {
6234 /* Only do this once. */
6235 return -EINVAL;
6236 }
6237
6238 printk(KERN_INFO "SELinux: Disabled at runtime.\n");
6239
6240 selinux_disabled = 1;
Stephen Smalley30d55282006-05-03 10:52:36 -04006241 selinux_enabled = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006242
Casey Schauflerb1d9e6b2015-05-02 15:11:42 -07006243 security_delete_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006244
Eric Parisaf8ff042009-09-20 21:23:01 -04006245 /* Try to destroy the avc node cache */
6246 avc_disable();
6247
Linus Torvalds1da177e2005-04-16 15:20:36 -07006248 /* Unregister netfilter hooks. */
6249 selinux_nf_ip_exit();
6250
6251 /* Unregister selinuxfs. */
6252 exit_sel_fs();
6253
6254 return 0;
6255}
6256#endif