blob: de2ffbdb9e5ad8c4cae5ae9c41461ad70f1a376c [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * NSA Security-Enhanced Linux (SELinux) security module
3 *
4 * This file contains the SELinux hook function implementations.
5 *
6 * Authors: Stephen Smalley, <sds@epoch.ncsc.mil>
Eric Paris828dfe12008-04-17 13:17:49 -04007 * Chris Vance, <cvance@nai.com>
8 * Wayne Salamon, <wsalamon@nai.com>
9 * James Morris <jmorris@redhat.com>
Linus Torvalds1da177e2005-04-16 15:20:36 -070010 *
11 * Copyright (C) 2001,2002 Networks Associates Technology, Inc.
Eric Paris2069f452008-07-04 09:47:13 +100012 * Copyright (C) 2003-2008 Red Hat, Inc., James Morris <jmorris@redhat.com>
13 * Eric Paris <eparis@redhat.com>
Linus Torvalds1da177e2005-04-16 15:20:36 -070014 * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
Eric Paris828dfe12008-04-17 13:17:49 -040015 * <dgoeddel@trustedcs.com>
Paul Mooreed6d76e2009-08-28 18:12:49 -040016 * Copyright (C) 2006, 2007, 2009 Hewlett-Packard Development Company, L.P.
Paul Moore82c21bf2011-08-01 11:10:33 +000017 * Paul Moore <paul@paul-moore.com>
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +090018 * Copyright (C) 2007 Hitachi Software Engineering Co., Ltd.
Eric Paris828dfe12008-04-17 13:17:49 -040019 * Yuichi Nakamura <ynakam@hitachisoft.jp>
Linus Torvalds1da177e2005-04-16 15:20:36 -070020 *
21 * This program is free software; you can redistribute it and/or modify
22 * it under the terms of the GNU General Public License version 2,
Eric Paris828dfe12008-04-17 13:17:49 -040023 * as published by the Free Software Foundation.
Linus Torvalds1da177e2005-04-16 15:20:36 -070024 */
25
Linus Torvalds1da177e2005-04-16 15:20:36 -070026#include <linux/init.h>
Eric Paris0b24dcb2011-02-25 15:39:20 -050027#include <linux/kd.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070028#include <linux/kernel.h>
Roland McGrath0d094ef2008-07-25 19:45:49 -070029#include <linux/tracehook.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070030#include <linux/errno.h>
31#include <linux/sched.h>
32#include <linux/security.h>
33#include <linux/xattr.h>
34#include <linux/capability.h>
35#include <linux/unistd.h>
36#include <linux/mm.h>
37#include <linux/mman.h>
38#include <linux/slab.h>
39#include <linux/pagemap.h>
Eric Paris0b24dcb2011-02-25 15:39:20 -050040#include <linux/proc_fs.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070041#include <linux/swap.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070042#include <linux/spinlock.h>
43#include <linux/syscalls.h>
Eric Paris2a7dba32011-02-01 11:05:39 -050044#include <linux/dcache.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070045#include <linux/file.h>
Al Viro9f3acc32008-04-24 07:44:08 -040046#include <linux/fdtable.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070047#include <linux/namei.h>
48#include <linux/mount.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070049#include <linux/netfilter_ipv4.h>
50#include <linux/netfilter_ipv6.h>
51#include <linux/tty.h>
52#include <net/icmp.h>
Stephen Hemminger227b60f2007-10-10 17:30:46 -070053#include <net/ip.h> /* for local_port_range[] */
Linus Torvalds1da177e2005-04-16 15:20:36 -070054#include <net/tcp.h> /* struct or_callable used in sock_rcv_skb */
Paul Moore3ac7b8d2013-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 Sharma60063492011-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 */
64#include <linux/netlink.h>
65#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>
Amir Samuelov6a22e462014-05-26 11:44:06 +030086#include <linux/pft.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070087
88#include "avc.h"
89#include "objsec.h"
90#include "netif.h"
Paul Moore224dfbd2008-01-29 08:38:13 -050091#include "netnode.h"
Paul Moore3e112172008-04-10 10:48:14 -040092#include "netport.h"
Trent Jaegerd28d1e02005-12-13 23:12:40 -080093#include "xfrm.h"
Paul Moorec60475b2007-02-28 15:14:23 -050094#include "netlabel.h"
Ahmed S. Darwish9d57a7f2008-03-01 22:03:14 +020095#include "audit.h"
James Morris7b98a582011-08-30 12:52:32 +100096#include "avc_ss.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070097
David P. Quigley11689d42009-01-16 09:22:03 -050098#define NUM_SEL_MNT_OPTS 5
Eric Parisc9180a52007-11-30 13:00:35 -050099
James Morris20510f22007-10-16 23:31:32 -0700100extern struct security_operations *security_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700101
Paul Moored621d352008-01-29 08:43:36 -0500102/* SECMARK reference count */
James Morris56a4ca92011-08-17 11:08:43 +1000103static atomic_t selinux_secmark_refcount = ATOMIC_INIT(0);
Paul Moored621d352008-01-29 08:43:36 -0500104
Linus Torvalds1da177e2005-04-16 15:20:36 -0700105#ifdef CONFIG_SECURITY_SELINUX_DEVELOP
Eric Paris828dfe12008-04-17 13:17:49 -0400106int selinux_enforcing;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700107
108static int __init enforcing_setup(char *str)
109{
Eric Parisf5269712008-05-14 11:27:45 -0400110 unsigned long enforcing;
111 if (!strict_strtoul(str, 0, &enforcing))
112 selinux_enforcing = enforcing ? 1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700113 return 1;
114}
115__setup("enforcing=", enforcing_setup);
116#endif
117
118#ifdef CONFIG_SECURITY_SELINUX_BOOTPARAM
119int selinux_enabled = CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE;
120
121static int __init selinux_enabled_setup(char *str)
122{
Eric Parisf5269712008-05-14 11:27:45 -0400123 unsigned long enabled;
124 if (!strict_strtoul(str, 0, &enabled))
125 selinux_enabled = enabled ? 1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126 return 1;
127}
128__setup("selinux=", selinux_enabled_setup);
Stephen Smalley30d55282006-05-03 10:52:36 -0400129#else
130int selinux_enabled = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700131#endif
132
Christoph Lametere18b8902006-12-06 20:33:20 -0800133static struct kmem_cache *sel_inode_cache;
James Morris7cae7e22006-03-22 00:09:22 -0800134
Paul Moored621d352008-01-29 08:43:36 -0500135/**
136 * selinux_secmark_enabled - Check to see if SECMARK is currently enabled
137 *
138 * Description:
139 * This function checks the SECMARK reference counter to see if any SECMARK
140 * targets are currently configured, if the reference counter is greater than
141 * zero SECMARK is considered to be enabled. Returns true (1) if SECMARK is
142 * enabled, false (0) if SECMARK is disabled.
143 *
144 */
145static int selinux_secmark_enabled(void)
146{
147 return (atomic_read(&selinux_secmark_refcount) > 0);
148}
149
David Howellsd84f4f92008-11-14 10:39:23 +1100150/*
151 * initialise the security for the init task
152 */
153static void cred_init_security(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700154{
David Howells3b11a1d2008-11-14 10:39:26 +1100155 struct cred *cred = (struct cred *) current->real_cred;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700156 struct task_security_struct *tsec;
157
James Morris89d155e2005-10-30 14:59:21 -0800158 tsec = kzalloc(sizeof(struct task_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700159 if (!tsec)
David Howellsd84f4f92008-11-14 10:39:23 +1100160 panic("SELinux: Failed to initialize initial task.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700161
David Howellsd84f4f92008-11-14 10:39:23 +1100162 tsec->osid = tsec->sid = SECINITSID_KERNEL;
David Howellsf1752ee2008-11-14 10:39:17 +1100163 cred->security = tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700164}
165
David Howells275bb412008-11-14 10:39:19 +1100166/*
David Howells88e67f32008-11-14 10:39:21 +1100167 * get the security ID of a set of credentials
168 */
169static inline u32 cred_sid(const struct cred *cred)
170{
171 const struct task_security_struct *tsec;
172
173 tsec = cred->security;
174 return tsec->sid;
175}
176
177/*
David Howells3b11a1d2008-11-14 10:39:26 +1100178 * get the objective security ID of a task
David Howells275bb412008-11-14 10:39:19 +1100179 */
180static inline u32 task_sid(const struct task_struct *task)
181{
David Howells275bb412008-11-14 10:39:19 +1100182 u32 sid;
183
184 rcu_read_lock();
David Howells88e67f32008-11-14 10:39:21 +1100185 sid = cred_sid(__task_cred(task));
David Howells275bb412008-11-14 10:39:19 +1100186 rcu_read_unlock();
187 return sid;
188}
189
190/*
David Howells3b11a1d2008-11-14 10:39:26 +1100191 * get the subjective security ID of the current task
David Howells275bb412008-11-14 10:39:19 +1100192 */
193static inline u32 current_sid(void)
194{
Paul Moore5fb49872010-04-22 14:46:19 -0400195 const struct task_security_struct *tsec = current_security();
David Howells275bb412008-11-14 10:39:19 +1100196
197 return tsec->sid;
198}
199
David Howells88e67f32008-11-14 10:39:21 +1100200/* Allocate and free functions for each kind of security blob. */
201
Linus Torvalds1da177e2005-04-16 15:20:36 -0700202static int inode_alloc_security(struct inode *inode)
203{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700204 struct inode_security_struct *isec;
David Howells275bb412008-11-14 10:39:19 +1100205 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700206
Josef Bacika02fe132008-04-04 09:35:05 +1100207 isec = kmem_cache_zalloc(sel_inode_cache, GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208 if (!isec)
209 return -ENOMEM;
210
Eric Paris23970742006-09-25 23:32:01 -0700211 mutex_init(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700212 INIT_LIST_HEAD(&isec->list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700213 isec->inode = inode;
214 isec->sid = SECINITSID_UNLABELED;
215 isec->sclass = SECCLASS_FILE;
David Howells275bb412008-11-14 10:39:19 +1100216 isec->task_sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700217 inode->i_security = isec;
218
219 return 0;
220}
221
Steven Rostedtc7e97422014-01-09 21:46:34 -0500222static void inode_free_rcu(struct rcu_head *head)
223{
224 struct inode_security_struct *isec;
225
226 isec = container_of(head, struct inode_security_struct, rcu);
227 kmem_cache_free(sel_inode_cache, isec);
228}
229
Linus Torvalds1da177e2005-04-16 15:20:36 -0700230static void inode_free_security(struct inode *inode)
231{
232 struct inode_security_struct *isec = inode->i_security;
233 struct superblock_security_struct *sbsec = inode->i_sb->s_security;
234
Linus Torvalds1da177e2005-04-16 15:20:36 -0700235 spin_lock(&sbsec->isec_lock);
236 if (!list_empty(&isec->list))
237 list_del_init(&isec->list);
238 spin_unlock(&sbsec->isec_lock);
239
Steven Rostedtc7e97422014-01-09 21:46:34 -0500240 /*
241 * The inode may still be referenced in a path walk and
242 * a call to selinux_inode_permission() can be made
243 * after inode_free_security() is called. Ideally, the VFS
244 * wouldn't do this, but fixing that is a much harder
245 * job. For now, simply free the i_security via RCU, and
246 * leave the current inode->i_security pointer intact.
247 * The inode will be freed after the RCU grace period too.
248 */
249 call_rcu(&isec->rcu, inode_free_rcu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700250}
251
252static int file_alloc_security(struct file *file)
253{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254 struct file_security_struct *fsec;
David Howells275bb412008-11-14 10:39:19 +1100255 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700256
Stephen Smalley26d2a4b2006-02-01 03:05:55 -0800257 fsec = kzalloc(sizeof(struct file_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258 if (!fsec)
259 return -ENOMEM;
260
David Howells275bb412008-11-14 10:39:19 +1100261 fsec->sid = sid;
262 fsec->fown_sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263 file->f_security = fsec;
264
265 return 0;
266}
267
268static void file_free_security(struct file *file)
269{
270 struct file_security_struct *fsec = file->f_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271 file->f_security = NULL;
272 kfree(fsec);
273}
274
275static int superblock_alloc_security(struct super_block *sb)
276{
277 struct superblock_security_struct *sbsec;
278
James Morris89d155e2005-10-30 14:59:21 -0800279 sbsec = kzalloc(sizeof(struct superblock_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700280 if (!sbsec)
281 return -ENOMEM;
282
Eric Parisbc7e9822006-09-25 23:32:02 -0700283 mutex_init(&sbsec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284 INIT_LIST_HEAD(&sbsec->isec_head);
285 spin_lock_init(&sbsec->isec_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700286 sbsec->sb = sb;
287 sbsec->sid = SECINITSID_UNLABELED;
288 sbsec->def_sid = SECINITSID_FILE;
Eric Parisc312feb2006-07-10 04:43:53 -0700289 sbsec->mntpoint_sid = SECINITSID_UNLABELED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700290 sb->s_security = sbsec;
291
292 return 0;
293}
294
295static void superblock_free_security(struct super_block *sb)
296{
297 struct superblock_security_struct *sbsec = sb->s_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700298 sb->s_security = NULL;
299 kfree(sbsec);
300}
301
Linus Torvalds1da177e2005-04-16 15:20:36 -0700302/* The file system's label must be initialized prior to use. */
303
Stephen Hemminger634a5392010-03-04 21:59:03 -0800304static const char *labeling_behaviors[6] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700305 "uses xattr",
306 "uses transition SIDs",
307 "uses task SIDs",
308 "uses genfs_contexts",
309 "not configured for labeling",
310 "uses mountpoint labeling",
311};
312
313static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry);
314
315static inline int inode_doinit(struct inode *inode)
316{
317 return inode_doinit_with_dentry(inode, NULL);
318}
319
320enum {
Eric Paris31e87932007-09-19 17:19:12 -0400321 Opt_error = -1,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700322 Opt_context = 1,
323 Opt_fscontext = 2,
Eric Parisc9180a52007-11-30 13:00:35 -0500324 Opt_defcontext = 3,
325 Opt_rootcontext = 4,
David P. Quigley11689d42009-01-16 09:22:03 -0500326 Opt_labelsupport = 5,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700327};
328
Steven Whitehousea447c092008-10-13 10:46:57 +0100329static const match_table_t tokens = {
Eric Paris832cbd92008-04-01 13:24:09 -0400330 {Opt_context, CONTEXT_STR "%s"},
331 {Opt_fscontext, FSCONTEXT_STR "%s"},
332 {Opt_defcontext, DEFCONTEXT_STR "%s"},
333 {Opt_rootcontext, ROOTCONTEXT_STR "%s"},
David P. Quigley11689d42009-01-16 09:22:03 -0500334 {Opt_labelsupport, LABELSUPP_STR},
Eric Paris31e87932007-09-19 17:19:12 -0400335 {Opt_error, NULL},
Linus Torvalds1da177e2005-04-16 15:20:36 -0700336};
337
338#define SEL_MOUNT_FAIL_MSG "SELinux: duplicate or incompatible mount options\n"
339
Eric Parisc312feb2006-07-10 04:43:53 -0700340static int may_context_mount_sb_relabel(u32 sid,
341 struct superblock_security_struct *sbsec,
David Howells275bb412008-11-14 10:39:19 +1100342 const struct cred *cred)
Eric Parisc312feb2006-07-10 04:43:53 -0700343{
David Howells275bb412008-11-14 10:39:19 +1100344 const struct task_security_struct *tsec = cred->security;
Eric Parisc312feb2006-07-10 04:43:53 -0700345 int rc;
346
347 rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
348 FILESYSTEM__RELABELFROM, NULL);
349 if (rc)
350 return rc;
351
352 rc = avc_has_perm(tsec->sid, sid, SECCLASS_FILESYSTEM,
353 FILESYSTEM__RELABELTO, NULL);
354 return rc;
355}
356
Eric Paris08089252006-07-10 04:43:55 -0700357static int may_context_mount_inode_relabel(u32 sid,
358 struct superblock_security_struct *sbsec,
David Howells275bb412008-11-14 10:39:19 +1100359 const struct cred *cred)
Eric Paris08089252006-07-10 04:43:55 -0700360{
David Howells275bb412008-11-14 10:39:19 +1100361 const struct task_security_struct *tsec = cred->security;
Eric Paris08089252006-07-10 04:43:55 -0700362 int rc;
363 rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
364 FILESYSTEM__RELABELFROM, NULL);
365 if (rc)
366 return rc;
367
368 rc = avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM,
369 FILESYSTEM__ASSOCIATE, NULL);
370 return rc;
371}
372
Eric Parisc9180a52007-11-30 13:00:35 -0500373static int sb_finish_set_opts(struct super_block *sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374{
375 struct superblock_security_struct *sbsec = sb->s_security;
376 struct dentry *root = sb->s_root;
Eric Parisc9180a52007-11-30 13:00:35 -0500377 struct inode *root_inode = root->d_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378 int rc = 0;
379
Linus Torvalds1da177e2005-04-16 15:20:36 -0700380 if (sbsec->behavior == SECURITY_FS_USE_XATTR) {
381 /* Make sure that the xattr handler exists and that no
382 error other than -ENODATA is returned by getxattr on
383 the root directory. -ENODATA is ok, as this may be
384 the first boot of the SELinux kernel before we have
385 assigned xattr values to the filesystem. */
Eric Parisc9180a52007-11-30 13:00:35 -0500386 if (!root_inode->i_op->getxattr) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387 printk(KERN_WARNING "SELinux: (dev %s, type %s) has no "
388 "xattr support\n", sb->s_id, sb->s_type->name);
389 rc = -EOPNOTSUPP;
390 goto out;
391 }
Eric Parisc9180a52007-11-30 13:00:35 -0500392 rc = root_inode->i_op->getxattr(root, XATTR_NAME_SELINUX, NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393 if (rc < 0 && rc != -ENODATA) {
394 if (rc == -EOPNOTSUPP)
395 printk(KERN_WARNING "SELinux: (dev %s, type "
396 "%s) has no security xattr handler\n",
397 sb->s_id, sb->s_type->name);
398 else
399 printk(KERN_WARNING "SELinux: (dev %s, type "
400 "%s) getxattr errno %d\n", sb->s_id,
401 sb->s_type->name, -rc);
402 goto out;
403 }
404 }
405
David P. Quigley11689d42009-01-16 09:22:03 -0500406 sbsec->flags |= (SE_SBINITIALIZED | SE_SBLABELSUPP);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700407
Eric Parisc9180a52007-11-30 13:00:35 -0500408 if (sbsec->behavior > ARRAY_SIZE(labeling_behaviors))
Eric Parisfadcdb42007-02-22 18:11:31 -0500409 printk(KERN_ERR "SELinux: initialized (dev %s, type %s), unknown behavior\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410 sb->s_id, sb->s_type->name);
Eric Parisc9180a52007-11-30 13:00:35 -0500411 else
Eric Parisfadcdb42007-02-22 18:11:31 -0500412 printk(KERN_DEBUG "SELinux: initialized (dev %s, type %s), %s\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413 sb->s_id, sb->s_type->name,
414 labeling_behaviors[sbsec->behavior-1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415
David P. Quigley11689d42009-01-16 09:22:03 -0500416 if (sbsec->behavior == SECURITY_FS_USE_GENFS ||
417 sbsec->behavior == SECURITY_FS_USE_MNTPOINT ||
418 sbsec->behavior == SECURITY_FS_USE_NONE ||
419 sbsec->behavior > ARRAY_SIZE(labeling_behaviors))
420 sbsec->flags &= ~SE_SBLABELSUPP;
421
Mark Salyzyn2c088052015-01-07 09:27:15 -0800422 /* Special handling. Is genfs but also has in-core setxattr handler*/
423 if (!strcmp(sb->s_type->name, "sysfs") ||
424 !strcmp(sb->s_type->name, "pstore") ||
425 !strcmp(sb->s_type->name, "debugfs") ||
426 !strcmp(sb->s_type->name, "rootfs"))
David P. Quigleyddd29ec2009-09-09 14:25:37 -0400427 sbsec->flags |= SE_SBLABELSUPP;
428
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429 /* Initialize the root inode. */
Eric Parisc9180a52007-11-30 13:00:35 -0500430 rc = inode_doinit_with_dentry(root_inode, root);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431
432 /* Initialize any other inodes associated with the superblock, e.g.
433 inodes created prior to initial policy load or inodes created
434 during get_sb by a pseudo filesystem that directly
435 populates itself. */
436 spin_lock(&sbsec->isec_lock);
437next_inode:
438 if (!list_empty(&sbsec->isec_head)) {
439 struct inode_security_struct *isec =
440 list_entry(sbsec->isec_head.next,
Eric Parisc9180a52007-11-30 13:00:35 -0500441 struct inode_security_struct, list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442 struct inode *inode = isec->inode;
443 spin_unlock(&sbsec->isec_lock);
444 inode = igrab(inode);
445 if (inode) {
Eric Parisc9180a52007-11-30 13:00:35 -0500446 if (!IS_PRIVATE(inode))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447 inode_doinit(inode);
448 iput(inode);
449 }
450 spin_lock(&sbsec->isec_lock);
451 list_del_init(&isec->list);
452 goto next_inode;
453 }
454 spin_unlock(&sbsec->isec_lock);
455out:
Eric Parisc9180a52007-11-30 13:00:35 -0500456 return rc;
457}
458
459/*
460 * This function should allow an FS to ask what it's mount security
461 * options were so it can use those later for submounts, displaying
462 * mount options, or whatever.
463 */
464static int selinux_get_mnt_opts(const struct super_block *sb,
Eric Parise0007522008-03-05 10:31:54 -0500465 struct security_mnt_opts *opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500466{
467 int rc = 0, i;
468 struct superblock_security_struct *sbsec = sb->s_security;
469 char *context = NULL;
470 u32 len;
471 char tmp;
472
Eric Parise0007522008-03-05 10:31:54 -0500473 security_init_mnt_opts(opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500474
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500475 if (!(sbsec->flags & SE_SBINITIALIZED))
Eric Parisc9180a52007-11-30 13:00:35 -0500476 return -EINVAL;
477
478 if (!ss_initialized)
479 return -EINVAL;
480
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500481 tmp = sbsec->flags & SE_MNTMASK;
Eric Parisc9180a52007-11-30 13:00:35 -0500482 /* count the number of mount options for this sb */
483 for (i = 0; i < 8; i++) {
484 if (tmp & 0x01)
Eric Parise0007522008-03-05 10:31:54 -0500485 opts->num_mnt_opts++;
Eric Parisc9180a52007-11-30 13:00:35 -0500486 tmp >>= 1;
487 }
David P. Quigley11689d42009-01-16 09:22:03 -0500488 /* Check if the Label support flag is set */
489 if (sbsec->flags & SE_SBLABELSUPP)
490 opts->num_mnt_opts++;
Eric Parisc9180a52007-11-30 13:00:35 -0500491
Eric Parise0007522008-03-05 10:31:54 -0500492 opts->mnt_opts = kcalloc(opts->num_mnt_opts, sizeof(char *), GFP_ATOMIC);
493 if (!opts->mnt_opts) {
Eric Parisc9180a52007-11-30 13:00:35 -0500494 rc = -ENOMEM;
495 goto out_free;
496 }
497
Eric Parise0007522008-03-05 10:31:54 -0500498 opts->mnt_opts_flags = kcalloc(opts->num_mnt_opts, sizeof(int), GFP_ATOMIC);
499 if (!opts->mnt_opts_flags) {
Eric Parisc9180a52007-11-30 13:00:35 -0500500 rc = -ENOMEM;
501 goto out_free;
502 }
503
504 i = 0;
505 if (sbsec->flags & FSCONTEXT_MNT) {
506 rc = security_sid_to_context(sbsec->sid, &context, &len);
507 if (rc)
508 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500509 opts->mnt_opts[i] = context;
510 opts->mnt_opts_flags[i++] = FSCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500511 }
512 if (sbsec->flags & CONTEXT_MNT) {
513 rc = security_sid_to_context(sbsec->mntpoint_sid, &context, &len);
514 if (rc)
515 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500516 opts->mnt_opts[i] = context;
517 opts->mnt_opts_flags[i++] = CONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500518 }
519 if (sbsec->flags & DEFCONTEXT_MNT) {
520 rc = security_sid_to_context(sbsec->def_sid, &context, &len);
521 if (rc)
522 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500523 opts->mnt_opts[i] = context;
524 opts->mnt_opts_flags[i++] = DEFCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500525 }
526 if (sbsec->flags & ROOTCONTEXT_MNT) {
527 struct inode *root = sbsec->sb->s_root->d_inode;
528 struct inode_security_struct *isec = root->i_security;
529
530 rc = security_sid_to_context(isec->sid, &context, &len);
531 if (rc)
532 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500533 opts->mnt_opts[i] = context;
534 opts->mnt_opts_flags[i++] = ROOTCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500535 }
David P. Quigley11689d42009-01-16 09:22:03 -0500536 if (sbsec->flags & SE_SBLABELSUPP) {
537 opts->mnt_opts[i] = NULL;
538 opts->mnt_opts_flags[i++] = SE_SBLABELSUPP;
539 }
Eric Parisc9180a52007-11-30 13:00:35 -0500540
Eric Parise0007522008-03-05 10:31:54 -0500541 BUG_ON(i != opts->num_mnt_opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500542
543 return 0;
544
545out_free:
Eric Parise0007522008-03-05 10:31:54 -0500546 security_free_mnt_opts(opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500547 return rc;
548}
549
550static int bad_option(struct superblock_security_struct *sbsec, char flag,
551 u32 old_sid, u32 new_sid)
552{
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500553 char mnt_flags = sbsec->flags & SE_MNTMASK;
554
Eric Parisc9180a52007-11-30 13:00:35 -0500555 /* check if the old mount command had the same options */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500556 if (sbsec->flags & SE_SBINITIALIZED)
Eric Parisc9180a52007-11-30 13:00:35 -0500557 if (!(sbsec->flags & flag) ||
558 (old_sid != new_sid))
559 return 1;
560
561 /* check if we were passed the same options twice,
562 * aka someone passed context=a,context=b
563 */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500564 if (!(sbsec->flags & SE_SBINITIALIZED))
565 if (mnt_flags & flag)
Eric Parisc9180a52007-11-30 13:00:35 -0500566 return 1;
567 return 0;
568}
Eric Parise0007522008-03-05 10:31:54 -0500569
Eric Parisc9180a52007-11-30 13:00:35 -0500570/*
571 * Allow filesystems with binary mount data to explicitly set mount point
572 * labeling information.
573 */
Eric Parise0007522008-03-05 10:31:54 -0500574static int selinux_set_mnt_opts(struct super_block *sb,
575 struct security_mnt_opts *opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500576{
David Howells275bb412008-11-14 10:39:19 +1100577 const struct cred *cred = current_cred();
Eric Parisc9180a52007-11-30 13:00:35 -0500578 int rc = 0, i;
Eric Parisc9180a52007-11-30 13:00:35 -0500579 struct superblock_security_struct *sbsec = sb->s_security;
580 const char *name = sb->s_type->name;
James Morris089be432008-07-15 18:32:49 +1000581 struct inode *inode = sbsec->sb->s_root->d_inode;
582 struct inode_security_struct *root_isec = inode->i_security;
Eric Parisc9180a52007-11-30 13:00:35 -0500583 u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0;
584 u32 defcontext_sid = 0;
Eric Parise0007522008-03-05 10:31:54 -0500585 char **mount_options = opts->mnt_opts;
586 int *flags = opts->mnt_opts_flags;
587 int num_opts = opts->num_mnt_opts;
Eric Parisc9180a52007-11-30 13:00:35 -0500588
589 mutex_lock(&sbsec->lock);
590
591 if (!ss_initialized) {
592 if (!num_opts) {
593 /* Defer initialization until selinux_complete_init,
594 after the initial policy is loaded and the security
595 server is ready to handle calls. */
Eric Parisc9180a52007-11-30 13:00:35 -0500596 goto out;
597 }
598 rc = -EINVAL;
Eric Paris744ba352008-04-17 11:52:44 -0400599 printk(KERN_WARNING "SELinux: Unable to set superblock options "
600 "before the security server is initialized\n");
Eric Parisc9180a52007-11-30 13:00:35 -0500601 goto out;
602 }
603
604 /*
Eric Parise0007522008-03-05 10:31:54 -0500605 * Binary mount data FS will come through this function twice. Once
606 * from an explicit call and once from the generic calls from the vfs.
607 * Since the generic VFS calls will not contain any security mount data
608 * we need to skip the double mount verification.
609 *
610 * This does open a hole in which we will not notice if the first
611 * mount using this sb set explict options and a second mount using
612 * this sb does not set any security options. (The first options
613 * will be used for both mounts)
614 */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500615 if ((sbsec->flags & SE_SBINITIALIZED) && (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)
Eric Parise0007522008-03-05 10:31:54 -0500616 && (num_opts == 0))
Eric Parisf5269712008-05-14 11:27:45 -0400617 goto out;
Eric Parise0007522008-03-05 10:31:54 -0500618
619 /*
Eric Parisc9180a52007-11-30 13:00:35 -0500620 * parse the mount options, check if they are valid sids.
621 * also check if someone is trying to mount the same sb more
622 * than once with different security options.
623 */
624 for (i = 0; i < num_opts; i++) {
625 u32 sid;
David P. Quigley11689d42009-01-16 09:22:03 -0500626
627 if (flags[i] == SE_SBLABELSUPP)
628 continue;
Eric Parisc9180a52007-11-30 13:00:35 -0500629 rc = security_context_to_sid(mount_options[i],
630 strlen(mount_options[i]), &sid);
631 if (rc) {
632 printk(KERN_WARNING "SELinux: security_context_to_sid"
633 "(%s) failed for (dev %s, type %s) errno=%d\n",
634 mount_options[i], sb->s_id, name, rc);
635 goto out;
636 }
637 switch (flags[i]) {
638 case FSCONTEXT_MNT:
639 fscontext_sid = sid;
640
641 if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid,
642 fscontext_sid))
643 goto out_double_mount;
644
645 sbsec->flags |= FSCONTEXT_MNT;
646 break;
647 case CONTEXT_MNT:
648 context_sid = sid;
649
650 if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid,
651 context_sid))
652 goto out_double_mount;
653
654 sbsec->flags |= CONTEXT_MNT;
655 break;
656 case ROOTCONTEXT_MNT:
657 rootcontext_sid = sid;
658
659 if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid,
660 rootcontext_sid))
661 goto out_double_mount;
662
663 sbsec->flags |= ROOTCONTEXT_MNT;
664
665 break;
666 case DEFCONTEXT_MNT:
667 defcontext_sid = sid;
668
669 if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid,
670 defcontext_sid))
671 goto out_double_mount;
672
673 sbsec->flags |= DEFCONTEXT_MNT;
674
675 break;
676 default:
677 rc = -EINVAL;
678 goto out;
679 }
680 }
681
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500682 if (sbsec->flags & SE_SBINITIALIZED) {
Eric Parisc9180a52007-11-30 13:00:35 -0500683 /* previously mounted with options, but not on this attempt? */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500684 if ((sbsec->flags & SE_MNTMASK) && !num_opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500685 goto out_double_mount;
686 rc = 0;
687 goto out;
688 }
689
James Morris089be432008-07-15 18:32:49 +1000690 if (strcmp(sb->s_type->name, "proc") == 0)
Stephen Smalleyf9aecb32015-05-19 13:59:12 -0400691 sbsec->flags |= SE_SBPROC | SE_SBGENFS;
692
Stephen Smalley043ab942015-05-20 12:33:16 -0400693 if (!strcmp(sb->s_type->name, "debugfs") ||
694 !strcmp(sb->s_type->name, "sysfs") ||
695 !strcmp(sb->s_type->name, "pstore"))
Stephen Smalleyf9aecb32015-05-19 13:59:12 -0400696 sbsec->flags |= SE_SBGENFS;
Eric Parisc9180a52007-11-30 13:00:35 -0500697
698 /* Determine the labeling behavior to use for this filesystem type. */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500699 rc = security_fs_use((sbsec->flags & SE_SBPROC) ? "proc" : sb->s_type->name, &sbsec->behavior, &sbsec->sid);
Eric Parisc9180a52007-11-30 13:00:35 -0500700 if (rc) {
701 printk(KERN_WARNING "%s: security_fs_use(%s) returned %d\n",
James Morris089be432008-07-15 18:32:49 +1000702 __func__, sb->s_type->name, rc);
Eric Parisc9180a52007-11-30 13:00:35 -0500703 goto out;
704 }
705
706 /* sets the context of the superblock for the fs being mounted. */
707 if (fscontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100708 rc = may_context_mount_sb_relabel(fscontext_sid, sbsec, cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500709 if (rc)
710 goto out;
711
712 sbsec->sid = fscontext_sid;
713 }
714
715 /*
716 * Switch to using mount point labeling behavior.
717 * sets the label used on all file below the mountpoint, and will set
718 * the superblock context if not already set.
719 */
720 if (context_sid) {
721 if (!fscontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100722 rc = may_context_mount_sb_relabel(context_sid, sbsec,
723 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500724 if (rc)
725 goto out;
726 sbsec->sid = context_sid;
727 } else {
David Howells275bb412008-11-14 10:39:19 +1100728 rc = may_context_mount_inode_relabel(context_sid, sbsec,
729 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500730 if (rc)
731 goto out;
732 }
733 if (!rootcontext_sid)
734 rootcontext_sid = context_sid;
735
736 sbsec->mntpoint_sid = context_sid;
737 sbsec->behavior = SECURITY_FS_USE_MNTPOINT;
738 }
739
740 if (rootcontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100741 rc = may_context_mount_inode_relabel(rootcontext_sid, sbsec,
742 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500743 if (rc)
744 goto out;
745
746 root_isec->sid = rootcontext_sid;
747 root_isec->initialized = 1;
748 }
749
750 if (defcontext_sid) {
751 if (sbsec->behavior != SECURITY_FS_USE_XATTR) {
752 rc = -EINVAL;
753 printk(KERN_WARNING "SELinux: defcontext option is "
754 "invalid for this filesystem type\n");
755 goto out;
756 }
757
758 if (defcontext_sid != sbsec->def_sid) {
759 rc = may_context_mount_inode_relabel(defcontext_sid,
David Howells275bb412008-11-14 10:39:19 +1100760 sbsec, cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500761 if (rc)
762 goto out;
763 }
764
765 sbsec->def_sid = defcontext_sid;
766 }
767
768 rc = sb_finish_set_opts(sb);
769out:
Eric Parisbc7e9822006-09-25 23:32:02 -0700770 mutex_unlock(&sbsec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700771 return rc;
Eric Parisc9180a52007-11-30 13:00:35 -0500772out_double_mount:
773 rc = -EINVAL;
774 printk(KERN_WARNING "SELinux: mount invalid. Same superblock, different "
775 "security settings for (dev %s, type %s)\n", sb->s_id, name);
776 goto out;
777}
778
779static void selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
780 struct super_block *newsb)
781{
782 const struct superblock_security_struct *oldsbsec = oldsb->s_security;
783 struct superblock_security_struct *newsbsec = newsb->s_security;
784
785 int set_fscontext = (oldsbsec->flags & FSCONTEXT_MNT);
786 int set_context = (oldsbsec->flags & CONTEXT_MNT);
787 int set_rootcontext = (oldsbsec->flags & ROOTCONTEXT_MNT);
788
Eric Paris0f5e6422008-04-21 16:24:11 -0400789 /*
790 * if the parent was able to be mounted it clearly had no special lsm
Al Viroe8c26252010-03-23 06:36:54 -0400791 * mount options. thus we can safely deal with this superblock later
Eric Paris0f5e6422008-04-21 16:24:11 -0400792 */
Al Viroe8c26252010-03-23 06:36:54 -0400793 if (!ss_initialized)
Eric Paris0f5e6422008-04-21 16:24:11 -0400794 return;
Eric Parisc9180a52007-11-30 13:00:35 -0500795
Eric Parisc9180a52007-11-30 13:00:35 -0500796 /* how can we clone if the old one wasn't set up?? */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500797 BUG_ON(!(oldsbsec->flags & SE_SBINITIALIZED));
Eric Parisc9180a52007-11-30 13:00:35 -0500798
Eric Paris5a552612008-04-09 14:08:35 -0400799 /* if fs is reusing a sb, just let its options stand... */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500800 if (newsbsec->flags & SE_SBINITIALIZED)
Eric Paris5a552612008-04-09 14:08:35 -0400801 return;
802
Eric Parisc9180a52007-11-30 13:00:35 -0500803 mutex_lock(&newsbsec->lock);
804
805 newsbsec->flags = oldsbsec->flags;
806
807 newsbsec->sid = oldsbsec->sid;
808 newsbsec->def_sid = oldsbsec->def_sid;
809 newsbsec->behavior = oldsbsec->behavior;
810
811 if (set_context) {
812 u32 sid = oldsbsec->mntpoint_sid;
813
814 if (!set_fscontext)
815 newsbsec->sid = sid;
816 if (!set_rootcontext) {
817 struct inode *newinode = newsb->s_root->d_inode;
818 struct inode_security_struct *newisec = newinode->i_security;
819 newisec->sid = sid;
820 }
821 newsbsec->mntpoint_sid = sid;
822 }
823 if (set_rootcontext) {
824 const struct inode *oldinode = oldsb->s_root->d_inode;
825 const struct inode_security_struct *oldisec = oldinode->i_security;
826 struct inode *newinode = newsb->s_root->d_inode;
827 struct inode_security_struct *newisec = newinode->i_security;
828
829 newisec->sid = oldisec->sid;
830 }
831
832 sb_finish_set_opts(newsb);
833 mutex_unlock(&newsbsec->lock);
834}
835
Adrian Bunk2e1479d2008-03-17 22:29:23 +0200836static int selinux_parse_opts_str(char *options,
837 struct security_mnt_opts *opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500838{
Eric Parise0007522008-03-05 10:31:54 -0500839 char *p;
Eric Parisc9180a52007-11-30 13:00:35 -0500840 char *context = NULL, *defcontext = NULL;
841 char *fscontext = NULL, *rootcontext = NULL;
Eric Parise0007522008-03-05 10:31:54 -0500842 int rc, num_mnt_opts = 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500843
Eric Parise0007522008-03-05 10:31:54 -0500844 opts->num_mnt_opts = 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500845
846 /* Standard string-based options. */
847 while ((p = strsep(&options, "|")) != NULL) {
848 int token;
849 substring_t args[MAX_OPT_ARGS];
850
851 if (!*p)
852 continue;
853
854 token = match_token(p, tokens, args);
855
856 switch (token) {
857 case Opt_context:
858 if (context || defcontext) {
859 rc = -EINVAL;
860 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
861 goto out_err;
862 }
863 context = match_strdup(&args[0]);
864 if (!context) {
865 rc = -ENOMEM;
866 goto out_err;
867 }
868 break;
869
870 case Opt_fscontext:
871 if (fscontext) {
872 rc = -EINVAL;
873 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
874 goto out_err;
875 }
876 fscontext = match_strdup(&args[0]);
877 if (!fscontext) {
878 rc = -ENOMEM;
879 goto out_err;
880 }
881 break;
882
883 case Opt_rootcontext:
884 if (rootcontext) {
885 rc = -EINVAL;
886 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
887 goto out_err;
888 }
889 rootcontext = match_strdup(&args[0]);
890 if (!rootcontext) {
891 rc = -ENOMEM;
892 goto out_err;
893 }
894 break;
895
896 case Opt_defcontext:
897 if (context || defcontext) {
898 rc = -EINVAL;
899 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
900 goto out_err;
901 }
902 defcontext = match_strdup(&args[0]);
903 if (!defcontext) {
904 rc = -ENOMEM;
905 goto out_err;
906 }
907 break;
David P. Quigley11689d42009-01-16 09:22:03 -0500908 case Opt_labelsupport:
909 break;
Eric Parisc9180a52007-11-30 13:00:35 -0500910 default:
911 rc = -EINVAL;
912 printk(KERN_WARNING "SELinux: unknown mount option\n");
913 goto out_err;
914
915 }
916 }
917
Eric Parise0007522008-03-05 10:31:54 -0500918 rc = -ENOMEM;
919 opts->mnt_opts = kcalloc(NUM_SEL_MNT_OPTS, sizeof(char *), GFP_ATOMIC);
920 if (!opts->mnt_opts)
921 goto out_err;
922
923 opts->mnt_opts_flags = kcalloc(NUM_SEL_MNT_OPTS, sizeof(int), GFP_ATOMIC);
924 if (!opts->mnt_opts_flags) {
925 kfree(opts->mnt_opts);
926 goto out_err;
Eric Parisc9180a52007-11-30 13:00:35 -0500927 }
928
Eric Parise0007522008-03-05 10:31:54 -0500929 if (fscontext) {
930 opts->mnt_opts[num_mnt_opts] = fscontext;
931 opts->mnt_opts_flags[num_mnt_opts++] = FSCONTEXT_MNT;
932 }
933 if (context) {
934 opts->mnt_opts[num_mnt_opts] = context;
935 opts->mnt_opts_flags[num_mnt_opts++] = CONTEXT_MNT;
936 }
937 if (rootcontext) {
938 opts->mnt_opts[num_mnt_opts] = rootcontext;
939 opts->mnt_opts_flags[num_mnt_opts++] = ROOTCONTEXT_MNT;
940 }
941 if (defcontext) {
942 opts->mnt_opts[num_mnt_opts] = defcontext;
943 opts->mnt_opts_flags[num_mnt_opts++] = DEFCONTEXT_MNT;
944 }
945
946 opts->num_mnt_opts = num_mnt_opts;
947 return 0;
948
Eric Parisc9180a52007-11-30 13:00:35 -0500949out_err:
950 kfree(context);
951 kfree(defcontext);
952 kfree(fscontext);
953 kfree(rootcontext);
954 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700955}
Eric Parise0007522008-03-05 10:31:54 -0500956/*
957 * string mount options parsing and call set the sbsec
958 */
959static int superblock_doinit(struct super_block *sb, void *data)
960{
961 int rc = 0;
962 char *options = data;
963 struct security_mnt_opts opts;
964
965 security_init_mnt_opts(&opts);
966
967 if (!data)
968 goto out;
969
970 BUG_ON(sb->s_type->fs_flags & FS_BINARY_MOUNTDATA);
971
972 rc = selinux_parse_opts_str(options, &opts);
973 if (rc)
974 goto out_err;
975
976out:
977 rc = selinux_set_mnt_opts(sb, &opts);
978
979out_err:
980 security_free_mnt_opts(&opts);
981 return rc;
982}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700983
Adrian Bunk3583a712008-07-22 20:21:23 +0300984static void selinux_write_opts(struct seq_file *m,
985 struct security_mnt_opts *opts)
Eric Paris2069f452008-07-04 09:47:13 +1000986{
987 int i;
988 char *prefix;
989
990 for (i = 0; i < opts->num_mnt_opts; i++) {
David P. Quigley11689d42009-01-16 09:22:03 -0500991 char *has_comma;
992
993 if (opts->mnt_opts[i])
994 has_comma = strchr(opts->mnt_opts[i], ',');
995 else
996 has_comma = NULL;
Eric Paris2069f452008-07-04 09:47:13 +1000997
998 switch (opts->mnt_opts_flags[i]) {
999 case CONTEXT_MNT:
1000 prefix = CONTEXT_STR;
1001 break;
1002 case FSCONTEXT_MNT:
1003 prefix = FSCONTEXT_STR;
1004 break;
1005 case ROOTCONTEXT_MNT:
1006 prefix = ROOTCONTEXT_STR;
1007 break;
1008 case DEFCONTEXT_MNT:
1009 prefix = DEFCONTEXT_STR;
1010 break;
David P. Quigley11689d42009-01-16 09:22:03 -05001011 case SE_SBLABELSUPP:
1012 seq_putc(m, ',');
1013 seq_puts(m, LABELSUPP_STR);
1014 continue;
Eric Paris2069f452008-07-04 09:47:13 +10001015 default:
1016 BUG();
Eric Parisa35c6c82011-04-20 10:21:28 -04001017 return;
Eric Paris2069f452008-07-04 09:47:13 +10001018 };
1019 /* we need a comma before each option */
1020 seq_putc(m, ',');
1021 seq_puts(m, prefix);
1022 if (has_comma)
1023 seq_putc(m, '\"');
1024 seq_puts(m, opts->mnt_opts[i]);
1025 if (has_comma)
1026 seq_putc(m, '\"');
1027 }
1028}
1029
1030static int selinux_sb_show_options(struct seq_file *m, struct super_block *sb)
1031{
1032 struct security_mnt_opts opts;
1033 int rc;
1034
1035 rc = selinux_get_mnt_opts(sb, &opts);
Eric Paris383795c2008-07-29 17:07:26 -04001036 if (rc) {
1037 /* before policy load we may get EINVAL, don't show anything */
1038 if (rc == -EINVAL)
1039 rc = 0;
Eric Paris2069f452008-07-04 09:47:13 +10001040 return rc;
Eric Paris383795c2008-07-29 17:07:26 -04001041 }
Eric Paris2069f452008-07-04 09:47:13 +10001042
1043 selinux_write_opts(m, &opts);
1044
1045 security_free_mnt_opts(&opts);
1046
1047 return rc;
1048}
1049
Linus Torvalds1da177e2005-04-16 15:20:36 -07001050static inline u16 inode_mode_to_security_class(umode_t mode)
1051{
1052 switch (mode & S_IFMT) {
1053 case S_IFSOCK:
1054 return SECCLASS_SOCK_FILE;
1055 case S_IFLNK:
1056 return SECCLASS_LNK_FILE;
1057 case S_IFREG:
1058 return SECCLASS_FILE;
1059 case S_IFBLK:
1060 return SECCLASS_BLK_FILE;
1061 case S_IFDIR:
1062 return SECCLASS_DIR;
1063 case S_IFCHR:
1064 return SECCLASS_CHR_FILE;
1065 case S_IFIFO:
1066 return SECCLASS_FIFO_FILE;
1067
1068 }
1069
1070 return SECCLASS_FILE;
1071}
1072
James Morris13402582005-09-30 14:24:34 -04001073static inline int default_protocol_stream(int protocol)
1074{
1075 return (protocol == IPPROTO_IP || protocol == IPPROTO_TCP);
1076}
1077
1078static inline int default_protocol_dgram(int protocol)
1079{
1080 return (protocol == IPPROTO_IP || protocol == IPPROTO_UDP);
1081}
1082
Linus Torvalds1da177e2005-04-16 15:20:36 -07001083static inline u16 socket_type_to_security_class(int family, int type, int protocol)
1084{
1085 switch (family) {
1086 case PF_UNIX:
1087 switch (type) {
1088 case SOCK_STREAM:
1089 case SOCK_SEQPACKET:
1090 return SECCLASS_UNIX_STREAM_SOCKET;
1091 case SOCK_DGRAM:
1092 return SECCLASS_UNIX_DGRAM_SOCKET;
1093 }
1094 break;
1095 case PF_INET:
1096 case PF_INET6:
1097 switch (type) {
1098 case SOCK_STREAM:
James Morris13402582005-09-30 14:24:34 -04001099 if (default_protocol_stream(protocol))
1100 return SECCLASS_TCP_SOCKET;
1101 else
1102 return SECCLASS_RAWIP_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001103 case SOCK_DGRAM:
James Morris13402582005-09-30 14:24:34 -04001104 if (default_protocol_dgram(protocol))
1105 return SECCLASS_UDP_SOCKET;
1106 else
1107 return SECCLASS_RAWIP_SOCKET;
James Morris2ee92d42006-11-13 16:09:01 -08001108 case SOCK_DCCP:
1109 return SECCLASS_DCCP_SOCKET;
James Morris13402582005-09-30 14:24:34 -04001110 default:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001111 return SECCLASS_RAWIP_SOCKET;
1112 }
1113 break;
1114 case PF_NETLINK:
1115 switch (protocol) {
1116 case NETLINK_ROUTE:
1117 return SECCLASS_NETLINK_ROUTE_SOCKET;
1118 case NETLINK_FIREWALL:
1119 return SECCLASS_NETLINK_FIREWALL_SOCKET;
Pavel Emelyanov7f1fb602011-12-06 07:56:43 +00001120 case NETLINK_SOCK_DIAG:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001121 return SECCLASS_NETLINK_TCPDIAG_SOCKET;
1122 case NETLINK_NFLOG:
1123 return SECCLASS_NETLINK_NFLOG_SOCKET;
1124 case NETLINK_XFRM:
1125 return SECCLASS_NETLINK_XFRM_SOCKET;
1126 case NETLINK_SELINUX:
1127 return SECCLASS_NETLINK_SELINUX_SOCKET;
1128 case NETLINK_AUDIT:
1129 return SECCLASS_NETLINK_AUDIT_SOCKET;
1130 case NETLINK_IP6_FW:
1131 return SECCLASS_NETLINK_IP6FW_SOCKET;
1132 case NETLINK_DNRTMSG:
1133 return SECCLASS_NETLINK_DNRT_SOCKET;
James Morris0c9b7942005-04-16 15:24:13 -07001134 case NETLINK_KOBJECT_UEVENT:
1135 return SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001136 default:
1137 return SECCLASS_NETLINK_SOCKET;
1138 }
1139 case PF_PACKET:
1140 return SECCLASS_PACKET_SOCKET;
1141 case PF_KEY:
1142 return SECCLASS_KEY_SOCKET;
Christopher J. PeBenito3e3ff152006-06-09 00:25:03 -07001143 case PF_APPLETALK:
1144 return SECCLASS_APPLETALK_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001145 }
1146
1147 return SECCLASS_SOCKET;
1148}
1149
Stephen Smalleyf9aecb32015-05-19 13:59:12 -04001150static int selinux_genfs_get_sid(struct dentry *dentry,
1151 u16 tclass,
1152 u16 flags,
1153 u32 *sid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001154{
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001155 int rc;
Stephen Smalleyf9aecb32015-05-19 13:59:12 -04001156 struct super_block *sb = dentry->d_inode->i_sb;
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001157 char *buffer, *path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001158
Eric Paris828dfe12008-04-17 13:17:49 -04001159 buffer = (char *)__get_free_page(GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001160 if (!buffer)
1161 return -ENOMEM;
1162
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001163 path = dentry_path_raw(dentry, buffer, PAGE_SIZE);
1164 if (IS_ERR(path))
1165 rc = PTR_ERR(path);
1166 else {
Stephen Smalleyf9aecb32015-05-19 13:59:12 -04001167 if (flags & SE_SBPROC) {
1168 /* each process gets a /proc/PID/ entry. Strip off the
1169 * PID part to get a valid selinux labeling.
1170 * e.g. /proc/1/net/rpc/nfs -> /net/rpc/nfs */
1171 while (path[1] >= '0' && path[1] <= '9') {
1172 path[1] = '/';
1173 path++;
1174 }
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001175 }
Stephen Smalleyf9aecb32015-05-19 13:59:12 -04001176 rc = security_genfs_sid(sb->s_type->name, path, tclass, sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001177 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001178 free_page((unsigned long)buffer);
1179 return rc;
1180}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001181
1182/* The inode's security attributes must be initialized before first use. */
1183static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry)
1184{
1185 struct superblock_security_struct *sbsec = NULL;
1186 struct inode_security_struct *isec = inode->i_security;
1187 u32 sid;
1188 struct dentry *dentry;
1189#define INITCONTEXTLEN 255
1190 char *context = NULL;
1191 unsigned len = 0;
1192 int rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001193
1194 if (isec->initialized)
1195 goto out;
1196
Eric Paris23970742006-09-25 23:32:01 -07001197 mutex_lock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001198 if (isec->initialized)
Eric Paris23970742006-09-25 23:32:01 -07001199 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001200
1201 sbsec = inode->i_sb->s_security;
David P. Quigley0d90a7e2009-01-16 09:22:02 -05001202 if (!(sbsec->flags & SE_SBINITIALIZED)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001203 /* Defer initialization until selinux_complete_init,
1204 after the initial policy is loaded and the security
1205 server is ready to handle calls. */
1206 spin_lock(&sbsec->isec_lock);
1207 if (list_empty(&isec->list))
1208 list_add(&isec->list, &sbsec->isec_head);
1209 spin_unlock(&sbsec->isec_lock);
Eric Paris23970742006-09-25 23:32:01 -07001210 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001211 }
1212
1213 switch (sbsec->behavior) {
1214 case SECURITY_FS_USE_XATTR:
1215 if (!inode->i_op->getxattr) {
1216 isec->sid = sbsec->def_sid;
1217 break;
1218 }
1219
1220 /* Need a dentry, since the xattr API requires one.
1221 Life would be simpler if we could just pass the inode. */
1222 if (opt_dentry) {
1223 /* Called from d_instantiate or d_splice_alias. */
1224 dentry = dget(opt_dentry);
1225 } else {
1226 /* Called from selinux_complete_init, try to find a dentry. */
1227 dentry = d_find_alias(inode);
1228 }
1229 if (!dentry) {
Eric Parisdf7f54c2009-03-09 14:35:58 -04001230 /*
1231 * this is can be hit on boot when a file is accessed
1232 * before the policy is loaded. When we load policy we
1233 * may find inodes that have no dentry on the
1234 * sbsec->isec_head list. No reason to complain as these
1235 * will get fixed up the next time we go through
1236 * inode_doinit with a dentry, before these inodes could
1237 * be used again by userspace.
1238 */
Eric Paris23970742006-09-25 23:32:01 -07001239 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001240 }
1241
1242 len = INITCONTEXTLEN;
Eric Paris4cb912f2009-02-12 14:50:05 -05001243 context = kmalloc(len+1, GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001244 if (!context) {
1245 rc = -ENOMEM;
1246 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001247 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001248 }
Eric Paris4cb912f2009-02-12 14:50:05 -05001249 context[len] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001250 rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX,
1251 context, len);
1252 if (rc == -ERANGE) {
James Morris314dabb2009-08-10 22:00:13 +10001253 kfree(context);
1254
Linus Torvalds1da177e2005-04-16 15:20:36 -07001255 /* Need a larger buffer. Query for the right size. */
1256 rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX,
1257 NULL, 0);
1258 if (rc < 0) {
1259 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001260 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001261 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001262 len = rc;
Eric Paris4cb912f2009-02-12 14:50:05 -05001263 context = kmalloc(len+1, GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001264 if (!context) {
1265 rc = -ENOMEM;
1266 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001267 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001268 }
Eric Paris4cb912f2009-02-12 14:50:05 -05001269 context[len] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001270 rc = inode->i_op->getxattr(dentry,
1271 XATTR_NAME_SELINUX,
1272 context, len);
1273 }
1274 dput(dentry);
1275 if (rc < 0) {
1276 if (rc != -ENODATA) {
Eric Paris744ba352008-04-17 11:52:44 -04001277 printk(KERN_WARNING "SELinux: %s: getxattr returned "
Harvey Harrisondd6f9532008-03-06 10:03:59 +11001278 "%d for dev=%s ino=%ld\n", __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001279 -rc, inode->i_sb->s_id, inode->i_ino);
1280 kfree(context);
Eric Paris23970742006-09-25 23:32:01 -07001281 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001282 }
1283 /* Map ENODATA to the default file SID */
1284 sid = sbsec->def_sid;
1285 rc = 0;
1286 } else {
James Morrisf5c1d5b2005-07-28 01:07:37 -07001287 rc = security_context_to_sid_default(context, rc, &sid,
Stephen Smalley869ab512008-04-04 08:46:05 -04001288 sbsec->def_sid,
1289 GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001290 if (rc) {
Eric Paris4ba0a8a2009-02-12 15:01:10 -05001291 char *dev = inode->i_sb->s_id;
1292 unsigned long ino = inode->i_ino;
1293
1294 if (rc == -EINVAL) {
1295 if (printk_ratelimit())
1296 printk(KERN_NOTICE "SELinux: inode=%lu on dev=%s was found to have an invalid "
1297 "context=%s. This indicates you may need to relabel the inode or the "
1298 "filesystem in question.\n", ino, dev, context);
1299 } else {
1300 printk(KERN_WARNING "SELinux: %s: context_to_sid(%s) "
1301 "returned %d for dev=%s ino=%ld\n",
1302 __func__, context, -rc, dev, ino);
1303 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001304 kfree(context);
1305 /* Leave with the unlabeled SID */
1306 rc = 0;
1307 break;
1308 }
1309 }
1310 kfree(context);
1311 isec->sid = sid;
1312 break;
1313 case SECURITY_FS_USE_TASK:
1314 isec->sid = isec->task_sid;
1315 break;
1316 case SECURITY_FS_USE_TRANS:
1317 /* Default to the fs SID. */
1318 isec->sid = sbsec->sid;
1319
1320 /* Try to obtain a transition SID. */
1321 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Eric Paris652bb9b2011-02-01 11:05:40 -05001322 rc = security_transition_sid(isec->task_sid, sbsec->sid,
1323 isec->sclass, NULL, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001324 if (rc)
Eric Paris23970742006-09-25 23:32:01 -07001325 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001326 isec->sid = sid;
1327 break;
Eric Parisc312feb2006-07-10 04:43:53 -07001328 case SECURITY_FS_USE_MNTPOINT:
1329 isec->sid = sbsec->mntpoint_sid;
1330 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001331 default:
Eric Parisc312feb2006-07-10 04:43:53 -07001332 /* Default to the fs superblock SID. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001333 isec->sid = sbsec->sid;
1334
Stephen Smalleyf9aecb32015-05-19 13:59:12 -04001335 if ((sbsec->flags & SE_SBGENFS) && !S_ISLNK(inode->i_mode)) {
Paul Moore810be002014-03-19 16:46:18 -04001336 /* We must have a dentry to determine the label on
1337 * procfs inodes */
1338 if (opt_dentry)
1339 /* Called from d_instantiate or
1340 * d_splice_alias. */
1341 dentry = dget(opt_dentry);
1342 else
1343 /* Called from selinux_complete_init, try to
1344 * find a dentry. */
1345 dentry = d_find_alias(inode);
1346 /*
1347 * This can be hit on boot when a file is accessed
1348 * before the policy is loaded. When we load policy we
1349 * may find inodes that have no dentry on the
1350 * sbsec->isec_head list. No reason to complain as
1351 * these will get fixed up the next time we go through
1352 * inode_doinit() with a dentry, before these inodes
1353 * could be used again by userspace.
1354 */
1355 if (!dentry)
1356 goto out_unlock;
1357 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Stephen Smalleyf9aecb32015-05-19 13:59:12 -04001358 rc = selinux_genfs_get_sid(dentry, isec->sclass,
1359 sbsec->flags, &sid);
Paul Moore810be002014-03-19 16:46:18 -04001360 dput(dentry);
1361 if (rc)
1362 goto out_unlock;
1363 isec->sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001364 }
1365 break;
1366 }
1367
1368 isec->initialized = 1;
1369
Eric Paris23970742006-09-25 23:32:01 -07001370out_unlock:
1371 mutex_unlock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001372out:
1373 if (isec->sclass == SECCLASS_FILE)
1374 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001375 return rc;
1376}
1377
1378/* Convert a Linux signal to an access vector. */
1379static inline u32 signal_to_av(int sig)
1380{
1381 u32 perm = 0;
1382
1383 switch (sig) {
1384 case SIGCHLD:
1385 /* Commonly granted from child to parent. */
1386 perm = PROCESS__SIGCHLD;
1387 break;
1388 case SIGKILL:
1389 /* Cannot be caught or ignored */
1390 perm = PROCESS__SIGKILL;
1391 break;
1392 case SIGSTOP:
1393 /* Cannot be caught or ignored */
1394 perm = PROCESS__SIGSTOP;
1395 break;
1396 default:
1397 /* All other signals. */
1398 perm = PROCESS__SIGNAL;
1399 break;
1400 }
1401
1402 return perm;
1403}
1404
David Howells275bb412008-11-14 10:39:19 +11001405/*
David Howellsd84f4f92008-11-14 10:39:23 +11001406 * Check permission between a pair of credentials
1407 * fork check, ptrace check, etc.
1408 */
1409static int cred_has_perm(const struct cred *actor,
1410 const struct cred *target,
1411 u32 perms)
1412{
1413 u32 asid = cred_sid(actor), tsid = cred_sid(target);
1414
1415 return avc_has_perm(asid, tsid, SECCLASS_PROCESS, perms, NULL);
1416}
1417
1418/*
David Howells88e67f32008-11-14 10:39:21 +11001419 * Check permission between a pair of tasks, e.g. signal checks,
David Howells275bb412008-11-14 10:39:19 +11001420 * fork check, ptrace check, etc.
1421 * tsk1 is the actor and tsk2 is the target
David Howells3b11a1d2008-11-14 10:39:26 +11001422 * - this uses the default subjective creds of tsk1
David Howells275bb412008-11-14 10:39:19 +11001423 */
1424static int task_has_perm(const struct task_struct *tsk1,
1425 const struct task_struct *tsk2,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001426 u32 perms)
1427{
David Howells275bb412008-11-14 10:39:19 +11001428 const struct task_security_struct *__tsec1, *__tsec2;
1429 u32 sid1, sid2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001430
David Howells275bb412008-11-14 10:39:19 +11001431 rcu_read_lock();
1432 __tsec1 = __task_cred(tsk1)->security; sid1 = __tsec1->sid;
1433 __tsec2 = __task_cred(tsk2)->security; sid2 = __tsec2->sid;
1434 rcu_read_unlock();
1435 return avc_has_perm(sid1, sid2, SECCLASS_PROCESS, perms, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001436}
1437
David Howells3b11a1d2008-11-14 10:39:26 +11001438/*
1439 * Check permission between current and another task, e.g. signal checks,
1440 * fork check, ptrace check, etc.
1441 * current is the actor and tsk2 is the target
1442 * - this uses current's subjective creds
1443 */
1444static int current_has_perm(const struct task_struct *tsk,
1445 u32 perms)
1446{
1447 u32 sid, tsid;
1448
1449 sid = current_sid();
1450 tsid = task_sid(tsk);
1451 return avc_has_perm(sid, tsid, SECCLASS_PROCESS, perms, NULL);
1452}
1453
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001454#if CAP_LAST_CAP > 63
1455#error Fix SELinux to handle capabilities > 63.
1456#endif
1457
Linus Torvalds1da177e2005-04-16 15:20:36 -07001458/* Check whether a task is allowed to use a capability. */
Eric Paris6a9de492012-01-03 12:25:14 -05001459static int cred_has_capability(const struct cred *cred,
Eric Paris06112162008-11-11 22:02:50 +11001460 int cap, int audit)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001461{
Thomas Liu2bf49692009-07-14 12:14:09 -04001462 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07001463 struct selinux_audit_data sad = {0,};
Eric Paris06112162008-11-11 22:02:50 +11001464 struct av_decision avd;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001465 u16 sclass;
David Howells3699c532009-01-06 22:27:01 +00001466 u32 sid = cred_sid(cred);
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001467 u32 av = CAP_TO_MASK(cap);
Eric Paris06112162008-11-11 22:02:50 +11001468 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001469
Thomas Liu2bf49692009-07-14 12:14:09 -04001470 COMMON_AUDIT_DATA_INIT(&ad, CAP);
Eric Paris3b3b0e42012-04-03 09:37:02 -07001471 ad.selinux_audit_data = &sad;
Eric Paris6a9de492012-01-03 12:25:14 -05001472 ad.tsk = current;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001473 ad.u.cap = cap;
1474
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001475 switch (CAP_TO_INDEX(cap)) {
1476 case 0:
1477 sclass = SECCLASS_CAPABILITY;
1478 break;
1479 case 1:
1480 sclass = SECCLASS_CAPABILITY2;
1481 break;
1482 default:
1483 printk(KERN_ERR
1484 "SELinux: out of range capability %d\n", cap);
1485 BUG();
Eric Parisa35c6c82011-04-20 10:21:28 -04001486 return -EINVAL;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001487 }
Eric Paris06112162008-11-11 22:02:50 +11001488
David Howells275bb412008-11-14 10:39:19 +11001489 rc = avc_has_perm_noaudit(sid, sid, sclass, av, 0, &avd);
Eric Paris9ade0cf2011-04-25 16:26:29 -04001490 if (audit == SECURITY_CAP_AUDIT) {
1491 int rc2 = avc_audit(sid, sid, sclass, av, &avd, rc, &ad, 0);
1492 if (rc2)
1493 return rc2;
1494 }
Eric Paris06112162008-11-11 22:02:50 +11001495 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001496}
1497
1498/* Check whether a task is allowed to use a system operation. */
1499static int task_has_system(struct task_struct *tsk,
1500 u32 perms)
1501{
David Howells275bb412008-11-14 10:39:19 +11001502 u32 sid = task_sid(tsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001503
David Howells275bb412008-11-14 10:39:19 +11001504 return avc_has_perm(sid, SECINITSID_KERNEL,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001505 SECCLASS_SYSTEM, perms, NULL);
1506}
1507
1508/* Check whether a task has a particular permission to an inode.
1509 The 'adp' parameter is optional and allows other audit
1510 data to be passed (e.g. the dentry). */
David Howells88e67f32008-11-14 10:39:21 +11001511static int inode_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001512 struct inode *inode,
1513 u32 perms,
Eric Paris9ade0cf2011-04-25 16:26:29 -04001514 struct common_audit_data *adp,
1515 unsigned flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001516{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001517 struct inode_security_struct *isec;
David Howells275bb412008-11-14 10:39:19 +11001518 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001519
David Howellse0e81732009-09-02 09:13:40 +01001520 validate_creds(cred);
1521
Eric Paris828dfe12008-04-17 13:17:49 -04001522 if (unlikely(IS_PRIVATE(inode)))
Stephen Smalleybbaca6c2007-02-14 00:34:16 -08001523 return 0;
1524
David Howells88e67f32008-11-14 10:39:21 +11001525 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001526 isec = inode->i_security;
1527
Eric Paris9ade0cf2011-04-25 16:26:29 -04001528 return avc_has_perm_flags(sid, isec->sid, isec->sclass, perms, adp, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001529}
1530
Linus Torvalds95f4efb2011-06-08 15:11:56 -07001531static int inode_has_perm_noadp(const struct cred *cred,
1532 struct inode *inode,
1533 u32 perms,
1534 unsigned flags)
1535{
1536 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07001537 struct selinux_audit_data sad = {0,};
Linus Torvalds95f4efb2011-06-08 15:11:56 -07001538
1539 COMMON_AUDIT_DATA_INIT(&ad, INODE);
1540 ad.u.inode = inode;
Eric Paris3b3b0e42012-04-03 09:37:02 -07001541 ad.selinux_audit_data = &sad;
Linus Torvalds95f4efb2011-06-08 15:11:56 -07001542 return inode_has_perm(cred, inode, perms, &ad, flags);
1543}
1544
Linus Torvalds1da177e2005-04-16 15:20:36 -07001545/* Same as inode_has_perm, but pass explicit audit data containing
1546 the dentry to help the auditing code to more easily generate the
1547 pathname if needed. */
David Howells88e67f32008-11-14 10:39:21 +11001548static inline int dentry_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001549 struct dentry *dentry,
1550 u32 av)
1551{
1552 struct inode *inode = dentry->d_inode;
Thomas Liu2bf49692009-07-14 12:14:09 -04001553 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07001554 struct selinux_audit_data sad = {0,};
David Howells88e67f32008-11-14 10:39:21 +11001555
Eric Paris2875fa02011-04-28 16:04:24 -04001556 COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
1557 ad.u.dentry = dentry;
Eric Paris3b3b0e42012-04-03 09:37:02 -07001558 ad.selinux_audit_data = &sad;
Eric Paris2875fa02011-04-28 16:04:24 -04001559 return inode_has_perm(cred, inode, av, &ad, 0);
1560}
1561
1562/* Same as inode_has_perm, but pass explicit audit data containing
1563 the path to help the auditing code to more easily generate the
1564 pathname if needed. */
1565static inline int path_has_perm(const struct cred *cred,
1566 struct path *path,
1567 u32 av)
1568{
1569 struct inode *inode = path->dentry->d_inode;
1570 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07001571 struct selinux_audit_data sad = {0,};
Eric Paris2875fa02011-04-28 16:04:24 -04001572
Eric Parisf48b7392011-04-25 12:54:27 -04001573 COMMON_AUDIT_DATA_INIT(&ad, PATH);
Eric Paris2875fa02011-04-28 16:04:24 -04001574 ad.u.path = *path;
Eric Paris3b3b0e42012-04-03 09:37:02 -07001575 ad.selinux_audit_data = &sad;
Eric Paris9ade0cf2011-04-25 16:26:29 -04001576 return inode_has_perm(cred, inode, av, &ad, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001577}
1578
1579/* Check whether a task can use an open file descriptor to
1580 access an inode in a given way. Check access to the
1581 descriptor itself, and then use dentry_has_perm to
1582 check a particular permission to the file.
1583 Access to the descriptor is implicitly granted if it
1584 has the same SID as the process. If av is zero, then
1585 access to the file is not checked, e.g. for cases
1586 where only the descriptor is affected like seek. */
David Howells88e67f32008-11-14 10:39:21 +11001587static int file_has_perm(const struct cred *cred,
1588 struct file *file,
1589 u32 av)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001590{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001591 struct file_security_struct *fsec = file->f_security;
Jan Blunck44707fd2008-02-14 19:38:33 -08001592 struct inode *inode = file->f_path.dentry->d_inode;
Thomas Liu2bf49692009-07-14 12:14:09 -04001593 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07001594 struct selinux_audit_data sad = {0,};
David Howells88e67f32008-11-14 10:39:21 +11001595 u32 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001596 int rc;
1597
Eric Parisf48b7392011-04-25 12:54:27 -04001598 COMMON_AUDIT_DATA_INIT(&ad, PATH);
1599 ad.u.path = file->f_path;
Eric Paris3b3b0e42012-04-03 09:37:02 -07001600 ad.selinux_audit_data = &sad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001601
David Howells275bb412008-11-14 10:39:19 +11001602 if (sid != fsec->sid) {
1603 rc = avc_has_perm(sid, fsec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001604 SECCLASS_FD,
1605 FD__USE,
1606 &ad);
1607 if (rc)
David Howells88e67f32008-11-14 10:39:21 +11001608 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001609 }
1610
1611 /* av is zero if only checking access to the descriptor. */
David Howells88e67f32008-11-14 10:39:21 +11001612 rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001613 if (av)
Eric Paris9ade0cf2011-04-25 16:26:29 -04001614 rc = inode_has_perm(cred, inode, av, &ad, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001615
David Howells88e67f32008-11-14 10:39:21 +11001616out:
1617 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001618}
1619
1620/* Check whether a task can create a file. */
1621static int may_create(struct inode *dir,
1622 struct dentry *dentry,
1623 u16 tclass)
1624{
Paul Moore5fb49872010-04-22 14:46:19 -04001625 const struct task_security_struct *tsec = current_security();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001626 struct inode_security_struct *dsec;
1627 struct superblock_security_struct *sbsec;
David Howells275bb412008-11-14 10:39:19 +11001628 u32 sid, newsid;
Thomas Liu2bf49692009-07-14 12:14:09 -04001629 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07001630 struct selinux_audit_data sad = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07001631 int rc;
1632
Linus Torvalds1da177e2005-04-16 15:20:36 -07001633 dsec = dir->i_security;
1634 sbsec = dir->i_sb->s_security;
1635
David Howells275bb412008-11-14 10:39:19 +11001636 sid = tsec->sid;
1637 newsid = tsec->create_sid;
1638
Eric Parisa2694342011-04-25 13:10:27 -04001639 COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
1640 ad.u.dentry = dentry;
Eric Paris3b3b0e42012-04-03 09:37:02 -07001641 ad.selinux_audit_data = &sad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001642
David Howells275bb412008-11-14 10:39:19 +11001643 rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001644 DIR__ADD_NAME | DIR__SEARCH,
1645 &ad);
1646 if (rc)
1647 return rc;
1648
David P. Quigleycd895962009-01-16 09:22:04 -05001649 if (!newsid || !(sbsec->flags & SE_SBLABELSUPP)) {
Eric Pariscb1e9222011-04-28 15:11:21 -04001650 rc = security_transition_sid(sid, dsec->sid, tclass,
1651 &dentry->d_name, &newsid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001652 if (rc)
1653 return rc;
1654 }
1655
David Howells275bb412008-11-14 10:39:19 +11001656 rc = avc_has_perm(sid, newsid, tclass, FILE__CREATE, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001657 if (rc)
1658 return rc;
1659
Amir Samuelov6a22e462014-05-26 11:44:06 +03001660 rc = avc_has_perm(newsid, sbsec->sid,
1661 SECCLASS_FILESYSTEM,
1662 FILESYSTEM__ASSOCIATE, &ad);
1663 if (rc)
1664 return rc;
1665
1666 rc = pft_inode_mknod(dir, dentry, 0, 0);
1667
1668 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001669}
1670
Michael LeMay4eb582c2006-06-26 00:24:57 -07001671/* Check whether a task can create a key. */
1672static int may_create_key(u32 ksid,
1673 struct task_struct *ctx)
1674{
David Howells275bb412008-11-14 10:39:19 +11001675 u32 sid = task_sid(ctx);
Michael LeMay4eb582c2006-06-26 00:24:57 -07001676
David Howells275bb412008-11-14 10:39:19 +11001677 return avc_has_perm(sid, ksid, SECCLASS_KEY, KEY__CREATE, NULL);
Michael LeMay4eb582c2006-06-26 00:24:57 -07001678}
1679
Eric Paris828dfe12008-04-17 13:17:49 -04001680#define MAY_LINK 0
1681#define MAY_UNLINK 1
1682#define MAY_RMDIR 2
Linus Torvalds1da177e2005-04-16 15:20:36 -07001683
1684/* Check whether a task can link, unlink, or rmdir a file/directory. */
1685static int may_link(struct inode *dir,
1686 struct dentry *dentry,
1687 int kind)
1688
1689{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001690 struct inode_security_struct *dsec, *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04001691 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07001692 struct selinux_audit_data sad = {0,};
David Howells275bb412008-11-14 10:39:19 +11001693 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001694 u32 av;
1695 int rc;
1696
Linus Torvalds1da177e2005-04-16 15:20:36 -07001697 dsec = dir->i_security;
1698 isec = dentry->d_inode->i_security;
1699
Eric Parisa2694342011-04-25 13:10:27 -04001700 COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
1701 ad.u.dentry = dentry;
Eric Paris3b3b0e42012-04-03 09:37:02 -07001702 ad.selinux_audit_data = &sad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001703
1704 av = DIR__SEARCH;
1705 av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME);
David Howells275bb412008-11-14 10:39:19 +11001706 rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001707 if (rc)
1708 return rc;
1709
1710 switch (kind) {
1711 case MAY_LINK:
1712 av = FILE__LINK;
1713 break;
1714 case MAY_UNLINK:
1715 av = FILE__UNLINK;
1716 break;
1717 case MAY_RMDIR:
1718 av = DIR__RMDIR;
1719 break;
1720 default:
Eric Paris744ba352008-04-17 11:52:44 -04001721 printk(KERN_WARNING "SELinux: %s: unrecognized kind %d\n",
1722 __func__, kind);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001723 return 0;
1724 }
1725
David Howells275bb412008-11-14 10:39:19 +11001726 rc = avc_has_perm(sid, isec->sid, isec->sclass, av, &ad);
Amir Samuelov6a22e462014-05-26 11:44:06 +03001727 if (rc)
1728 return rc;
1729
1730 if (kind == MAY_UNLINK)
1731 rc = pft_inode_unlink(dir, dentry);
1732
Linus Torvalds1da177e2005-04-16 15:20:36 -07001733 return rc;
1734}
1735
1736static inline int may_rename(struct inode *old_dir,
1737 struct dentry *old_dentry,
1738 struct inode *new_dir,
1739 struct dentry *new_dentry)
1740{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001741 struct inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04001742 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07001743 struct selinux_audit_data sad = {0,};
David Howells275bb412008-11-14 10:39:19 +11001744 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001745 u32 av;
1746 int old_is_dir, new_is_dir;
1747 int rc;
1748
Linus Torvalds1da177e2005-04-16 15:20:36 -07001749 old_dsec = old_dir->i_security;
1750 old_isec = old_dentry->d_inode->i_security;
1751 old_is_dir = S_ISDIR(old_dentry->d_inode->i_mode);
1752 new_dsec = new_dir->i_security;
1753
Eric Parisa2694342011-04-25 13:10:27 -04001754 COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
Eric Paris3b3b0e42012-04-03 09:37:02 -07001755 ad.selinux_audit_data = &sad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001756
Eric Parisa2694342011-04-25 13:10:27 -04001757 ad.u.dentry = old_dentry;
David Howells275bb412008-11-14 10:39:19 +11001758 rc = avc_has_perm(sid, old_dsec->sid, SECCLASS_DIR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001759 DIR__REMOVE_NAME | DIR__SEARCH, &ad);
1760 if (rc)
1761 return rc;
David Howells275bb412008-11-14 10:39:19 +11001762 rc = avc_has_perm(sid, old_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001763 old_isec->sclass, FILE__RENAME, &ad);
1764 if (rc)
1765 return rc;
1766 if (old_is_dir && new_dir != old_dir) {
David Howells275bb412008-11-14 10:39:19 +11001767 rc = avc_has_perm(sid, old_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001768 old_isec->sclass, DIR__REPARENT, &ad);
1769 if (rc)
1770 return rc;
1771 }
1772
Eric Parisa2694342011-04-25 13:10:27 -04001773 ad.u.dentry = new_dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001774 av = DIR__ADD_NAME | DIR__SEARCH;
1775 if (new_dentry->d_inode)
1776 av |= DIR__REMOVE_NAME;
David Howells275bb412008-11-14 10:39:19 +11001777 rc = avc_has_perm(sid, new_dsec->sid, SECCLASS_DIR, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001778 if (rc)
1779 return rc;
1780 if (new_dentry->d_inode) {
1781 new_isec = new_dentry->d_inode->i_security;
1782 new_is_dir = S_ISDIR(new_dentry->d_inode->i_mode);
David Howells275bb412008-11-14 10:39:19 +11001783 rc = avc_has_perm(sid, new_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001784 new_isec->sclass,
1785 (new_is_dir ? DIR__RMDIR : FILE__UNLINK), &ad);
1786 if (rc)
1787 return rc;
1788 }
1789
1790 return 0;
1791}
1792
1793/* Check whether a task can perform a filesystem operation. */
David Howells88e67f32008-11-14 10:39:21 +11001794static int superblock_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001795 struct super_block *sb,
1796 u32 perms,
Thomas Liu2bf49692009-07-14 12:14:09 -04001797 struct common_audit_data *ad)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001798{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001799 struct superblock_security_struct *sbsec;
David Howells88e67f32008-11-14 10:39:21 +11001800 u32 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001801
Linus Torvalds1da177e2005-04-16 15:20:36 -07001802 sbsec = sb->s_security;
David Howells275bb412008-11-14 10:39:19 +11001803 return avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM, perms, ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001804}
1805
1806/* Convert a Linux mode and permission mask to an access vector. */
1807static inline u32 file_mask_to_av(int mode, int mask)
1808{
1809 u32 av = 0;
1810
Al Virodba19c62011-07-25 20:49:29 -04001811 if (!S_ISDIR(mode)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001812 if (mask & MAY_EXEC)
1813 av |= FILE__EXECUTE;
1814 if (mask & MAY_READ)
1815 av |= FILE__READ;
1816
1817 if (mask & MAY_APPEND)
1818 av |= FILE__APPEND;
1819 else if (mask & MAY_WRITE)
1820 av |= FILE__WRITE;
1821
1822 } else {
1823 if (mask & MAY_EXEC)
1824 av |= DIR__SEARCH;
1825 if (mask & MAY_WRITE)
1826 av |= DIR__WRITE;
1827 if (mask & MAY_READ)
1828 av |= DIR__READ;
1829 }
1830
1831 return av;
1832}
1833
1834/* Convert a Linux file to an access vector. */
1835static inline u32 file_to_av(struct file *file)
1836{
1837 u32 av = 0;
1838
1839 if (file->f_mode & FMODE_READ)
1840 av |= FILE__READ;
1841 if (file->f_mode & FMODE_WRITE) {
1842 if (file->f_flags & O_APPEND)
1843 av |= FILE__APPEND;
1844 else
1845 av |= FILE__WRITE;
1846 }
Stephen Smalley0794c662008-03-17 08:55:18 -04001847 if (!av) {
1848 /*
1849 * Special file opened with flags 3 for ioctl-only use.
1850 */
1851 av = FILE__IOCTL;
1852 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001853
1854 return av;
1855}
1856
Eric Paris8b6a5a32008-10-29 17:06:46 -04001857/*
1858 * Convert a file to an access vector and include the correct open
1859 * open permission.
1860 */
1861static inline u32 open_file_to_av(struct file *file)
1862{
1863 u32 av = file_to_av(file);
1864
Eric Paris49b7b8d2010-07-23 11:44:09 -04001865 if (selinux_policycap_openperm)
1866 av |= FILE__OPEN;
1867
Eric Paris8b6a5a32008-10-29 17:06:46 -04001868 return av;
1869}
1870
Linus Torvalds1da177e2005-04-16 15:20:36 -07001871/* Hook functions begin here. */
1872
Stephen Smalley48a23702012-11-05 08:15:34 -05001873static int selinux_binder_set_context_mgr(struct task_struct *mgr)
1874{
1875 u32 mysid = current_sid();
1876 u32 mgrsid = task_sid(mgr);
1877
1878 return avc_has_perm(mysid, mgrsid, SECCLASS_BINDER, BINDER__SET_CONTEXT_MGR, NULL);
1879}
1880
1881static int selinux_binder_transaction(struct task_struct *from, struct task_struct *to)
1882{
1883 u32 mysid = current_sid();
1884 u32 fromsid = task_sid(from);
1885 u32 tosid = task_sid(to);
1886 int rc;
1887
1888 if (mysid != fromsid) {
1889 rc = avc_has_perm(mysid, fromsid, SECCLASS_BINDER, BINDER__IMPERSONATE, NULL);
1890 if (rc)
1891 return rc;
1892 }
1893
1894 return avc_has_perm(fromsid, tosid, SECCLASS_BINDER, BINDER__CALL, NULL);
1895}
1896
1897static int selinux_binder_transfer_binder(struct task_struct *from, struct task_struct *to)
1898{
1899 u32 fromsid = task_sid(from);
1900 u32 tosid = task_sid(to);
1901 return avc_has_perm(fromsid, tosid, SECCLASS_BINDER, BINDER__TRANSFER, NULL);
1902}
1903
1904static int selinux_binder_transfer_file(struct task_struct *from, struct task_struct *to, struct file *file)
1905{
1906 u32 sid = task_sid(to);
1907 struct file_security_struct *fsec = file->f_security;
1908 struct inode *inode = file->f_path.dentry->d_inode;
1909 struct inode_security_struct *isec = inode->i_security;
1910 struct common_audit_data ad;
1911 struct selinux_audit_data sad = {0,};
1912 int rc;
1913
1914 COMMON_AUDIT_DATA_INIT(&ad, PATH);
1915 ad.u.path = file->f_path;
1916 ad.selinux_audit_data = &sad;
1917
1918 if (sid != fsec->sid) {
1919 rc = avc_has_perm(sid, fsec->sid,
1920 SECCLASS_FD,
1921 FD__USE,
1922 &ad);
1923 if (rc)
1924 return rc;
1925 }
1926
1927 if (unlikely(IS_PRIVATE(inode)))
1928 return 0;
1929
1930 return avc_has_perm(sid, isec->sid, isec->sclass, file_to_av(file),
1931 &ad);
1932}
1933
Ingo Molnar9e488582009-05-07 19:26:19 +10001934static int selinux_ptrace_access_check(struct task_struct *child,
David Howells5cd9c582008-08-14 11:37:28 +01001935 unsigned int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001936{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001937 int rc;
1938
Ingo Molnar9e488582009-05-07 19:26:19 +10001939 rc = cap_ptrace_access_check(child, mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001940 if (rc)
1941 return rc;
1942
Eric Paris69f594a2012-01-03 12:25:15 -05001943 if (mode & PTRACE_MODE_READ) {
David Howells275bb412008-11-14 10:39:19 +11001944 u32 sid = current_sid();
1945 u32 csid = task_sid(child);
1946 return avc_has_perm(sid, csid, SECCLASS_FILE, FILE__READ, NULL);
Stephen Smalley006ebb42008-05-19 08:32:49 -04001947 }
1948
David Howells3b11a1d2008-11-14 10:39:26 +11001949 return current_has_perm(child, PROCESS__PTRACE);
David Howells5cd9c582008-08-14 11:37:28 +01001950}
1951
1952static int selinux_ptrace_traceme(struct task_struct *parent)
1953{
1954 int rc;
1955
Eric Paris200ac532009-02-12 15:01:04 -05001956 rc = cap_ptrace_traceme(parent);
David Howells5cd9c582008-08-14 11:37:28 +01001957 if (rc)
1958 return rc;
1959
1960 return task_has_perm(parent, current, PROCESS__PTRACE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001961}
1962
1963static int selinux_capget(struct task_struct *target, kernel_cap_t *effective,
Eric Paris828dfe12008-04-17 13:17:49 -04001964 kernel_cap_t *inheritable, kernel_cap_t *permitted)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001965{
1966 int error;
1967
David Howells3b11a1d2008-11-14 10:39:26 +11001968 error = current_has_perm(target, PROCESS__GETCAP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001969 if (error)
1970 return error;
1971
Eric Paris200ac532009-02-12 15:01:04 -05001972 return cap_capget(target, effective, inheritable, permitted);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001973}
1974
David Howellsd84f4f92008-11-14 10:39:23 +11001975static int selinux_capset(struct cred *new, const struct cred *old,
1976 const kernel_cap_t *effective,
1977 const kernel_cap_t *inheritable,
1978 const kernel_cap_t *permitted)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001979{
1980 int error;
1981
Eric Paris200ac532009-02-12 15:01:04 -05001982 error = cap_capset(new, old,
David Howellsd84f4f92008-11-14 10:39:23 +11001983 effective, inheritable, permitted);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001984 if (error)
1985 return error;
1986
David Howellsd84f4f92008-11-14 10:39:23 +11001987 return cred_has_perm(old, new, PROCESS__SETCAP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001988}
1989
James Morris5626d3e2009-01-30 10:05:06 +11001990/*
1991 * (This comment used to live with the selinux_task_setuid hook,
1992 * which was removed).
1993 *
1994 * Since setuid only affects the current process, and since the SELinux
1995 * controls are not based on the Linux identity attributes, SELinux does not
1996 * need to control this operation. However, SELinux does control the use of
1997 * the CAP_SETUID and CAP_SETGID capabilities using the capable hook.
1998 */
1999
Eric Paris6a9de492012-01-03 12:25:14 -05002000static int selinux_capable(const struct cred *cred, struct user_namespace *ns,
2001 int cap, int audit)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002002{
2003 int rc;
2004
Eric Paris6a9de492012-01-03 12:25:14 -05002005 rc = cap_capable(cred, ns, cap, audit);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002006 if (rc)
2007 return rc;
2008
Eric Paris6a9de492012-01-03 12:25:14 -05002009 return cred_has_capability(cred, cap, audit);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002010}
2011
Linus Torvalds1da177e2005-04-16 15:20:36 -07002012static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb)
2013{
David Howells88e67f32008-11-14 10:39:21 +11002014 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002015 int rc = 0;
2016
2017 if (!sb)
2018 return 0;
2019
2020 switch (cmds) {
Eric Paris828dfe12008-04-17 13:17:49 -04002021 case Q_SYNC:
2022 case Q_QUOTAON:
2023 case Q_QUOTAOFF:
2024 case Q_SETINFO:
2025 case Q_SETQUOTA:
David Howells88e67f32008-11-14 10:39:21 +11002026 rc = superblock_has_perm(cred, sb, FILESYSTEM__QUOTAMOD, NULL);
Eric Paris828dfe12008-04-17 13:17:49 -04002027 break;
2028 case Q_GETFMT:
2029 case Q_GETINFO:
2030 case Q_GETQUOTA:
David Howells88e67f32008-11-14 10:39:21 +11002031 rc = superblock_has_perm(cred, sb, FILESYSTEM__QUOTAGET, NULL);
Eric Paris828dfe12008-04-17 13:17:49 -04002032 break;
2033 default:
2034 rc = 0; /* let the kernel handle invalid cmds */
2035 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002036 }
2037 return rc;
2038}
2039
2040static int selinux_quota_on(struct dentry *dentry)
2041{
David Howells88e67f32008-11-14 10:39:21 +11002042 const struct cred *cred = current_cred();
2043
Eric Paris2875fa02011-04-28 16:04:24 -04002044 return dentry_has_perm(cred, dentry, FILE__QUOTAON);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002045}
2046
Eric Paris12b30522010-11-15 18:36:29 -05002047static int selinux_syslog(int type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002048{
2049 int rc;
2050
Linus Torvalds1da177e2005-04-16 15:20:36 -07002051 switch (type) {
Kees Cookd78ca3c2010-02-03 15:37:13 -08002052 case SYSLOG_ACTION_READ_ALL: /* Read last kernel messages */
2053 case SYSLOG_ACTION_SIZE_BUFFER: /* Return size of the log buffer */
Eric Paris828dfe12008-04-17 13:17:49 -04002054 rc = task_has_system(current, SYSTEM__SYSLOG_READ);
2055 break;
Kees Cookd78ca3c2010-02-03 15:37:13 -08002056 case SYSLOG_ACTION_CONSOLE_OFF: /* Disable logging to console */
2057 case SYSLOG_ACTION_CONSOLE_ON: /* Enable logging to console */
2058 /* Set level of messages printed to console */
2059 case SYSLOG_ACTION_CONSOLE_LEVEL:
Eric Paris828dfe12008-04-17 13:17:49 -04002060 rc = task_has_system(current, SYSTEM__SYSLOG_CONSOLE);
2061 break;
Kees Cookd78ca3c2010-02-03 15:37:13 -08002062 case SYSLOG_ACTION_CLOSE: /* Close log */
2063 case SYSLOG_ACTION_OPEN: /* Open log */
2064 case SYSLOG_ACTION_READ: /* Read from log */
2065 case SYSLOG_ACTION_READ_CLEAR: /* Read/clear last kernel messages */
2066 case SYSLOG_ACTION_CLEAR: /* Clear ring buffer */
Eric Paris828dfe12008-04-17 13:17:49 -04002067 default:
2068 rc = task_has_system(current, SYSTEM__SYSLOG_MOD);
2069 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002070 }
2071 return rc;
2072}
2073
2074/*
2075 * Check that a process has enough memory to allocate a new virtual
2076 * mapping. 0 means there is enough memory for the allocation to
2077 * succeed and -ENOMEM implies there is not.
2078 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07002079 * Do not audit the selinux permission check, as this is applied to all
2080 * processes that allocate mappings.
2081 */
Alan Cox34b4e4a2007-08-22 14:01:28 -07002082static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002083{
2084 int rc, cap_sys_admin = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002085
Eric Paris6a9de492012-01-03 12:25:14 -05002086 rc = selinux_capable(current_cred(), &init_user_ns, CAP_SYS_ADMIN,
David Howells3699c532009-01-06 22:27:01 +00002087 SECURITY_CAP_NOAUDIT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002088 if (rc == 0)
2089 cap_sys_admin = 1;
2090
Alan Cox34b4e4a2007-08-22 14:01:28 -07002091 return __vm_enough_memory(mm, pages, cap_sys_admin);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002092}
2093
2094/* binprm security operations */
2095
David Howellsa6f76f22008-11-14 10:39:24 +11002096static int selinux_bprm_set_creds(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002097{
David Howellsa6f76f22008-11-14 10:39:24 +11002098 const struct task_security_struct *old_tsec;
2099 struct task_security_struct *new_tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002100 struct inode_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04002101 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07002102 struct selinux_audit_data sad = {0,};
David Howellsa6f76f22008-11-14 10:39:24 +11002103 struct inode *inode = bprm->file->f_path.dentry->d_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002104 int rc;
2105
Eric Paris200ac532009-02-12 15:01:04 -05002106 rc = cap_bprm_set_creds(bprm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002107 if (rc)
2108 return rc;
2109
David Howellsa6f76f22008-11-14 10:39:24 +11002110 /* SELinux context only depends on initial program or script and not
2111 * the script interpreter */
2112 if (bprm->cred_prepared)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002113 return 0;
2114
David Howellsa6f76f22008-11-14 10:39:24 +11002115 old_tsec = current_security();
2116 new_tsec = bprm->cred->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002117 isec = inode->i_security;
2118
2119 /* Default to the current task SID. */
David Howellsa6f76f22008-11-14 10:39:24 +11002120 new_tsec->sid = old_tsec->sid;
2121 new_tsec->osid = old_tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002122
Michael LeMay28eba5b2006-06-27 02:53:42 -07002123 /* Reset fs, key, and sock SIDs on execve. */
David Howellsa6f76f22008-11-14 10:39:24 +11002124 new_tsec->create_sid = 0;
2125 new_tsec->keycreate_sid = 0;
2126 new_tsec->sockcreate_sid = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002127
David Howellsa6f76f22008-11-14 10:39:24 +11002128 if (old_tsec->exec_sid) {
2129 new_tsec->sid = old_tsec->exec_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002130 /* Reset exec SID on execve. */
David Howellsa6f76f22008-11-14 10:39:24 +11002131 new_tsec->exec_sid = 0;
Andy Lutomirski397a85e2012-01-30 08:17:26 -08002132
2133 /*
2134 * Minimize confusion: if no_new_privs and a transition is
2135 * explicitly requested, then fail the exec.
2136 */
2137 if (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS)
2138 return -EPERM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002139 } else {
2140 /* Check for a default transition on this program. */
David Howellsa6f76f22008-11-14 10:39:24 +11002141 rc = security_transition_sid(old_tsec->sid, isec->sid,
Eric Paris652bb9b2011-02-01 11:05:40 -05002142 SECCLASS_PROCESS, NULL,
2143 &new_tsec->sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002144 if (rc)
2145 return rc;
2146 }
2147
Eric Parisf48b7392011-04-25 12:54:27 -04002148 COMMON_AUDIT_DATA_INIT(&ad, PATH);
Eric Paris3b3b0e42012-04-03 09:37:02 -07002149 ad.selinux_audit_data = &sad;
Eric Parisf48b7392011-04-25 12:54:27 -04002150 ad.u.path = bprm->file->f_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002151
Andy Lutomirski397a85e2012-01-30 08:17:26 -08002152 if ((bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) ||
2153 (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS))
David Howellsa6f76f22008-11-14 10:39:24 +11002154 new_tsec->sid = old_tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002155
David Howellsa6f76f22008-11-14 10:39:24 +11002156 if (new_tsec->sid == old_tsec->sid) {
2157 rc = avc_has_perm(old_tsec->sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002158 SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, &ad);
2159 if (rc)
2160 return rc;
2161 } else {
2162 /* Check permissions for the transition. */
David Howellsa6f76f22008-11-14 10:39:24 +11002163 rc = avc_has_perm(old_tsec->sid, new_tsec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002164 SECCLASS_PROCESS, PROCESS__TRANSITION, &ad);
2165 if (rc)
2166 return rc;
2167
David Howellsa6f76f22008-11-14 10:39:24 +11002168 rc = avc_has_perm(new_tsec->sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002169 SECCLASS_FILE, FILE__ENTRYPOINT, &ad);
2170 if (rc)
2171 return rc;
2172
David Howellsa6f76f22008-11-14 10:39:24 +11002173 /* Check for shared state */
2174 if (bprm->unsafe & LSM_UNSAFE_SHARE) {
2175 rc = avc_has_perm(old_tsec->sid, new_tsec->sid,
2176 SECCLASS_PROCESS, PROCESS__SHARE,
2177 NULL);
2178 if (rc)
2179 return -EPERM;
2180 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002181
David Howellsa6f76f22008-11-14 10:39:24 +11002182 /* Make sure that anyone attempting to ptrace over a task that
2183 * changes its SID has the appropriate permit */
2184 if (bprm->unsafe &
2185 (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) {
2186 struct task_struct *tracer;
2187 struct task_security_struct *sec;
2188 u32 ptsid = 0;
2189
2190 rcu_read_lock();
Tejun Heo06d98472011-06-17 16:50:40 +02002191 tracer = ptrace_parent(current);
David Howellsa6f76f22008-11-14 10:39:24 +11002192 if (likely(tracer != NULL)) {
2193 sec = __task_cred(tracer)->security;
2194 ptsid = sec->sid;
2195 }
2196 rcu_read_unlock();
2197
2198 if (ptsid != 0) {
2199 rc = avc_has_perm(ptsid, new_tsec->sid,
2200 SECCLASS_PROCESS,
2201 PROCESS__PTRACE, NULL);
2202 if (rc)
2203 return -EPERM;
2204 }
2205 }
2206
2207 /* Clear any possibly unsafe personality bits on exec: */
2208 bprm->per_clear |= PER_CLEAR_ON_SETID;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002209 }
2210
Linus Torvalds1da177e2005-04-16 15:20:36 -07002211 return 0;
2212}
2213
Eric Paris828dfe12008-04-17 13:17:49 -04002214static int selinux_bprm_secureexec(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002215{
Paul Moore5fb49872010-04-22 14:46:19 -04002216 const struct task_security_struct *tsec = current_security();
David Howells275bb412008-11-14 10:39:19 +11002217 u32 sid, osid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002218 int atsecure = 0;
2219
David Howells275bb412008-11-14 10:39:19 +11002220 sid = tsec->sid;
2221 osid = tsec->osid;
2222
2223 if (osid != sid) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002224 /* Enable secure mode for SIDs transitions unless
2225 the noatsecure permission is granted between
2226 the two SIDs, i.e. ahp returns 0. */
David Howells275bb412008-11-14 10:39:19 +11002227 atsecure = avc_has_perm(osid, sid,
David Howellsa6f76f22008-11-14 10:39:24 +11002228 SECCLASS_PROCESS,
2229 PROCESS__NOATSECURE, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002230 }
2231
Eric Paris200ac532009-02-12 15:01:04 -05002232 return (atsecure || cap_bprm_secureexec(bprm));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002233}
2234
Linus Torvalds1da177e2005-04-16 15:20:36 -07002235/* Derived from fs/exec.c:flush_old_files. */
David Howells745ca242008-11-14 10:39:22 +11002236static inline void flush_unauthorized_files(const struct cred *cred,
2237 struct files_struct *files)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002238{
Thomas Liu2bf49692009-07-14 12:14:09 -04002239 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07002240 struct selinux_audit_data sad = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07002241 struct file *file, *devnull = NULL;
Stephen Smalleyb20c8122006-09-25 23:32:03 -07002242 struct tty_struct *tty;
Dipankar Sarmabadf1662005-09-09 13:04:10 -07002243 struct fdtable *fdt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002244 long j = -1;
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002245 int drop_tty = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002246
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002247 tty = get_current_tty();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002248 if (tty) {
Nick Pigginee2ffa02010-08-18 04:37:35 +10002249 spin_lock(&tty_files_lock);
Eric Paris37dd0bd2008-10-31 17:40:00 -04002250 if (!list_empty(&tty->tty_files)) {
Nick Piggind996b622010-08-18 04:37:36 +10002251 struct tty_file_private *file_priv;
Eric Paris37dd0bd2008-10-31 17:40:00 -04002252 struct inode *inode;
2253
Linus Torvalds1da177e2005-04-16 15:20:36 -07002254 /* Revalidate access to controlling tty.
2255 Use inode_has_perm on the tty inode directly rather
2256 than using file_has_perm, as this particular open
2257 file may belong to another process and we are only
2258 interested in the inode-based check here. */
Nick Piggind996b622010-08-18 04:37:36 +10002259 file_priv = list_first_entry(&tty->tty_files,
2260 struct tty_file_private, list);
2261 file = file_priv->file;
Eric Paris37dd0bd2008-10-31 17:40:00 -04002262 inode = file->f_path.dentry->d_inode;
Linus Torvalds95f4efb2011-06-08 15:11:56 -07002263 if (inode_has_perm_noadp(cred, inode,
2264 FILE__READ | FILE__WRITE, 0)) {
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002265 drop_tty = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002266 }
2267 }
Nick Pigginee2ffa02010-08-18 04:37:35 +10002268 spin_unlock(&tty_files_lock);
Alan Cox452a00d2008-10-13 10:39:13 +01002269 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002270 }
Eric W. Biederman98a27ba2007-05-08 00:26:56 -07002271 /* Reset controlling tty. */
2272 if (drop_tty)
2273 no_tty();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002274
2275 /* Revalidate access to inherited open files. */
2276
Eric Parisf48b7392011-04-25 12:54:27 -04002277 COMMON_AUDIT_DATA_INIT(&ad, INODE);
Eric Paris3b3b0e42012-04-03 09:37:02 -07002278 ad.selinux_audit_data = &sad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002279
2280 spin_lock(&files->file_lock);
2281 for (;;) {
2282 unsigned long set, i;
2283 int fd;
2284
2285 j++;
Josh Boyerf17e9232012-07-25 10:40:34 -04002286 i = j * BITS_PER_LONG;
Dipankar Sarmabadf1662005-09-09 13:04:10 -07002287 fdt = files_fdtable(files);
Vadim Lobanovbbea9f62006-12-10 02:21:12 -08002288 if (i >= fdt->max_fds)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002289 break;
David Howells1fd36ad2012-02-16 17:49:54 +00002290 set = fdt->open_fds[j];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002291 if (!set)
2292 continue;
2293 spin_unlock(&files->file_lock);
Eric Paris828dfe12008-04-17 13:17:49 -04002294 for ( ; set ; i++, set >>= 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002295 if (set & 1) {
2296 file = fget(i);
2297 if (!file)
2298 continue;
David Howells88e67f32008-11-14 10:39:21 +11002299 if (file_has_perm(cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002300 file,
2301 file_to_av(file))) {
2302 sys_close(i);
2303 fd = get_unused_fd();
2304 if (fd != i) {
2305 if (fd >= 0)
2306 put_unused_fd(fd);
2307 fput(file);
2308 continue;
2309 }
2310 if (devnull) {
Nick Piggin095975d2006-01-08 01:02:19 -08002311 get_file(devnull);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002312 } else {
David Howells745ca242008-11-14 10:39:22 +11002313 devnull = dentry_open(
2314 dget(selinux_null),
2315 mntget(selinuxfs_mount),
2316 O_RDWR, cred);
Akinobu Mitafc5d81e2006-11-27 15:16:48 +09002317 if (IS_ERR(devnull)) {
2318 devnull = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002319 put_unused_fd(fd);
2320 fput(file);
2321 continue;
2322 }
2323 }
2324 fd_install(fd, devnull);
2325 }
2326 fput(file);
2327 }
2328 }
2329 spin_lock(&files->file_lock);
2330
2331 }
2332 spin_unlock(&files->file_lock);
2333}
2334
Linus Torvalds1da177e2005-04-16 15:20:36 -07002335/*
David Howellsa6f76f22008-11-14 10:39:24 +11002336 * Prepare a process for imminent new credential changes due to exec
Linus Torvalds1da177e2005-04-16 15:20:36 -07002337 */
David Howellsa6f76f22008-11-14 10:39:24 +11002338static void selinux_bprm_committing_creds(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002339{
David Howellsa6f76f22008-11-14 10:39:24 +11002340 struct task_security_struct *new_tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002341 struct rlimit *rlim, *initrlim;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002342 int rc, i;
2343
David Howellsa6f76f22008-11-14 10:39:24 +11002344 new_tsec = bprm->cred->security;
2345 if (new_tsec->sid == new_tsec->osid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002346 return;
2347
2348 /* Close files for which the new task SID is not authorized. */
David Howellsa6f76f22008-11-14 10:39:24 +11002349 flush_unauthorized_files(bprm->cred, current->files);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002350
David Howellsa6f76f22008-11-14 10:39:24 +11002351 /* Always clear parent death signal on SID transitions. */
2352 current->pdeath_signal = 0;
2353
2354 /* Check whether the new SID can inherit resource limits from the old
2355 * SID. If not, reset all soft limits to the lower of the current
2356 * task's hard limit and the init task's soft limit.
2357 *
2358 * Note that the setting of hard limits (even to lower them) can be
2359 * controlled by the setrlimit check. The inclusion of the init task's
2360 * soft limit into the computation is to avoid resetting soft limits
2361 * higher than the default soft limit for cases where the default is
2362 * lower than the hard limit, e.g. RLIMIT_CORE or RLIMIT_STACK.
2363 */
2364 rc = avc_has_perm(new_tsec->osid, new_tsec->sid, SECCLASS_PROCESS,
2365 PROCESS__RLIMITINH, NULL);
2366 if (rc) {
Oleg Nesteroveb2d55a2010-06-23 22:43:32 +02002367 /* protect against do_prlimit() */
2368 task_lock(current);
David Howellsa6f76f22008-11-14 10:39:24 +11002369 for (i = 0; i < RLIM_NLIMITS; i++) {
2370 rlim = current->signal->rlim + i;
2371 initrlim = init_task.signal->rlim + i;
2372 rlim->rlim_cur = min(rlim->rlim_max, initrlim->rlim_cur);
2373 }
Oleg Nesteroveb2d55a2010-06-23 22:43:32 +02002374 task_unlock(current);
2375 update_rlimit_cpu(current, rlimit(RLIMIT_CPU));
David Howellsa6f76f22008-11-14 10:39:24 +11002376 }
2377}
2378
2379/*
2380 * Clean up the process immediately after the installation of new credentials
2381 * due to exec
2382 */
2383static void selinux_bprm_committed_creds(struct linux_binprm *bprm)
2384{
2385 const struct task_security_struct *tsec = current_security();
2386 struct itimerval itimer;
David Howellsa6f76f22008-11-14 10:39:24 +11002387 u32 osid, sid;
2388 int rc, i;
David Howellsa6f76f22008-11-14 10:39:24 +11002389
David Howellsa6f76f22008-11-14 10:39:24 +11002390 osid = tsec->osid;
2391 sid = tsec->sid;
2392
2393 if (sid == osid)
2394 return;
2395
2396 /* Check whether the new SID can inherit signal state from the old SID.
2397 * If not, clear itimers to avoid subsequent signal generation and
2398 * flush and unblock signals.
2399 *
2400 * This must occur _after_ the task SID has been updated so that any
2401 * kill done after the flush will be checked against the new SID.
2402 */
2403 rc = avc_has_perm(osid, sid, SECCLASS_PROCESS, PROCESS__SIGINH, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002404 if (rc) {
2405 memset(&itimer, 0, sizeof itimer);
2406 for (i = 0; i < 3; i++)
2407 do_setitimer(i, &itimer, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002408 spin_lock_irq(&current->sighand->siglock);
David Howells3bcac022009-04-29 13:45:05 +01002409 if (!(current->signal->flags & SIGNAL_GROUP_EXIT)) {
2410 __flush_signals(current);
2411 flush_signal_handlers(current, 1);
2412 sigemptyset(&current->blocked);
2413 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002414 spin_unlock_irq(&current->sighand->siglock);
2415 }
2416
David Howellsa6f76f22008-11-14 10:39:24 +11002417 /* Wake up the parent if it is waiting so that it can recheck
2418 * wait permission to the new task SID. */
Oleg Nesterovecd6de32009-04-29 16:02:24 +02002419 read_lock(&tasklist_lock);
Oleg Nesterov0b7570e2009-09-23 15:56:46 -07002420 __wake_up_parent(current, current->real_parent);
Oleg Nesterovecd6de32009-04-29 16:02:24 +02002421 read_unlock(&tasklist_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002422}
2423
2424/* superblock security operations */
2425
2426static int selinux_sb_alloc_security(struct super_block *sb)
2427{
2428 return superblock_alloc_security(sb);
2429}
2430
2431static void selinux_sb_free_security(struct super_block *sb)
2432{
2433 superblock_free_security(sb);
2434}
2435
2436static inline int match_prefix(char *prefix, int plen, char *option, int olen)
2437{
2438 if (plen > olen)
2439 return 0;
2440
2441 return !memcmp(prefix, option, plen);
2442}
2443
2444static inline int selinux_option(char *option, int len)
2445{
Eric Paris832cbd92008-04-01 13:24:09 -04002446 return (match_prefix(CONTEXT_STR, sizeof(CONTEXT_STR)-1, option, len) ||
2447 match_prefix(FSCONTEXT_STR, sizeof(FSCONTEXT_STR)-1, option, len) ||
2448 match_prefix(DEFCONTEXT_STR, sizeof(DEFCONTEXT_STR)-1, option, len) ||
David P. Quigley11689d42009-01-16 09:22:03 -05002449 match_prefix(ROOTCONTEXT_STR, sizeof(ROOTCONTEXT_STR)-1, option, len) ||
2450 match_prefix(LABELSUPP_STR, sizeof(LABELSUPP_STR)-1, option, len));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002451}
2452
2453static inline void take_option(char **to, char *from, int *first, int len)
2454{
2455 if (!*first) {
2456 **to = ',';
2457 *to += 1;
Cory Olmo3528a952006-09-29 01:58:44 -07002458 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002459 *first = 0;
2460 memcpy(*to, from, len);
2461 *to += len;
2462}
2463
Eric Paris828dfe12008-04-17 13:17:49 -04002464static inline void take_selinux_option(char **to, char *from, int *first,
2465 int len)
Cory Olmo3528a952006-09-29 01:58:44 -07002466{
2467 int current_size = 0;
2468
2469 if (!*first) {
2470 **to = '|';
2471 *to += 1;
Eric Paris828dfe12008-04-17 13:17:49 -04002472 } else
Cory Olmo3528a952006-09-29 01:58:44 -07002473 *first = 0;
2474
2475 while (current_size < len) {
2476 if (*from != '"') {
2477 **to = *from;
2478 *to += 1;
2479 }
2480 from += 1;
2481 current_size += 1;
2482 }
2483}
2484
Eric Parise0007522008-03-05 10:31:54 -05002485static int selinux_sb_copy_data(char *orig, char *copy)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002486{
2487 int fnosec, fsec, rc = 0;
2488 char *in_save, *in_curr, *in_end;
2489 char *sec_curr, *nosec_save, *nosec;
Cory Olmo3528a952006-09-29 01:58:44 -07002490 int open_quote = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002491
2492 in_curr = orig;
2493 sec_curr = copy;
2494
Linus Torvalds1da177e2005-04-16 15:20:36 -07002495 nosec = (char *)get_zeroed_page(GFP_KERNEL);
2496 if (!nosec) {
2497 rc = -ENOMEM;
2498 goto out;
2499 }
2500
2501 nosec_save = nosec;
2502 fnosec = fsec = 1;
2503 in_save = in_end = orig;
2504
2505 do {
Cory Olmo3528a952006-09-29 01:58:44 -07002506 if (*in_end == '"')
2507 open_quote = !open_quote;
2508 if ((*in_end == ',' && open_quote == 0) ||
2509 *in_end == '\0') {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002510 int len = in_end - in_curr;
2511
2512 if (selinux_option(in_curr, len))
Cory Olmo3528a952006-09-29 01:58:44 -07002513 take_selinux_option(&sec_curr, in_curr, &fsec, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002514 else
2515 take_option(&nosec, in_curr, &fnosec, len);
2516
2517 in_curr = in_end + 1;
2518 }
2519 } while (*in_end++);
2520
Eric Paris6931dfc2005-06-30 02:58:51 -07002521 strcpy(in_save, nosec_save);
Gerald Schaeferda3caa22005-06-21 17:15:18 -07002522 free_page((unsigned long)nosec_save);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002523out:
2524 return rc;
2525}
2526
Eric Paris026eb162011-03-03 16:09:14 -05002527static int selinux_sb_remount(struct super_block *sb, void *data)
2528{
2529 int rc, i, *flags;
2530 struct security_mnt_opts opts;
2531 char *secdata, **mount_options;
2532 struct superblock_security_struct *sbsec = sb->s_security;
2533
2534 if (!(sbsec->flags & SE_SBINITIALIZED))
2535 return 0;
2536
2537 if (!data)
2538 return 0;
2539
2540 if (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)
2541 return 0;
2542
2543 security_init_mnt_opts(&opts);
2544 secdata = alloc_secdata();
2545 if (!secdata)
2546 return -ENOMEM;
2547 rc = selinux_sb_copy_data(data, secdata);
2548 if (rc)
2549 goto out_free_secdata;
2550
2551 rc = selinux_parse_opts_str(secdata, &opts);
2552 if (rc)
2553 goto out_free_secdata;
2554
2555 mount_options = opts.mnt_opts;
2556 flags = opts.mnt_opts_flags;
2557
2558 for (i = 0; i < opts.num_mnt_opts; i++) {
2559 u32 sid;
2560 size_t len;
2561
2562 if (flags[i] == SE_SBLABELSUPP)
2563 continue;
2564 len = strlen(mount_options[i]);
2565 rc = security_context_to_sid(mount_options[i], len, &sid);
2566 if (rc) {
2567 printk(KERN_WARNING "SELinux: security_context_to_sid"
2568 "(%s) failed for (dev %s, type %s) errno=%d\n",
2569 mount_options[i], sb->s_id, sb->s_type->name, rc);
2570 goto out_free_opts;
2571 }
2572 rc = -EINVAL;
2573 switch (flags[i]) {
2574 case FSCONTEXT_MNT:
2575 if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid, sid))
2576 goto out_bad_option;
2577 break;
2578 case CONTEXT_MNT:
2579 if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid, sid))
2580 goto out_bad_option;
2581 break;
2582 case ROOTCONTEXT_MNT: {
2583 struct inode_security_struct *root_isec;
2584 root_isec = sb->s_root->d_inode->i_security;
2585
2586 if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid, sid))
2587 goto out_bad_option;
2588 break;
2589 }
2590 case DEFCONTEXT_MNT:
2591 if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid, sid))
2592 goto out_bad_option;
2593 break;
2594 default:
2595 goto out_free_opts;
2596 }
2597 }
2598
2599 rc = 0;
2600out_free_opts:
2601 security_free_mnt_opts(&opts);
2602out_free_secdata:
2603 free_secdata(secdata);
2604 return rc;
2605out_bad_option:
2606 printk(KERN_WARNING "SELinux: unable to change security options "
2607 "during remount (dev %s, type=%s)\n", sb->s_id,
2608 sb->s_type->name);
2609 goto out_free_opts;
2610}
2611
James Morris12204e22008-12-19 10:44:42 +11002612static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002613{
David Howells88e67f32008-11-14 10:39:21 +11002614 const struct cred *cred = current_cred();
Thomas Liu2bf49692009-07-14 12:14:09 -04002615 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07002616 struct selinux_audit_data sad = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07002617 int rc;
2618
2619 rc = superblock_doinit(sb, data);
2620 if (rc)
2621 return rc;
2622
James Morris74192242008-12-19 11:41:10 +11002623 /* Allow all mounts performed by the kernel */
2624 if (flags & MS_KERNMOUNT)
2625 return 0;
2626
Eric Parisa2694342011-04-25 13:10:27 -04002627 COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
Eric Paris3b3b0e42012-04-03 09:37:02 -07002628 ad.selinux_audit_data = &sad;
Eric Parisa2694342011-04-25 13:10:27 -04002629 ad.u.dentry = sb->s_root;
David Howells88e67f32008-11-14 10:39:21 +11002630 return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002631}
2632
David Howells726c3342006-06-23 02:02:58 -07002633static int selinux_sb_statfs(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002634{
David Howells88e67f32008-11-14 10:39:21 +11002635 const struct cred *cred = current_cred();
Thomas Liu2bf49692009-07-14 12:14:09 -04002636 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07002637 struct selinux_audit_data sad = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07002638
Eric Parisa2694342011-04-25 13:10:27 -04002639 COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
Eric Paris3b3b0e42012-04-03 09:37:02 -07002640 ad.selinux_audit_data = &sad;
Eric Parisa2694342011-04-25 13:10:27 -04002641 ad.u.dentry = dentry->d_sb->s_root;
David Howells88e67f32008-11-14 10:39:21 +11002642 return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002643}
2644
Al Viroddaa16d2012-10-11 11:42:01 -04002645static int selinux_mount(const char *dev_name,
Al Virob5266eb2008-03-22 17:48:24 -04002646 struct path *path,
Al Viroddaa16d2012-10-11 11:42:01 -04002647 const char *type,
Eric Paris828dfe12008-04-17 13:17:49 -04002648 unsigned long flags,
2649 void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002650{
David Howells88e67f32008-11-14 10:39:21 +11002651 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002652
2653 if (flags & MS_REMOUNT)
Al Virod8c95842011-12-07 18:16:57 -05002654 return superblock_has_perm(cred, path->dentry->d_sb,
Eric Paris828dfe12008-04-17 13:17:49 -04002655 FILESYSTEM__REMOUNT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002656 else
Eric Paris2875fa02011-04-28 16:04:24 -04002657 return path_has_perm(cred, path, FILE__MOUNTON);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002658}
2659
2660static int selinux_umount(struct vfsmount *mnt, int flags)
2661{
David Howells88e67f32008-11-14 10:39:21 +11002662 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002663
David Howells88e67f32008-11-14 10:39:21 +11002664 return superblock_has_perm(cred, mnt->mnt_sb,
Eric Paris828dfe12008-04-17 13:17:49 -04002665 FILESYSTEM__UNMOUNT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002666}
2667
2668/* inode security operations */
2669
2670static int selinux_inode_alloc_security(struct inode *inode)
2671{
2672 return inode_alloc_security(inode);
2673}
2674
2675static void selinux_inode_free_security(struct inode *inode)
2676{
2677 inode_free_security(inode);
2678}
2679
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002680static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
Eric Paris2a7dba32011-02-01 11:05:39 -05002681 const struct qstr *qstr, char **name,
2682 void **value, size_t *len)
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002683{
Paul Moore5fb49872010-04-22 14:46:19 -04002684 const struct task_security_struct *tsec = current_security();
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002685 struct inode_security_struct *dsec;
2686 struct superblock_security_struct *sbsec;
David Howells275bb412008-11-14 10:39:19 +11002687 u32 sid, newsid, clen;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002688 int rc;
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002689 char *namep = NULL, *context;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002690
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002691 dsec = dir->i_security;
2692 sbsec = dir->i_sb->s_security;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002693
David Howells275bb412008-11-14 10:39:19 +11002694 sid = tsec->sid;
2695 newsid = tsec->create_sid;
2696
Eric Paris415103f2010-12-02 16:13:40 -05002697 if ((sbsec->flags & SE_SBINITIALIZED) &&
2698 (sbsec->behavior == SECURITY_FS_USE_MNTPOINT))
2699 newsid = sbsec->mntpoint_sid;
2700 else if (!newsid || !(sbsec->flags & SE_SBLABELSUPP)) {
David Howells275bb412008-11-14 10:39:19 +11002701 rc = security_transition_sid(sid, dsec->sid,
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002702 inode_mode_to_security_class(inode->i_mode),
Eric Paris652bb9b2011-02-01 11:05:40 -05002703 qstr, &newsid);
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002704 if (rc) {
2705 printk(KERN_WARNING "%s: "
2706 "security_transition_sid failed, rc=%d (dev=%s "
2707 "ino=%ld)\n",
Harvey Harrisondd6f9532008-03-06 10:03:59 +11002708 __func__,
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002709 -rc, inode->i_sb->s_id, inode->i_ino);
2710 return rc;
2711 }
2712 }
2713
Eric Paris296fddf2006-09-25 23:32:00 -07002714 /* Possibly defer initialization to selinux_complete_init. */
David P. Quigley0d90a7e2009-01-16 09:22:02 -05002715 if (sbsec->flags & SE_SBINITIALIZED) {
Eric Paris296fddf2006-09-25 23:32:00 -07002716 struct inode_security_struct *isec = inode->i_security;
2717 isec->sclass = inode_mode_to_security_class(inode->i_mode);
2718 isec->sid = newsid;
2719 isec->initialized = 1;
2720 }
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002721
David P. Quigleycd895962009-01-16 09:22:04 -05002722 if (!ss_initialized || !(sbsec->flags & SE_SBLABELSUPP))
Stephen Smalley25a74f32005-11-08 21:34:33 -08002723 return -EOPNOTSUPP;
2724
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002725 if (name) {
Josef Bacika02fe132008-04-04 09:35:05 +11002726 namep = kstrdup(XATTR_SELINUX_SUFFIX, GFP_NOFS);
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002727 if (!namep)
2728 return -ENOMEM;
2729 *name = namep;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002730 }
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002731
2732 if (value && len) {
Stephen Smalley12b29f32008-05-07 13:03:20 -04002733 rc = security_sid_to_context_force(newsid, &context, &clen);
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002734 if (rc) {
2735 kfree(namep);
2736 return rc;
2737 }
2738 *value = context;
2739 *len = clen;
2740 }
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002741
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002742 return 0;
2743}
2744
Al Viro4acdaf22011-07-26 01:42:34 -04002745static int selinux_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002746{
Amir Samuelov6a22e462014-05-26 11:44:06 +03002747 int ret;
2748
2749 ret = pft_inode_create(dir, dentry, mode);
2750 if (ret < 0)
2751 return ret;
2752
Linus Torvalds1da177e2005-04-16 15:20:36 -07002753 return may_create(dir, dentry, SECCLASS_FILE);
2754}
2755
Amir Samuelov6a22e462014-05-26 11:44:06 +03002756static int selinux_inode_post_create(struct inode *dir, struct dentry *dentry,
2757 umode_t mode)
2758{
2759 int ret;
2760
2761 ret = pft_inode_post_create(dir, dentry, mode);
2762
2763 return ret;
2764}
2765
Linus Torvalds1da177e2005-04-16 15:20:36 -07002766static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
2767{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002768 return may_link(dir, old_dentry, MAY_LINK);
2769}
2770
Linus Torvalds1da177e2005-04-16 15:20:36 -07002771static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry)
2772{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002773 return may_link(dir, dentry, MAY_UNLINK);
2774}
2775
2776static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry, const char *name)
2777{
2778 return may_create(dir, dentry, SECCLASS_LNK_FILE);
2779}
2780
Al Viro18bb1db2011-07-26 01:41:39 -04002781static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry, umode_t mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002782{
2783 return may_create(dir, dentry, SECCLASS_DIR);
2784}
2785
Linus Torvalds1da177e2005-04-16 15:20:36 -07002786static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry)
2787{
2788 return may_link(dir, dentry, MAY_RMDIR);
2789}
2790
Al Viro1a67aaf2011-07-26 01:52:52 -04002791static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002792{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002793 return may_create(dir, dentry, inode_mode_to_security_class(mode));
2794}
2795
Linus Torvalds1da177e2005-04-16 15:20:36 -07002796static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
Eric Paris828dfe12008-04-17 13:17:49 -04002797 struct inode *new_inode, struct dentry *new_dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002798{
Amir Samuelov6a22e462014-05-26 11:44:06 +03002799 int rc;
2800
2801 rc = pft_inode_rename(old_inode, old_dentry, new_inode, new_dentry);
2802 if (rc)
2803 return rc;
2804
Linus Torvalds1da177e2005-04-16 15:20:36 -07002805 return may_rename(old_inode, old_dentry, new_inode, new_dentry);
2806}
2807
Linus Torvalds1da177e2005-04-16 15:20:36 -07002808static int selinux_inode_readlink(struct dentry *dentry)
2809{
David Howells88e67f32008-11-14 10:39:21 +11002810 const struct cred *cred = current_cred();
2811
Eric Paris2875fa02011-04-28 16:04:24 -04002812 return dentry_has_perm(cred, dentry, FILE__READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002813}
2814
2815static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *nameidata)
2816{
David Howells88e67f32008-11-14 10:39:21 +11002817 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002818
Eric Paris2875fa02011-04-28 16:04:24 -04002819 return dentry_has_perm(cred, dentry, FILE__READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002820}
2821
Al Viroe74f71e2011-06-20 19:38:15 -04002822static int selinux_inode_permission(struct inode *inode, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002823{
David Howells88e67f32008-11-14 10:39:21 +11002824 const struct cred *cred = current_cred();
Eric Parisb782e0a2010-07-23 11:44:03 -04002825 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07002826 struct selinux_audit_data sad = {0,};
Eric Parisb782e0a2010-07-23 11:44:03 -04002827 u32 perms;
2828 bool from_access;
Al Virocf1dd1d2011-06-20 19:44:08 -04002829 unsigned flags = mask & MAY_NOT_BLOCK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002830
Eric Parisb782e0a2010-07-23 11:44:03 -04002831 from_access = mask & MAY_ACCESS;
Eric Parisd09ca732010-07-23 11:43:57 -04002832 mask &= (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND);
2833
Eric Parisb782e0a2010-07-23 11:44:03 -04002834 /* No permission to check. Existence test. */
2835 if (!mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002836 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002837
Eric Parisf48b7392011-04-25 12:54:27 -04002838 COMMON_AUDIT_DATA_INIT(&ad, INODE);
Eric Paris3b3b0e42012-04-03 09:37:02 -07002839 ad.selinux_audit_data = &sad;
Eric Parisf48b7392011-04-25 12:54:27 -04002840 ad.u.inode = inode;
Eric Parisb782e0a2010-07-23 11:44:03 -04002841
2842 if (from_access)
Eric Paris3b3b0e42012-04-03 09:37:02 -07002843 ad.selinux_audit_data->auditdeny |= FILE__AUDIT_ACCESS;
Eric Parisb782e0a2010-07-23 11:44:03 -04002844
2845 perms = file_mask_to_av(inode->i_mode, mask);
2846
Eric Paris9ade0cf2011-04-25 16:26:29 -04002847 return inode_has_perm(cred, inode, perms, &ad, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002848}
2849
2850static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
2851{
David Howells88e67f32008-11-14 10:39:21 +11002852 const struct cred *cred = current_cred();
Amerigo Wangbc6a6002009-08-20 19:29:02 -07002853 unsigned int ia_valid = iattr->ia_valid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002854
Amerigo Wangbc6a6002009-08-20 19:29:02 -07002855 /* ATTR_FORCE is just used for ATTR_KILL_S[UG]ID. */
2856 if (ia_valid & ATTR_FORCE) {
2857 ia_valid &= ~(ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_MODE |
2858 ATTR_FORCE);
2859 if (!ia_valid)
2860 return 0;
2861 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002862
Amerigo Wangbc6a6002009-08-20 19:29:02 -07002863 if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID |
2864 ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_TIMES_SET))
Eric Paris2875fa02011-04-28 16:04:24 -04002865 return dentry_has_perm(cred, dentry, FILE__SETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002866
Eric Paris2875fa02011-04-28 16:04:24 -04002867 return dentry_has_perm(cred, dentry, FILE__WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002868}
2869
2870static int selinux_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
2871{
David Howells88e67f32008-11-14 10:39:21 +11002872 const struct cred *cred = current_cred();
Eric Paris2875fa02011-04-28 16:04:24 -04002873 struct path path;
David Howells88e67f32008-11-14 10:39:21 +11002874
Eric Paris2875fa02011-04-28 16:04:24 -04002875 path.dentry = dentry;
2876 path.mnt = mnt;
2877
2878 return path_has_perm(cred, &path, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002879}
2880
David Howells8f0cfa52008-04-29 00:59:41 -07002881static int selinux_inode_setotherxattr(struct dentry *dentry, const char *name)
Serge E. Hallynb5376772007-10-16 23:31:36 -07002882{
David Howells88e67f32008-11-14 10:39:21 +11002883 const struct cred *cred = current_cred();
2884
Amir Samuelov6a22e462014-05-26 11:44:06 +03002885 if (pft_inode_set_xattr(dentry, name) < 0)
2886 return -EACCES;
2887
2888
Serge E. Hallynb5376772007-10-16 23:31:36 -07002889 if (!strncmp(name, XATTR_SECURITY_PREFIX,
2890 sizeof XATTR_SECURITY_PREFIX - 1)) {
2891 if (!strcmp(name, XATTR_NAME_CAPS)) {
2892 if (!capable(CAP_SETFCAP))
2893 return -EPERM;
2894 } else if (!capable(CAP_SYS_ADMIN)) {
2895 /* A different attribute in the security namespace.
2896 Restrict to administrator. */
2897 return -EPERM;
2898 }
2899 }
2900
2901 /* Not an attribute we recognize, so just check the
2902 ordinary setattr permission. */
Eric Paris2875fa02011-04-28 16:04:24 -04002903 return dentry_has_perm(cred, dentry, FILE__SETATTR);
Serge E. Hallynb5376772007-10-16 23:31:36 -07002904}
2905
David Howells8f0cfa52008-04-29 00:59:41 -07002906static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
2907 const void *value, size_t size, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002908{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002909 struct inode *inode = dentry->d_inode;
2910 struct inode_security_struct *isec = inode->i_security;
2911 struct superblock_security_struct *sbsec;
Thomas Liu2bf49692009-07-14 12:14:09 -04002912 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07002913 struct selinux_audit_data sad = {0,};
David Howells275bb412008-11-14 10:39:19 +11002914 u32 newsid, sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002915 int rc = 0;
2916
Serge E. Hallynb5376772007-10-16 23:31:36 -07002917 if (strcmp(name, XATTR_NAME_SELINUX))
2918 return selinux_inode_setotherxattr(dentry, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002919
2920 sbsec = inode->i_sb->s_security;
David P. Quigleycd895962009-01-16 09:22:04 -05002921 if (!(sbsec->flags & SE_SBLABELSUPP))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002922 return -EOPNOTSUPP;
2923
Serge E. Hallyn2e149672011-03-23 16:43:26 -07002924 if (!inode_owner_or_capable(inode))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002925 return -EPERM;
2926
Eric Parisa2694342011-04-25 13:10:27 -04002927 COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
Eric Paris3b3b0e42012-04-03 09:37:02 -07002928 ad.selinux_audit_data = &sad;
Eric Parisa2694342011-04-25 13:10:27 -04002929 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002930
David Howells275bb412008-11-14 10:39:19 +11002931 rc = avc_has_perm(sid, isec->sid, isec->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002932 FILE__RELABELFROM, &ad);
2933 if (rc)
2934 return rc;
2935
2936 rc = security_context_to_sid(value, size, &newsid);
Stephen Smalley12b29f32008-05-07 13:03:20 -04002937 if (rc == -EINVAL) {
2938 if (!capable(CAP_MAC_ADMIN))
2939 return rc;
2940 rc = security_context_to_sid_force(value, size, &newsid);
2941 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002942 if (rc)
2943 return rc;
2944
David Howells275bb412008-11-14 10:39:19 +11002945 rc = avc_has_perm(sid, newsid, isec->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002946 FILE__RELABELTO, &ad);
2947 if (rc)
2948 return rc;
2949
David Howells275bb412008-11-14 10:39:19 +11002950 rc = security_validate_transition(isec->sid, newsid, sid,
Eric Paris828dfe12008-04-17 13:17:49 -04002951 isec->sclass);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002952 if (rc)
2953 return rc;
2954
2955 return avc_has_perm(newsid,
2956 sbsec->sid,
2957 SECCLASS_FILESYSTEM,
2958 FILESYSTEM__ASSOCIATE,
2959 &ad);
2960}
2961
David Howells8f0cfa52008-04-29 00:59:41 -07002962static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
Eric Parisf5269712008-05-14 11:27:45 -04002963 const void *value, size_t size,
David Howells8f0cfa52008-04-29 00:59:41 -07002964 int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002965{
2966 struct inode *inode = dentry->d_inode;
2967 struct inode_security_struct *isec = inode->i_security;
2968 u32 newsid;
2969 int rc;
2970
2971 if (strcmp(name, XATTR_NAME_SELINUX)) {
2972 /* Not an attribute we recognize, so nothing to do. */
2973 return;
2974 }
2975
Stephen Smalley12b29f32008-05-07 13:03:20 -04002976 rc = security_context_to_sid_force(value, size, &newsid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002977 if (rc) {
Stephen Smalley12b29f32008-05-07 13:03:20 -04002978 printk(KERN_ERR "SELinux: unable to map context to SID"
2979 "for (%s, %lu), rc=%d\n",
2980 inode->i_sb->s_id, inode->i_ino, -rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002981 return;
2982 }
2983
2984 isec->sid = newsid;
2985 return;
2986}
2987
David Howells8f0cfa52008-04-29 00:59:41 -07002988static int selinux_inode_getxattr(struct dentry *dentry, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002989{
David Howells88e67f32008-11-14 10:39:21 +11002990 const struct cred *cred = current_cred();
2991
Eric Paris2875fa02011-04-28 16:04:24 -04002992 return dentry_has_perm(cred, dentry, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002993}
2994
Eric Paris828dfe12008-04-17 13:17:49 -04002995static int selinux_inode_listxattr(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002996{
David Howells88e67f32008-11-14 10:39:21 +11002997 const struct cred *cred = current_cred();
2998
Eric Paris2875fa02011-04-28 16:04:24 -04002999 return dentry_has_perm(cred, dentry, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003000}
3001
David Howells8f0cfa52008-04-29 00:59:41 -07003002static int selinux_inode_removexattr(struct dentry *dentry, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003003{
Serge E. Hallynb5376772007-10-16 23:31:36 -07003004 if (strcmp(name, XATTR_NAME_SELINUX))
3005 return selinux_inode_setotherxattr(dentry, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003006
3007 /* No one is allowed to remove a SELinux security label.
3008 You can change the label, but all data must be labeled. */
3009 return -EACCES;
3010}
3011
James Morrisd381d8a2005-10-30 14:59:22 -08003012/*
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04003013 * Copy the inode security context value to the user.
James Morrisd381d8a2005-10-30 14:59:22 -08003014 *
3015 * Permission check is handled by selinux_inode_getxattr hook.
3016 */
David P. Quigley42492592008-02-04 22:29:39 -08003017static int selinux_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003018{
David P. Quigley42492592008-02-04 22:29:39 -08003019 u32 size;
3020 int error;
3021 char *context = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003022 struct inode_security_struct *isec = inode->i_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003023
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00003024 if (strcmp(name, XATTR_SELINUX_SUFFIX))
3025 return -EOPNOTSUPP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003026
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04003027 /*
3028 * If the caller has CAP_MAC_ADMIN, then get the raw context
3029 * value even if it is not defined by current policy; otherwise,
3030 * use the in-core value under current policy.
3031 * Use the non-auditing forms of the permission checks since
3032 * getxattr may be called by unprivileged processes commonly
3033 * and lack of permission just means that we fall back to the
3034 * in-core context value, not a denial.
3035 */
Eric Paris6a9de492012-01-03 12:25:14 -05003036 error = selinux_capable(current_cred(), &init_user_ns, CAP_MAC_ADMIN,
David Howells3699c532009-01-06 22:27:01 +00003037 SECURITY_CAP_NOAUDIT);
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04003038 if (!error)
3039 error = security_sid_to_context_force(isec->sid, &context,
3040 &size);
3041 else
3042 error = security_sid_to_context(isec->sid, &context, &size);
David P. Quigley42492592008-02-04 22:29:39 -08003043 if (error)
3044 return error;
3045 error = size;
3046 if (alloc) {
3047 *buffer = context;
3048 goto out_nofree;
3049 }
3050 kfree(context);
3051out_nofree:
3052 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003053}
3054
3055static int selinux_inode_setsecurity(struct inode *inode, const char *name,
Eric Paris828dfe12008-04-17 13:17:49 -04003056 const void *value, size_t size, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003057{
3058 struct inode_security_struct *isec = inode->i_security;
3059 u32 newsid;
3060 int rc;
3061
3062 if (strcmp(name, XATTR_SELINUX_SUFFIX))
3063 return -EOPNOTSUPP;
3064
3065 if (!value || !size)
3066 return -EACCES;
3067
Eric Paris828dfe12008-04-17 13:17:49 -04003068 rc = security_context_to_sid((void *)value, size, &newsid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003069 if (rc)
3070 return rc;
3071
3072 isec->sid = newsid;
David P. Quigleyddd29ec2009-09-09 14:25:37 -04003073 isec->initialized = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003074 return 0;
3075}
3076
3077static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size)
3078{
3079 const int len = sizeof(XATTR_NAME_SELINUX);
3080 if (buffer && len <= buffer_size)
3081 memcpy(buffer, XATTR_NAME_SELINUX, len);
3082 return len;
3083}
3084
Ahmed S. Darwish713a04a2008-03-01 21:52:30 +02003085static void selinux_inode_getsecid(const struct inode *inode, u32 *secid)
3086{
3087 struct inode_security_struct *isec = inode->i_security;
3088 *secid = isec->sid;
3089}
3090
Linus Torvalds1da177e2005-04-16 15:20:36 -07003091/* file security operations */
3092
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003093static int selinux_revalidate_file_permission(struct file *file, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003094{
David Howells88e67f32008-11-14 10:39:21 +11003095 const struct cred *cred = current_cred();
Josef Sipek3d5ff522006-12-08 02:37:38 -08003096 struct inode *inode = file->f_path.dentry->d_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003097
Linus Torvalds1da177e2005-04-16 15:20:36 -07003098 /* file_mask_to_av won't add FILE__WRITE if MAY_APPEND is set */
3099 if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE))
3100 mask |= MAY_APPEND;
3101
Paul Moore389fb802009-03-27 17:10:34 -04003102 return file_has_perm(cred, file,
3103 file_mask_to_av(inode->i_mode, mask));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003104}
3105
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003106static int selinux_file_permission(struct file *file, int mask)
3107{
Stephen Smalley20dda182009-06-22 14:54:53 -04003108 struct inode *inode = file->f_path.dentry->d_inode;
3109 struct file_security_struct *fsec = file->f_security;
3110 struct inode_security_struct *isec = inode->i_security;
3111 u32 sid = current_sid();
Amir Samuelov6a22e462014-05-26 11:44:06 +03003112 int ret;
Stephen Smalley20dda182009-06-22 14:54:53 -04003113
Paul Moore389fb802009-03-27 17:10:34 -04003114 if (!mask)
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003115 /* No permission to check. Existence test. */
3116 return 0;
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003117
Amir Samuelov6a22e462014-05-26 11:44:06 +03003118 ret = pft_file_permission(file, mask);
3119 if (ret < 0)
3120 return ret;
3121
Stephen Smalley20dda182009-06-22 14:54:53 -04003122 if (sid == fsec->sid && fsec->isid == isec->sid &&
3123 fsec->pseqno == avc_policy_seqno())
3124 /* No change since dentry_open check. */
3125 return 0;
3126
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003127 return selinux_revalidate_file_permission(file, mask);
3128}
3129
Linus Torvalds1da177e2005-04-16 15:20:36 -07003130static int selinux_file_alloc_security(struct file *file)
3131{
3132 return file_alloc_security(file);
3133}
3134
3135static void selinux_file_free_security(struct file *file)
3136{
3137 file_free_security(file);
3138}
3139
Jeff Vander Stoep581be712015-07-10 17:19:56 -04003140/*
3141 * Check whether a task has the ioctl permission and cmd
3142 * operation to an inode.
3143 */
3144int ioctl_has_perm(const struct cred *cred, struct file *file,
3145 u32 requested, u16 cmd)
3146{
3147 struct common_audit_data ad;
3148 struct file_security_struct *fsec = file->f_security;
3149 struct inode *inode = file->f_path.dentry->d_inode;
3150 struct inode_security_struct *isec = inode->i_security;
3151 struct lsm_ioctlop_audit ioctl;
3152 u32 ssid = cred_sid(cred);
3153 struct selinux_audit_data sad = {0,};
3154 int rc;
3155 u8 driver = cmd >> 8;
3156 u8 xperm = cmd & 0xff;
3157
3158 COMMON_AUDIT_DATA_INIT(&ad, IOCTL_OP);
3159 ad.u.op = &ioctl;
3160 ad.u.op->cmd = cmd;
3161 ad.selinux_audit_data = &sad;
3162 ad.u.op->path = file->f_path;
3163
3164 if (ssid != fsec->sid) {
3165 rc = avc_has_perm(ssid, fsec->sid,
3166 SECCLASS_FD,
3167 FD__USE,
3168 &ad);
3169 if (rc)
3170 goto out;
3171 }
3172
3173 if (unlikely(IS_PRIVATE(inode)))
3174 return 0;
3175
3176 rc = avc_has_extended_perms(ssid, isec->sid, isec->sclass,
3177 requested, driver, xperm, &ad);
3178out:
3179 return rc;
3180}
3181
Linus Torvalds1da177e2005-04-16 15:20:36 -07003182static int selinux_file_ioctl(struct file *file, unsigned int cmd,
3183 unsigned long arg)
3184{
David Howells88e67f32008-11-14 10:39:21 +11003185 const struct cred *cred = current_cred();
Eric Paris0b24dcb2011-02-25 15:39:20 -05003186 int error = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003187
Eric Paris0b24dcb2011-02-25 15:39:20 -05003188 switch (cmd) {
3189 case FIONREAD:
3190 /* fall through */
3191 case FIBMAP:
3192 /* fall through */
3193 case FIGETBSZ:
3194 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003195 case FS_IOC_GETFLAGS:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003196 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003197 case FS_IOC_GETVERSION:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003198 error = file_has_perm(cred, file, FILE__GETATTR);
3199 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003200
Al Viro2f99c362012-03-23 16:04:05 -04003201 case FS_IOC_SETFLAGS:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003202 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003203 case FS_IOC_SETVERSION:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003204 error = file_has_perm(cred, file, FILE__SETATTR);
3205 break;
3206
3207 /* sys_ioctl() checks */
3208 case FIONBIO:
3209 /* fall through */
3210 case FIOASYNC:
3211 error = file_has_perm(cred, file, 0);
3212 break;
3213
3214 case KDSKBENT:
3215 case KDSKBSENT:
Eric Paris6a9de492012-01-03 12:25:14 -05003216 error = cred_has_capability(cred, CAP_SYS_TTY_CONFIG,
3217 SECURITY_CAP_AUDIT);
Eric Paris0b24dcb2011-02-25 15:39:20 -05003218 break;
3219
3220 /* default case assumes that the command will go
3221 * to the file's ioctl() function.
3222 */
3223 default:
Jeff Vander Stoep581be712015-07-10 17:19:56 -04003224 error = ioctl_has_perm(cred, file, FILE__IOCTL, (u16) cmd);
Eric Paris0b24dcb2011-02-25 15:39:20 -05003225 }
3226 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003227}
3228
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003229static int default_noexec;
3230
Linus Torvalds1da177e2005-04-16 15:20:36 -07003231static int file_map_prot_check(struct file *file, unsigned long prot, int shared)
3232{
David Howells88e67f32008-11-14 10:39:21 +11003233 const struct cred *cred = current_cred();
David Howellsd84f4f92008-11-14 10:39:23 +11003234 int rc = 0;
David Howells88e67f32008-11-14 10:39:21 +11003235
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003236 if (default_noexec &&
3237 (prot & PROT_EXEC) && (!file || (!shared && (prot & PROT_WRITE)))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003238 /*
3239 * We are making executable an anonymous mapping or a
3240 * private file mapping that will also be writable.
3241 * This has an additional check.
3242 */
David Howellsd84f4f92008-11-14 10:39:23 +11003243 rc = cred_has_perm(cred, cred, PROCESS__EXECMEM);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003244 if (rc)
David Howellsd84f4f92008-11-14 10:39:23 +11003245 goto error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003246 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003247
3248 if (file) {
3249 /* read access is always possible with a mapping */
3250 u32 av = FILE__READ;
3251
3252 /* write access only matters if the mapping is shared */
3253 if (shared && (prot & PROT_WRITE))
3254 av |= FILE__WRITE;
3255
3256 if (prot & PROT_EXEC)
3257 av |= FILE__EXECUTE;
3258
David Howells88e67f32008-11-14 10:39:21 +11003259 return file_has_perm(cred, file, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003260 }
David Howellsd84f4f92008-11-14 10:39:23 +11003261
3262error:
3263 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003264}
3265
3266static int selinux_file_mmap(struct file *file, unsigned long reqprot,
Eric Parised032182007-06-28 15:55:21 -04003267 unsigned long prot, unsigned long flags,
3268 unsigned long addr, unsigned long addr_only)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003269{
Eric Parised032182007-06-28 15:55:21 -04003270 int rc = 0;
David Howells275bb412008-11-14 10:39:19 +11003271 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003272
Eric Paris84336d1a2009-07-31 12:54:05 -04003273 /*
3274 * notice that we are intentionally putting the SELinux check before
3275 * the secondary cap_file_mmap check. This is such a likely attempt
3276 * at bad behaviour/exploit that we always want to get the AVC, even
3277 * if DAC would have also denied the operation.
3278 */
Eric Parisa2551df2009-07-31 12:54:11 -04003279 if (addr < CONFIG_LSM_MMAP_MIN_ADDR) {
Eric Parised032182007-06-28 15:55:21 -04003280 rc = avc_has_perm(sid, sid, SECCLASS_MEMPROTECT,
3281 MEMPROTECT__MMAP_ZERO, NULL);
Eric Paris84336d1a2009-07-31 12:54:05 -04003282 if (rc)
3283 return rc;
3284 }
3285
3286 /* do DAC check on address space usage */
3287 rc = cap_file_mmap(file, reqprot, prot, flags, addr, addr_only);
Eric Parised032182007-06-28 15:55:21 -04003288 if (rc || addr_only)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003289 return rc;
3290
3291 if (selinux_checkreqprot)
3292 prot = reqprot;
3293
3294 return file_map_prot_check(file, prot,
3295 (flags & MAP_TYPE) == MAP_SHARED);
3296}
3297
3298static int selinux_file_mprotect(struct vm_area_struct *vma,
3299 unsigned long reqprot,
3300 unsigned long prot)
3301{
David Howells88e67f32008-11-14 10:39:21 +11003302 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003303
3304 if (selinux_checkreqprot)
3305 prot = reqprot;
3306
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003307 if (default_noexec &&
3308 (prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) {
James Morrisd541bbe2009-01-29 12:19:51 +11003309 int rc = 0;
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003310 if (vma->vm_start >= vma->vm_mm->start_brk &&
3311 vma->vm_end <= vma->vm_mm->brk) {
David Howellsd84f4f92008-11-14 10:39:23 +11003312 rc = cred_has_perm(cred, cred, PROCESS__EXECHEAP);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003313 } else if (!vma->vm_file &&
3314 vma->vm_start <= vma->vm_mm->start_stack &&
3315 vma->vm_end >= vma->vm_mm->start_stack) {
David Howells3b11a1d2008-11-14 10:39:26 +11003316 rc = current_has_perm(current, PROCESS__EXECSTACK);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003317 } else if (vma->vm_file && vma->anon_vma) {
3318 /*
3319 * We are making executable a file mapping that has
3320 * had some COW done. Since pages might have been
3321 * written, check ability to execute the possibly
3322 * modified content. This typically should only
3323 * occur for text relocations.
3324 */
David Howellsd84f4f92008-11-14 10:39:23 +11003325 rc = file_has_perm(cred, vma->vm_file, FILE__EXECMOD);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003326 }
Lorenzo Hernandez García-Hierro6b992192005-06-25 14:54:34 -07003327 if (rc)
3328 return rc;
3329 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003330
3331 return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED);
3332}
3333
3334static int selinux_file_lock(struct file *file, unsigned int cmd)
3335{
David Howells88e67f32008-11-14 10:39:21 +11003336 const struct cred *cred = current_cred();
3337
3338 return file_has_perm(cred, file, FILE__LOCK);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003339}
3340
3341static int selinux_file_fcntl(struct file *file, unsigned int cmd,
3342 unsigned long arg)
3343{
David Howells88e67f32008-11-14 10:39:21 +11003344 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003345 int err = 0;
3346
3347 switch (cmd) {
Eric Paris828dfe12008-04-17 13:17:49 -04003348 case F_SETFL:
3349 if (!file->f_path.dentry || !file->f_path.dentry->d_inode) {
3350 err = -EINVAL;
3351 break;
3352 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003353
Eric Paris828dfe12008-04-17 13:17:49 -04003354 if ((file->f_flags & O_APPEND) && !(arg & O_APPEND)) {
David Howells88e67f32008-11-14 10:39:21 +11003355 err = file_has_perm(cred, file, FILE__WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003356 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003357 }
3358 /* fall through */
3359 case F_SETOWN:
3360 case F_SETSIG:
3361 case F_GETFL:
3362 case F_GETOWN:
3363 case F_GETSIG:
3364 /* Just check FD__USE permission */
David Howells88e67f32008-11-14 10:39:21 +11003365 err = file_has_perm(cred, file, 0);
Eric Paris828dfe12008-04-17 13:17:49 -04003366 break;
3367 case F_GETLK:
3368 case F_SETLK:
3369 case F_SETLKW:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003370#if BITS_PER_LONG == 32
Eric Paris828dfe12008-04-17 13:17:49 -04003371 case F_GETLK64:
3372 case F_SETLK64:
3373 case F_SETLKW64:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003374#endif
Eric Paris828dfe12008-04-17 13:17:49 -04003375 if (!file->f_path.dentry || !file->f_path.dentry->d_inode) {
3376 err = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003377 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003378 }
David Howells88e67f32008-11-14 10:39:21 +11003379 err = file_has_perm(cred, file, FILE__LOCK);
Eric Paris828dfe12008-04-17 13:17:49 -04003380 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003381 }
3382
3383 return err;
3384}
3385
3386static int selinux_file_set_fowner(struct file *file)
3387{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003388 struct file_security_struct *fsec;
3389
Linus Torvalds1da177e2005-04-16 15:20:36 -07003390 fsec = file->f_security;
David Howells275bb412008-11-14 10:39:19 +11003391 fsec->fown_sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003392
3393 return 0;
3394}
3395
3396static int selinux_file_send_sigiotask(struct task_struct *tsk,
3397 struct fown_struct *fown, int signum)
3398{
Eric Paris828dfe12008-04-17 13:17:49 -04003399 struct file *file;
Stephen Smalley65c90bc2009-05-04 15:43:18 -04003400 u32 sid = task_sid(tsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003401 u32 perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003402 struct file_security_struct *fsec;
3403
3404 /* struct fown_struct is never outside the context of a struct file */
Eric Paris828dfe12008-04-17 13:17:49 -04003405 file = container_of(fown, struct file, f_owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003406
Linus Torvalds1da177e2005-04-16 15:20:36 -07003407 fsec = file->f_security;
3408
3409 if (!signum)
3410 perm = signal_to_av(SIGIO); /* as per send_sigio_to_task */
3411 else
3412 perm = signal_to_av(signum);
3413
David Howells275bb412008-11-14 10:39:19 +11003414 return avc_has_perm(fsec->fown_sid, sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003415 SECCLASS_PROCESS, perm, NULL);
3416}
3417
3418static int selinux_file_receive(struct file *file)
3419{
David Howells88e67f32008-11-14 10:39:21 +11003420 const struct cred *cred = current_cred();
3421
3422 return file_has_perm(cred, file, file_to_av(file));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003423}
3424
David Howells745ca242008-11-14 10:39:22 +11003425static int selinux_dentry_open(struct file *file, const struct cred *cred)
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003426{
3427 struct file_security_struct *fsec;
3428 struct inode *inode;
3429 struct inode_security_struct *isec;
Amir Samuelov6a22e462014-05-26 11:44:06 +03003430 int ret;
3431
3432 ret = pft_file_open(file, cred);
3433 if (ret < 0)
3434 return ret;
David Howellsd84f4f92008-11-14 10:39:23 +11003435
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003436 inode = file->f_path.dentry->d_inode;
3437 fsec = file->f_security;
3438 isec = inode->i_security;
3439 /*
3440 * Save inode label and policy sequence number
3441 * at open-time so that selinux_file_permission
3442 * can determine whether revalidation is necessary.
3443 * Task label is already saved in the file security
3444 * struct as its SID.
3445 */
3446 fsec->isid = isec->sid;
3447 fsec->pseqno = avc_policy_seqno();
3448 /*
3449 * Since the inode label or policy seqno may have changed
3450 * between the selinux_inode_permission check and the saving
3451 * of state above, recheck that access is still permitted.
3452 * Otherwise, access might never be revalidated against the
3453 * new inode label or new policy.
3454 * This check is not redundant - do not remove.
3455 */
Linus Torvalds95f4efb2011-06-08 15:11:56 -07003456 return inode_has_perm_noadp(cred, inode, open_file_to_av(file), 0);
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003457}
3458
Amir Samuelov6a22e462014-05-26 11:44:06 +03003459static int selinux_file_close(struct file *file)
3460{
3461 return pft_file_close(file);
3462}
3463
3464static bool selinux_allow_merge_bio(struct bio *bio1, struct bio *bio2)
3465{
3466 return pft_allow_merge_bio(bio1, bio2);
3467}
3468
Linus Torvalds1da177e2005-04-16 15:20:36 -07003469/* task security operations */
3470
3471static int selinux_task_create(unsigned long clone_flags)
3472{
David Howells3b11a1d2008-11-14 10:39:26 +11003473 return current_has_perm(current, PROCESS__FORK);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003474}
3475
David Howellsf1752ee2008-11-14 10:39:17 +11003476/*
David Howellsee18d642009-09-02 09:14:21 +01003477 * allocate the SELinux part of blank credentials
3478 */
3479static int selinux_cred_alloc_blank(struct cred *cred, gfp_t gfp)
3480{
3481 struct task_security_struct *tsec;
3482
3483 tsec = kzalloc(sizeof(struct task_security_struct), gfp);
3484 if (!tsec)
3485 return -ENOMEM;
3486
3487 cred->security = tsec;
3488 return 0;
3489}
3490
3491/*
David Howellsf1752ee2008-11-14 10:39:17 +11003492 * detach and free the LSM part of a set of credentials
3493 */
3494static void selinux_cred_free(struct cred *cred)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003495{
David Howellsf1752ee2008-11-14 10:39:17 +11003496 struct task_security_struct *tsec = cred->security;
David Howellse0e81732009-09-02 09:13:40 +01003497
Tetsuo Handa2edeaa32011-02-07 13:36:10 +00003498 /*
3499 * cred->security == NULL if security_cred_alloc_blank() or
3500 * security_prepare_creds() returned an error.
3501 */
3502 BUG_ON(cred->security && (unsigned long) cred->security < PAGE_SIZE);
David Howellse0e81732009-09-02 09:13:40 +01003503 cred->security = (void *) 0x7UL;
David Howellsf1752ee2008-11-14 10:39:17 +11003504 kfree(tsec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003505}
3506
David Howellsd84f4f92008-11-14 10:39:23 +11003507/*
3508 * prepare a new set of credentials for modification
3509 */
3510static int selinux_cred_prepare(struct cred *new, const struct cred *old,
3511 gfp_t gfp)
3512{
3513 const struct task_security_struct *old_tsec;
3514 struct task_security_struct *tsec;
3515
3516 old_tsec = old->security;
3517
3518 tsec = kmemdup(old_tsec, sizeof(struct task_security_struct), gfp);
3519 if (!tsec)
3520 return -ENOMEM;
3521
3522 new->security = tsec;
3523 return 0;
3524}
3525
3526/*
David Howellsee18d642009-09-02 09:14:21 +01003527 * transfer the SELinux data to a blank set of creds
3528 */
3529static void selinux_cred_transfer(struct cred *new, const struct cred *old)
3530{
3531 const struct task_security_struct *old_tsec = old->security;
3532 struct task_security_struct *tsec = new->security;
3533
3534 *tsec = *old_tsec;
3535}
3536
3537/*
David Howells3a3b7ce2008-11-14 10:39:28 +11003538 * set the security data for a kernel service
3539 * - all the creation contexts are set to unlabelled
3540 */
3541static int selinux_kernel_act_as(struct cred *new, u32 secid)
3542{
3543 struct task_security_struct *tsec = new->security;
3544 u32 sid = current_sid();
3545 int ret;
3546
3547 ret = avc_has_perm(sid, secid,
3548 SECCLASS_KERNEL_SERVICE,
3549 KERNEL_SERVICE__USE_AS_OVERRIDE,
3550 NULL);
3551 if (ret == 0) {
3552 tsec->sid = secid;
3553 tsec->create_sid = 0;
3554 tsec->keycreate_sid = 0;
3555 tsec->sockcreate_sid = 0;
3556 }
3557 return ret;
3558}
3559
3560/*
3561 * set the file creation context in a security record to the same as the
3562 * objective context of the specified inode
3563 */
3564static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode)
3565{
3566 struct inode_security_struct *isec = inode->i_security;
3567 struct task_security_struct *tsec = new->security;
3568 u32 sid = current_sid();
3569 int ret;
3570
3571 ret = avc_has_perm(sid, isec->sid,
3572 SECCLASS_KERNEL_SERVICE,
3573 KERNEL_SERVICE__CREATE_FILES_AS,
3574 NULL);
3575
3576 if (ret == 0)
3577 tsec->create_sid = isec->sid;
David Howellsef574712010-02-26 01:56:16 +00003578 return ret;
David Howells3a3b7ce2008-11-14 10:39:28 +11003579}
3580
Eric Parisdd8dbf22009-11-03 16:35:32 +11003581static int selinux_kernel_module_request(char *kmod_name)
Eric Paris25354c42009-08-13 09:45:03 -04003582{
Eric Parisdd8dbf22009-11-03 16:35:32 +11003583 u32 sid;
3584 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07003585 struct selinux_audit_data sad = {0,};
Eric Parisdd8dbf22009-11-03 16:35:32 +11003586
3587 sid = task_sid(current);
3588
3589 COMMON_AUDIT_DATA_INIT(&ad, KMOD);
Eric Paris3b3b0e42012-04-03 09:37:02 -07003590 ad.selinux_audit_data = &sad;
Eric Parisdd8dbf22009-11-03 16:35:32 +11003591 ad.u.kmod_name = kmod_name;
3592
3593 return avc_has_perm(sid, SECINITSID_KERNEL, SECCLASS_SYSTEM,
3594 SYSTEM__MODULE_REQUEST, &ad);
Eric Paris25354c42009-08-13 09:45:03 -04003595}
3596
Linus Torvalds1da177e2005-04-16 15:20:36 -07003597static int selinux_task_setpgid(struct task_struct *p, pid_t pgid)
3598{
David Howells3b11a1d2008-11-14 10:39:26 +11003599 return current_has_perm(p, PROCESS__SETPGID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003600}
3601
3602static int selinux_task_getpgid(struct task_struct *p)
3603{
David Howells3b11a1d2008-11-14 10:39:26 +11003604 return current_has_perm(p, PROCESS__GETPGID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003605}
3606
3607static int selinux_task_getsid(struct task_struct *p)
3608{
David Howells3b11a1d2008-11-14 10:39:26 +11003609 return current_has_perm(p, PROCESS__GETSESSION);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003610}
3611
David Quigleyf9008e42006-06-30 01:55:46 -07003612static void selinux_task_getsecid(struct task_struct *p, u32 *secid)
3613{
David Howells275bb412008-11-14 10:39:19 +11003614 *secid = task_sid(p);
David Quigleyf9008e42006-06-30 01:55:46 -07003615}
3616
Linus Torvalds1da177e2005-04-16 15:20:36 -07003617static int selinux_task_setnice(struct task_struct *p, int nice)
3618{
3619 int rc;
3620
Eric Paris200ac532009-02-12 15:01:04 -05003621 rc = cap_task_setnice(p, nice);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003622 if (rc)
3623 return rc;
3624
David Howells3b11a1d2008-11-14 10:39:26 +11003625 return current_has_perm(p, PROCESS__SETSCHED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003626}
3627
James Morris03e68062006-06-23 02:03:58 -07003628static int selinux_task_setioprio(struct task_struct *p, int ioprio)
3629{
Serge E. Hallynb5376772007-10-16 23:31:36 -07003630 int rc;
3631
Eric Paris200ac532009-02-12 15:01:04 -05003632 rc = cap_task_setioprio(p, ioprio);
Serge E. Hallynb5376772007-10-16 23:31:36 -07003633 if (rc)
3634 return rc;
3635
David Howells3b11a1d2008-11-14 10:39:26 +11003636 return current_has_perm(p, PROCESS__SETSCHED);
James Morris03e68062006-06-23 02:03:58 -07003637}
3638
David Quigleya1836a42006-06-30 01:55:49 -07003639static int selinux_task_getioprio(struct task_struct *p)
3640{
David Howells3b11a1d2008-11-14 10:39:26 +11003641 return current_has_perm(p, PROCESS__GETSCHED);
David Quigleya1836a42006-06-30 01:55:49 -07003642}
3643
Jiri Slaby8fd00b42009-08-26 18:41:16 +02003644static int selinux_task_setrlimit(struct task_struct *p, unsigned int resource,
3645 struct rlimit *new_rlim)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003646{
Jiri Slaby8fd00b42009-08-26 18:41:16 +02003647 struct rlimit *old_rlim = p->signal->rlim + resource;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003648
3649 /* Control the ability to change the hard limit (whether
3650 lowering or raising it), so that the hard limit can
3651 later be used as a safe reset point for the soft limit
David Howellsd84f4f92008-11-14 10:39:23 +11003652 upon context transitions. See selinux_bprm_committing_creds. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003653 if (old_rlim->rlim_max != new_rlim->rlim_max)
Jiri Slaby8fd00b42009-08-26 18:41:16 +02003654 return current_has_perm(p, PROCESS__SETRLIMIT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003655
3656 return 0;
3657}
3658
KOSAKI Motohirob0ae1982010-10-15 04:21:18 +09003659static int selinux_task_setscheduler(struct task_struct *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003660{
Serge E. Hallynb5376772007-10-16 23:31:36 -07003661 int rc;
3662
KOSAKI Motohirob0ae1982010-10-15 04:21:18 +09003663 rc = cap_task_setscheduler(p);
Serge E. Hallynb5376772007-10-16 23:31:36 -07003664 if (rc)
3665 return rc;
3666
David Howells3b11a1d2008-11-14 10:39:26 +11003667 return current_has_perm(p, PROCESS__SETSCHED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003668}
3669
3670static int selinux_task_getscheduler(struct task_struct *p)
3671{
David Howells3b11a1d2008-11-14 10:39:26 +11003672 return current_has_perm(p, PROCESS__GETSCHED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003673}
3674
David Quigley35601542006-06-23 02:04:01 -07003675static int selinux_task_movememory(struct task_struct *p)
3676{
David Howells3b11a1d2008-11-14 10:39:26 +11003677 return current_has_perm(p, PROCESS__SETSCHED);
David Quigley35601542006-06-23 02:04:01 -07003678}
3679
David Quigleyf9008e42006-06-30 01:55:46 -07003680static int selinux_task_kill(struct task_struct *p, struct siginfo *info,
3681 int sig, u32 secid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003682{
3683 u32 perm;
3684 int rc;
3685
Linus Torvalds1da177e2005-04-16 15:20:36 -07003686 if (!sig)
3687 perm = PROCESS__SIGNULL; /* null signal; existence test */
3688 else
3689 perm = signal_to_av(sig);
David Quigleyf9008e42006-06-30 01:55:46 -07003690 if (secid)
David Howells275bb412008-11-14 10:39:19 +11003691 rc = avc_has_perm(secid, task_sid(p),
3692 SECCLASS_PROCESS, perm, NULL);
David Quigleyf9008e42006-06-30 01:55:46 -07003693 else
David Howells3b11a1d2008-11-14 10:39:26 +11003694 rc = current_has_perm(p, perm);
David Quigleyf9008e42006-06-30 01:55:46 -07003695 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003696}
3697
Linus Torvalds1da177e2005-04-16 15:20:36 -07003698static int selinux_task_wait(struct task_struct *p)
3699{
Eric Paris8a535142007-10-22 16:10:31 -04003700 return task_has_perm(p, current, PROCESS__SIGCHLD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003701}
3702
Linus Torvalds1da177e2005-04-16 15:20:36 -07003703static void selinux_task_to_inode(struct task_struct *p,
3704 struct inode *inode)
3705{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003706 struct inode_security_struct *isec = inode->i_security;
David Howells275bb412008-11-14 10:39:19 +11003707 u32 sid = task_sid(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003708
David Howells275bb412008-11-14 10:39:19 +11003709 isec->sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003710 isec->initialized = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003711}
3712
Linus Torvalds1da177e2005-04-16 15:20:36 -07003713/* Returns error only if unable to parse addresses */
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003714static int selinux_parse_skb_ipv4(struct sk_buff *skb,
Thomas Liu2bf49692009-07-14 12:14:09 -04003715 struct common_audit_data *ad, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003716{
3717 int offset, ihlen, ret = -EINVAL;
3718 struct iphdr _iph, *ih;
3719
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03003720 offset = skb_network_offset(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003721 ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph);
3722 if (ih == NULL)
3723 goto out;
3724
3725 ihlen = ih->ihl * 4;
3726 if (ihlen < sizeof(_iph))
3727 goto out;
3728
Eric Paris48c62af2012-04-02 13:15:44 -04003729 ad->u.net->v4info.saddr = ih->saddr;
3730 ad->u.net->v4info.daddr = ih->daddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003731 ret = 0;
3732
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003733 if (proto)
3734 *proto = ih->protocol;
3735
Linus Torvalds1da177e2005-04-16 15:20:36 -07003736 switch (ih->protocol) {
Eric Paris828dfe12008-04-17 13:17:49 -04003737 case IPPROTO_TCP: {
3738 struct tcphdr _tcph, *th;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003739
Eric Paris828dfe12008-04-17 13:17:49 -04003740 if (ntohs(ih->frag_off) & IP_OFFSET)
3741 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003742
3743 offset += ihlen;
3744 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
3745 if (th == NULL)
3746 break;
3747
Eric Paris48c62af2012-04-02 13:15:44 -04003748 ad->u.net->sport = th->source;
3749 ad->u.net->dport = th->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003750 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003751 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003752
Eric Paris828dfe12008-04-17 13:17:49 -04003753 case IPPROTO_UDP: {
3754 struct udphdr _udph, *uh;
3755
3756 if (ntohs(ih->frag_off) & IP_OFFSET)
3757 break;
3758
3759 offset += ihlen;
3760 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
3761 if (uh == NULL)
3762 break;
3763
Eric Paris48c62af2012-04-02 13:15:44 -04003764 ad->u.net->sport = uh->source;
3765 ad->u.net->dport = uh->dest;
Eric Paris828dfe12008-04-17 13:17:49 -04003766 break;
3767 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003768
James Morris2ee92d42006-11-13 16:09:01 -08003769 case IPPROTO_DCCP: {
3770 struct dccp_hdr _dccph, *dh;
3771
3772 if (ntohs(ih->frag_off) & IP_OFFSET)
3773 break;
3774
3775 offset += ihlen;
3776 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
3777 if (dh == NULL)
3778 break;
3779
Eric Paris48c62af2012-04-02 13:15:44 -04003780 ad->u.net->sport = dh->dccph_sport;
3781 ad->u.net->dport = dh->dccph_dport;
James Morris2ee92d42006-11-13 16:09:01 -08003782 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003783 }
James Morris2ee92d42006-11-13 16:09:01 -08003784
Eric Paris828dfe12008-04-17 13:17:49 -04003785 default:
3786 break;
3787 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003788out:
3789 return ret;
3790}
3791
3792#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
3793
3794/* Returns error only if unable to parse addresses */
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003795static int selinux_parse_skb_ipv6(struct sk_buff *skb,
Thomas Liu2bf49692009-07-14 12:14:09 -04003796 struct common_audit_data *ad, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003797{
3798 u8 nexthdr;
3799 int ret = -EINVAL, offset;
3800 struct ipv6hdr _ipv6h, *ip6;
Jesse Gross75f28112011-11-30 17:05:51 -08003801 __be16 frag_off;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003802
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03003803 offset = skb_network_offset(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003804 ip6 = skb_header_pointer(skb, offset, sizeof(_ipv6h), &_ipv6h);
3805 if (ip6 == NULL)
3806 goto out;
3807
Eric Paris48c62af2012-04-02 13:15:44 -04003808 ad->u.net->v6info.saddr = ip6->saddr;
3809 ad->u.net->v6info.daddr = ip6->daddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003810 ret = 0;
3811
3812 nexthdr = ip6->nexthdr;
3813 offset += sizeof(_ipv6h);
Jesse Gross75f28112011-11-30 17:05:51 -08003814 offset = ipv6_skip_exthdr(skb, offset, &nexthdr, &frag_off);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003815 if (offset < 0)
3816 goto out;
3817
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003818 if (proto)
3819 *proto = nexthdr;
3820
Linus Torvalds1da177e2005-04-16 15:20:36 -07003821 switch (nexthdr) {
3822 case IPPROTO_TCP: {
Eric Paris828dfe12008-04-17 13:17:49 -04003823 struct tcphdr _tcph, *th;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003824
3825 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
3826 if (th == NULL)
3827 break;
3828
Eric Paris48c62af2012-04-02 13:15:44 -04003829 ad->u.net->sport = th->source;
3830 ad->u.net->dport = th->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003831 break;
3832 }
3833
3834 case IPPROTO_UDP: {
3835 struct udphdr _udph, *uh;
3836
3837 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
3838 if (uh == NULL)
3839 break;
3840
Eric Paris48c62af2012-04-02 13:15:44 -04003841 ad->u.net->sport = uh->source;
3842 ad->u.net->dport = uh->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003843 break;
3844 }
3845
James Morris2ee92d42006-11-13 16:09:01 -08003846 case IPPROTO_DCCP: {
3847 struct dccp_hdr _dccph, *dh;
3848
3849 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
3850 if (dh == NULL)
3851 break;
3852
Eric Paris48c62af2012-04-02 13:15:44 -04003853 ad->u.net->sport = dh->dccph_sport;
3854 ad->u.net->dport = dh->dccph_dport;
James Morris2ee92d42006-11-13 16:09:01 -08003855 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003856 }
James Morris2ee92d42006-11-13 16:09:01 -08003857
Linus Torvalds1da177e2005-04-16 15:20:36 -07003858 /* includes fragments */
3859 default:
3860 break;
3861 }
3862out:
3863 return ret;
3864}
3865
3866#endif /* IPV6 */
3867
Thomas Liu2bf49692009-07-14 12:14:09 -04003868static int selinux_parse_skb(struct sk_buff *skb, struct common_audit_data *ad,
David Howellscf9481e2008-07-27 21:31:07 +10003869 char **_addrp, int src, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003870{
David Howellscf9481e2008-07-27 21:31:07 +10003871 char *addrp;
3872 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003873
Eric Paris48c62af2012-04-02 13:15:44 -04003874 switch (ad->u.net->family) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003875 case PF_INET:
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003876 ret = selinux_parse_skb_ipv4(skb, ad, proto);
David Howellscf9481e2008-07-27 21:31:07 +10003877 if (ret)
3878 goto parse_error;
Eric Paris48c62af2012-04-02 13:15:44 -04003879 addrp = (char *)(src ? &ad->u.net->v4info.saddr :
3880 &ad->u.net->v4info.daddr);
David Howellscf9481e2008-07-27 21:31:07 +10003881 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003882
3883#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
3884 case PF_INET6:
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003885 ret = selinux_parse_skb_ipv6(skb, ad, proto);
David Howellscf9481e2008-07-27 21:31:07 +10003886 if (ret)
3887 goto parse_error;
Eric Paris48c62af2012-04-02 13:15:44 -04003888 addrp = (char *)(src ? &ad->u.net->v6info.saddr :
3889 &ad->u.net->v6info.daddr);
David Howellscf9481e2008-07-27 21:31:07 +10003890 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003891#endif /* IPV6 */
3892 default:
David Howellscf9481e2008-07-27 21:31:07 +10003893 addrp = NULL;
3894 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003895 }
3896
David Howellscf9481e2008-07-27 21:31:07 +10003897parse_error:
3898 printk(KERN_WARNING
3899 "SELinux: failure in selinux_parse_skb(),"
3900 " unable to parse packet\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003901 return ret;
David Howellscf9481e2008-07-27 21:31:07 +10003902
3903okay:
3904 if (_addrp)
3905 *_addrp = addrp;
3906 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003907}
3908
Paul Moore4f6a9932007-03-01 14:35:22 -05003909/**
Paul Moore220deb92008-01-29 08:38:23 -05003910 * selinux_skb_peerlbl_sid - Determine the peer label of a packet
Paul Moore4f6a9932007-03-01 14:35:22 -05003911 * @skb: the packet
Paul Moore75e22912008-01-29 08:38:04 -05003912 * @family: protocol family
Paul Moore220deb92008-01-29 08:38:23 -05003913 * @sid: the packet's peer label SID
Paul Moore4f6a9932007-03-01 14:35:22 -05003914 *
3915 * Description:
Paul Moore220deb92008-01-29 08:38:23 -05003916 * Check the various different forms of network peer labeling and determine
3917 * the peer label/SID for the packet; most of the magic actually occurs in
3918 * the security server function security_net_peersid_cmp(). The function
3919 * returns zero if the value in @sid is valid (although it may be SECSID_NULL)
3920 * or -EACCES if @sid is invalid due to inconsistencies with the different
3921 * peer labels.
Paul Moore4f6a9932007-03-01 14:35:22 -05003922 *
3923 */
Paul Moore220deb92008-01-29 08:38:23 -05003924static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)
Paul Moore4f6a9932007-03-01 14:35:22 -05003925{
Paul Moore71f1cb02008-01-29 08:51:16 -05003926 int err;
Paul Moore4f6a9932007-03-01 14:35:22 -05003927 u32 xfrm_sid;
3928 u32 nlbl_sid;
Paul Moore220deb92008-01-29 08:38:23 -05003929 u32 nlbl_type;
Paul Moore4f6a9932007-03-01 14:35:22 -05003930
Paul Moorec09348c2013-12-10 14:57:54 -05003931 selinux_xfrm_skb_sid(skb, &xfrm_sid);
Paul Moore5dbe1eb2008-01-29 08:44:18 -05003932 selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid);
Paul Moore220deb92008-01-29 08:38:23 -05003933
Paul Moore71f1cb02008-01-29 08:51:16 -05003934 err = security_net_peersid_resolve(nlbl_sid, nlbl_type, xfrm_sid, sid);
3935 if (unlikely(err)) {
3936 printk(KERN_WARNING
3937 "SELinux: failure in selinux_skb_peerlbl_sid(),"
3938 " unable to determine packet's peer label\n");
Paul Moore220deb92008-01-29 08:38:23 -05003939 return -EACCES;
Paul Moore71f1cb02008-01-29 08:51:16 -05003940 }
Paul Moore220deb92008-01-29 08:38:23 -05003941
3942 return 0;
Paul Moore4f6a9932007-03-01 14:35:22 -05003943}
3944
Paul Moore96d2c172013-12-04 16:10:51 -05003945/**
3946 * selinux_conn_sid - Determine the child socket label for a connection
3947 * @sk_sid: the parent socket's SID
3948 * @skb_sid: the packet's SID
3949 * @conn_sid: the resulting connection SID
3950 *
3951 * If @skb_sid is valid then the user:role:type information from @sk_sid is
3952 * combined with the MLS information from @skb_sid in order to create
3953 * @conn_sid. If @skb_sid is not valid then then @conn_sid is simply a copy
3954 * of @sk_sid. Returns zero on success, negative values on failure.
3955 *
3956 */
3957static int selinux_conn_sid(u32 sk_sid, u32 skb_sid, u32 *conn_sid)
3958{
3959 int err = 0;
3960
3961 if (skb_sid != SECSID_NULL)
3962 err = security_sid_mls_copy(sk_sid, skb_sid, conn_sid);
3963 else
3964 *conn_sid = sk_sid;
3965
3966 return err;
3967}
3968
Linus Torvalds1da177e2005-04-16 15:20:36 -07003969/* socket security operations */
Paul Moored4f2d972010-04-22 14:46:18 -04003970
Harry Ciao2ad18bd2011-03-02 13:32:34 +08003971static int socket_sockcreate_sid(const struct task_security_struct *tsec,
3972 u16 secclass, u32 *socksid)
Paul Moored4f2d972010-04-22 14:46:18 -04003973{
Harry Ciao2ad18bd2011-03-02 13:32:34 +08003974 if (tsec->sockcreate_sid > SECSID_NULL) {
3975 *socksid = tsec->sockcreate_sid;
3976 return 0;
3977 }
3978
3979 return security_transition_sid(tsec->sid, tsec->sid, secclass, NULL,
3980 socksid);
Paul Moored4f2d972010-04-22 14:46:18 -04003981}
3982
Paul Moore253bfae2010-04-22 14:46:19 -04003983static int sock_has_perm(struct task_struct *task, struct sock *sk, u32 perms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003984{
Paul Moore253bfae2010-04-22 14:46:19 -04003985 struct sk_security_struct *sksec = sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04003986 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07003987 struct selinux_audit_data sad = {0,};
Eric Paris48c62af2012-04-02 13:15:44 -04003988 struct lsm_network_audit net = {0,};
Paul Moore253bfae2010-04-22 14:46:19 -04003989 u32 tsid = task_sid(task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003990
Satya Durga Srinivasu Prabhala90280652013-09-24 15:23:48 -07003991 if (unlikely(!sksec)) {
3992 pr_warn("SELinux: sksec is NULL, socket is already freed\n");
3993 return -EINVAL;
3994 }
3995
Paul Moore253bfae2010-04-22 14:46:19 -04003996 if (sksec->sid == SECINITSID_KERNEL)
3997 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003998
Thomas Liu2bf49692009-07-14 12:14:09 -04003999 COMMON_AUDIT_DATA_INIT(&ad, NET);
Eric Paris3b3b0e42012-04-03 09:37:02 -07004000 ad.selinux_audit_data = &sad;
Eric Paris48c62af2012-04-02 13:15:44 -04004001 ad.u.net = &net;
4002 ad.u.net->sk = sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004003
Paul Moore253bfae2010-04-22 14:46:19 -04004004 return avc_has_perm(tsid, sksec->sid, sksec->sclass, perms, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004005}
4006
4007static int selinux_socket_create(int family, int type,
4008 int protocol, int kern)
4009{
Paul Moore5fb49872010-04-22 14:46:19 -04004010 const struct task_security_struct *tsec = current_security();
Paul Moored4f2d972010-04-22 14:46:18 -04004011 u32 newsid;
David Howells275bb412008-11-14 10:39:19 +11004012 u16 secclass;
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004013 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004014
4015 if (kern)
Paul Moored4f2d972010-04-22 14:46:18 -04004016 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004017
David Howells275bb412008-11-14 10:39:19 +11004018 secclass = socket_type_to_security_class(family, type, protocol);
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004019 rc = socket_sockcreate_sid(tsec, secclass, &newsid);
4020 if (rc)
4021 return rc;
4022
Paul Moored4f2d972010-04-22 14:46:18 -04004023 return avc_has_perm(tsec->sid, newsid, secclass, SOCKET__CREATE, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004024}
4025
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07004026static int selinux_socket_post_create(struct socket *sock, int family,
4027 int type, int protocol, int kern)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004028{
Paul Moore5fb49872010-04-22 14:46:19 -04004029 const struct task_security_struct *tsec = current_security();
Paul Moored4f2d972010-04-22 14:46:18 -04004030 struct inode_security_struct *isec = SOCK_INODE(sock)->i_security;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004031 struct sk_security_struct *sksec;
David Howells275bb412008-11-14 10:39:19 +11004032 int err = 0;
4033
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004034 isec->sclass = socket_type_to_security_class(family, type, protocol);
4035
David Howells275bb412008-11-14 10:39:19 +11004036 if (kern)
4037 isec->sid = SECINITSID_KERNEL;
Harry Ciao2ad18bd2011-03-02 13:32:34 +08004038 else {
4039 err = socket_sockcreate_sid(tsec, isec->sclass, &(isec->sid));
4040 if (err)
4041 return err;
4042 }
David Howells275bb412008-11-14 10:39:19 +11004043
Linus Torvalds1da177e2005-04-16 15:20:36 -07004044 isec->initialized = 1;
4045
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004046 if (sock->sk) {
4047 sksec = sock->sk->sk_security;
4048 sksec->sid = isec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05004049 sksec->sclass = isec->sclass;
Paul Moore389fb802009-03-27 17:10:34 -04004050 err = selinux_netlbl_socket_post_create(sock->sk, family);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004051 }
4052
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07004053 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004054}
4055
4056/* Range of port numbers used to automatically bind.
4057 Need to determine whether we should perform a name_bind
4058 permission check between the socket and the port number. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004059
4060static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen)
4061{
Paul Moore253bfae2010-04-22 14:46:19 -04004062 struct sock *sk = sock->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004063 u16 family;
4064 int err;
4065
Paul Moore253bfae2010-04-22 14:46:19 -04004066 err = sock_has_perm(current, sk, SOCKET__BIND);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004067 if (err)
4068 goto out;
4069
4070 /*
4071 * If PF_INET or PF_INET6, check name_bind permission for the port.
James Morris13402582005-09-30 14:24:34 -04004072 * Multiple address binding for SCTP is not supported yet: we just
4073 * check the first address now.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004074 */
Paul Moore253bfae2010-04-22 14:46:19 -04004075 family = sk->sk_family;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004076 if (family == PF_INET || family == PF_INET6) {
4077 char *addrp;
Paul Moore253bfae2010-04-22 14:46:19 -04004078 struct sk_security_struct *sksec = sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004079 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07004080 struct selinux_audit_data sad = {0,};
Eric Paris48c62af2012-04-02 13:15:44 -04004081 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004082 struct sockaddr_in *addr4 = NULL;
4083 struct sockaddr_in6 *addr6 = NULL;
4084 unsigned short snum;
James Morrise399f982008-06-12 01:39:58 +10004085 u32 sid, node_perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004086
Linus Torvalds1da177e2005-04-16 15:20:36 -07004087 if (family == PF_INET) {
4088 addr4 = (struct sockaddr_in *)address;
4089 snum = ntohs(addr4->sin_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004090 addrp = (char *)&addr4->sin_addr.s_addr;
4091 } else {
4092 addr6 = (struct sockaddr_in6 *)address;
4093 snum = ntohs(addr6->sin6_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004094 addrp = (char *)&addr6->sin6_addr.s6_addr;
4095 }
4096
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004097 if (snum) {
4098 int low, high;
4099
4100 inet_get_local_port_range(&low, &high);
4101
4102 if (snum < max(PROT_SOCK, low) || snum > high) {
Paul Moore3e112172008-04-10 10:48:14 -04004103 err = sel_netport_sid(sk->sk_protocol,
4104 snum, &sid);
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004105 if (err)
4106 goto out;
Thomas Liu2bf49692009-07-14 12:14:09 -04004107 COMMON_AUDIT_DATA_INIT(&ad, NET);
Eric Paris3b3b0e42012-04-03 09:37:02 -07004108 ad.selinux_audit_data = &sad;
Eric Paris48c62af2012-04-02 13:15:44 -04004109 ad.u.net = &net;
4110 ad.u.net->sport = htons(snum);
4111 ad.u.net->family = family;
Paul Moore253bfae2010-04-22 14:46:19 -04004112 err = avc_has_perm(sksec->sid, sid,
4113 sksec->sclass,
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004114 SOCKET__NAME_BIND, &ad);
4115 if (err)
4116 goto out;
4117 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004118 }
Eric Paris828dfe12008-04-17 13:17:49 -04004119
Paul Moore253bfae2010-04-22 14:46:19 -04004120 switch (sksec->sclass) {
James Morris13402582005-09-30 14:24:34 -04004121 case SECCLASS_TCP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004122 node_perm = TCP_SOCKET__NODE_BIND;
4123 break;
Eric Paris828dfe12008-04-17 13:17:49 -04004124
James Morris13402582005-09-30 14:24:34 -04004125 case SECCLASS_UDP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004126 node_perm = UDP_SOCKET__NODE_BIND;
4127 break;
James Morris2ee92d42006-11-13 16:09:01 -08004128
4129 case SECCLASS_DCCP_SOCKET:
4130 node_perm = DCCP_SOCKET__NODE_BIND;
4131 break;
4132
Linus Torvalds1da177e2005-04-16 15:20:36 -07004133 default:
4134 node_perm = RAWIP_SOCKET__NODE_BIND;
4135 break;
4136 }
Eric Paris828dfe12008-04-17 13:17:49 -04004137
Paul Moore224dfbd2008-01-29 08:38:13 -05004138 err = sel_netnode_sid(addrp, family, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004139 if (err)
4140 goto out;
Eric Paris828dfe12008-04-17 13:17:49 -04004141
Thomas Liu2bf49692009-07-14 12:14:09 -04004142 COMMON_AUDIT_DATA_INIT(&ad, NET);
Eric Paris3b3b0e42012-04-03 09:37:02 -07004143 ad.selinux_audit_data = &sad;
Eric Paris48c62af2012-04-02 13:15:44 -04004144 ad.u.net = &net;
4145 ad.u.net->sport = htons(snum);
4146 ad.u.net->family = family;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004147
4148 if (family == PF_INET)
Eric Paris48c62af2012-04-02 13:15:44 -04004149 ad.u.net->v4info.saddr = addr4->sin_addr.s_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004150 else
Eric Paris48c62af2012-04-02 13:15:44 -04004151 ad.u.net->v6info.saddr = addr6->sin6_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004152
Paul Moore253bfae2010-04-22 14:46:19 -04004153 err = avc_has_perm(sksec->sid, sid,
4154 sksec->sclass, node_perm, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004155 if (err)
4156 goto out;
4157 }
4158out:
4159 return err;
4160}
4161
4162static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen)
4163{
Paul Moore014ab192008-10-10 10:16:33 -04004164 struct sock *sk = sock->sk;
Paul Moore253bfae2010-04-22 14:46:19 -04004165 struct sk_security_struct *sksec = sk->sk_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004166 int err;
4167
Paul Moore253bfae2010-04-22 14:46:19 -04004168 err = sock_has_perm(current, sk, SOCKET__CONNECT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004169 if (err)
4170 return err;
4171
4172 /*
James Morris2ee92d42006-11-13 16:09:01 -08004173 * If a TCP or DCCP socket, check name_connect permission for the port.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004174 */
Paul Moore253bfae2010-04-22 14:46:19 -04004175 if (sksec->sclass == SECCLASS_TCP_SOCKET ||
4176 sksec->sclass == SECCLASS_DCCP_SOCKET) {
Thomas Liu2bf49692009-07-14 12:14:09 -04004177 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07004178 struct selinux_audit_data sad = {0,};
Eric Paris48c62af2012-04-02 13:15:44 -04004179 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004180 struct sockaddr_in *addr4 = NULL;
4181 struct sockaddr_in6 *addr6 = NULL;
4182 unsigned short snum;
James Morris2ee92d42006-11-13 16:09:01 -08004183 u32 sid, perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004184
4185 if (sk->sk_family == PF_INET) {
4186 addr4 = (struct sockaddr_in *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07004187 if (addrlen < sizeof(struct sockaddr_in))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004188 return -EINVAL;
4189 snum = ntohs(addr4->sin_port);
4190 } else {
4191 addr6 = (struct sockaddr_in6 *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07004192 if (addrlen < SIN6_LEN_RFC2133)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004193 return -EINVAL;
4194 snum = ntohs(addr6->sin6_port);
4195 }
4196
Paul Moore3e112172008-04-10 10:48:14 -04004197 err = sel_netport_sid(sk->sk_protocol, snum, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004198 if (err)
4199 goto out;
4200
Paul Moore253bfae2010-04-22 14:46:19 -04004201 perm = (sksec->sclass == SECCLASS_TCP_SOCKET) ?
James Morris2ee92d42006-11-13 16:09:01 -08004202 TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT;
4203
Thomas Liu2bf49692009-07-14 12:14:09 -04004204 COMMON_AUDIT_DATA_INIT(&ad, NET);
Eric Paris3b3b0e42012-04-03 09:37:02 -07004205 ad.selinux_audit_data = &sad;
Eric Paris48c62af2012-04-02 13:15:44 -04004206 ad.u.net = &net;
4207 ad.u.net->dport = htons(snum);
4208 ad.u.net->family = sk->sk_family;
Paul Moore253bfae2010-04-22 14:46:19 -04004209 err = avc_has_perm(sksec->sid, sid, sksec->sclass, perm, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004210 if (err)
4211 goto out;
4212 }
4213
Paul Moore014ab192008-10-10 10:16:33 -04004214 err = selinux_netlbl_socket_connect(sk, address);
4215
Linus Torvalds1da177e2005-04-16 15:20:36 -07004216out:
4217 return err;
4218}
4219
4220static int selinux_socket_listen(struct socket *sock, int backlog)
4221{
Paul Moore253bfae2010-04-22 14:46:19 -04004222 return sock_has_perm(current, sock->sk, SOCKET__LISTEN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004223}
4224
4225static int selinux_socket_accept(struct socket *sock, struct socket *newsock)
4226{
4227 int err;
4228 struct inode_security_struct *isec;
4229 struct inode_security_struct *newisec;
4230
Paul Moore253bfae2010-04-22 14:46:19 -04004231 err = sock_has_perm(current, sock->sk, SOCKET__ACCEPT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004232 if (err)
4233 return err;
4234
4235 newisec = SOCK_INODE(newsock)->i_security;
4236
4237 isec = SOCK_INODE(sock)->i_security;
4238 newisec->sclass = isec->sclass;
4239 newisec->sid = isec->sid;
4240 newisec->initialized = 1;
4241
4242 return 0;
4243}
4244
4245static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg,
Eric Paris828dfe12008-04-17 13:17:49 -04004246 int size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004247{
Paul Moore253bfae2010-04-22 14:46:19 -04004248 return sock_has_perm(current, sock->sk, SOCKET__WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004249}
4250
4251static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg,
4252 int size, int flags)
4253{
Paul Moore253bfae2010-04-22 14:46:19 -04004254 return sock_has_perm(current, sock->sk, SOCKET__READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004255}
4256
4257static int selinux_socket_getsockname(struct socket *sock)
4258{
Paul Moore253bfae2010-04-22 14:46:19 -04004259 return sock_has_perm(current, sock->sk, SOCKET__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004260}
4261
4262static int selinux_socket_getpeername(struct socket *sock)
4263{
Paul Moore253bfae2010-04-22 14:46:19 -04004264 return sock_has_perm(current, sock->sk, SOCKET__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004265}
4266
Eric Paris828dfe12008-04-17 13:17:49 -04004267static int selinux_socket_setsockopt(struct socket *sock, int level, int optname)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004268{
Paul Mooref8687af2006-10-30 15:22:15 -08004269 int err;
4270
Paul Moore253bfae2010-04-22 14:46:19 -04004271 err = sock_has_perm(current, sock->sk, SOCKET__SETOPT);
Paul Mooref8687af2006-10-30 15:22:15 -08004272 if (err)
4273 return err;
4274
4275 return selinux_netlbl_socket_setsockopt(sock, level, optname);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004276}
4277
4278static int selinux_socket_getsockopt(struct socket *sock, int level,
4279 int optname)
4280{
Paul Moore253bfae2010-04-22 14:46:19 -04004281 return sock_has_perm(current, sock->sk, SOCKET__GETOPT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004282}
4283
4284static int selinux_socket_shutdown(struct socket *sock, int how)
4285{
Paul Moore253bfae2010-04-22 14:46:19 -04004286 return sock_has_perm(current, sock->sk, SOCKET__SHUTDOWN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004287}
4288
David S. Miller3610cda2011-01-05 15:38:53 -08004289static int selinux_socket_unix_stream_connect(struct sock *sock,
4290 struct sock *other,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004291 struct sock *newsk)
4292{
David S. Miller3610cda2011-01-05 15:38:53 -08004293 struct sk_security_struct *sksec_sock = sock->sk_security;
4294 struct sk_security_struct *sksec_other = other->sk_security;
Paul Moore4d1e2452010-04-22 14:46:18 -04004295 struct sk_security_struct *sksec_new = newsk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004296 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07004297 struct selinux_audit_data sad = {0,};
Eric Paris48c62af2012-04-02 13:15:44 -04004298 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004299 int err;
4300
Thomas Liu2bf49692009-07-14 12:14:09 -04004301 COMMON_AUDIT_DATA_INIT(&ad, NET);
Eric Paris3b3b0e42012-04-03 09:37:02 -07004302 ad.selinux_audit_data = &sad;
Eric Paris48c62af2012-04-02 13:15:44 -04004303 ad.u.net = &net;
4304 ad.u.net->sk = other;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004305
Paul Moore4d1e2452010-04-22 14:46:18 -04004306 err = avc_has_perm(sksec_sock->sid, sksec_other->sid,
4307 sksec_other->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004308 UNIX_STREAM_SOCKET__CONNECTTO, &ad);
4309 if (err)
4310 return err;
4311
Linus Torvalds1da177e2005-04-16 15:20:36 -07004312 /* server child socket */
Paul Moore4d1e2452010-04-22 14:46:18 -04004313 sksec_new->peer_sid = sksec_sock->sid;
4314 err = security_sid_mls_copy(sksec_other->sid, sksec_sock->sid,
4315 &sksec_new->sid);
4316 if (err)
4317 return err;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004318
Paul Moore4d1e2452010-04-22 14:46:18 -04004319 /* connecting socket */
4320 sksec_sock->peer_sid = sksec_new->sid;
4321
4322 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004323}
4324
4325static int selinux_socket_unix_may_send(struct socket *sock,
4326 struct socket *other)
4327{
Paul Moore253bfae2010-04-22 14:46:19 -04004328 struct sk_security_struct *ssec = sock->sk->sk_security;
4329 struct sk_security_struct *osec = other->sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004330 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07004331 struct selinux_audit_data sad = {0,};
Eric Paris48c62af2012-04-02 13:15:44 -04004332 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004333
Thomas Liu2bf49692009-07-14 12:14:09 -04004334 COMMON_AUDIT_DATA_INIT(&ad, NET);
Eric Paris3b3b0e42012-04-03 09:37:02 -07004335 ad.selinux_audit_data = &sad;
Eric Paris48c62af2012-04-02 13:15:44 -04004336 ad.u.net = &net;
4337 ad.u.net->sk = other->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004338
Paul Moore253bfae2010-04-22 14:46:19 -04004339 return avc_has_perm(ssec->sid, osec->sid, osec->sclass, SOCKET__SENDTO,
4340 &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004341}
4342
Paul Mooreeffad8d2008-01-29 08:49:27 -05004343static int selinux_inet_sys_rcv_skb(int ifindex, char *addrp, u16 family,
4344 u32 peer_sid,
Thomas Liu2bf49692009-07-14 12:14:09 -04004345 struct common_audit_data *ad)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004346{
4347 int err;
4348 u32 if_sid;
4349 u32 node_sid;
4350
4351 err = sel_netif_sid(ifindex, &if_sid);
4352 if (err)
4353 return err;
4354 err = avc_has_perm(peer_sid, if_sid,
4355 SECCLASS_NETIF, NETIF__INGRESS, ad);
4356 if (err)
4357 return err;
4358
4359 err = sel_netnode_sid(addrp, family, &node_sid);
4360 if (err)
4361 return err;
4362 return avc_has_perm(peer_sid, node_sid,
4363 SECCLASS_NODE, NODE__RECVFROM, ad);
4364}
4365
Paul Moore220deb92008-01-29 08:38:23 -05004366static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
Paul Moored8395c82008-10-10 10:16:30 -04004367 u16 family)
Paul Moore220deb92008-01-29 08:38:23 -05004368{
Paul Moore277d3422008-12-31 12:54:11 -05004369 int err = 0;
Paul Moore220deb92008-01-29 08:38:23 -05004370 struct sk_security_struct *sksec = sk->sk_security;
Paul Moore220deb92008-01-29 08:38:23 -05004371 u32 sk_sid = sksec->sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04004372 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07004373 struct selinux_audit_data sad = {0,};
Eric Paris48c62af2012-04-02 13:15:44 -04004374 struct lsm_network_audit net = {0,};
Paul Moored8395c82008-10-10 10:16:30 -04004375 char *addrp;
4376
Thomas Liu2bf49692009-07-14 12:14:09 -04004377 COMMON_AUDIT_DATA_INIT(&ad, NET);
Eric Paris3b3b0e42012-04-03 09:37:02 -07004378 ad.selinux_audit_data = &sad;
Eric Paris48c62af2012-04-02 13:15:44 -04004379 ad.u.net = &net;
4380 ad.u.net->netif = skb->skb_iif;
4381 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04004382 err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
4383 if (err)
4384 return err;
Paul Moore220deb92008-01-29 08:38:23 -05004385
Paul Moore58bfbb52009-03-27 17:10:41 -04004386 if (selinux_secmark_enabled()) {
Paul Moore220deb92008-01-29 08:38:23 -05004387 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
Paul Moored8395c82008-10-10 10:16:30 -04004388 PACKET__RECV, &ad);
Paul Moore58bfbb52009-03-27 17:10:41 -04004389 if (err)
4390 return err;
4391 }
Paul Moore220deb92008-01-29 08:38:23 -05004392
Steffen Klassertb9679a72011-02-23 12:55:21 +01004393 err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, &ad);
4394 if (err)
4395 return err;
4396 err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, &ad);
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004397
James Morris4e5ab4c2006-06-09 00:33:33 -07004398 return err;
4399}
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004400
James Morris4e5ab4c2006-06-09 00:33:33 -07004401static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
4402{
Paul Moore220deb92008-01-29 08:38:23 -05004403 int err;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004404 struct sk_security_struct *sksec = sk->sk_security;
Paul Moore220deb92008-01-29 08:38:23 -05004405 u16 family = sk->sk_family;
4406 u32 sk_sid = sksec->sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04004407 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07004408 struct selinux_audit_data sad = {0,};
Eric Paris48c62af2012-04-02 13:15:44 -04004409 struct lsm_network_audit net = {0,};
Paul Moore220deb92008-01-29 08:38:23 -05004410 char *addrp;
Paul Moored8395c82008-10-10 10:16:30 -04004411 u8 secmark_active;
4412 u8 peerlbl_active;
James Morris4e5ab4c2006-06-09 00:33:33 -07004413
James Morris4e5ab4c2006-06-09 00:33:33 -07004414 if (family != PF_INET && family != PF_INET6)
Paul Moore220deb92008-01-29 08:38:23 -05004415 return 0;
James Morris4e5ab4c2006-06-09 00:33:33 -07004416
4417 /* Handle mapped IPv4 packets arriving via IPv6 sockets */
Al Viro87fcd702006-12-04 22:00:55 +00004418 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
James Morris4e5ab4c2006-06-09 00:33:33 -07004419 family = PF_INET;
4420
Paul Moored8395c82008-10-10 10:16:30 -04004421 /* If any sort of compatibility mode is enabled then handoff processing
4422 * to the selinux_sock_rcv_skb_compat() function to deal with the
4423 * special handling. We do this in an attempt to keep this function
4424 * as fast and as clean as possible. */
Paul Moore58bfbb52009-03-27 17:10:41 -04004425 if (!selinux_policycap_netpeer)
Paul Moored8395c82008-10-10 10:16:30 -04004426 return selinux_sock_rcv_skb_compat(sk, skb, family);
4427
4428 secmark_active = selinux_secmark_enabled();
4429 peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled();
4430 if (!secmark_active && !peerlbl_active)
4431 return 0;
4432
Thomas Liu2bf49692009-07-14 12:14:09 -04004433 COMMON_AUDIT_DATA_INIT(&ad, NET);
Eric Paris3b3b0e42012-04-03 09:37:02 -07004434 ad.selinux_audit_data = &sad;
Eric Paris48c62af2012-04-02 13:15:44 -04004435 ad.u.net = &net;
4436 ad.u.net->netif = skb->skb_iif;
4437 ad.u.net->family = family;
Paul Moore224dfbd2008-01-29 08:38:13 -05004438 err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
James Morris4e5ab4c2006-06-09 00:33:33 -07004439 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05004440 return err;
James Morris4e5ab4c2006-06-09 00:33:33 -07004441
Paul Moored8395c82008-10-10 10:16:30 -04004442 if (peerlbl_active) {
Paul Moored621d352008-01-29 08:43:36 -05004443 u32 peer_sid;
4444
4445 err = selinux_skb_peerlbl_sid(skb, family, &peer_sid);
4446 if (err)
4447 return err;
Eric Dumazet8964be42009-11-20 15:35:04 -08004448 err = selinux_inet_sys_rcv_skb(skb->skb_iif, addrp, family,
Paul Mooreeffad8d2008-01-29 08:49:27 -05004449 peer_sid, &ad);
Paul Mooredfaebe92008-10-10 10:16:31 -04004450 if (err) {
4451 selinux_netlbl_err(skb, err, 0);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004452 return err;
Paul Mooredfaebe92008-10-10 10:16:31 -04004453 }
Paul Moored621d352008-01-29 08:43:36 -05004454 err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER,
4455 PEER__RECV, &ad);
Chad Hanson619af682013-12-23 17:45:01 -05004456 if (err) {
Paul Mooredfaebe92008-10-10 10:16:31 -04004457 selinux_netlbl_err(skb, err, 0);
Chad Hanson619af682013-12-23 17:45:01 -05004458 return err;
4459 }
Paul Moored621d352008-01-29 08:43:36 -05004460 }
4461
Paul Moored8395c82008-10-10 10:16:30 -04004462 if (secmark_active) {
Paul Mooreeffad8d2008-01-29 08:49:27 -05004463 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
4464 PACKET__RECV, &ad);
4465 if (err)
4466 return err;
4467 }
4468
Paul Moored621d352008-01-29 08:43:36 -05004469 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004470}
4471
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004472static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *optval,
4473 int __user *optlen, unsigned len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004474{
4475 int err = 0;
4476 char *scontext;
4477 u32 scontext_len;
Paul Moore253bfae2010-04-22 14:46:19 -04004478 struct sk_security_struct *sksec = sock->sk->sk_security;
Paul Moore3de4bab2006-11-17 17:38:54 -05004479 u32 peer_sid = SECSID_NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004480
Paul Moore253bfae2010-04-22 14:46:19 -04004481 if (sksec->sclass == SECCLASS_UNIX_STREAM_SOCKET ||
4482 sksec->sclass == SECCLASS_TCP_SOCKET)
Eric Parisdd3e7832010-04-07 15:08:46 -04004483 peer_sid = sksec->peer_sid;
Paul Moore253bfae2010-04-22 14:46:19 -04004484 if (peer_sid == SECSID_NULL)
4485 return -ENOPROTOOPT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004486
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004487 err = security_sid_to_context(peer_sid, &scontext, &scontext_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004488 if (err)
Paul Moore253bfae2010-04-22 14:46:19 -04004489 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004490
4491 if (scontext_len > len) {
4492 err = -ERANGE;
4493 goto out_len;
4494 }
4495
4496 if (copy_to_user(optval, scontext, scontext_len))
4497 err = -EFAULT;
4498
4499out_len:
4500 if (put_user(scontext_len, optlen))
4501 err = -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004502 kfree(scontext);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004503 return err;
4504}
4505
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004506static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid)
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004507{
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004508 u32 peer_secid = SECSID_NULL;
Paul Moore75e22912008-01-29 08:38:04 -05004509 u16 family;
Catherine Zhang877ce7c2006-06-29 12:27:47 -07004510
Paul Mooreaa862902008-10-10 10:16:29 -04004511 if (skb && skb->protocol == htons(ETH_P_IP))
4512 family = PF_INET;
4513 else if (skb && skb->protocol == htons(ETH_P_IPV6))
4514 family = PF_INET6;
4515 else if (sock)
Paul Moore75e22912008-01-29 08:38:04 -05004516 family = sock->sk->sk_family;
Paul Moore75e22912008-01-29 08:38:04 -05004517 else
4518 goto out;
4519
4520 if (sock && family == PF_UNIX)
Ahmed S. Darwish713a04a2008-03-01 21:52:30 +02004521 selinux_inode_getsecid(SOCK_INODE(sock), &peer_secid);
Paul Moore3de4bab2006-11-17 17:38:54 -05004522 else if (skb)
Paul Moore220deb92008-01-29 08:38:23 -05004523 selinux_skb_peerlbl_sid(skb, family, &peer_secid);
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004524
Paul Moore75e22912008-01-29 08:38:04 -05004525out:
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004526 *secid = peer_secid;
Paul Moore75e22912008-01-29 08:38:04 -05004527 if (peer_secid == SECSID_NULL)
4528 return -EINVAL;
4529 return 0;
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004530}
4531
Al Viro7d877f32005-10-21 03:20:43 -04004532static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004533{
Paul Moore84914b72010-04-22 14:46:18 -04004534 struct sk_security_struct *sksec;
4535
4536 sksec = kzalloc(sizeof(*sksec), priority);
4537 if (!sksec)
4538 return -ENOMEM;
4539
4540 sksec->peer_sid = SECINITSID_UNLABELED;
4541 sksec->sid = SECINITSID_UNLABELED;
4542 selinux_netlbl_sk_security_reset(sksec);
4543 sk->sk_security = sksec;
4544
4545 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004546}
4547
4548static void selinux_sk_free_security(struct sock *sk)
4549{
Paul Moore84914b72010-04-22 14:46:18 -04004550 struct sk_security_struct *sksec = sk->sk_security;
4551
4552 sk->sk_security = NULL;
4553 selinux_netlbl_sk_security_free(sksec);
4554 kfree(sksec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004555}
4556
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004557static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk)
4558{
Eric Parisdd3e7832010-04-07 15:08:46 -04004559 struct sk_security_struct *sksec = sk->sk_security;
4560 struct sk_security_struct *newsksec = newsk->sk_security;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004561
Eric Parisdd3e7832010-04-07 15:08:46 -04004562 newsksec->sid = sksec->sid;
4563 newsksec->peer_sid = sksec->peer_sid;
4564 newsksec->sclass = sksec->sclass;
Paul Moore99f59ed2006-08-29 17:53:48 -07004565
Eric Parisdd3e7832010-04-07 15:08:46 -04004566 selinux_netlbl_sk_security_reset(newsksec);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004567}
4568
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004569static void selinux_sk_getsecid(struct sock *sk, u32 *secid)
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004570{
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004571 if (!sk)
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004572 *secid = SECINITSID_ANY_SOCKET;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004573 else {
4574 struct sk_security_struct *sksec = sk->sk_security;
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004575
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004576 *secid = sksec->sid;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004577 }
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004578}
4579
Eric Paris828dfe12008-04-17 13:17:49 -04004580static void selinux_sock_graft(struct sock *sk, struct socket *parent)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004581{
4582 struct inode_security_struct *isec = SOCK_INODE(parent)->i_security;
4583 struct sk_security_struct *sksec = sk->sk_security;
4584
David Woodhouse2148ccc2006-09-29 15:50:25 -07004585 if (sk->sk_family == PF_INET || sk->sk_family == PF_INET6 ||
4586 sk->sk_family == PF_UNIX)
4587 isec->sid = sksec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05004588 sksec->sclass = isec->sclass;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004589}
4590
Adrian Bunk9a673e52006-08-15 00:03:53 -07004591static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
4592 struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004593{
4594 struct sk_security_struct *sksec = sk->sk_security;
4595 int err;
Paul Mooreaa862902008-10-10 10:16:29 -04004596 u16 family = sk->sk_family;
Paul Moore96d2c172013-12-04 16:10:51 -05004597 u32 connsid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004598 u32 peersid;
4599
Paul Mooreaa862902008-10-10 10:16:29 -04004600 /* handle mapped IPv4 packets arriving via IPv6 sockets */
4601 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
4602 family = PF_INET;
4603
4604 err = selinux_skb_peerlbl_sid(skb, family, &peersid);
Paul Moore220deb92008-01-29 08:38:23 -05004605 if (err)
4606 return err;
Paul Moore96d2c172013-12-04 16:10:51 -05004607 err = selinux_conn_sid(sksec->sid, peersid, &connsid);
4608 if (err)
4609 return err;
4610 req->secid = connsid;
4611 req->peer_secid = peersid;
Venkat Yekkiralaa51c64f2006-07-27 22:01:34 -07004612
Paul Moore389fb802009-03-27 17:10:34 -04004613 return selinux_netlbl_inet_conn_request(req, family);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004614}
4615
Adrian Bunk9a673e52006-08-15 00:03:53 -07004616static void selinux_inet_csk_clone(struct sock *newsk,
4617 const struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004618{
4619 struct sk_security_struct *newsksec = newsk->sk_security;
4620
4621 newsksec->sid = req->secid;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004622 newsksec->peer_sid = req->peer_secid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004623 /* NOTE: Ideally, we should also get the isec->sid for the
4624 new socket in sync, but we don't have the isec available yet.
4625 So we will wait until sock_graft to do it, by which
4626 time it will have been created and available. */
Paul Moore99f59ed2006-08-29 17:53:48 -07004627
Paul Moore9f2ad662006-11-17 17:38:53 -05004628 /* We don't need to take any sort of lock here as we are the only
4629 * thread with access to newsksec */
Paul Moore389fb802009-03-27 17:10:34 -04004630 selinux_netlbl_inet_csk_clone(newsk, req->rsk_ops->family);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004631}
4632
Paul Moore014ab192008-10-10 10:16:33 -04004633static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb)
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004634{
Paul Mooreaa862902008-10-10 10:16:29 -04004635 u16 family = sk->sk_family;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004636 struct sk_security_struct *sksec = sk->sk_security;
4637
Paul Mooreaa862902008-10-10 10:16:29 -04004638 /* handle mapped IPv4 packets arriving via IPv6 sockets */
4639 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
4640 family = PF_INET;
4641
4642 selinux_skb_peerlbl_sid(skb, family, &sksec->peer_sid);
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004643}
4644
Eric Paris2606fd12010-10-13 16:24:41 -04004645static int selinux_secmark_relabel_packet(u32 sid)
4646{
4647 const struct task_security_struct *__tsec;
4648 u32 tsid;
4649
4650 __tsec = current_security();
4651 tsid = __tsec->sid;
4652
4653 return avc_has_perm(tsid, sid, SECCLASS_PACKET, PACKET__RELABELTO, NULL);
4654}
4655
4656static void selinux_secmark_refcount_inc(void)
4657{
4658 atomic_inc(&selinux_secmark_refcount);
4659}
4660
4661static void selinux_secmark_refcount_dec(void)
4662{
4663 atomic_dec(&selinux_secmark_refcount);
4664}
4665
Adrian Bunk9a673e52006-08-15 00:03:53 -07004666static void selinux_req_classify_flow(const struct request_sock *req,
4667 struct flowi *fl)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004668{
David S. Miller1d28f422011-03-12 00:29:39 -05004669 fl->flowi_secid = req->secid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004670}
4671
Paul Mooreed6d76e2009-08-28 18:12:49 -04004672static int selinux_tun_dev_create(void)
4673{
4674 u32 sid = current_sid();
4675
4676 /* we aren't taking into account the "sockcreate" SID since the socket
4677 * that is being created here is not a socket in the traditional sense,
4678 * instead it is a private sock, accessible only to the kernel, and
4679 * representing a wide range of network traffic spanning multiple
4680 * connections unlike traditional sockets - check the TUN driver to
4681 * get a better understanding of why this socket is special */
4682
4683 return avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET, TUN_SOCKET__CREATE,
4684 NULL);
4685}
4686
4687static void selinux_tun_dev_post_create(struct sock *sk)
4688{
4689 struct sk_security_struct *sksec = sk->sk_security;
4690
4691 /* we don't currently perform any NetLabel based labeling here and it
4692 * isn't clear that we would want to do so anyway; while we could apply
4693 * labeling without the support of the TUN user the resulting labeled
4694 * traffic from the other end of the connection would almost certainly
4695 * cause confusion to the TUN user that had no idea network labeling
4696 * protocols were being used */
4697
4698 /* see the comments in selinux_tun_dev_create() about why we don't use
4699 * the sockcreate SID here */
4700
4701 sksec->sid = current_sid();
4702 sksec->sclass = SECCLASS_TUN_SOCKET;
4703}
4704
4705static int selinux_tun_dev_attach(struct sock *sk)
4706{
4707 struct sk_security_struct *sksec = sk->sk_security;
4708 u32 sid = current_sid();
4709 int err;
4710
4711 err = avc_has_perm(sid, sksec->sid, SECCLASS_TUN_SOCKET,
4712 TUN_SOCKET__RELABELFROM, NULL);
4713 if (err)
4714 return err;
4715 err = avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET,
4716 TUN_SOCKET__RELABELTO, NULL);
4717 if (err)
4718 return err;
4719
4720 sksec->sid = sid;
4721
4722 return 0;
4723}
4724
Linus Torvalds1da177e2005-04-16 15:20:36 -07004725static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
4726{
4727 int err = 0;
4728 u32 perm;
4729 struct nlmsghdr *nlh;
Paul Moore253bfae2010-04-22 14:46:19 -04004730 struct sk_security_struct *sksec = sk->sk_security;
Eric Paris828dfe12008-04-17 13:17:49 -04004731
Linus Torvalds1da177e2005-04-16 15:20:36 -07004732 if (skb->len < NLMSG_SPACE(0)) {
4733 err = -EINVAL;
4734 goto out;
4735 }
Arnaldo Carvalho de Melob529ccf2007-04-25 19:08:35 -07004736 nlh = nlmsg_hdr(skb);
Eric Paris828dfe12008-04-17 13:17:49 -04004737
Paul Moore253bfae2010-04-22 14:46:19 -04004738 err = selinux_nlmsg_lookup(sksec->sclass, nlh->nlmsg_type, &perm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004739 if (err) {
4740 if (err == -EINVAL) {
David Woodhouse9ad9ad32005-06-22 15:04:33 +01004741 audit_log(current->audit_context, GFP_KERNEL, AUDIT_SELINUX_ERR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004742 "SELinux: unrecognized netlink message"
4743 " type=%hu for sclass=%hu\n",
Paul Moore253bfae2010-04-22 14:46:19 -04004744 nlh->nlmsg_type, sksec->sclass);
Eric Paris39c9aed2008-11-05 09:34:42 -05004745 if (!selinux_enforcing || security_get_allow_unknown())
Linus Torvalds1da177e2005-04-16 15:20:36 -07004746 err = 0;
4747 }
4748
4749 /* Ignore */
4750 if (err == -ENOENT)
4751 err = 0;
4752 goto out;
4753 }
4754
Paul Moore253bfae2010-04-22 14:46:19 -04004755 err = sock_has_perm(current, sk, perm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004756out:
4757 return err;
4758}
4759
4760#ifdef CONFIG_NETFILTER
4761
Paul Mooreeffad8d2008-01-29 08:49:27 -05004762static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex,
4763 u16 family)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004764{
Paul Mooredfaebe92008-10-10 10:16:31 -04004765 int err;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004766 char *addrp;
4767 u32 peer_sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04004768 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07004769 struct selinux_audit_data sad = {0,};
Eric Paris48c62af2012-04-02 13:15:44 -04004770 struct lsm_network_audit net = {0,};
Paul Mooreeffad8d2008-01-29 08:49:27 -05004771 u8 secmark_active;
Paul Moore948bf852008-10-10 10:16:32 -04004772 u8 netlbl_active;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004773 u8 peerlbl_active;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004774
Paul Mooreeffad8d2008-01-29 08:49:27 -05004775 if (!selinux_policycap_netpeer)
4776 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004777
Paul Mooreeffad8d2008-01-29 08:49:27 -05004778 secmark_active = selinux_secmark_enabled();
Paul Moore948bf852008-10-10 10:16:32 -04004779 netlbl_active = netlbl_enabled();
4780 peerlbl_active = netlbl_active || selinux_xfrm_enabled();
Paul Mooreeffad8d2008-01-29 08:49:27 -05004781 if (!secmark_active && !peerlbl_active)
4782 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004783
Paul Moored8395c82008-10-10 10:16:30 -04004784 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0)
4785 return NF_DROP;
4786
Thomas Liu2bf49692009-07-14 12:14:09 -04004787 COMMON_AUDIT_DATA_INIT(&ad, NET);
Eric Paris3b3b0e42012-04-03 09:37:02 -07004788 ad.selinux_audit_data = &sad;
Eric Paris48c62af2012-04-02 13:15:44 -04004789 ad.u.net = &net;
4790 ad.u.net->netif = ifindex;
4791 ad.u.net->family = family;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004792 if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0)
4793 return NF_DROP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004794
Paul Mooredfaebe92008-10-10 10:16:31 -04004795 if (peerlbl_active) {
4796 err = selinux_inet_sys_rcv_skb(ifindex, addrp, family,
4797 peer_sid, &ad);
4798 if (err) {
4799 selinux_netlbl_err(skb, err, 1);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004800 return NF_DROP;
Paul Mooredfaebe92008-10-10 10:16:31 -04004801 }
4802 }
Paul Mooreeffad8d2008-01-29 08:49:27 -05004803
4804 if (secmark_active)
4805 if (avc_has_perm(peer_sid, skb->secmark,
4806 SECCLASS_PACKET, PACKET__FORWARD_IN, &ad))
4807 return NF_DROP;
4808
Paul Moore948bf852008-10-10 10:16:32 -04004809 if (netlbl_active)
4810 /* we do this in the FORWARD path and not the POST_ROUTING
4811 * path because we want to make sure we apply the necessary
4812 * labeling before IPsec is applied so we can leverage AH
4813 * protection */
4814 if (selinux_netlbl_skbuff_setsid(skb, family, peer_sid) != 0)
4815 return NF_DROP;
4816
Paul Mooreeffad8d2008-01-29 08:49:27 -05004817 return NF_ACCEPT;
4818}
4819
4820static unsigned int selinux_ipv4_forward(unsigned int hooknum,
4821 struct sk_buff *skb,
4822 const struct net_device *in,
4823 const struct net_device *out,
4824 int (*okfn)(struct sk_buff *))
4825{
4826 return selinux_ip_forward(skb, in->ifindex, PF_INET);
4827}
4828
4829#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
4830static unsigned int selinux_ipv6_forward(unsigned int hooknum,
4831 struct sk_buff *skb,
4832 const struct net_device *in,
4833 const struct net_device *out,
4834 int (*okfn)(struct sk_buff *))
4835{
4836 return selinux_ip_forward(skb, in->ifindex, PF_INET6);
4837}
4838#endif /* IPV6 */
4839
Paul Moore948bf852008-10-10 10:16:32 -04004840static unsigned int selinux_ip_output(struct sk_buff *skb,
4841 u16 family)
4842{
Paul Moore3ac7b8d2013-12-04 16:10:45 -05004843 struct sock *sk;
Paul Moore948bf852008-10-10 10:16:32 -04004844 u32 sid;
4845
4846 if (!netlbl_enabled())
4847 return NF_ACCEPT;
4848
4849 /* we do this in the LOCAL_OUT path and not the POST_ROUTING path
4850 * because we want to make sure we apply the necessary labeling
4851 * before IPsec is applied so we can leverage AH protection */
Paul Moore3ac7b8d2013-12-04 16:10:45 -05004852 sk = skb->sk;
4853 if (sk) {
4854 struct sk_security_struct *sksec;
4855
4856 if (sk->sk_state == TCP_LISTEN)
4857 /* if the socket is the listening state then this
4858 * packet is a SYN-ACK packet which means it needs to
4859 * be labeled based on the connection/request_sock and
4860 * not the parent socket. unfortunately, we can't
4861 * lookup the request_sock yet as it isn't queued on
4862 * the parent socket until after the SYN-ACK is sent.
4863 * the "solution" is to simply pass the packet as-is
4864 * as any IP option based labeling should be copied
4865 * from the initial connection request (in the IP
4866 * layer). it is far from ideal, but until we get a
4867 * security label in the packet itself this is the
4868 * best we can do. */
4869 return NF_ACCEPT;
4870
4871 /* standard practice, label using the parent socket */
4872 sksec = sk->sk_security;
Paul Moore948bf852008-10-10 10:16:32 -04004873 sid = sksec->sid;
4874 } else
4875 sid = SECINITSID_KERNEL;
4876 if (selinux_netlbl_skbuff_setsid(skb, family, sid) != 0)
4877 return NF_DROP;
4878
4879 return NF_ACCEPT;
4880}
4881
4882static unsigned int selinux_ipv4_output(unsigned int hooknum,
4883 struct sk_buff *skb,
4884 const struct net_device *in,
4885 const struct net_device *out,
4886 int (*okfn)(struct sk_buff *))
4887{
4888 return selinux_ip_output(skb, PF_INET);
4889}
4890
Paul Mooreeffad8d2008-01-29 08:49:27 -05004891static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
4892 int ifindex,
Paul Moored8395c82008-10-10 10:16:30 -04004893 u16 family)
James Morris4e5ab4c2006-06-09 00:33:33 -07004894{
Paul Mooreeffad8d2008-01-29 08:49:27 -05004895 struct sock *sk = skb->sk;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004896 struct sk_security_struct *sksec;
Thomas Liu2bf49692009-07-14 12:14:09 -04004897 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07004898 struct selinux_audit_data sad = {0,};
Eric Paris48c62af2012-04-02 13:15:44 -04004899 struct lsm_network_audit net = {0,};
Paul Moored8395c82008-10-10 10:16:30 -04004900 char *addrp;
4901 u8 proto;
James Morris4e5ab4c2006-06-09 00:33:33 -07004902
Paul Mooreeffad8d2008-01-29 08:49:27 -05004903 if (sk == NULL)
4904 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004905 sksec = sk->sk_security;
James Morris4e5ab4c2006-06-09 00:33:33 -07004906
Thomas Liu2bf49692009-07-14 12:14:09 -04004907 COMMON_AUDIT_DATA_INIT(&ad, NET);
Eric Paris3b3b0e42012-04-03 09:37:02 -07004908 ad.selinux_audit_data = &sad;
Eric Paris48c62af2012-04-02 13:15:44 -04004909 ad.u.net = &net;
4910 ad.u.net->netif = ifindex;
4911 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04004912 if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto))
4913 return NF_DROP;
4914
Paul Moore58bfbb52009-03-27 17:10:41 -04004915 if (selinux_secmark_enabled())
Paul Mooreeffad8d2008-01-29 08:49:27 -05004916 if (avc_has_perm(sksec->sid, skb->secmark,
Paul Moored8395c82008-10-10 10:16:30 -04004917 SECCLASS_PACKET, PACKET__SEND, &ad))
Eric Paris2fe66ec2010-11-23 06:28:08 +00004918 return NF_DROP_ERR(-ECONNREFUSED);
James Morris4e5ab4c2006-06-09 00:33:33 -07004919
Steffen Klassertb9679a72011-02-23 12:55:21 +01004920 if (selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto))
4921 return NF_DROP_ERR(-ECONNREFUSED);
James Morris4e5ab4c2006-06-09 00:33:33 -07004922
Paul Mooreeffad8d2008-01-29 08:49:27 -05004923 return NF_ACCEPT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004924}
4925
Paul Mooreeffad8d2008-01-29 08:49:27 -05004926static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
4927 u16 family)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004928{
Paul Mooreeffad8d2008-01-29 08:49:27 -05004929 u32 secmark_perm;
4930 u32 peer_sid;
4931 struct sock *sk;
Thomas Liu2bf49692009-07-14 12:14:09 -04004932 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07004933 struct selinux_audit_data sad = {0,};
Eric Paris48c62af2012-04-02 13:15:44 -04004934 struct lsm_network_audit net = {0,};
Paul Mooreeffad8d2008-01-29 08:49:27 -05004935 char *addrp;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004936 u8 secmark_active;
4937 u8 peerlbl_active;
4938
Paul Mooreeffad8d2008-01-29 08:49:27 -05004939 /* If any sort of compatibility mode is enabled then handoff processing
4940 * to the selinux_ip_postroute_compat() function to deal with the
4941 * special handling. We do this in an attempt to keep this function
4942 * as fast and as clean as possible. */
Paul Moore58bfbb52009-03-27 17:10:41 -04004943 if (!selinux_policycap_netpeer)
Paul Moored8395c82008-10-10 10:16:30 -04004944 return selinux_ip_postroute_compat(skb, ifindex, family);
Paul Moorea7379832013-12-10 14:58:01 -05004945
Paul Mooreeffad8d2008-01-29 08:49:27 -05004946 secmark_active = selinux_secmark_enabled();
4947 peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled();
4948 if (!secmark_active && !peerlbl_active)
4949 return NF_ACCEPT;
4950
Paul Mooreeffad8d2008-01-29 08:49:27 -05004951 sk = skb->sk;
Paul Moorea7379832013-12-10 14:58:01 -05004952
4953#ifdef CONFIG_XFRM
4954 /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec
4955 * packet transformation so allow the packet to pass without any checks
4956 * since we'll have another chance to perform access control checks
4957 * when the packet is on it's final way out.
4958 * NOTE: there appear to be some IPv6 multicast cases where skb->dst
4959 * is NULL, in this case go ahead and apply access control.
4960 * is NULL, in this case go ahead and apply access control.
4961 * NOTE: if this is a local socket (skb->sk != NULL) that is in the
4962 * TCP listening state we cannot wait until the XFRM processing
4963 * is done as we will miss out on the SA label if we do;
4964 * unfortunately, this means more work, but it is only once per
4965 * connection. */
4966 if (skb_dst(skb) != NULL && skb_dst(skb)->xfrm != NULL &&
4967 !(sk != NULL && sk->sk_state == TCP_LISTEN))
4968 return NF_ACCEPT;
4969#endif
4970
Paul Moored8395c82008-10-10 10:16:30 -04004971 if (sk == NULL) {
Paul Moore96d2c172013-12-04 16:10:51 -05004972 /* Without an associated socket the packet is either coming
4973 * from the kernel or it is being forwarded; check the packet
4974 * to determine which and if the packet is being forwarded
4975 * query the packet directly to determine the security label. */
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01004976 if (skb->skb_iif) {
4977 secmark_perm = PACKET__FORWARD_OUT;
Paul Moored8395c82008-10-10 10:16:30 -04004978 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00004979 return NF_DROP;
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01004980 } else {
4981 secmark_perm = PACKET__SEND;
Paul Moored8395c82008-10-10 10:16:30 -04004982 peer_sid = SECINITSID_KERNEL;
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01004983 }
Paul Moore96d2c172013-12-04 16:10:51 -05004984 } else if (sk->sk_state == TCP_LISTEN) {
4985 /* Locally generated packet but the associated socket is in the
4986 * listening state which means this is a SYN-ACK packet. In
4987 * this particular case the correct security label is assigned
4988 * to the connection/request_sock but unfortunately we can't
4989 * query the request_sock as it isn't queued on the parent
4990 * socket until after the SYN-ACK packet is sent; the only
4991 * viable choice is to regenerate the label like we do in
4992 * selinux_inet_conn_request(). See also selinux_ip_output()
4993 * for similar problems. */
4994 u32 skb_sid;
4995 struct sk_security_struct *sksec = sk->sk_security;
4996 if (selinux_skb_peerlbl_sid(skb, family, &skb_sid))
4997 return NF_DROP;
Paul Moorea7379832013-12-10 14:58:01 -05004998 /* At this point, if the returned skb peerlbl is SECSID_NULL
4999 * and the packet has been through at least one XFRM
5000 * transformation then we must be dealing with the "final"
5001 * form of labeled IPsec packet; since we've already applied
5002 * all of our access controls on this packet we can safely
5003 * pass the packet. */
5004 if (skb_sid == SECSID_NULL) {
5005 switch (family) {
5006 case PF_INET:
5007 if (IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED)
5008 return NF_ACCEPT;
5009 break;
5010 case PF_INET6:
5011 if (IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED)
5012 return NF_ACCEPT;
5013 default:
5014 return NF_DROP_ERR(-ECONNREFUSED);
5015 }
5016 }
Paul Moore96d2c172013-12-04 16:10:51 -05005017 if (selinux_conn_sid(sksec->sid, skb_sid, &peer_sid))
5018 return NF_DROP;
5019 secmark_perm = PACKET__SEND;
Paul Moored8395c82008-10-10 10:16:30 -04005020 } else {
Paul Moore96d2c172013-12-04 16:10:51 -05005021 /* Locally generated packet, fetch the security label from the
5022 * associated socket. */
Paul Mooreeffad8d2008-01-29 08:49:27 -05005023 struct sk_security_struct *sksec = sk->sk_security;
5024 peer_sid = sksec->sid;
5025 secmark_perm = PACKET__SEND;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005026 }
5027
Thomas Liu2bf49692009-07-14 12:14:09 -04005028 COMMON_AUDIT_DATA_INIT(&ad, NET);
Eric Paris3b3b0e42012-04-03 09:37:02 -07005029 ad.selinux_audit_data = &sad;
Eric Paris48c62af2012-04-02 13:15:44 -04005030 ad.u.net = &net;
5031 ad.u.net->netif = ifindex;
5032 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04005033 if (selinux_parse_skb(skb, &ad, &addrp, 0, NULL))
Eric Paris04f6d702010-11-23 06:28:02 +00005034 return NF_DROP;
Paul Moored8395c82008-10-10 10:16:30 -04005035
Paul Mooreeffad8d2008-01-29 08:49:27 -05005036 if (secmark_active)
5037 if (avc_has_perm(peer_sid, skb->secmark,
5038 SECCLASS_PACKET, secmark_perm, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00005039 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005040
5041 if (peerlbl_active) {
5042 u32 if_sid;
5043 u32 node_sid;
5044
5045 if (sel_netif_sid(ifindex, &if_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00005046 return NF_DROP;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005047 if (avc_has_perm(peer_sid, if_sid,
5048 SECCLASS_NETIF, NETIF__EGRESS, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00005049 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005050
5051 if (sel_netnode_sid(addrp, family, &node_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00005052 return NF_DROP;
Paul Mooreeffad8d2008-01-29 08:49:27 -05005053 if (avc_has_perm(peer_sid, node_sid,
5054 SECCLASS_NODE, NODE__SENDTO, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00005055 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05005056 }
5057
5058 return NF_ACCEPT;
5059}
5060
5061static unsigned int selinux_ipv4_postroute(unsigned int hooknum,
5062 struct sk_buff *skb,
5063 const struct net_device *in,
5064 const struct net_device *out,
5065 int (*okfn)(struct sk_buff *))
5066{
5067 return selinux_ip_postroute(skb, out->ifindex, PF_INET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005068}
5069
5070#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Paul Mooreeffad8d2008-01-29 08:49:27 -05005071static unsigned int selinux_ipv6_postroute(unsigned int hooknum,
5072 struct sk_buff *skb,
5073 const struct net_device *in,
5074 const struct net_device *out,
5075 int (*okfn)(struct sk_buff *))
Linus Torvalds1da177e2005-04-16 15:20:36 -07005076{
Paul Mooreeffad8d2008-01-29 08:49:27 -05005077 return selinux_ip_postroute(skb, out->ifindex, PF_INET6);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005078}
Linus Torvalds1da177e2005-04-16 15:20:36 -07005079#endif /* IPV6 */
5080
5081#endif /* CONFIG_NETFILTER */
5082
Linus Torvalds1da177e2005-04-16 15:20:36 -07005083static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb)
5084{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005085 int err;
5086
Eric Paris200ac532009-02-12 15:01:04 -05005087 err = cap_netlink_send(sk, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005088 if (err)
5089 return err;
5090
Stephen Smalley941fc5b2009-10-01 14:48:23 -04005091 return selinux_nlmsg_perm(sk, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005092}
5093
Linus Torvalds1da177e2005-04-16 15:20:36 -07005094static int ipc_alloc_security(struct task_struct *task,
5095 struct kern_ipc_perm *perm,
5096 u16 sclass)
5097{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005098 struct ipc_security_struct *isec;
David Howells275bb412008-11-14 10:39:19 +11005099 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005100
James Morris89d155e2005-10-30 14:59:21 -08005101 isec = kzalloc(sizeof(struct ipc_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005102 if (!isec)
5103 return -ENOMEM;
5104
David Howells275bb412008-11-14 10:39:19 +11005105 sid = task_sid(task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005106 isec->sclass = sclass;
David Howells275bb412008-11-14 10:39:19 +11005107 isec->sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005108 perm->security = isec;
5109
5110 return 0;
5111}
5112
5113static void ipc_free_security(struct kern_ipc_perm *perm)
5114{
5115 struct ipc_security_struct *isec = perm->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005116 perm->security = NULL;
5117 kfree(isec);
5118}
5119
5120static int msg_msg_alloc_security(struct msg_msg *msg)
5121{
5122 struct msg_security_struct *msec;
5123
James Morris89d155e2005-10-30 14:59:21 -08005124 msec = kzalloc(sizeof(struct msg_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005125 if (!msec)
5126 return -ENOMEM;
5127
Linus Torvalds1da177e2005-04-16 15:20:36 -07005128 msec->sid = SECINITSID_UNLABELED;
5129 msg->security = msec;
5130
5131 return 0;
5132}
5133
5134static void msg_msg_free_security(struct msg_msg *msg)
5135{
5136 struct msg_security_struct *msec = msg->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005137
5138 msg->security = NULL;
5139 kfree(msec);
5140}
5141
5142static int ipc_has_perm(struct kern_ipc_perm *ipc_perms,
Stephen Smalley6af963f2005-05-01 08:58:39 -07005143 u32 perms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005144{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005145 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005146 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07005147 struct selinux_audit_data sad = {0,};
David Howells275bb412008-11-14 10:39:19 +11005148 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005149
Linus Torvalds1da177e2005-04-16 15:20:36 -07005150 isec = ipc_perms->security;
5151
Thomas Liu2bf49692009-07-14 12:14:09 -04005152 COMMON_AUDIT_DATA_INIT(&ad, IPC);
Eric Paris3b3b0e42012-04-03 09:37:02 -07005153 ad.selinux_audit_data = &sad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005154 ad.u.ipc_id = ipc_perms->key;
5155
David Howells275bb412008-11-14 10:39:19 +11005156 return avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005157}
5158
5159static int selinux_msg_msg_alloc_security(struct msg_msg *msg)
5160{
5161 return msg_msg_alloc_security(msg);
5162}
5163
5164static void selinux_msg_msg_free_security(struct msg_msg *msg)
5165{
5166 msg_msg_free_security(msg);
5167}
5168
5169/* message queue security operations */
5170static int selinux_msg_queue_alloc_security(struct msg_queue *msq)
5171{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005172 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005173 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07005174 struct selinux_audit_data sad = {0,};
David Howells275bb412008-11-14 10:39:19 +11005175 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005176 int rc;
5177
5178 rc = ipc_alloc_security(current, &msq->q_perm, SECCLASS_MSGQ);
5179 if (rc)
5180 return rc;
5181
Linus Torvalds1da177e2005-04-16 15:20:36 -07005182 isec = msq->q_perm.security;
5183
Thomas Liu2bf49692009-07-14 12:14:09 -04005184 COMMON_AUDIT_DATA_INIT(&ad, IPC);
Eric Paris3b3b0e42012-04-03 09:37:02 -07005185 ad.selinux_audit_data = &sad;
Eric Paris828dfe12008-04-17 13:17:49 -04005186 ad.u.ipc_id = msq->q_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005187
David Howells275bb412008-11-14 10:39:19 +11005188 rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005189 MSGQ__CREATE, &ad);
5190 if (rc) {
5191 ipc_free_security(&msq->q_perm);
5192 return rc;
5193 }
5194 return 0;
5195}
5196
5197static void selinux_msg_queue_free_security(struct msg_queue *msq)
5198{
5199 ipc_free_security(&msq->q_perm);
5200}
5201
5202static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg)
5203{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005204 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005205 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07005206 struct selinux_audit_data sad = {0,};
David Howells275bb412008-11-14 10:39:19 +11005207 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005208
Linus Torvalds1da177e2005-04-16 15:20:36 -07005209 isec = msq->q_perm.security;
5210
Thomas Liu2bf49692009-07-14 12:14:09 -04005211 COMMON_AUDIT_DATA_INIT(&ad, IPC);
Eric Paris3b3b0e42012-04-03 09:37:02 -07005212 ad.selinux_audit_data = &sad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005213 ad.u.ipc_id = msq->q_perm.key;
5214
David Howells275bb412008-11-14 10:39:19 +11005215 return avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005216 MSGQ__ASSOCIATE, &ad);
5217}
5218
5219static int selinux_msg_queue_msgctl(struct msg_queue *msq, int cmd)
5220{
5221 int err;
5222 int perms;
5223
Eric Paris828dfe12008-04-17 13:17:49 -04005224 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005225 case IPC_INFO:
5226 case MSG_INFO:
5227 /* No specific object, just general system-wide information. */
5228 return task_has_system(current, SYSTEM__IPC_INFO);
5229 case IPC_STAT:
5230 case MSG_STAT:
5231 perms = MSGQ__GETATTR | MSGQ__ASSOCIATE;
5232 break;
5233 case IPC_SET:
5234 perms = MSGQ__SETATTR;
5235 break;
5236 case IPC_RMID:
5237 perms = MSGQ__DESTROY;
5238 break;
5239 default:
5240 return 0;
5241 }
5242
Stephen Smalley6af963f2005-05-01 08:58:39 -07005243 err = ipc_has_perm(&msq->q_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005244 return err;
5245}
5246
5247static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, int msqflg)
5248{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005249 struct ipc_security_struct *isec;
5250 struct msg_security_struct *msec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005251 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07005252 struct selinux_audit_data sad = {0,};
David Howells275bb412008-11-14 10:39:19 +11005253 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005254 int rc;
5255
Linus Torvalds1da177e2005-04-16 15:20:36 -07005256 isec = msq->q_perm.security;
5257 msec = msg->security;
5258
5259 /*
5260 * First time through, need to assign label to the message
5261 */
5262 if (msec->sid == SECINITSID_UNLABELED) {
5263 /*
5264 * Compute new sid based on current process and
5265 * message queue this message will be stored in
5266 */
David Howells275bb412008-11-14 10:39:19 +11005267 rc = security_transition_sid(sid, isec->sid, SECCLASS_MSG,
Eric Paris652bb9b2011-02-01 11:05:40 -05005268 NULL, &msec->sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005269 if (rc)
5270 return rc;
5271 }
5272
Thomas Liu2bf49692009-07-14 12:14:09 -04005273 COMMON_AUDIT_DATA_INIT(&ad, IPC);
Eric Paris3b3b0e42012-04-03 09:37:02 -07005274 ad.selinux_audit_data = &sad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005275 ad.u.ipc_id = msq->q_perm.key;
5276
5277 /* Can this process write to the queue? */
David Howells275bb412008-11-14 10:39:19 +11005278 rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005279 MSGQ__WRITE, &ad);
5280 if (!rc)
5281 /* Can this process send the message */
David Howells275bb412008-11-14 10:39:19 +11005282 rc = avc_has_perm(sid, msec->sid, SECCLASS_MSG,
5283 MSG__SEND, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005284 if (!rc)
5285 /* Can the message be put in the queue? */
David Howells275bb412008-11-14 10:39:19 +11005286 rc = avc_has_perm(msec->sid, isec->sid, SECCLASS_MSGQ,
5287 MSGQ__ENQUEUE, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005288
5289 return rc;
5290}
5291
5292static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
5293 struct task_struct *target,
5294 long type, int mode)
5295{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005296 struct ipc_security_struct *isec;
5297 struct msg_security_struct *msec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005298 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07005299 struct selinux_audit_data sad = {0,};
David Howells275bb412008-11-14 10:39:19 +11005300 u32 sid = task_sid(target);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005301 int rc;
5302
Linus Torvalds1da177e2005-04-16 15:20:36 -07005303 isec = msq->q_perm.security;
5304 msec = msg->security;
5305
Thomas Liu2bf49692009-07-14 12:14:09 -04005306 COMMON_AUDIT_DATA_INIT(&ad, IPC);
Eric Paris3b3b0e42012-04-03 09:37:02 -07005307 ad.selinux_audit_data = &sad;
Eric Paris828dfe12008-04-17 13:17:49 -04005308 ad.u.ipc_id = msq->q_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005309
David Howells275bb412008-11-14 10:39:19 +11005310 rc = avc_has_perm(sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005311 SECCLASS_MSGQ, MSGQ__READ, &ad);
5312 if (!rc)
David Howells275bb412008-11-14 10:39:19 +11005313 rc = avc_has_perm(sid, msec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005314 SECCLASS_MSG, MSG__RECEIVE, &ad);
5315 return rc;
5316}
5317
5318/* Shared Memory security operations */
5319static int selinux_shm_alloc_security(struct shmid_kernel *shp)
5320{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005321 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005322 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07005323 struct selinux_audit_data sad = {0,};
David Howells275bb412008-11-14 10:39:19 +11005324 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005325 int rc;
5326
5327 rc = ipc_alloc_security(current, &shp->shm_perm, SECCLASS_SHM);
5328 if (rc)
5329 return rc;
5330
Linus Torvalds1da177e2005-04-16 15:20:36 -07005331 isec = shp->shm_perm.security;
5332
Thomas Liu2bf49692009-07-14 12:14:09 -04005333 COMMON_AUDIT_DATA_INIT(&ad, IPC);
Eric Paris3b3b0e42012-04-03 09:37:02 -07005334 ad.selinux_audit_data = &sad;
Eric Paris828dfe12008-04-17 13:17:49 -04005335 ad.u.ipc_id = shp->shm_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005336
David Howells275bb412008-11-14 10:39:19 +11005337 rc = avc_has_perm(sid, isec->sid, SECCLASS_SHM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005338 SHM__CREATE, &ad);
5339 if (rc) {
5340 ipc_free_security(&shp->shm_perm);
5341 return rc;
5342 }
5343 return 0;
5344}
5345
5346static void selinux_shm_free_security(struct shmid_kernel *shp)
5347{
5348 ipc_free_security(&shp->shm_perm);
5349}
5350
5351static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg)
5352{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005353 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005354 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07005355 struct selinux_audit_data sad = {0,};
David Howells275bb412008-11-14 10:39:19 +11005356 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005357
Linus Torvalds1da177e2005-04-16 15:20:36 -07005358 isec = shp->shm_perm.security;
5359
Thomas Liu2bf49692009-07-14 12:14:09 -04005360 COMMON_AUDIT_DATA_INIT(&ad, IPC);
Eric Paris3b3b0e42012-04-03 09:37:02 -07005361 ad.selinux_audit_data = &sad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005362 ad.u.ipc_id = shp->shm_perm.key;
5363
David Howells275bb412008-11-14 10:39:19 +11005364 return avc_has_perm(sid, isec->sid, SECCLASS_SHM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005365 SHM__ASSOCIATE, &ad);
5366}
5367
5368/* Note, at this point, shp is locked down */
5369static int selinux_shm_shmctl(struct shmid_kernel *shp, int cmd)
5370{
5371 int perms;
5372 int err;
5373
Eric Paris828dfe12008-04-17 13:17:49 -04005374 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005375 case IPC_INFO:
5376 case SHM_INFO:
5377 /* No specific object, just general system-wide information. */
5378 return task_has_system(current, SYSTEM__IPC_INFO);
5379 case IPC_STAT:
5380 case SHM_STAT:
5381 perms = SHM__GETATTR | SHM__ASSOCIATE;
5382 break;
5383 case IPC_SET:
5384 perms = SHM__SETATTR;
5385 break;
5386 case SHM_LOCK:
5387 case SHM_UNLOCK:
5388 perms = SHM__LOCK;
5389 break;
5390 case IPC_RMID:
5391 perms = SHM__DESTROY;
5392 break;
5393 default:
5394 return 0;
5395 }
5396
Stephen Smalley6af963f2005-05-01 08:58:39 -07005397 err = ipc_has_perm(&shp->shm_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005398 return err;
5399}
5400
5401static int selinux_shm_shmat(struct shmid_kernel *shp,
5402 char __user *shmaddr, int shmflg)
5403{
5404 u32 perms;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005405
5406 if (shmflg & SHM_RDONLY)
5407 perms = SHM__READ;
5408 else
5409 perms = SHM__READ | SHM__WRITE;
5410
Stephen Smalley6af963f2005-05-01 08:58:39 -07005411 return ipc_has_perm(&shp->shm_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005412}
5413
5414/* Semaphore security operations */
5415static int selinux_sem_alloc_security(struct sem_array *sma)
5416{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005417 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005418 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07005419 struct selinux_audit_data sad = {0,};
David Howells275bb412008-11-14 10:39:19 +11005420 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005421 int rc;
5422
5423 rc = ipc_alloc_security(current, &sma->sem_perm, SECCLASS_SEM);
5424 if (rc)
5425 return rc;
5426
Linus Torvalds1da177e2005-04-16 15:20:36 -07005427 isec = sma->sem_perm.security;
5428
Thomas Liu2bf49692009-07-14 12:14:09 -04005429 COMMON_AUDIT_DATA_INIT(&ad, IPC);
Eric Paris3b3b0e42012-04-03 09:37:02 -07005430 ad.selinux_audit_data = &sad;
Eric Paris828dfe12008-04-17 13:17:49 -04005431 ad.u.ipc_id = sma->sem_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005432
David Howells275bb412008-11-14 10:39:19 +11005433 rc = avc_has_perm(sid, isec->sid, SECCLASS_SEM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005434 SEM__CREATE, &ad);
5435 if (rc) {
5436 ipc_free_security(&sma->sem_perm);
5437 return rc;
5438 }
5439 return 0;
5440}
5441
5442static void selinux_sem_free_security(struct sem_array *sma)
5443{
5444 ipc_free_security(&sma->sem_perm);
5445}
5446
5447static int selinux_sem_associate(struct sem_array *sma, int semflg)
5448{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005449 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005450 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07005451 struct selinux_audit_data sad = {0,};
David Howells275bb412008-11-14 10:39:19 +11005452 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005453
Linus Torvalds1da177e2005-04-16 15:20:36 -07005454 isec = sma->sem_perm.security;
5455
Thomas Liu2bf49692009-07-14 12:14:09 -04005456 COMMON_AUDIT_DATA_INIT(&ad, IPC);
Eric Paris3b3b0e42012-04-03 09:37:02 -07005457 ad.selinux_audit_data = &sad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005458 ad.u.ipc_id = sma->sem_perm.key;
5459
David Howells275bb412008-11-14 10:39:19 +11005460 return avc_has_perm(sid, isec->sid, SECCLASS_SEM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005461 SEM__ASSOCIATE, &ad);
5462}
5463
5464/* Note, at this point, sma is locked down */
5465static int selinux_sem_semctl(struct sem_array *sma, int cmd)
5466{
5467 int err;
5468 u32 perms;
5469
Eric Paris828dfe12008-04-17 13:17:49 -04005470 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005471 case IPC_INFO:
5472 case SEM_INFO:
5473 /* No specific object, just general system-wide information. */
5474 return task_has_system(current, SYSTEM__IPC_INFO);
5475 case GETPID:
5476 case GETNCNT:
5477 case GETZCNT:
5478 perms = SEM__GETATTR;
5479 break;
5480 case GETVAL:
5481 case GETALL:
5482 perms = SEM__READ;
5483 break;
5484 case SETVAL:
5485 case SETALL:
5486 perms = SEM__WRITE;
5487 break;
5488 case IPC_RMID:
5489 perms = SEM__DESTROY;
5490 break;
5491 case IPC_SET:
5492 perms = SEM__SETATTR;
5493 break;
5494 case IPC_STAT:
5495 case SEM_STAT:
5496 perms = SEM__GETATTR | SEM__ASSOCIATE;
5497 break;
5498 default:
5499 return 0;
5500 }
5501
Stephen Smalley6af963f2005-05-01 08:58:39 -07005502 err = ipc_has_perm(&sma->sem_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005503 return err;
5504}
5505
5506static int selinux_sem_semop(struct sem_array *sma,
5507 struct sembuf *sops, unsigned nsops, int alter)
5508{
5509 u32 perms;
5510
5511 if (alter)
5512 perms = SEM__READ | SEM__WRITE;
5513 else
5514 perms = SEM__READ;
5515
Stephen Smalley6af963f2005-05-01 08:58:39 -07005516 return ipc_has_perm(&sma->sem_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005517}
5518
5519static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
5520{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005521 u32 av = 0;
5522
Linus Torvalds1da177e2005-04-16 15:20:36 -07005523 av = 0;
5524 if (flag & S_IRUGO)
5525 av |= IPC__UNIX_READ;
5526 if (flag & S_IWUGO)
5527 av |= IPC__UNIX_WRITE;
5528
5529 if (av == 0)
5530 return 0;
5531
Stephen Smalley6af963f2005-05-01 08:58:39 -07005532 return ipc_has_perm(ipcp, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005533}
5534
Ahmed S. Darwish713a04a2008-03-01 21:52:30 +02005535static void selinux_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
5536{
5537 struct ipc_security_struct *isec = ipcp->security;
5538 *secid = isec->sid;
5539}
5540
Eric Paris828dfe12008-04-17 13:17:49 -04005541static void selinux_d_instantiate(struct dentry *dentry, struct inode *inode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005542{
5543 if (inode)
5544 inode_doinit_with_dentry(inode, dentry);
5545}
5546
5547static int selinux_getprocattr(struct task_struct *p,
Al Viro04ff9702007-03-12 16:17:58 +00005548 char *name, char **value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005549{
David Howells275bb412008-11-14 10:39:19 +11005550 const struct task_security_struct *__tsec;
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00005551 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005552 int error;
Al Viro04ff9702007-03-12 16:17:58 +00005553 unsigned len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005554
5555 if (current != p) {
David Howells3b11a1d2008-11-14 10:39:26 +11005556 error = current_has_perm(p, PROCESS__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005557 if (error)
5558 return error;
5559 }
5560
David Howells275bb412008-11-14 10:39:19 +11005561 rcu_read_lock();
5562 __tsec = __task_cred(p)->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005563
5564 if (!strcmp(name, "current"))
David Howells275bb412008-11-14 10:39:19 +11005565 sid = __tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005566 else if (!strcmp(name, "prev"))
David Howells275bb412008-11-14 10:39:19 +11005567 sid = __tsec->osid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005568 else if (!strcmp(name, "exec"))
David Howells275bb412008-11-14 10:39:19 +11005569 sid = __tsec->exec_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005570 else if (!strcmp(name, "fscreate"))
David Howells275bb412008-11-14 10:39:19 +11005571 sid = __tsec->create_sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005572 else if (!strcmp(name, "keycreate"))
David Howells275bb412008-11-14 10:39:19 +11005573 sid = __tsec->keycreate_sid;
Eric Paris42c3e032006-06-26 00:26:03 -07005574 else if (!strcmp(name, "sockcreate"))
David Howells275bb412008-11-14 10:39:19 +11005575 sid = __tsec->sockcreate_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005576 else
David Howells275bb412008-11-14 10:39:19 +11005577 goto invalid;
5578 rcu_read_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005579
5580 if (!sid)
5581 return 0;
5582
Al Viro04ff9702007-03-12 16:17:58 +00005583 error = security_sid_to_context(sid, value, &len);
5584 if (error)
5585 return error;
5586 return len;
David Howells275bb412008-11-14 10:39:19 +11005587
5588invalid:
5589 rcu_read_unlock();
5590 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005591}
5592
5593static int selinux_setprocattr(struct task_struct *p,
5594 char *name, void *value, size_t size)
5595{
5596 struct task_security_struct *tsec;
Roland McGrath03563572008-03-26 15:46:39 -07005597 struct task_struct *tracer;
David Howellsd84f4f92008-11-14 10:39:23 +11005598 struct cred *new;
5599 u32 sid = 0, ptsid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005600 int error;
5601 char *str = value;
5602
5603 if (current != p) {
5604 /* SELinux only allows a process to change its own
5605 security attributes. */
5606 return -EACCES;
5607 }
5608
5609 /*
5610 * Basic control over ability to set these attributes at all.
5611 * current == p, but we'll pass them separately in case the
5612 * above restriction is ever removed.
5613 */
5614 if (!strcmp(name, "exec"))
David Howells3b11a1d2008-11-14 10:39:26 +11005615 error = current_has_perm(p, PROCESS__SETEXEC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005616 else if (!strcmp(name, "fscreate"))
David Howells3b11a1d2008-11-14 10:39:26 +11005617 error = current_has_perm(p, PROCESS__SETFSCREATE);
Michael LeMay4eb582c2006-06-26 00:24:57 -07005618 else if (!strcmp(name, "keycreate"))
David Howells3b11a1d2008-11-14 10:39:26 +11005619 error = current_has_perm(p, PROCESS__SETKEYCREATE);
Eric Paris42c3e032006-06-26 00:26:03 -07005620 else if (!strcmp(name, "sockcreate"))
David Howells3b11a1d2008-11-14 10:39:26 +11005621 error = current_has_perm(p, PROCESS__SETSOCKCREATE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005622 else if (!strcmp(name, "current"))
David Howells3b11a1d2008-11-14 10:39:26 +11005623 error = current_has_perm(p, PROCESS__SETCURRENT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005624 else
5625 error = -EINVAL;
5626 if (error)
5627 return error;
5628
5629 /* Obtain a SID for the context, if one was specified. */
Stephen Smalleye44b57e2017-01-31 11:54:04 -05005630 if (size && str[0] && str[0] != '\n') {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005631 if (str[size-1] == '\n') {
5632 str[size-1] = 0;
5633 size--;
5634 }
5635 error = security_context_to_sid(value, size, &sid);
Stephen Smalley12b29f32008-05-07 13:03:20 -04005636 if (error == -EINVAL && !strcmp(name, "fscreate")) {
5637 if (!capable(CAP_MAC_ADMIN))
5638 return error;
5639 error = security_context_to_sid_force(value, size,
5640 &sid);
5641 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005642 if (error)
5643 return error;
5644 }
5645
David Howellsd84f4f92008-11-14 10:39:23 +11005646 new = prepare_creds();
5647 if (!new)
5648 return -ENOMEM;
5649
Linus Torvalds1da177e2005-04-16 15:20:36 -07005650 /* Permission checking based on the specified context is
5651 performed during the actual operation (execve,
5652 open/mkdir/...), when we know the full context of the
David Howellsd84f4f92008-11-14 10:39:23 +11005653 operation. See selinux_bprm_set_creds for the execve
Linus Torvalds1da177e2005-04-16 15:20:36 -07005654 checks and may_create for the file creation checks. The
5655 operation will then fail if the context is not permitted. */
David Howellsd84f4f92008-11-14 10:39:23 +11005656 tsec = new->security;
5657 if (!strcmp(name, "exec")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005658 tsec->exec_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005659 } else if (!strcmp(name, "fscreate")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005660 tsec->create_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005661 } else if (!strcmp(name, "keycreate")) {
Michael LeMay4eb582c2006-06-26 00:24:57 -07005662 error = may_create_key(sid, p);
5663 if (error)
David Howellsd84f4f92008-11-14 10:39:23 +11005664 goto abort_change;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005665 tsec->keycreate_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005666 } else if (!strcmp(name, "sockcreate")) {
Eric Paris42c3e032006-06-26 00:26:03 -07005667 tsec->sockcreate_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005668 } else if (!strcmp(name, "current")) {
5669 error = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005670 if (sid == 0)
David Howellsd84f4f92008-11-14 10:39:23 +11005671 goto abort_change;
KaiGai Koheid9250de2008-08-28 16:35:57 +09005672
David Howellsd84f4f92008-11-14 10:39:23 +11005673 /* Only allow single threaded processes to change context */
5674 error = -EPERM;
Oleg Nesterov5bb459b2009-07-10 03:48:23 +02005675 if (!current_is_single_threaded()) {
David Howellsd84f4f92008-11-14 10:39:23 +11005676 error = security_bounded_transition(tsec->sid, sid);
5677 if (error)
5678 goto abort_change;
Eric Paris828dfe12008-04-17 13:17:49 -04005679 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005680
5681 /* Check permissions for the transition. */
5682 error = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS,
Eric Paris828dfe12008-04-17 13:17:49 -04005683 PROCESS__DYNTRANSITION, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005684 if (error)
David Howellsd84f4f92008-11-14 10:39:23 +11005685 goto abort_change;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005686
5687 /* Check for ptracing, and update the task SID if ok.
5688 Otherwise, leave SID unchanged and fail. */
David Howellsd84f4f92008-11-14 10:39:23 +11005689 ptsid = 0;
Oleg Nesterovcdeb0b02013-12-23 17:45:01 -05005690 rcu_read_lock();
Tejun Heo06d98472011-06-17 16:50:40 +02005691 tracer = ptrace_parent(p);
David Howellsd84f4f92008-11-14 10:39:23 +11005692 if (tracer)
5693 ptsid = task_sid(tracer);
Oleg Nesterovcdeb0b02013-12-23 17:45:01 -05005694 rcu_read_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005695
David Howellsd84f4f92008-11-14 10:39:23 +11005696 if (tracer) {
5697 error = avc_has_perm(ptsid, sid, SECCLASS_PROCESS,
5698 PROCESS__PTRACE, NULL);
5699 if (error)
5700 goto abort_change;
5701 }
5702
5703 tsec->sid = sid;
5704 } else {
5705 error = -EINVAL;
5706 goto abort_change;
5707 }
5708
5709 commit_creds(new);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005710 return size;
David Howellsd84f4f92008-11-14 10:39:23 +11005711
5712abort_change:
5713 abort_creds(new);
5714 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005715}
5716
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005717static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
5718{
5719 return security_sid_to_context(secid, secdata, seclen);
5720}
5721
David Howells7bf570d2008-04-29 20:52:51 +01005722static int selinux_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
David Howells63cb3442008-01-15 23:47:35 +00005723{
5724 return security_context_to_sid(secdata, seclen, secid);
5725}
5726
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005727static void selinux_release_secctx(char *secdata, u32 seclen)
5728{
Paul Moore088999e2007-08-01 11:12:58 -04005729 kfree(secdata);
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005730}
5731
David P. Quigley1ee65e32009-09-03 14:25:57 -04005732/*
5733 * called with inode->i_mutex locked
5734 */
5735static int selinux_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen)
5736{
5737 return selinux_inode_setsecurity(inode, XATTR_SELINUX_SUFFIX, ctx, ctxlen, 0);
5738}
5739
5740/*
5741 * called with inode->i_mutex locked
5742 */
5743static int selinux_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen)
5744{
5745 return __vfs_setxattr_noperm(dentry, XATTR_NAME_SELINUX, ctx, ctxlen, 0);
5746}
5747
5748static int selinux_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen)
5749{
5750 int len = 0;
5751 len = selinux_inode_getsecurity(inode, XATTR_SELINUX_SUFFIX,
5752 ctx, true);
5753 if (len < 0)
5754 return len;
5755 *ctxlen = len;
5756 return 0;
5757}
Michael LeMayd7200242006-06-22 14:47:17 -07005758#ifdef CONFIG_KEYS
5759
David Howellsd84f4f92008-11-14 10:39:23 +11005760static int selinux_key_alloc(struct key *k, const struct cred *cred,
David Howells7e047ef2006-06-26 00:24:50 -07005761 unsigned long flags)
Michael LeMayd7200242006-06-22 14:47:17 -07005762{
David Howellsd84f4f92008-11-14 10:39:23 +11005763 const struct task_security_struct *tsec;
Michael LeMayd7200242006-06-22 14:47:17 -07005764 struct key_security_struct *ksec;
5765
5766 ksec = kzalloc(sizeof(struct key_security_struct), GFP_KERNEL);
5767 if (!ksec)
5768 return -ENOMEM;
5769
David Howellsd84f4f92008-11-14 10:39:23 +11005770 tsec = cred->security;
5771 if (tsec->keycreate_sid)
5772 ksec->sid = tsec->keycreate_sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005773 else
David Howellsd84f4f92008-11-14 10:39:23 +11005774 ksec->sid = tsec->sid;
Michael LeMayd7200242006-06-22 14:47:17 -07005775
David Howells275bb412008-11-14 10:39:19 +11005776 k->security = ksec;
Michael LeMayd7200242006-06-22 14:47:17 -07005777 return 0;
5778}
5779
5780static void selinux_key_free(struct key *k)
5781{
5782 struct key_security_struct *ksec = k->security;
5783
5784 k->security = NULL;
5785 kfree(ksec);
5786}
5787
5788static int selinux_key_permission(key_ref_t key_ref,
David Howellsd84f4f92008-11-14 10:39:23 +11005789 const struct cred *cred,
5790 key_perm_t perm)
Michael LeMayd7200242006-06-22 14:47:17 -07005791{
5792 struct key *key;
Michael LeMayd7200242006-06-22 14:47:17 -07005793 struct key_security_struct *ksec;
David Howells275bb412008-11-14 10:39:19 +11005794 u32 sid;
Michael LeMayd7200242006-06-22 14:47:17 -07005795
5796 /* if no specific permissions are requested, we skip the
5797 permission check. No serious, additional covert channels
5798 appear to be created. */
5799 if (perm == 0)
5800 return 0;
5801
David Howellsd84f4f92008-11-14 10:39:23 +11005802 sid = cred_sid(cred);
David Howells275bb412008-11-14 10:39:19 +11005803
5804 key = key_ref_to_ptr(key_ref);
5805 ksec = key->security;
5806
5807 return avc_has_perm(sid, ksec->sid, SECCLASS_KEY, perm, NULL);
Michael LeMayd7200242006-06-22 14:47:17 -07005808}
5809
David Howells70a5bb72008-04-29 01:01:26 -07005810static int selinux_key_getsecurity(struct key *key, char **_buffer)
5811{
5812 struct key_security_struct *ksec = key->security;
5813 char *context = NULL;
5814 unsigned len;
5815 int rc;
5816
5817 rc = security_sid_to_context(ksec->sid, &context, &len);
5818 if (!rc)
5819 rc = len;
5820 *_buffer = context;
5821 return rc;
5822}
5823
Michael LeMayd7200242006-06-22 14:47:17 -07005824#endif
5825
Linus Torvalds1da177e2005-04-16 15:20:36 -07005826static struct security_operations selinux_ops = {
Ahmed S. Darwish076c54c2008-03-06 18:09:10 +02005827 .name = "selinux",
5828
Stephen Smalley48a23702012-11-05 08:15:34 -05005829 .binder_set_context_mgr = selinux_binder_set_context_mgr,
5830 .binder_transaction = selinux_binder_transaction,
5831 .binder_transfer_binder = selinux_binder_transfer_binder,
5832 .binder_transfer_file = selinux_binder_transfer_file,
5833
Ingo Molnar9e488582009-05-07 19:26:19 +10005834 .ptrace_access_check = selinux_ptrace_access_check,
David Howells5cd9c582008-08-14 11:37:28 +01005835 .ptrace_traceme = selinux_ptrace_traceme,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005836 .capget = selinux_capget,
David Howellsd84f4f92008-11-14 10:39:23 +11005837 .capset = selinux_capset,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005838 .capable = selinux_capable,
5839 .quotactl = selinux_quotactl,
5840 .quota_on = selinux_quota_on,
5841 .syslog = selinux_syslog,
5842 .vm_enough_memory = selinux_vm_enough_memory,
5843
5844 .netlink_send = selinux_netlink_send,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005845
David Howellsa6f76f22008-11-14 10:39:24 +11005846 .bprm_set_creds = selinux_bprm_set_creds,
David Howellsa6f76f22008-11-14 10:39:24 +11005847 .bprm_committing_creds = selinux_bprm_committing_creds,
5848 .bprm_committed_creds = selinux_bprm_committed_creds,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005849 .bprm_secureexec = selinux_bprm_secureexec,
5850
5851 .sb_alloc_security = selinux_sb_alloc_security,
5852 .sb_free_security = selinux_sb_free_security,
5853 .sb_copy_data = selinux_sb_copy_data,
Eric Paris026eb162011-03-03 16:09:14 -05005854 .sb_remount = selinux_sb_remount,
Eric Paris828dfe12008-04-17 13:17:49 -04005855 .sb_kern_mount = selinux_sb_kern_mount,
Eric Paris2069f452008-07-04 09:47:13 +10005856 .sb_show_options = selinux_sb_show_options,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005857 .sb_statfs = selinux_sb_statfs,
5858 .sb_mount = selinux_mount,
5859 .sb_umount = selinux_umount,
Eric Parisc9180a52007-11-30 13:00:35 -05005860 .sb_set_mnt_opts = selinux_set_mnt_opts,
Eric Paris828dfe12008-04-17 13:17:49 -04005861 .sb_clone_mnt_opts = selinux_sb_clone_mnt_opts,
Eric Parise0007522008-03-05 10:31:54 -05005862 .sb_parse_opts_str = selinux_parse_opts_str,
5863
Linus Torvalds1da177e2005-04-16 15:20:36 -07005864
5865 .inode_alloc_security = selinux_inode_alloc_security,
5866 .inode_free_security = selinux_inode_free_security,
Stephen Smalley5e41ff92005-09-09 13:01:35 -07005867 .inode_init_security = selinux_inode_init_security,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005868 .inode_create = selinux_inode_create,
Amir Samuelov6a22e462014-05-26 11:44:06 +03005869 .inode_post_create = selinux_inode_post_create,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005870 .inode_link = selinux_inode_link,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005871 .inode_unlink = selinux_inode_unlink,
5872 .inode_symlink = selinux_inode_symlink,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005873 .inode_mkdir = selinux_inode_mkdir,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005874 .inode_rmdir = selinux_inode_rmdir,
5875 .inode_mknod = selinux_inode_mknod,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005876 .inode_rename = selinux_inode_rename,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005877 .inode_readlink = selinux_inode_readlink,
5878 .inode_follow_link = selinux_inode_follow_link,
5879 .inode_permission = selinux_inode_permission,
5880 .inode_setattr = selinux_inode_setattr,
5881 .inode_getattr = selinux_inode_getattr,
5882 .inode_setxattr = selinux_inode_setxattr,
5883 .inode_post_setxattr = selinux_inode_post_setxattr,
5884 .inode_getxattr = selinux_inode_getxattr,
5885 .inode_listxattr = selinux_inode_listxattr,
5886 .inode_removexattr = selinux_inode_removexattr,
Eric Paris828dfe12008-04-17 13:17:49 -04005887 .inode_getsecurity = selinux_inode_getsecurity,
5888 .inode_setsecurity = selinux_inode_setsecurity,
5889 .inode_listsecurity = selinux_inode_listsecurity,
Eric Parisf5269712008-05-14 11:27:45 -04005890 .inode_getsecid = selinux_inode_getsecid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005891
5892 .file_permission = selinux_file_permission,
5893 .file_alloc_security = selinux_file_alloc_security,
5894 .file_free_security = selinux_file_free_security,
5895 .file_ioctl = selinux_file_ioctl,
5896 .file_mmap = selinux_file_mmap,
5897 .file_mprotect = selinux_file_mprotect,
5898 .file_lock = selinux_file_lock,
5899 .file_fcntl = selinux_file_fcntl,
5900 .file_set_fowner = selinux_file_set_fowner,
5901 .file_send_sigiotask = selinux_file_send_sigiotask,
5902 .file_receive = selinux_file_receive,
5903
Eric Paris828dfe12008-04-17 13:17:49 -04005904 .dentry_open = selinux_dentry_open,
Amir Samuelov6a22e462014-05-26 11:44:06 +03005905 .file_close = selinux_file_close,
5906 .allow_merge_bio = selinux_allow_merge_bio,
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09005907
Linus Torvalds1da177e2005-04-16 15:20:36 -07005908 .task_create = selinux_task_create,
David Howellsee18d642009-09-02 09:14:21 +01005909 .cred_alloc_blank = selinux_cred_alloc_blank,
David Howellsf1752ee2008-11-14 10:39:17 +11005910 .cred_free = selinux_cred_free,
David Howellsd84f4f92008-11-14 10:39:23 +11005911 .cred_prepare = selinux_cred_prepare,
David Howellsee18d642009-09-02 09:14:21 +01005912 .cred_transfer = selinux_cred_transfer,
David Howells3a3b7ce2008-11-14 10:39:28 +11005913 .kernel_act_as = selinux_kernel_act_as,
5914 .kernel_create_files_as = selinux_kernel_create_files_as,
Eric Paris25354c42009-08-13 09:45:03 -04005915 .kernel_module_request = selinux_kernel_module_request,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005916 .task_setpgid = selinux_task_setpgid,
5917 .task_getpgid = selinux_task_getpgid,
Eric Paris828dfe12008-04-17 13:17:49 -04005918 .task_getsid = selinux_task_getsid,
David Quigleyf9008e42006-06-30 01:55:46 -07005919 .task_getsecid = selinux_task_getsecid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005920 .task_setnice = selinux_task_setnice,
James Morris03e68062006-06-23 02:03:58 -07005921 .task_setioprio = selinux_task_setioprio,
David Quigleya1836a42006-06-30 01:55:49 -07005922 .task_getioprio = selinux_task_getioprio,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005923 .task_setrlimit = selinux_task_setrlimit,
5924 .task_setscheduler = selinux_task_setscheduler,
5925 .task_getscheduler = selinux_task_getscheduler,
David Quigley35601542006-06-23 02:04:01 -07005926 .task_movememory = selinux_task_movememory,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005927 .task_kill = selinux_task_kill,
5928 .task_wait = selinux_task_wait,
Eric Paris828dfe12008-04-17 13:17:49 -04005929 .task_to_inode = selinux_task_to_inode,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005930
5931 .ipc_permission = selinux_ipc_permission,
Eric Parisf5269712008-05-14 11:27:45 -04005932 .ipc_getsecid = selinux_ipc_getsecid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005933
5934 .msg_msg_alloc_security = selinux_msg_msg_alloc_security,
5935 .msg_msg_free_security = selinux_msg_msg_free_security,
5936
5937 .msg_queue_alloc_security = selinux_msg_queue_alloc_security,
5938 .msg_queue_free_security = selinux_msg_queue_free_security,
5939 .msg_queue_associate = selinux_msg_queue_associate,
5940 .msg_queue_msgctl = selinux_msg_queue_msgctl,
5941 .msg_queue_msgsnd = selinux_msg_queue_msgsnd,
5942 .msg_queue_msgrcv = selinux_msg_queue_msgrcv,
5943
5944 .shm_alloc_security = selinux_shm_alloc_security,
5945 .shm_free_security = selinux_shm_free_security,
5946 .shm_associate = selinux_shm_associate,
5947 .shm_shmctl = selinux_shm_shmctl,
5948 .shm_shmat = selinux_shm_shmat,
5949
Eric Paris828dfe12008-04-17 13:17:49 -04005950 .sem_alloc_security = selinux_sem_alloc_security,
5951 .sem_free_security = selinux_sem_free_security,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005952 .sem_associate = selinux_sem_associate,
5953 .sem_semctl = selinux_sem_semctl,
5954 .sem_semop = selinux_sem_semop,
5955
Eric Paris828dfe12008-04-17 13:17:49 -04005956 .d_instantiate = selinux_d_instantiate,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005957
Eric Paris828dfe12008-04-17 13:17:49 -04005958 .getprocattr = selinux_getprocattr,
5959 .setprocattr = selinux_setprocattr,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005960
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005961 .secid_to_secctx = selinux_secid_to_secctx,
David Howells63cb3442008-01-15 23:47:35 +00005962 .secctx_to_secid = selinux_secctx_to_secid,
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005963 .release_secctx = selinux_release_secctx,
David P. Quigley1ee65e32009-09-03 14:25:57 -04005964 .inode_notifysecctx = selinux_inode_notifysecctx,
5965 .inode_setsecctx = selinux_inode_setsecctx,
5966 .inode_getsecctx = selinux_inode_getsecctx,
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005967
Eric Paris828dfe12008-04-17 13:17:49 -04005968 .unix_stream_connect = selinux_socket_unix_stream_connect,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005969 .unix_may_send = selinux_socket_unix_may_send,
5970
5971 .socket_create = selinux_socket_create,
5972 .socket_post_create = selinux_socket_post_create,
5973 .socket_bind = selinux_socket_bind,
5974 .socket_connect = selinux_socket_connect,
5975 .socket_listen = selinux_socket_listen,
5976 .socket_accept = selinux_socket_accept,
5977 .socket_sendmsg = selinux_socket_sendmsg,
5978 .socket_recvmsg = selinux_socket_recvmsg,
5979 .socket_getsockname = selinux_socket_getsockname,
5980 .socket_getpeername = selinux_socket_getpeername,
5981 .socket_getsockopt = selinux_socket_getsockopt,
5982 .socket_setsockopt = selinux_socket_setsockopt,
5983 .socket_shutdown = selinux_socket_shutdown,
5984 .socket_sock_rcv_skb = selinux_socket_sock_rcv_skb,
Catherine Zhang2c7946a2006-03-20 22:41:23 -08005985 .socket_getpeersec_stream = selinux_socket_getpeersec_stream,
5986 .socket_getpeersec_dgram = selinux_socket_getpeersec_dgram,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005987 .sk_alloc_security = selinux_sk_alloc_security,
5988 .sk_free_security = selinux_sk_free_security,
Venkat Yekkirala892c1412006-08-04 23:08:56 -07005989 .sk_clone_security = selinux_sk_clone_security,
Eric Paris828dfe12008-04-17 13:17:49 -04005990 .sk_getsecid = selinux_sk_getsecid,
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005991 .sock_graft = selinux_sock_graft,
5992 .inet_conn_request = selinux_inet_conn_request,
5993 .inet_csk_clone = selinux_inet_csk_clone,
Venkat Yekkirala6b877692006-11-08 17:04:09 -06005994 .inet_conn_established = selinux_inet_conn_established,
Eric Paris2606fd12010-10-13 16:24:41 -04005995 .secmark_relabel_packet = selinux_secmark_relabel_packet,
5996 .secmark_refcount_inc = selinux_secmark_refcount_inc,
5997 .secmark_refcount_dec = selinux_secmark_refcount_dec,
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005998 .req_classify_flow = selinux_req_classify_flow,
Paul Mooreed6d76e2009-08-28 18:12:49 -04005999 .tun_dev_create = selinux_tun_dev_create,
6000 .tun_dev_post_create = selinux_tun_dev_post_create,
6001 .tun_dev_attach = selinux_tun_dev_attach,
Trent Jaegerd28d1e02005-12-13 23:12:40 -08006002
6003#ifdef CONFIG_SECURITY_NETWORK_XFRM
6004 .xfrm_policy_alloc_security = selinux_xfrm_policy_alloc,
6005 .xfrm_policy_clone_security = selinux_xfrm_policy_clone,
6006 .xfrm_policy_free_security = selinux_xfrm_policy_free,
Catherine Zhangc8c05a82006-06-08 23:39:49 -07006007 .xfrm_policy_delete_security = selinux_xfrm_policy_delete,
Trent Jaegerd28d1e02005-12-13 23:12:40 -08006008 .xfrm_state_alloc_security = selinux_xfrm_state_alloc,
6009 .xfrm_state_free_security = selinux_xfrm_state_free,
Catherine Zhangc8c05a82006-06-08 23:39:49 -07006010 .xfrm_state_delete_security = selinux_xfrm_state_delete,
Eric Paris828dfe12008-04-17 13:17:49 -04006011 .xfrm_policy_lookup = selinux_xfrm_policy_lookup,
Venkat Yekkiralae0d1caa2006-07-24 23:29:07 -07006012 .xfrm_state_pol_flow_match = selinux_xfrm_state_pol_flow_match,
Venkat Yekkiralae0d1caa2006-07-24 23:29:07 -07006013 .xfrm_decode_session = selinux_xfrm_decode_session,
Linus Torvalds1da177e2005-04-16 15:20:36 -07006014#endif
Michael LeMayd7200242006-06-22 14:47:17 -07006015
6016#ifdef CONFIG_KEYS
Eric Paris828dfe12008-04-17 13:17:49 -04006017 .key_alloc = selinux_key_alloc,
6018 .key_free = selinux_key_free,
6019 .key_permission = selinux_key_permission,
David Howells70a5bb72008-04-29 01:01:26 -07006020 .key_getsecurity = selinux_key_getsecurity,
Michael LeMayd7200242006-06-22 14:47:17 -07006021#endif
Ahmed S. Darwish9d57a7f2008-03-01 22:03:14 +02006022
6023#ifdef CONFIG_AUDIT
6024 .audit_rule_init = selinux_audit_rule_init,
6025 .audit_rule_known = selinux_audit_rule_known,
6026 .audit_rule_match = selinux_audit_rule_match,
6027 .audit_rule_free = selinux_audit_rule_free,
6028#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07006029};
6030
6031static __init int selinux_init(void)
6032{
Ahmed S. Darwish076c54c2008-03-06 18:09:10 +02006033 if (!security_module_enable(&selinux_ops)) {
6034 selinux_enabled = 0;
6035 return 0;
6036 }
6037
Linus Torvalds1da177e2005-04-16 15:20:36 -07006038 if (!selinux_enabled) {
6039 printk(KERN_INFO "SELinux: Disabled at boot.\n");
6040 return 0;
6041 }
6042
6043 printk(KERN_INFO "SELinux: Initializing.\n");
6044
6045 /* Set the security state for the initial task. */
David Howellsd84f4f92008-11-14 10:39:23 +11006046 cred_init_security();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006047
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04006048 default_noexec = !(VM_DATA_DEFAULT_FLAGS & VM_EXEC);
6049
James Morris7cae7e22006-03-22 00:09:22 -08006050 sel_inode_cache = kmem_cache_create("selinux_inode_security",
6051 sizeof(struct inode_security_struct),
Paul Mundt20c2df82007-07-20 10:11:58 +09006052 0, SLAB_PANIC, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006053 avc_init();
6054
Eric Paris828dfe12008-04-17 13:17:49 -04006055 if (register_security(&selinux_ops))
Linus Torvalds1da177e2005-04-16 15:20:36 -07006056 panic("SELinux: Unable to register with kernel.\n");
6057
Eric Paris828dfe12008-04-17 13:17:49 -04006058 if (selinux_enforcing)
Eric Parisfadcdb42007-02-22 18:11:31 -05006059 printk(KERN_DEBUG "SELinux: Starting in enforcing mode\n");
Eric Paris828dfe12008-04-17 13:17:49 -04006060 else
Eric Parisfadcdb42007-02-22 18:11:31 -05006061 printk(KERN_DEBUG "SELinux: Starting in permissive mode\n");
Michael LeMayd7200242006-06-22 14:47:17 -07006062
Linus Torvalds1da177e2005-04-16 15:20:36 -07006063 return 0;
6064}
6065
Al Viroe8c26252010-03-23 06:36:54 -04006066static void delayed_superblock_init(struct super_block *sb, void *unused)
6067{
6068 superblock_doinit(sb, NULL);
6069}
6070
Linus Torvalds1da177e2005-04-16 15:20:36 -07006071void selinux_complete_init(void)
6072{
Eric Parisfadcdb42007-02-22 18:11:31 -05006073 printk(KERN_DEBUG "SELinux: Completing initialization.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07006074
6075 /* Set up any superblocks initialized prior to the policy load. */
Eric Parisfadcdb42007-02-22 18:11:31 -05006076 printk(KERN_DEBUG "SELinux: Setting up existing superblocks.\n");
Al Viroe8c26252010-03-23 06:36:54 -04006077 iterate_supers(delayed_superblock_init, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006078}
6079
6080/* SELinux requires early initialization in order to label
6081 all processes and objects when they are created. */
6082security_initcall(selinux_init);
6083
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08006084#if defined(CONFIG_NETFILTER)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006085
Paul Mooreeffad8d2008-01-29 08:49:27 -05006086static struct nf_hook_ops selinux_ipv4_ops[] = {
6087 {
6088 .hook = selinux_ipv4_postroute,
6089 .owner = THIS_MODULE,
6090 .pf = PF_INET,
6091 .hooknum = NF_INET_POST_ROUTING,
6092 .priority = NF_IP_PRI_SELINUX_LAST,
6093 },
6094 {
6095 .hook = selinux_ipv4_forward,
6096 .owner = THIS_MODULE,
6097 .pf = PF_INET,
6098 .hooknum = NF_INET_FORWARD,
6099 .priority = NF_IP_PRI_SELINUX_FIRST,
Paul Moore948bf852008-10-10 10:16:32 -04006100 },
6101 {
6102 .hook = selinux_ipv4_output,
6103 .owner = THIS_MODULE,
6104 .pf = PF_INET,
6105 .hooknum = NF_INET_LOCAL_OUT,
6106 .priority = NF_IP_PRI_SELINUX_FIRST,
Paul Mooreeffad8d2008-01-29 08:49:27 -05006107 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006108};
6109
6110#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
6111
Paul Mooreeffad8d2008-01-29 08:49:27 -05006112static struct nf_hook_ops selinux_ipv6_ops[] = {
6113 {
6114 .hook = selinux_ipv6_postroute,
6115 .owner = THIS_MODULE,
6116 .pf = PF_INET6,
6117 .hooknum = NF_INET_POST_ROUTING,
6118 .priority = NF_IP6_PRI_SELINUX_LAST,
6119 },
6120 {
6121 .hook = selinux_ipv6_forward,
6122 .owner = THIS_MODULE,
6123 .pf = PF_INET6,
6124 .hooknum = NF_INET_FORWARD,
6125 .priority = NF_IP6_PRI_SELINUX_FIRST,
6126 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006127};
6128
6129#endif /* IPV6 */
6130
6131static int __init selinux_nf_ip_init(void)
6132{
6133 int err = 0;
6134
6135 if (!selinux_enabled)
6136 goto out;
Eric Parisfadcdb42007-02-22 18:11:31 -05006137
6138 printk(KERN_DEBUG "SELinux: Registering netfilter hooks\n");
6139
Alexey Dobriyan6c5a9d22008-07-26 17:48:15 -07006140 err = nf_register_hooks(selinux_ipv4_ops, ARRAY_SIZE(selinux_ipv4_ops));
6141 if (err)
6142 panic("SELinux: nf_register_hooks for IPv4: error %d\n", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006143
6144#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Alexey Dobriyan6c5a9d22008-07-26 17:48:15 -07006145 err = nf_register_hooks(selinux_ipv6_ops, ARRAY_SIZE(selinux_ipv6_ops));
6146 if (err)
6147 panic("SELinux: nf_register_hooks for IPv6: error %d\n", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006148#endif /* IPV6 */
Trent Jaegerd28d1e02005-12-13 23:12:40 -08006149
Linus Torvalds1da177e2005-04-16 15:20:36 -07006150out:
6151 return err;
6152}
6153
6154__initcall(selinux_nf_ip_init);
6155
6156#ifdef CONFIG_SECURITY_SELINUX_DISABLE
6157static void selinux_nf_ip_exit(void)
6158{
Eric Parisfadcdb42007-02-22 18:11:31 -05006159 printk(KERN_DEBUG "SELinux: Unregistering netfilter hooks\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07006160
Alexey Dobriyan6c5a9d22008-07-26 17:48:15 -07006161 nf_unregister_hooks(selinux_ipv4_ops, ARRAY_SIZE(selinux_ipv4_ops));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006162#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Alexey Dobriyan6c5a9d22008-07-26 17:48:15 -07006163 nf_unregister_hooks(selinux_ipv6_ops, ARRAY_SIZE(selinux_ipv6_ops));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006164#endif /* IPV6 */
6165}
6166#endif
6167
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08006168#else /* CONFIG_NETFILTER */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006169
6170#ifdef CONFIG_SECURITY_SELINUX_DISABLE
6171#define selinux_nf_ip_exit()
6172#endif
6173
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08006174#endif /* CONFIG_NETFILTER */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006175
6176#ifdef CONFIG_SECURITY_SELINUX_DISABLE
Eric Paris828dfe12008-04-17 13:17:49 -04006177static int selinux_disabled;
6178
Linus Torvalds1da177e2005-04-16 15:20:36 -07006179int selinux_disable(void)
6180{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006181 if (ss_initialized) {
6182 /* Not permitted after initial policy load. */
6183 return -EINVAL;
6184 }
6185
6186 if (selinux_disabled) {
6187 /* Only do this once. */
6188 return -EINVAL;
6189 }
6190
6191 printk(KERN_INFO "SELinux: Disabled at runtime.\n");
6192
6193 selinux_disabled = 1;
Stephen Smalley30d55282006-05-03 10:52:36 -04006194 selinux_enabled = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006195
wzt.wzt@gmail.com189b3b12010-02-23 23:15:28 +08006196 reset_security_ops();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006197
Eric Parisaf8ff042009-09-20 21:23:01 -04006198 /* Try to destroy the avc node cache */
6199 avc_disable();
6200
Linus Torvalds1da177e2005-04-16 15:20:36 -07006201 /* Unregister netfilter hooks. */
6202 selinux_nf_ip_exit();
6203
6204 /* Unregister selinuxfs. */
6205 exit_sel_fs();
6206
6207 return 0;
6208}
6209#endif