blob: 3b32a031fd2bd65e5bd9ebf69a6dc1c5e5560b1b [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 Moore220deb92008-01-29 08:38:23 -050055#include <net/net_namespace.h>
Paul Moored621d352008-01-29 08:43:36 -050056#include <net/netlabel.h>
Eric Parisf5269712008-05-14 11:27:45 -040057#include <linux/uaccess.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070058#include <asm/ioctls.h>
Arun Sharma60063492011-07-26 16:09:06 -070059#include <linux/atomic.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070060#include <linux/bitops.h>
61#include <linux/interrupt.h>
62#include <linux/netdevice.h> /* for network interface checks */
63#include <linux/netlink.h>
64#include <linux/tcp.h>
65#include <linux/udp.h>
James Morris2ee92d42006-11-13 16:09:01 -080066#include <linux/dccp.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070067#include <linux/quota.h>
68#include <linux/un.h> /* for Unix socket types */
69#include <net/af_unix.h> /* for Unix socket types */
70#include <linux/parser.h>
71#include <linux/nfs_mount.h>
72#include <net/ipv6.h>
73#include <linux/hugetlb.h>
74#include <linux/personality.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070075#include <linux/audit.h>
Eric Paris6931dfc2005-06-30 02:58:51 -070076#include <linux/string.h>
Catherine Zhang877ce7c2006-06-29 12:27:47 -070077#include <linux/selinux.h>
Eric Paris23970742006-09-25 23:32:01 -070078#include <linux/mutex.h>
Frank Mayharf06febc2008-09-12 09:54:39 -070079#include <linux/posix-timers.h>
Kees Cook00234592010-02-03 15:36:43 -080080#include <linux/syslog.h>
Serge E. Hallyn34867402011-03-23 16:43:17 -070081#include <linux/user_namespace.h>
Paul Gortmaker44fc7ea2011-05-26 20:52:10 -040082#include <linux/export.h>
Al Viro40401532012-02-13 03:58:52 +000083#include <linux/msg.h>
84#include <linux/shm.h>
Amir Samuelov6a22e462014-05-26 11:44:06 +030085#include <linux/pft.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070086
87#include "avc.h"
88#include "objsec.h"
89#include "netif.h"
Paul Moore224dfbd2008-01-29 08:38:13 -050090#include "netnode.h"
Paul Moore3e112172008-04-10 10:48:14 -040091#include "netport.h"
Trent Jaegerd28d1e02005-12-13 23:12:40 -080092#include "xfrm.h"
Paul Moorec60475b2007-02-28 15:14:23 -050093#include "netlabel.h"
Ahmed S. Darwish9d57a7f2008-03-01 22:03:14 +020094#include "audit.h"
James Morris7b98a582011-08-30 12:52:32 +100095#include "avc_ss.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070096
David P. Quigley11689d42009-01-16 09:22:03 -050097#define NUM_SEL_MNT_OPTS 5
Eric Parisc9180a52007-11-30 13:00:35 -050098
James Morris20510f22007-10-16 23:31:32 -070099extern struct security_operations *security_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700100
Paul Moored621d352008-01-29 08:43:36 -0500101/* SECMARK reference count */
James Morris56a4ca92011-08-17 11:08:43 +1000102static atomic_t selinux_secmark_refcount = ATOMIC_INIT(0);
Paul Moored621d352008-01-29 08:43:36 -0500103
Linus Torvalds1da177e2005-04-16 15:20:36 -0700104#ifdef CONFIG_SECURITY_SELINUX_DEVELOP
Eric Paris828dfe12008-04-17 13:17:49 -0400105int selinux_enforcing;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700106
107static int __init enforcing_setup(char *str)
108{
Eric Parisf5269712008-05-14 11:27:45 -0400109 unsigned long enforcing;
110 if (!strict_strtoul(str, 0, &enforcing))
111 selinux_enforcing = enforcing ? 1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112 return 1;
113}
114__setup("enforcing=", enforcing_setup);
115#endif
116
117#ifdef CONFIG_SECURITY_SELINUX_BOOTPARAM
118int selinux_enabled = CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE;
119
120static int __init selinux_enabled_setup(char *str)
121{
Eric Parisf5269712008-05-14 11:27:45 -0400122 unsigned long enabled;
123 if (!strict_strtoul(str, 0, &enabled))
124 selinux_enabled = enabled ? 1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125 return 1;
126}
127__setup("selinux=", selinux_enabled_setup);
Stephen Smalley30d55282006-05-03 10:52:36 -0400128#else
129int selinux_enabled = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700130#endif
131
Christoph Lametere18b8902006-12-06 20:33:20 -0800132static struct kmem_cache *sel_inode_cache;
James Morris7cae7e22006-03-22 00:09:22 -0800133
Paul Moored621d352008-01-29 08:43:36 -0500134/**
135 * selinux_secmark_enabled - Check to see if SECMARK is currently enabled
136 *
137 * Description:
138 * This function checks the SECMARK reference counter to see if any SECMARK
139 * targets are currently configured, if the reference counter is greater than
140 * zero SECMARK is considered to be enabled. Returns true (1) if SECMARK is
141 * enabled, false (0) if SECMARK is disabled.
142 *
143 */
144static int selinux_secmark_enabled(void)
145{
146 return (atomic_read(&selinux_secmark_refcount) > 0);
147}
148
David Howellsd84f4f92008-11-14 10:39:23 +1100149/*
150 * initialise the security for the init task
151 */
152static void cred_init_security(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700153{
David Howells3b11a1d2008-11-14 10:39:26 +1100154 struct cred *cred = (struct cred *) current->real_cred;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155 struct task_security_struct *tsec;
156
James Morris89d155e2005-10-30 14:59:21 -0800157 tsec = kzalloc(sizeof(struct task_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700158 if (!tsec)
David Howellsd84f4f92008-11-14 10:39:23 +1100159 panic("SELinux: Failed to initialize initial task.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700160
David Howellsd84f4f92008-11-14 10:39:23 +1100161 tsec->osid = tsec->sid = SECINITSID_KERNEL;
David Howellsf1752ee2008-11-14 10:39:17 +1100162 cred->security = tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700163}
164
David Howells275bb412008-11-14 10:39:19 +1100165/*
David Howells88e67f32008-11-14 10:39:21 +1100166 * get the security ID of a set of credentials
167 */
168static inline u32 cred_sid(const struct cred *cred)
169{
170 const struct task_security_struct *tsec;
171
172 tsec = cred->security;
173 return tsec->sid;
174}
175
176/*
David Howells3b11a1d2008-11-14 10:39:26 +1100177 * get the objective security ID of a task
David Howells275bb412008-11-14 10:39:19 +1100178 */
179static inline u32 task_sid(const struct task_struct *task)
180{
David Howells275bb412008-11-14 10:39:19 +1100181 u32 sid;
182
183 rcu_read_lock();
David Howells88e67f32008-11-14 10:39:21 +1100184 sid = cred_sid(__task_cred(task));
David Howells275bb412008-11-14 10:39:19 +1100185 rcu_read_unlock();
186 return sid;
187}
188
189/*
David Howells3b11a1d2008-11-14 10:39:26 +1100190 * get the subjective security ID of the current task
David Howells275bb412008-11-14 10:39:19 +1100191 */
192static inline u32 current_sid(void)
193{
Paul Moore5fb49872010-04-22 14:46:19 -0400194 const struct task_security_struct *tsec = current_security();
David Howells275bb412008-11-14 10:39:19 +1100195
196 return tsec->sid;
197}
198
David Howells88e67f32008-11-14 10:39:21 +1100199/* Allocate and free functions for each kind of security blob. */
200
Linus Torvalds1da177e2005-04-16 15:20:36 -0700201static int inode_alloc_security(struct inode *inode)
202{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700203 struct inode_security_struct *isec;
David Howells275bb412008-11-14 10:39:19 +1100204 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700205
Josef Bacika02fe132008-04-04 09:35:05 +1100206 isec = kmem_cache_zalloc(sel_inode_cache, GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700207 if (!isec)
208 return -ENOMEM;
209
Eric Paris23970742006-09-25 23:32:01 -0700210 mutex_init(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700211 INIT_LIST_HEAD(&isec->list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700212 isec->inode = inode;
213 isec->sid = SECINITSID_UNLABELED;
214 isec->sclass = SECCLASS_FILE;
David Howells275bb412008-11-14 10:39:19 +1100215 isec->task_sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700216 inode->i_security = isec;
217
218 return 0;
219}
220
221static void inode_free_security(struct inode *inode)
222{
223 struct inode_security_struct *isec = inode->i_security;
224 struct superblock_security_struct *sbsec = inode->i_sb->s_security;
225
Linus Torvalds1da177e2005-04-16 15:20:36 -0700226 spin_lock(&sbsec->isec_lock);
227 if (!list_empty(&isec->list))
228 list_del_init(&isec->list);
229 spin_unlock(&sbsec->isec_lock);
230
231 inode->i_security = NULL;
James Morris7cae7e22006-03-22 00:09:22 -0800232 kmem_cache_free(sel_inode_cache, isec);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700233}
234
235static int file_alloc_security(struct file *file)
236{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700237 struct file_security_struct *fsec;
David Howells275bb412008-11-14 10:39:19 +1100238 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239
Stephen Smalley26d2a4b2006-02-01 03:05:55 -0800240 fsec = kzalloc(sizeof(struct file_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700241 if (!fsec)
242 return -ENOMEM;
243
David Howells275bb412008-11-14 10:39:19 +1100244 fsec->sid = sid;
245 fsec->fown_sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700246 file->f_security = fsec;
247
248 return 0;
249}
250
251static void file_free_security(struct file *file)
252{
253 struct file_security_struct *fsec = file->f_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254 file->f_security = NULL;
255 kfree(fsec);
256}
257
258static int superblock_alloc_security(struct super_block *sb)
259{
260 struct superblock_security_struct *sbsec;
261
James Morris89d155e2005-10-30 14:59:21 -0800262 sbsec = kzalloc(sizeof(struct superblock_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263 if (!sbsec)
264 return -ENOMEM;
265
Eric Parisbc7e9822006-09-25 23:32:02 -0700266 mutex_init(&sbsec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700267 INIT_LIST_HEAD(&sbsec->isec_head);
268 spin_lock_init(&sbsec->isec_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269 sbsec->sb = sb;
270 sbsec->sid = SECINITSID_UNLABELED;
271 sbsec->def_sid = SECINITSID_FILE;
Eric Parisc312feb2006-07-10 04:43:53 -0700272 sbsec->mntpoint_sid = SECINITSID_UNLABELED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273 sb->s_security = sbsec;
274
275 return 0;
276}
277
278static void superblock_free_security(struct super_block *sb)
279{
280 struct superblock_security_struct *sbsec = sb->s_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700281 sb->s_security = NULL;
282 kfree(sbsec);
283}
284
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285/* The file system's label must be initialized prior to use. */
286
Stephen Hemminger634a5392010-03-04 21:59:03 -0800287static const char *labeling_behaviors[6] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288 "uses xattr",
289 "uses transition SIDs",
290 "uses task SIDs",
291 "uses genfs_contexts",
292 "not configured for labeling",
293 "uses mountpoint labeling",
294};
295
296static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry);
297
298static inline int inode_doinit(struct inode *inode)
299{
300 return inode_doinit_with_dentry(inode, NULL);
301}
302
303enum {
Eric Paris31e87932007-09-19 17:19:12 -0400304 Opt_error = -1,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700305 Opt_context = 1,
306 Opt_fscontext = 2,
Eric Parisc9180a52007-11-30 13:00:35 -0500307 Opt_defcontext = 3,
308 Opt_rootcontext = 4,
David P. Quigley11689d42009-01-16 09:22:03 -0500309 Opt_labelsupport = 5,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700310};
311
Steven Whitehousea447c092008-10-13 10:46:57 +0100312static const match_table_t tokens = {
Eric Paris832cbd92008-04-01 13:24:09 -0400313 {Opt_context, CONTEXT_STR "%s"},
314 {Opt_fscontext, FSCONTEXT_STR "%s"},
315 {Opt_defcontext, DEFCONTEXT_STR "%s"},
316 {Opt_rootcontext, ROOTCONTEXT_STR "%s"},
David P. Quigley11689d42009-01-16 09:22:03 -0500317 {Opt_labelsupport, LABELSUPP_STR},
Eric Paris31e87932007-09-19 17:19:12 -0400318 {Opt_error, NULL},
Linus Torvalds1da177e2005-04-16 15:20:36 -0700319};
320
321#define SEL_MOUNT_FAIL_MSG "SELinux: duplicate or incompatible mount options\n"
322
Eric Parisc312feb2006-07-10 04:43:53 -0700323static int may_context_mount_sb_relabel(u32 sid,
324 struct superblock_security_struct *sbsec,
David Howells275bb412008-11-14 10:39:19 +1100325 const struct cred *cred)
Eric Parisc312feb2006-07-10 04:43:53 -0700326{
David Howells275bb412008-11-14 10:39:19 +1100327 const struct task_security_struct *tsec = cred->security;
Eric Parisc312feb2006-07-10 04:43:53 -0700328 int rc;
329
330 rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
331 FILESYSTEM__RELABELFROM, NULL);
332 if (rc)
333 return rc;
334
335 rc = avc_has_perm(tsec->sid, sid, SECCLASS_FILESYSTEM,
336 FILESYSTEM__RELABELTO, NULL);
337 return rc;
338}
339
Eric Paris08089252006-07-10 04:43:55 -0700340static int may_context_mount_inode_relabel(u32 sid,
341 struct superblock_security_struct *sbsec,
David Howells275bb412008-11-14 10:39:19 +1100342 const struct cred *cred)
Eric Paris08089252006-07-10 04:43:55 -0700343{
David Howells275bb412008-11-14 10:39:19 +1100344 const struct task_security_struct *tsec = cred->security;
Eric Paris08089252006-07-10 04:43:55 -0700345 int rc;
346 rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
347 FILESYSTEM__RELABELFROM, NULL);
348 if (rc)
349 return rc;
350
351 rc = avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM,
352 FILESYSTEM__ASSOCIATE, NULL);
353 return rc;
354}
355
Eric Parisc9180a52007-11-30 13:00:35 -0500356static int sb_finish_set_opts(struct super_block *sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357{
358 struct superblock_security_struct *sbsec = sb->s_security;
359 struct dentry *root = sb->s_root;
Eric Parisc9180a52007-11-30 13:00:35 -0500360 struct inode *root_inode = root->d_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700361 int rc = 0;
362
Linus Torvalds1da177e2005-04-16 15:20:36 -0700363 if (sbsec->behavior == SECURITY_FS_USE_XATTR) {
364 /* Make sure that the xattr handler exists and that no
365 error other than -ENODATA is returned by getxattr on
366 the root directory. -ENODATA is ok, as this may be
367 the first boot of the SELinux kernel before we have
368 assigned xattr values to the filesystem. */
Eric Parisc9180a52007-11-30 13:00:35 -0500369 if (!root_inode->i_op->getxattr) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700370 printk(KERN_WARNING "SELinux: (dev %s, type %s) has no "
371 "xattr support\n", sb->s_id, sb->s_type->name);
372 rc = -EOPNOTSUPP;
373 goto out;
374 }
Eric Parisc9180a52007-11-30 13:00:35 -0500375 rc = root_inode->i_op->getxattr(root, XATTR_NAME_SELINUX, NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700376 if (rc < 0 && rc != -ENODATA) {
377 if (rc == -EOPNOTSUPP)
378 printk(KERN_WARNING "SELinux: (dev %s, type "
379 "%s) has no security xattr handler\n",
380 sb->s_id, sb->s_type->name);
381 else
382 printk(KERN_WARNING "SELinux: (dev %s, type "
383 "%s) getxattr errno %d\n", sb->s_id,
384 sb->s_type->name, -rc);
385 goto out;
386 }
387 }
388
David P. Quigley11689d42009-01-16 09:22:03 -0500389 sbsec->flags |= (SE_SBINITIALIZED | SE_SBLABELSUPP);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390
Eric Parisc9180a52007-11-30 13:00:35 -0500391 if (sbsec->behavior > ARRAY_SIZE(labeling_behaviors))
Eric Parisfadcdb42007-02-22 18:11:31 -0500392 printk(KERN_ERR "SELinux: initialized (dev %s, type %s), unknown behavior\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393 sb->s_id, sb->s_type->name);
Eric Parisc9180a52007-11-30 13:00:35 -0500394 else
Eric Parisfadcdb42007-02-22 18:11:31 -0500395 printk(KERN_DEBUG "SELinux: initialized (dev %s, type %s), %s\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396 sb->s_id, sb->s_type->name,
397 labeling_behaviors[sbsec->behavior-1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700398
David P. Quigley11689d42009-01-16 09:22:03 -0500399 if (sbsec->behavior == SECURITY_FS_USE_GENFS ||
400 sbsec->behavior == SECURITY_FS_USE_MNTPOINT ||
401 sbsec->behavior == SECURITY_FS_USE_NONE ||
402 sbsec->behavior > ARRAY_SIZE(labeling_behaviors))
403 sbsec->flags &= ~SE_SBLABELSUPP;
404
Mark Salyzyn2c088052015-01-07 09:27:15 -0800405 /* Special handling. Is genfs but also has in-core setxattr handler*/
406 if (!strcmp(sb->s_type->name, "sysfs") ||
407 !strcmp(sb->s_type->name, "pstore") ||
408 !strcmp(sb->s_type->name, "debugfs") ||
409 !strcmp(sb->s_type->name, "rootfs"))
David P. Quigleyddd29ec2009-09-09 14:25:37 -0400410 sbsec->flags |= SE_SBLABELSUPP;
411
Linus Torvalds1da177e2005-04-16 15:20:36 -0700412 /* Initialize the root inode. */
Eric Parisc9180a52007-11-30 13:00:35 -0500413 rc = inode_doinit_with_dentry(root_inode, root);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414
415 /* Initialize any other inodes associated with the superblock, e.g.
416 inodes created prior to initial policy load or inodes created
417 during get_sb by a pseudo filesystem that directly
418 populates itself. */
419 spin_lock(&sbsec->isec_lock);
420next_inode:
421 if (!list_empty(&sbsec->isec_head)) {
422 struct inode_security_struct *isec =
423 list_entry(sbsec->isec_head.next,
Eric Parisc9180a52007-11-30 13:00:35 -0500424 struct inode_security_struct, list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425 struct inode *inode = isec->inode;
426 spin_unlock(&sbsec->isec_lock);
427 inode = igrab(inode);
428 if (inode) {
Eric Parisc9180a52007-11-30 13:00:35 -0500429 if (!IS_PRIVATE(inode))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430 inode_doinit(inode);
431 iput(inode);
432 }
433 spin_lock(&sbsec->isec_lock);
434 list_del_init(&isec->list);
435 goto next_inode;
436 }
437 spin_unlock(&sbsec->isec_lock);
438out:
Eric Parisc9180a52007-11-30 13:00:35 -0500439 return rc;
440}
441
442/*
443 * This function should allow an FS to ask what it's mount security
444 * options were so it can use those later for submounts, displaying
445 * mount options, or whatever.
446 */
447static int selinux_get_mnt_opts(const struct super_block *sb,
Eric Parise0007522008-03-05 10:31:54 -0500448 struct security_mnt_opts *opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500449{
450 int rc = 0, i;
451 struct superblock_security_struct *sbsec = sb->s_security;
452 char *context = NULL;
453 u32 len;
454 char tmp;
455
Eric Parise0007522008-03-05 10:31:54 -0500456 security_init_mnt_opts(opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500457
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500458 if (!(sbsec->flags & SE_SBINITIALIZED))
Eric Parisc9180a52007-11-30 13:00:35 -0500459 return -EINVAL;
460
461 if (!ss_initialized)
462 return -EINVAL;
463
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500464 tmp = sbsec->flags & SE_MNTMASK;
Eric Parisc9180a52007-11-30 13:00:35 -0500465 /* count the number of mount options for this sb */
466 for (i = 0; i < 8; i++) {
467 if (tmp & 0x01)
Eric Parise0007522008-03-05 10:31:54 -0500468 opts->num_mnt_opts++;
Eric Parisc9180a52007-11-30 13:00:35 -0500469 tmp >>= 1;
470 }
David P. Quigley11689d42009-01-16 09:22:03 -0500471 /* Check if the Label support flag is set */
472 if (sbsec->flags & SE_SBLABELSUPP)
473 opts->num_mnt_opts++;
Eric Parisc9180a52007-11-30 13:00:35 -0500474
Eric Parise0007522008-03-05 10:31:54 -0500475 opts->mnt_opts = kcalloc(opts->num_mnt_opts, sizeof(char *), GFP_ATOMIC);
476 if (!opts->mnt_opts) {
Eric Parisc9180a52007-11-30 13:00:35 -0500477 rc = -ENOMEM;
478 goto out_free;
479 }
480
Eric Parise0007522008-03-05 10:31:54 -0500481 opts->mnt_opts_flags = kcalloc(opts->num_mnt_opts, sizeof(int), GFP_ATOMIC);
482 if (!opts->mnt_opts_flags) {
Eric Parisc9180a52007-11-30 13:00:35 -0500483 rc = -ENOMEM;
484 goto out_free;
485 }
486
487 i = 0;
488 if (sbsec->flags & FSCONTEXT_MNT) {
489 rc = security_sid_to_context(sbsec->sid, &context, &len);
490 if (rc)
491 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500492 opts->mnt_opts[i] = context;
493 opts->mnt_opts_flags[i++] = FSCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500494 }
495 if (sbsec->flags & CONTEXT_MNT) {
496 rc = security_sid_to_context(sbsec->mntpoint_sid, &context, &len);
497 if (rc)
498 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500499 opts->mnt_opts[i] = context;
500 opts->mnt_opts_flags[i++] = CONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500501 }
502 if (sbsec->flags & DEFCONTEXT_MNT) {
503 rc = security_sid_to_context(sbsec->def_sid, &context, &len);
504 if (rc)
505 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500506 opts->mnt_opts[i] = context;
507 opts->mnt_opts_flags[i++] = DEFCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500508 }
509 if (sbsec->flags & ROOTCONTEXT_MNT) {
510 struct inode *root = sbsec->sb->s_root->d_inode;
511 struct inode_security_struct *isec = root->i_security;
512
513 rc = security_sid_to_context(isec->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++] = ROOTCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500518 }
David P. Quigley11689d42009-01-16 09:22:03 -0500519 if (sbsec->flags & SE_SBLABELSUPP) {
520 opts->mnt_opts[i] = NULL;
521 opts->mnt_opts_flags[i++] = SE_SBLABELSUPP;
522 }
Eric Parisc9180a52007-11-30 13:00:35 -0500523
Eric Parise0007522008-03-05 10:31:54 -0500524 BUG_ON(i != opts->num_mnt_opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500525
526 return 0;
527
528out_free:
Eric Parise0007522008-03-05 10:31:54 -0500529 security_free_mnt_opts(opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500530 return rc;
531}
532
533static int bad_option(struct superblock_security_struct *sbsec, char flag,
534 u32 old_sid, u32 new_sid)
535{
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500536 char mnt_flags = sbsec->flags & SE_MNTMASK;
537
Eric Parisc9180a52007-11-30 13:00:35 -0500538 /* check if the old mount command had the same options */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500539 if (sbsec->flags & SE_SBINITIALIZED)
Eric Parisc9180a52007-11-30 13:00:35 -0500540 if (!(sbsec->flags & flag) ||
541 (old_sid != new_sid))
542 return 1;
543
544 /* check if we were passed the same options twice,
545 * aka someone passed context=a,context=b
546 */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500547 if (!(sbsec->flags & SE_SBINITIALIZED))
548 if (mnt_flags & flag)
Eric Parisc9180a52007-11-30 13:00:35 -0500549 return 1;
550 return 0;
551}
Eric Parise0007522008-03-05 10:31:54 -0500552
Eric Parisc9180a52007-11-30 13:00:35 -0500553/*
554 * Allow filesystems with binary mount data to explicitly set mount point
555 * labeling information.
556 */
Eric Parise0007522008-03-05 10:31:54 -0500557static int selinux_set_mnt_opts(struct super_block *sb,
558 struct security_mnt_opts *opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500559{
David Howells275bb412008-11-14 10:39:19 +1100560 const struct cred *cred = current_cred();
Eric Parisc9180a52007-11-30 13:00:35 -0500561 int rc = 0, i;
Eric Parisc9180a52007-11-30 13:00:35 -0500562 struct superblock_security_struct *sbsec = sb->s_security;
563 const char *name = sb->s_type->name;
James Morris089be432008-07-15 18:32:49 +1000564 struct inode *inode = sbsec->sb->s_root->d_inode;
565 struct inode_security_struct *root_isec = inode->i_security;
Eric Parisc9180a52007-11-30 13:00:35 -0500566 u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0;
567 u32 defcontext_sid = 0;
Eric Parise0007522008-03-05 10:31:54 -0500568 char **mount_options = opts->mnt_opts;
569 int *flags = opts->mnt_opts_flags;
570 int num_opts = opts->num_mnt_opts;
Eric Parisc9180a52007-11-30 13:00:35 -0500571
572 mutex_lock(&sbsec->lock);
573
574 if (!ss_initialized) {
575 if (!num_opts) {
576 /* Defer initialization until selinux_complete_init,
577 after the initial policy is loaded and the security
578 server is ready to handle calls. */
Eric Parisc9180a52007-11-30 13:00:35 -0500579 goto out;
580 }
581 rc = -EINVAL;
Eric Paris744ba352008-04-17 11:52:44 -0400582 printk(KERN_WARNING "SELinux: Unable to set superblock options "
583 "before the security server is initialized\n");
Eric Parisc9180a52007-11-30 13:00:35 -0500584 goto out;
585 }
586
587 /*
Eric Parise0007522008-03-05 10:31:54 -0500588 * Binary mount data FS will come through this function twice. Once
589 * from an explicit call and once from the generic calls from the vfs.
590 * Since the generic VFS calls will not contain any security mount data
591 * we need to skip the double mount verification.
592 *
593 * This does open a hole in which we will not notice if the first
594 * mount using this sb set explict options and a second mount using
595 * this sb does not set any security options. (The first options
596 * will be used for both mounts)
597 */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500598 if ((sbsec->flags & SE_SBINITIALIZED) && (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)
Eric Parise0007522008-03-05 10:31:54 -0500599 && (num_opts == 0))
Eric Parisf5269712008-05-14 11:27:45 -0400600 goto out;
Eric Parise0007522008-03-05 10:31:54 -0500601
602 /*
Eric Parisc9180a52007-11-30 13:00:35 -0500603 * parse the mount options, check if they are valid sids.
604 * also check if someone is trying to mount the same sb more
605 * than once with different security options.
606 */
607 for (i = 0; i < num_opts; i++) {
608 u32 sid;
David P. Quigley11689d42009-01-16 09:22:03 -0500609
610 if (flags[i] == SE_SBLABELSUPP)
611 continue;
Eric Parisc9180a52007-11-30 13:00:35 -0500612 rc = security_context_to_sid(mount_options[i],
613 strlen(mount_options[i]), &sid);
614 if (rc) {
615 printk(KERN_WARNING "SELinux: security_context_to_sid"
616 "(%s) failed for (dev %s, type %s) errno=%d\n",
617 mount_options[i], sb->s_id, name, rc);
618 goto out;
619 }
620 switch (flags[i]) {
621 case FSCONTEXT_MNT:
622 fscontext_sid = sid;
623
624 if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid,
625 fscontext_sid))
626 goto out_double_mount;
627
628 sbsec->flags |= FSCONTEXT_MNT;
629 break;
630 case CONTEXT_MNT:
631 context_sid = sid;
632
633 if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid,
634 context_sid))
635 goto out_double_mount;
636
637 sbsec->flags |= CONTEXT_MNT;
638 break;
639 case ROOTCONTEXT_MNT:
640 rootcontext_sid = sid;
641
642 if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid,
643 rootcontext_sid))
644 goto out_double_mount;
645
646 sbsec->flags |= ROOTCONTEXT_MNT;
647
648 break;
649 case DEFCONTEXT_MNT:
650 defcontext_sid = sid;
651
652 if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid,
653 defcontext_sid))
654 goto out_double_mount;
655
656 sbsec->flags |= DEFCONTEXT_MNT;
657
658 break;
659 default:
660 rc = -EINVAL;
661 goto out;
662 }
663 }
664
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500665 if (sbsec->flags & SE_SBINITIALIZED) {
Eric Parisc9180a52007-11-30 13:00:35 -0500666 /* previously mounted with options, but not on this attempt? */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500667 if ((sbsec->flags & SE_MNTMASK) && !num_opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500668 goto out_double_mount;
669 rc = 0;
670 goto out;
671 }
672
James Morris089be432008-07-15 18:32:49 +1000673 if (strcmp(sb->s_type->name, "proc") == 0)
Stephen Smalleyf9aecb32015-05-19 13:59:12 -0400674 sbsec->flags |= SE_SBPROC | SE_SBGENFS;
675
Stephen Smalley043ab942015-05-20 12:33:16 -0400676 if (!strcmp(sb->s_type->name, "debugfs") ||
677 !strcmp(sb->s_type->name, "sysfs") ||
678 !strcmp(sb->s_type->name, "pstore"))
Stephen Smalleyf9aecb32015-05-19 13:59:12 -0400679 sbsec->flags |= SE_SBGENFS;
Eric Parisc9180a52007-11-30 13:00:35 -0500680
681 /* Determine the labeling behavior to use for this filesystem type. */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500682 rc = security_fs_use((sbsec->flags & SE_SBPROC) ? "proc" : sb->s_type->name, &sbsec->behavior, &sbsec->sid);
Eric Parisc9180a52007-11-30 13:00:35 -0500683 if (rc) {
684 printk(KERN_WARNING "%s: security_fs_use(%s) returned %d\n",
James Morris089be432008-07-15 18:32:49 +1000685 __func__, sb->s_type->name, rc);
Eric Parisc9180a52007-11-30 13:00:35 -0500686 goto out;
687 }
688
689 /* sets the context of the superblock for the fs being mounted. */
690 if (fscontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100691 rc = may_context_mount_sb_relabel(fscontext_sid, sbsec, cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500692 if (rc)
693 goto out;
694
695 sbsec->sid = fscontext_sid;
696 }
697
698 /*
699 * Switch to using mount point labeling behavior.
700 * sets the label used on all file below the mountpoint, and will set
701 * the superblock context if not already set.
702 */
703 if (context_sid) {
704 if (!fscontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100705 rc = may_context_mount_sb_relabel(context_sid, sbsec,
706 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500707 if (rc)
708 goto out;
709 sbsec->sid = context_sid;
710 } else {
David Howells275bb412008-11-14 10:39:19 +1100711 rc = may_context_mount_inode_relabel(context_sid, sbsec,
712 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500713 if (rc)
714 goto out;
715 }
716 if (!rootcontext_sid)
717 rootcontext_sid = context_sid;
718
719 sbsec->mntpoint_sid = context_sid;
720 sbsec->behavior = SECURITY_FS_USE_MNTPOINT;
721 }
722
723 if (rootcontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100724 rc = may_context_mount_inode_relabel(rootcontext_sid, sbsec,
725 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500726 if (rc)
727 goto out;
728
729 root_isec->sid = rootcontext_sid;
730 root_isec->initialized = 1;
731 }
732
733 if (defcontext_sid) {
734 if (sbsec->behavior != SECURITY_FS_USE_XATTR) {
735 rc = -EINVAL;
736 printk(KERN_WARNING "SELinux: defcontext option is "
737 "invalid for this filesystem type\n");
738 goto out;
739 }
740
741 if (defcontext_sid != sbsec->def_sid) {
742 rc = may_context_mount_inode_relabel(defcontext_sid,
David Howells275bb412008-11-14 10:39:19 +1100743 sbsec, cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500744 if (rc)
745 goto out;
746 }
747
748 sbsec->def_sid = defcontext_sid;
749 }
750
751 rc = sb_finish_set_opts(sb);
752out:
Eric Parisbc7e9822006-09-25 23:32:02 -0700753 mutex_unlock(&sbsec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700754 return rc;
Eric Parisc9180a52007-11-30 13:00:35 -0500755out_double_mount:
756 rc = -EINVAL;
757 printk(KERN_WARNING "SELinux: mount invalid. Same superblock, different "
758 "security settings for (dev %s, type %s)\n", sb->s_id, name);
759 goto out;
760}
761
762static void selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
763 struct super_block *newsb)
764{
765 const struct superblock_security_struct *oldsbsec = oldsb->s_security;
766 struct superblock_security_struct *newsbsec = newsb->s_security;
767
768 int set_fscontext = (oldsbsec->flags & FSCONTEXT_MNT);
769 int set_context = (oldsbsec->flags & CONTEXT_MNT);
770 int set_rootcontext = (oldsbsec->flags & ROOTCONTEXT_MNT);
771
Eric Paris0f5e6422008-04-21 16:24:11 -0400772 /*
773 * if the parent was able to be mounted it clearly had no special lsm
Al Viroe8c26252010-03-23 06:36:54 -0400774 * mount options. thus we can safely deal with this superblock later
Eric Paris0f5e6422008-04-21 16:24:11 -0400775 */
Al Viroe8c26252010-03-23 06:36:54 -0400776 if (!ss_initialized)
Eric Paris0f5e6422008-04-21 16:24:11 -0400777 return;
Eric Parisc9180a52007-11-30 13:00:35 -0500778
Eric Parisc9180a52007-11-30 13:00:35 -0500779 /* how can we clone if the old one wasn't set up?? */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500780 BUG_ON(!(oldsbsec->flags & SE_SBINITIALIZED));
Eric Parisc9180a52007-11-30 13:00:35 -0500781
Eric Paris5a552612008-04-09 14:08:35 -0400782 /* if fs is reusing a sb, just let its options stand... */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500783 if (newsbsec->flags & SE_SBINITIALIZED)
Eric Paris5a552612008-04-09 14:08:35 -0400784 return;
785
Eric Parisc9180a52007-11-30 13:00:35 -0500786 mutex_lock(&newsbsec->lock);
787
788 newsbsec->flags = oldsbsec->flags;
789
790 newsbsec->sid = oldsbsec->sid;
791 newsbsec->def_sid = oldsbsec->def_sid;
792 newsbsec->behavior = oldsbsec->behavior;
793
794 if (set_context) {
795 u32 sid = oldsbsec->mntpoint_sid;
796
797 if (!set_fscontext)
798 newsbsec->sid = sid;
799 if (!set_rootcontext) {
800 struct inode *newinode = newsb->s_root->d_inode;
801 struct inode_security_struct *newisec = newinode->i_security;
802 newisec->sid = sid;
803 }
804 newsbsec->mntpoint_sid = sid;
805 }
806 if (set_rootcontext) {
807 const struct inode *oldinode = oldsb->s_root->d_inode;
808 const struct inode_security_struct *oldisec = oldinode->i_security;
809 struct inode *newinode = newsb->s_root->d_inode;
810 struct inode_security_struct *newisec = newinode->i_security;
811
812 newisec->sid = oldisec->sid;
813 }
814
815 sb_finish_set_opts(newsb);
816 mutex_unlock(&newsbsec->lock);
817}
818
Adrian Bunk2e1479d2008-03-17 22:29:23 +0200819static int selinux_parse_opts_str(char *options,
820 struct security_mnt_opts *opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500821{
Eric Parise0007522008-03-05 10:31:54 -0500822 char *p;
Eric Parisc9180a52007-11-30 13:00:35 -0500823 char *context = NULL, *defcontext = NULL;
824 char *fscontext = NULL, *rootcontext = NULL;
Eric Parise0007522008-03-05 10:31:54 -0500825 int rc, num_mnt_opts = 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500826
Eric Parise0007522008-03-05 10:31:54 -0500827 opts->num_mnt_opts = 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500828
829 /* Standard string-based options. */
830 while ((p = strsep(&options, "|")) != NULL) {
831 int token;
832 substring_t args[MAX_OPT_ARGS];
833
834 if (!*p)
835 continue;
836
837 token = match_token(p, tokens, args);
838
839 switch (token) {
840 case Opt_context:
841 if (context || defcontext) {
842 rc = -EINVAL;
843 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
844 goto out_err;
845 }
846 context = match_strdup(&args[0]);
847 if (!context) {
848 rc = -ENOMEM;
849 goto out_err;
850 }
851 break;
852
853 case Opt_fscontext:
854 if (fscontext) {
855 rc = -EINVAL;
856 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
857 goto out_err;
858 }
859 fscontext = match_strdup(&args[0]);
860 if (!fscontext) {
861 rc = -ENOMEM;
862 goto out_err;
863 }
864 break;
865
866 case Opt_rootcontext:
867 if (rootcontext) {
868 rc = -EINVAL;
869 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
870 goto out_err;
871 }
872 rootcontext = match_strdup(&args[0]);
873 if (!rootcontext) {
874 rc = -ENOMEM;
875 goto out_err;
876 }
877 break;
878
879 case Opt_defcontext:
880 if (context || defcontext) {
881 rc = -EINVAL;
882 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
883 goto out_err;
884 }
885 defcontext = match_strdup(&args[0]);
886 if (!defcontext) {
887 rc = -ENOMEM;
888 goto out_err;
889 }
890 break;
David P. Quigley11689d42009-01-16 09:22:03 -0500891 case Opt_labelsupport:
892 break;
Eric Parisc9180a52007-11-30 13:00:35 -0500893 default:
894 rc = -EINVAL;
895 printk(KERN_WARNING "SELinux: unknown mount option\n");
896 goto out_err;
897
898 }
899 }
900
Eric Parise0007522008-03-05 10:31:54 -0500901 rc = -ENOMEM;
902 opts->mnt_opts = kcalloc(NUM_SEL_MNT_OPTS, sizeof(char *), GFP_ATOMIC);
903 if (!opts->mnt_opts)
904 goto out_err;
905
906 opts->mnt_opts_flags = kcalloc(NUM_SEL_MNT_OPTS, sizeof(int), GFP_ATOMIC);
907 if (!opts->mnt_opts_flags) {
908 kfree(opts->mnt_opts);
909 goto out_err;
Eric Parisc9180a52007-11-30 13:00:35 -0500910 }
911
Eric Parise0007522008-03-05 10:31:54 -0500912 if (fscontext) {
913 opts->mnt_opts[num_mnt_opts] = fscontext;
914 opts->mnt_opts_flags[num_mnt_opts++] = FSCONTEXT_MNT;
915 }
916 if (context) {
917 opts->mnt_opts[num_mnt_opts] = context;
918 opts->mnt_opts_flags[num_mnt_opts++] = CONTEXT_MNT;
919 }
920 if (rootcontext) {
921 opts->mnt_opts[num_mnt_opts] = rootcontext;
922 opts->mnt_opts_flags[num_mnt_opts++] = ROOTCONTEXT_MNT;
923 }
924 if (defcontext) {
925 opts->mnt_opts[num_mnt_opts] = defcontext;
926 opts->mnt_opts_flags[num_mnt_opts++] = DEFCONTEXT_MNT;
927 }
928
929 opts->num_mnt_opts = num_mnt_opts;
930 return 0;
931
Eric Parisc9180a52007-11-30 13:00:35 -0500932out_err:
933 kfree(context);
934 kfree(defcontext);
935 kfree(fscontext);
936 kfree(rootcontext);
937 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700938}
Eric Parise0007522008-03-05 10:31:54 -0500939/*
940 * string mount options parsing and call set the sbsec
941 */
942static int superblock_doinit(struct super_block *sb, void *data)
943{
944 int rc = 0;
945 char *options = data;
946 struct security_mnt_opts opts;
947
948 security_init_mnt_opts(&opts);
949
950 if (!data)
951 goto out;
952
953 BUG_ON(sb->s_type->fs_flags & FS_BINARY_MOUNTDATA);
954
955 rc = selinux_parse_opts_str(options, &opts);
956 if (rc)
957 goto out_err;
958
959out:
960 rc = selinux_set_mnt_opts(sb, &opts);
961
962out_err:
963 security_free_mnt_opts(&opts);
964 return rc;
965}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700966
Adrian Bunk3583a712008-07-22 20:21:23 +0300967static void selinux_write_opts(struct seq_file *m,
968 struct security_mnt_opts *opts)
Eric Paris2069f452008-07-04 09:47:13 +1000969{
970 int i;
971 char *prefix;
972
973 for (i = 0; i < opts->num_mnt_opts; i++) {
David P. Quigley11689d42009-01-16 09:22:03 -0500974 char *has_comma;
975
976 if (opts->mnt_opts[i])
977 has_comma = strchr(opts->mnt_opts[i], ',');
978 else
979 has_comma = NULL;
Eric Paris2069f452008-07-04 09:47:13 +1000980
981 switch (opts->mnt_opts_flags[i]) {
982 case CONTEXT_MNT:
983 prefix = CONTEXT_STR;
984 break;
985 case FSCONTEXT_MNT:
986 prefix = FSCONTEXT_STR;
987 break;
988 case ROOTCONTEXT_MNT:
989 prefix = ROOTCONTEXT_STR;
990 break;
991 case DEFCONTEXT_MNT:
992 prefix = DEFCONTEXT_STR;
993 break;
David P. Quigley11689d42009-01-16 09:22:03 -0500994 case SE_SBLABELSUPP:
995 seq_putc(m, ',');
996 seq_puts(m, LABELSUPP_STR);
997 continue;
Eric Paris2069f452008-07-04 09:47:13 +1000998 default:
999 BUG();
Eric Parisa35c6c82011-04-20 10:21:28 -04001000 return;
Eric Paris2069f452008-07-04 09:47:13 +10001001 };
1002 /* we need a comma before each option */
1003 seq_putc(m, ',');
1004 seq_puts(m, prefix);
1005 if (has_comma)
1006 seq_putc(m, '\"');
1007 seq_puts(m, opts->mnt_opts[i]);
1008 if (has_comma)
1009 seq_putc(m, '\"');
1010 }
1011}
1012
1013static int selinux_sb_show_options(struct seq_file *m, struct super_block *sb)
1014{
1015 struct security_mnt_opts opts;
1016 int rc;
1017
1018 rc = selinux_get_mnt_opts(sb, &opts);
Eric Paris383795c2008-07-29 17:07:26 -04001019 if (rc) {
1020 /* before policy load we may get EINVAL, don't show anything */
1021 if (rc == -EINVAL)
1022 rc = 0;
Eric Paris2069f452008-07-04 09:47:13 +10001023 return rc;
Eric Paris383795c2008-07-29 17:07:26 -04001024 }
Eric Paris2069f452008-07-04 09:47:13 +10001025
1026 selinux_write_opts(m, &opts);
1027
1028 security_free_mnt_opts(&opts);
1029
1030 return rc;
1031}
1032
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033static inline u16 inode_mode_to_security_class(umode_t mode)
1034{
1035 switch (mode & S_IFMT) {
1036 case S_IFSOCK:
1037 return SECCLASS_SOCK_FILE;
1038 case S_IFLNK:
1039 return SECCLASS_LNK_FILE;
1040 case S_IFREG:
1041 return SECCLASS_FILE;
1042 case S_IFBLK:
1043 return SECCLASS_BLK_FILE;
1044 case S_IFDIR:
1045 return SECCLASS_DIR;
1046 case S_IFCHR:
1047 return SECCLASS_CHR_FILE;
1048 case S_IFIFO:
1049 return SECCLASS_FIFO_FILE;
1050
1051 }
1052
1053 return SECCLASS_FILE;
1054}
1055
James Morris13402582005-09-30 14:24:34 -04001056static inline int default_protocol_stream(int protocol)
1057{
1058 return (protocol == IPPROTO_IP || protocol == IPPROTO_TCP);
1059}
1060
1061static inline int default_protocol_dgram(int protocol)
1062{
1063 return (protocol == IPPROTO_IP || protocol == IPPROTO_UDP);
1064}
1065
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066static inline u16 socket_type_to_security_class(int family, int type, int protocol)
1067{
1068 switch (family) {
1069 case PF_UNIX:
1070 switch (type) {
1071 case SOCK_STREAM:
1072 case SOCK_SEQPACKET:
1073 return SECCLASS_UNIX_STREAM_SOCKET;
1074 case SOCK_DGRAM:
1075 return SECCLASS_UNIX_DGRAM_SOCKET;
1076 }
1077 break;
1078 case PF_INET:
1079 case PF_INET6:
1080 switch (type) {
1081 case SOCK_STREAM:
James Morris13402582005-09-30 14:24:34 -04001082 if (default_protocol_stream(protocol))
1083 return SECCLASS_TCP_SOCKET;
1084 else
1085 return SECCLASS_RAWIP_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001086 case SOCK_DGRAM:
James Morris13402582005-09-30 14:24:34 -04001087 if (default_protocol_dgram(protocol))
1088 return SECCLASS_UDP_SOCKET;
1089 else
1090 return SECCLASS_RAWIP_SOCKET;
James Morris2ee92d42006-11-13 16:09:01 -08001091 case SOCK_DCCP:
1092 return SECCLASS_DCCP_SOCKET;
James Morris13402582005-09-30 14:24:34 -04001093 default:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094 return SECCLASS_RAWIP_SOCKET;
1095 }
1096 break;
1097 case PF_NETLINK:
1098 switch (protocol) {
1099 case NETLINK_ROUTE:
1100 return SECCLASS_NETLINK_ROUTE_SOCKET;
1101 case NETLINK_FIREWALL:
1102 return SECCLASS_NETLINK_FIREWALL_SOCKET;
Pavel Emelyanov7f1fb602011-12-06 07:56:43 +00001103 case NETLINK_SOCK_DIAG:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001104 return SECCLASS_NETLINK_TCPDIAG_SOCKET;
1105 case NETLINK_NFLOG:
1106 return SECCLASS_NETLINK_NFLOG_SOCKET;
1107 case NETLINK_XFRM:
1108 return SECCLASS_NETLINK_XFRM_SOCKET;
1109 case NETLINK_SELINUX:
1110 return SECCLASS_NETLINK_SELINUX_SOCKET;
1111 case NETLINK_AUDIT:
1112 return SECCLASS_NETLINK_AUDIT_SOCKET;
1113 case NETLINK_IP6_FW:
1114 return SECCLASS_NETLINK_IP6FW_SOCKET;
1115 case NETLINK_DNRTMSG:
1116 return SECCLASS_NETLINK_DNRT_SOCKET;
James Morris0c9b7942005-04-16 15:24:13 -07001117 case NETLINK_KOBJECT_UEVENT:
1118 return SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001119 default:
1120 return SECCLASS_NETLINK_SOCKET;
1121 }
1122 case PF_PACKET:
1123 return SECCLASS_PACKET_SOCKET;
1124 case PF_KEY:
1125 return SECCLASS_KEY_SOCKET;
Christopher J. PeBenito3e3ff152006-06-09 00:25:03 -07001126 case PF_APPLETALK:
1127 return SECCLASS_APPLETALK_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001128 }
1129
1130 return SECCLASS_SOCKET;
1131}
1132
Stephen Smalleyf9aecb32015-05-19 13:59:12 -04001133static int selinux_genfs_get_sid(struct dentry *dentry,
1134 u16 tclass,
1135 u16 flags,
1136 u32 *sid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001137{
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001138 int rc;
Stephen Smalleyf9aecb32015-05-19 13:59:12 -04001139 struct super_block *sb = dentry->d_inode->i_sb;
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001140 char *buffer, *path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001141
Eric Paris828dfe12008-04-17 13:17:49 -04001142 buffer = (char *)__get_free_page(GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001143 if (!buffer)
1144 return -ENOMEM;
1145
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001146 path = dentry_path_raw(dentry, buffer, PAGE_SIZE);
1147 if (IS_ERR(path))
1148 rc = PTR_ERR(path);
1149 else {
Stephen Smalleyf9aecb32015-05-19 13:59:12 -04001150 if (flags & SE_SBPROC) {
1151 /* each process gets a /proc/PID/ entry. Strip off the
1152 * PID part to get a valid selinux labeling.
1153 * e.g. /proc/1/net/rpc/nfs -> /net/rpc/nfs */
1154 while (path[1] >= '0' && path[1] <= '9') {
1155 path[1] = '/';
1156 path++;
1157 }
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001158 }
Stephen Smalleyf9aecb32015-05-19 13:59:12 -04001159 rc = security_genfs_sid(sb->s_type->name, path, tclass, sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001160 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001161 free_page((unsigned long)buffer);
1162 return rc;
1163}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001164
1165/* The inode's security attributes must be initialized before first use. */
1166static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry)
1167{
1168 struct superblock_security_struct *sbsec = NULL;
1169 struct inode_security_struct *isec = inode->i_security;
1170 u32 sid;
1171 struct dentry *dentry;
1172#define INITCONTEXTLEN 255
1173 char *context = NULL;
1174 unsigned len = 0;
1175 int rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001176
1177 if (isec->initialized)
1178 goto out;
1179
Eric Paris23970742006-09-25 23:32:01 -07001180 mutex_lock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001181 if (isec->initialized)
Eric Paris23970742006-09-25 23:32:01 -07001182 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001183
1184 sbsec = inode->i_sb->s_security;
David P. Quigley0d90a7e2009-01-16 09:22:02 -05001185 if (!(sbsec->flags & SE_SBINITIALIZED)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001186 /* Defer initialization until selinux_complete_init,
1187 after the initial policy is loaded and the security
1188 server is ready to handle calls. */
1189 spin_lock(&sbsec->isec_lock);
1190 if (list_empty(&isec->list))
1191 list_add(&isec->list, &sbsec->isec_head);
1192 spin_unlock(&sbsec->isec_lock);
Eric Paris23970742006-09-25 23:32:01 -07001193 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001194 }
1195
1196 switch (sbsec->behavior) {
1197 case SECURITY_FS_USE_XATTR:
1198 if (!inode->i_op->getxattr) {
1199 isec->sid = sbsec->def_sid;
1200 break;
1201 }
1202
1203 /* Need a dentry, since the xattr API requires one.
1204 Life would be simpler if we could just pass the inode. */
1205 if (opt_dentry) {
1206 /* Called from d_instantiate or d_splice_alias. */
1207 dentry = dget(opt_dentry);
1208 } else {
1209 /* Called from selinux_complete_init, try to find a dentry. */
1210 dentry = d_find_alias(inode);
1211 }
1212 if (!dentry) {
Eric Parisdf7f54c2009-03-09 14:35:58 -04001213 /*
1214 * this is can be hit on boot when a file is accessed
1215 * before the policy is loaded. When we load policy we
1216 * may find inodes that have no dentry on the
1217 * sbsec->isec_head list. No reason to complain as these
1218 * will get fixed up the next time we go through
1219 * inode_doinit with a dentry, before these inodes could
1220 * be used again by userspace.
1221 */
Eric Paris23970742006-09-25 23:32:01 -07001222 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001223 }
1224
1225 len = INITCONTEXTLEN;
Eric Paris4cb912f2009-02-12 14:50:05 -05001226 context = kmalloc(len+1, GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001227 if (!context) {
1228 rc = -ENOMEM;
1229 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001230 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001231 }
Eric Paris4cb912f2009-02-12 14:50:05 -05001232 context[len] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001233 rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX,
1234 context, len);
1235 if (rc == -ERANGE) {
James Morris314dabb2009-08-10 22:00:13 +10001236 kfree(context);
1237
Linus Torvalds1da177e2005-04-16 15:20:36 -07001238 /* Need a larger buffer. Query for the right size. */
1239 rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX,
1240 NULL, 0);
1241 if (rc < 0) {
1242 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001243 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001244 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001245 len = rc;
Eric Paris4cb912f2009-02-12 14:50:05 -05001246 context = kmalloc(len+1, GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001247 if (!context) {
1248 rc = -ENOMEM;
1249 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001250 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001251 }
Eric Paris4cb912f2009-02-12 14:50:05 -05001252 context[len] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001253 rc = inode->i_op->getxattr(dentry,
1254 XATTR_NAME_SELINUX,
1255 context, len);
1256 }
1257 dput(dentry);
1258 if (rc < 0) {
1259 if (rc != -ENODATA) {
Eric Paris744ba352008-04-17 11:52:44 -04001260 printk(KERN_WARNING "SELinux: %s: getxattr returned "
Harvey Harrisondd6f9532008-03-06 10:03:59 +11001261 "%d for dev=%s ino=%ld\n", __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001262 -rc, inode->i_sb->s_id, inode->i_ino);
1263 kfree(context);
Eric Paris23970742006-09-25 23:32:01 -07001264 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001265 }
1266 /* Map ENODATA to the default file SID */
1267 sid = sbsec->def_sid;
1268 rc = 0;
1269 } else {
James Morrisf5c1d5b2005-07-28 01:07:37 -07001270 rc = security_context_to_sid_default(context, rc, &sid,
Stephen Smalley869ab512008-04-04 08:46:05 -04001271 sbsec->def_sid,
1272 GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001273 if (rc) {
Eric Paris4ba0a8a2009-02-12 15:01:10 -05001274 char *dev = inode->i_sb->s_id;
1275 unsigned long ino = inode->i_ino;
1276
1277 if (rc == -EINVAL) {
1278 if (printk_ratelimit())
1279 printk(KERN_NOTICE "SELinux: inode=%lu on dev=%s was found to have an invalid "
1280 "context=%s. This indicates you may need to relabel the inode or the "
1281 "filesystem in question.\n", ino, dev, context);
1282 } else {
1283 printk(KERN_WARNING "SELinux: %s: context_to_sid(%s) "
1284 "returned %d for dev=%s ino=%ld\n",
1285 __func__, context, -rc, dev, ino);
1286 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001287 kfree(context);
1288 /* Leave with the unlabeled SID */
1289 rc = 0;
1290 break;
1291 }
1292 }
1293 kfree(context);
1294 isec->sid = sid;
1295 break;
1296 case SECURITY_FS_USE_TASK:
1297 isec->sid = isec->task_sid;
1298 break;
1299 case SECURITY_FS_USE_TRANS:
1300 /* Default to the fs SID. */
1301 isec->sid = sbsec->sid;
1302
1303 /* Try to obtain a transition SID. */
1304 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Eric Paris652bb9b2011-02-01 11:05:40 -05001305 rc = security_transition_sid(isec->task_sid, sbsec->sid,
1306 isec->sclass, NULL, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001307 if (rc)
Eric Paris23970742006-09-25 23:32:01 -07001308 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001309 isec->sid = sid;
1310 break;
Eric Parisc312feb2006-07-10 04:43:53 -07001311 case SECURITY_FS_USE_MNTPOINT:
1312 isec->sid = sbsec->mntpoint_sid;
1313 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001314 default:
Eric Parisc312feb2006-07-10 04:43:53 -07001315 /* Default to the fs superblock SID. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001316 isec->sid = sbsec->sid;
1317
Stephen Smalleyf9aecb32015-05-19 13:59:12 -04001318 if ((sbsec->flags & SE_SBGENFS) && !S_ISLNK(inode->i_mode)) {
Paul Moore810be002014-03-19 16:46:18 -04001319 /* We must have a dentry to determine the label on
1320 * procfs inodes */
1321 if (opt_dentry)
1322 /* Called from d_instantiate or
1323 * d_splice_alias. */
1324 dentry = dget(opt_dentry);
1325 else
1326 /* Called from selinux_complete_init, try to
1327 * find a dentry. */
1328 dentry = d_find_alias(inode);
1329 /*
1330 * This can be hit on boot when a file is accessed
1331 * before the policy is loaded. When we load policy we
1332 * may find inodes that have no dentry on the
1333 * sbsec->isec_head list. No reason to complain as
1334 * these will get fixed up the next time we go through
1335 * inode_doinit() with a dentry, before these inodes
1336 * could be used again by userspace.
1337 */
1338 if (!dentry)
1339 goto out_unlock;
1340 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Stephen Smalleyf9aecb32015-05-19 13:59:12 -04001341 rc = selinux_genfs_get_sid(dentry, isec->sclass,
1342 sbsec->flags, &sid);
Paul Moore810be002014-03-19 16:46:18 -04001343 dput(dentry);
1344 if (rc)
1345 goto out_unlock;
1346 isec->sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001347 }
1348 break;
1349 }
1350
1351 isec->initialized = 1;
1352
Eric Paris23970742006-09-25 23:32:01 -07001353out_unlock:
1354 mutex_unlock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001355out:
1356 if (isec->sclass == SECCLASS_FILE)
1357 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001358 return rc;
1359}
1360
1361/* Convert a Linux signal to an access vector. */
1362static inline u32 signal_to_av(int sig)
1363{
1364 u32 perm = 0;
1365
1366 switch (sig) {
1367 case SIGCHLD:
1368 /* Commonly granted from child to parent. */
1369 perm = PROCESS__SIGCHLD;
1370 break;
1371 case SIGKILL:
1372 /* Cannot be caught or ignored */
1373 perm = PROCESS__SIGKILL;
1374 break;
1375 case SIGSTOP:
1376 /* Cannot be caught or ignored */
1377 perm = PROCESS__SIGSTOP;
1378 break;
1379 default:
1380 /* All other signals. */
1381 perm = PROCESS__SIGNAL;
1382 break;
1383 }
1384
1385 return perm;
1386}
1387
David Howells275bb412008-11-14 10:39:19 +11001388/*
David Howellsd84f4f92008-11-14 10:39:23 +11001389 * Check permission between a pair of credentials
1390 * fork check, ptrace check, etc.
1391 */
1392static int cred_has_perm(const struct cred *actor,
1393 const struct cred *target,
1394 u32 perms)
1395{
1396 u32 asid = cred_sid(actor), tsid = cred_sid(target);
1397
1398 return avc_has_perm(asid, tsid, SECCLASS_PROCESS, perms, NULL);
1399}
1400
1401/*
David Howells88e67f32008-11-14 10:39:21 +11001402 * Check permission between a pair of tasks, e.g. signal checks,
David Howells275bb412008-11-14 10:39:19 +11001403 * fork check, ptrace check, etc.
1404 * tsk1 is the actor and tsk2 is the target
David Howells3b11a1d2008-11-14 10:39:26 +11001405 * - this uses the default subjective creds of tsk1
David Howells275bb412008-11-14 10:39:19 +11001406 */
1407static int task_has_perm(const struct task_struct *tsk1,
1408 const struct task_struct *tsk2,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001409 u32 perms)
1410{
David Howells275bb412008-11-14 10:39:19 +11001411 const struct task_security_struct *__tsec1, *__tsec2;
1412 u32 sid1, sid2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001413
David Howells275bb412008-11-14 10:39:19 +11001414 rcu_read_lock();
1415 __tsec1 = __task_cred(tsk1)->security; sid1 = __tsec1->sid;
1416 __tsec2 = __task_cred(tsk2)->security; sid2 = __tsec2->sid;
1417 rcu_read_unlock();
1418 return avc_has_perm(sid1, sid2, SECCLASS_PROCESS, perms, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001419}
1420
David Howells3b11a1d2008-11-14 10:39:26 +11001421/*
1422 * Check permission between current and another task, e.g. signal checks,
1423 * fork check, ptrace check, etc.
1424 * current is the actor and tsk2 is the target
1425 * - this uses current's subjective creds
1426 */
1427static int current_has_perm(const struct task_struct *tsk,
1428 u32 perms)
1429{
1430 u32 sid, tsid;
1431
1432 sid = current_sid();
1433 tsid = task_sid(tsk);
1434 return avc_has_perm(sid, tsid, SECCLASS_PROCESS, perms, NULL);
1435}
1436
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001437#if CAP_LAST_CAP > 63
1438#error Fix SELinux to handle capabilities > 63.
1439#endif
1440
Linus Torvalds1da177e2005-04-16 15:20:36 -07001441/* Check whether a task is allowed to use a capability. */
Eric Paris6a9de492012-01-03 12:25:14 -05001442static int cred_has_capability(const struct cred *cred,
Eric Paris06112162008-11-11 22:02:50 +11001443 int cap, int audit)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001444{
Thomas Liu2bf49692009-07-14 12:14:09 -04001445 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07001446 struct selinux_audit_data sad = {0,};
Eric Paris06112162008-11-11 22:02:50 +11001447 struct av_decision avd;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001448 u16 sclass;
David Howells3699c532009-01-06 22:27:01 +00001449 u32 sid = cred_sid(cred);
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001450 u32 av = CAP_TO_MASK(cap);
Eric Paris06112162008-11-11 22:02:50 +11001451 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001452
Thomas Liu2bf49692009-07-14 12:14:09 -04001453 COMMON_AUDIT_DATA_INIT(&ad, CAP);
Eric Paris3b3b0e42012-04-03 09:37:02 -07001454 ad.selinux_audit_data = &sad;
Eric Paris6a9de492012-01-03 12:25:14 -05001455 ad.tsk = current;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001456 ad.u.cap = cap;
1457
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001458 switch (CAP_TO_INDEX(cap)) {
1459 case 0:
1460 sclass = SECCLASS_CAPABILITY;
1461 break;
1462 case 1:
1463 sclass = SECCLASS_CAPABILITY2;
1464 break;
1465 default:
1466 printk(KERN_ERR
1467 "SELinux: out of range capability %d\n", cap);
1468 BUG();
Eric Parisa35c6c82011-04-20 10:21:28 -04001469 return -EINVAL;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001470 }
Eric Paris06112162008-11-11 22:02:50 +11001471
David Howells275bb412008-11-14 10:39:19 +11001472 rc = avc_has_perm_noaudit(sid, sid, sclass, av, 0, &avd);
Eric Paris9ade0cf2011-04-25 16:26:29 -04001473 if (audit == SECURITY_CAP_AUDIT) {
1474 int rc2 = avc_audit(sid, sid, sclass, av, &avd, rc, &ad, 0);
1475 if (rc2)
1476 return rc2;
1477 }
Eric Paris06112162008-11-11 22:02:50 +11001478 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001479}
1480
1481/* Check whether a task is allowed to use a system operation. */
1482static int task_has_system(struct task_struct *tsk,
1483 u32 perms)
1484{
David Howells275bb412008-11-14 10:39:19 +11001485 u32 sid = task_sid(tsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001486
David Howells275bb412008-11-14 10:39:19 +11001487 return avc_has_perm(sid, SECINITSID_KERNEL,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001488 SECCLASS_SYSTEM, perms, NULL);
1489}
1490
1491/* Check whether a task has a particular permission to an inode.
1492 The 'adp' parameter is optional and allows other audit
1493 data to be passed (e.g. the dentry). */
David Howells88e67f32008-11-14 10:39:21 +11001494static int inode_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001495 struct inode *inode,
1496 u32 perms,
Eric Paris9ade0cf2011-04-25 16:26:29 -04001497 struct common_audit_data *adp,
1498 unsigned flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001499{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001500 struct inode_security_struct *isec;
David Howells275bb412008-11-14 10:39:19 +11001501 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001502
David Howellse0e81732009-09-02 09:13:40 +01001503 validate_creds(cred);
1504
Eric Paris828dfe12008-04-17 13:17:49 -04001505 if (unlikely(IS_PRIVATE(inode)))
Stephen Smalleybbaca6c2007-02-14 00:34:16 -08001506 return 0;
1507
David Howells88e67f32008-11-14 10:39:21 +11001508 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001509 isec = inode->i_security;
1510
Eric Paris9ade0cf2011-04-25 16:26:29 -04001511 return avc_has_perm_flags(sid, isec->sid, isec->sclass, perms, adp, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001512}
1513
Linus Torvalds95f4efb2011-06-08 15:11:56 -07001514static int inode_has_perm_noadp(const struct cred *cred,
1515 struct inode *inode,
1516 u32 perms,
1517 unsigned flags)
1518{
1519 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07001520 struct selinux_audit_data sad = {0,};
Linus Torvalds95f4efb2011-06-08 15:11:56 -07001521
1522 COMMON_AUDIT_DATA_INIT(&ad, INODE);
1523 ad.u.inode = inode;
Eric Paris3b3b0e42012-04-03 09:37:02 -07001524 ad.selinux_audit_data = &sad;
Linus Torvalds95f4efb2011-06-08 15:11:56 -07001525 return inode_has_perm(cred, inode, perms, &ad, flags);
1526}
1527
Linus Torvalds1da177e2005-04-16 15:20:36 -07001528/* Same as inode_has_perm, but pass explicit audit data containing
1529 the dentry to help the auditing code to more easily generate the
1530 pathname if needed. */
David Howells88e67f32008-11-14 10:39:21 +11001531static inline int dentry_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001532 struct dentry *dentry,
1533 u32 av)
1534{
1535 struct inode *inode = dentry->d_inode;
Thomas Liu2bf49692009-07-14 12:14:09 -04001536 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07001537 struct selinux_audit_data sad = {0,};
David Howells88e67f32008-11-14 10:39:21 +11001538
Eric Paris2875fa02011-04-28 16:04:24 -04001539 COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
1540 ad.u.dentry = dentry;
Eric Paris3b3b0e42012-04-03 09:37:02 -07001541 ad.selinux_audit_data = &sad;
Eric Paris2875fa02011-04-28 16:04:24 -04001542 return inode_has_perm(cred, inode, av, &ad, 0);
1543}
1544
1545/* Same as inode_has_perm, but pass explicit audit data containing
1546 the path to help the auditing code to more easily generate the
1547 pathname if needed. */
1548static inline int path_has_perm(const struct cred *cred,
1549 struct path *path,
1550 u32 av)
1551{
1552 struct inode *inode = path->dentry->d_inode;
1553 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07001554 struct selinux_audit_data sad = {0,};
Eric Paris2875fa02011-04-28 16:04:24 -04001555
Eric Parisf48b7392011-04-25 12:54:27 -04001556 COMMON_AUDIT_DATA_INIT(&ad, PATH);
Eric Paris2875fa02011-04-28 16:04:24 -04001557 ad.u.path = *path;
Eric Paris3b3b0e42012-04-03 09:37:02 -07001558 ad.selinux_audit_data = &sad;
Eric Paris9ade0cf2011-04-25 16:26:29 -04001559 return inode_has_perm(cred, inode, av, &ad, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001560}
1561
1562/* Check whether a task can use an open file descriptor to
1563 access an inode in a given way. Check access to the
1564 descriptor itself, and then use dentry_has_perm to
1565 check a particular permission to the file.
1566 Access to the descriptor is implicitly granted if it
1567 has the same SID as the process. If av is zero, then
1568 access to the file is not checked, e.g. for cases
1569 where only the descriptor is affected like seek. */
David Howells88e67f32008-11-14 10:39:21 +11001570static int file_has_perm(const struct cred *cred,
1571 struct file *file,
1572 u32 av)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001573{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001574 struct file_security_struct *fsec = file->f_security;
Jan Blunck44707fd2008-02-14 19:38:33 -08001575 struct inode *inode = file->f_path.dentry->d_inode;
Thomas Liu2bf49692009-07-14 12:14:09 -04001576 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07001577 struct selinux_audit_data sad = {0,};
David Howells88e67f32008-11-14 10:39:21 +11001578 u32 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001579 int rc;
1580
Eric Parisf48b7392011-04-25 12:54:27 -04001581 COMMON_AUDIT_DATA_INIT(&ad, PATH);
1582 ad.u.path = file->f_path;
Eric Paris3b3b0e42012-04-03 09:37:02 -07001583 ad.selinux_audit_data = &sad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001584
David Howells275bb412008-11-14 10:39:19 +11001585 if (sid != fsec->sid) {
1586 rc = avc_has_perm(sid, fsec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001587 SECCLASS_FD,
1588 FD__USE,
1589 &ad);
1590 if (rc)
David Howells88e67f32008-11-14 10:39:21 +11001591 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001592 }
1593
1594 /* av is zero if only checking access to the descriptor. */
David Howells88e67f32008-11-14 10:39:21 +11001595 rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001596 if (av)
Eric Paris9ade0cf2011-04-25 16:26:29 -04001597 rc = inode_has_perm(cred, inode, av, &ad, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001598
David Howells88e67f32008-11-14 10:39:21 +11001599out:
1600 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001601}
1602
1603/* Check whether a task can create a file. */
1604static int may_create(struct inode *dir,
1605 struct dentry *dentry,
1606 u16 tclass)
1607{
Paul Moore5fb49872010-04-22 14:46:19 -04001608 const struct task_security_struct *tsec = current_security();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001609 struct inode_security_struct *dsec;
1610 struct superblock_security_struct *sbsec;
David Howells275bb412008-11-14 10:39:19 +11001611 u32 sid, newsid;
Thomas Liu2bf49692009-07-14 12:14:09 -04001612 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07001613 struct selinux_audit_data sad = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07001614 int rc;
1615
Linus Torvalds1da177e2005-04-16 15:20:36 -07001616 dsec = dir->i_security;
1617 sbsec = dir->i_sb->s_security;
1618
David Howells275bb412008-11-14 10:39:19 +11001619 sid = tsec->sid;
1620 newsid = tsec->create_sid;
1621
Eric Parisa2694342011-04-25 13:10:27 -04001622 COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
1623 ad.u.dentry = dentry;
Eric Paris3b3b0e42012-04-03 09:37:02 -07001624 ad.selinux_audit_data = &sad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001625
David Howells275bb412008-11-14 10:39:19 +11001626 rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001627 DIR__ADD_NAME | DIR__SEARCH,
1628 &ad);
1629 if (rc)
1630 return rc;
1631
David P. Quigleycd895962009-01-16 09:22:04 -05001632 if (!newsid || !(sbsec->flags & SE_SBLABELSUPP)) {
Eric Pariscb1e9222011-04-28 15:11:21 -04001633 rc = security_transition_sid(sid, dsec->sid, tclass,
1634 &dentry->d_name, &newsid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001635 if (rc)
1636 return rc;
1637 }
1638
David Howells275bb412008-11-14 10:39:19 +11001639 rc = avc_has_perm(sid, newsid, tclass, FILE__CREATE, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001640 if (rc)
1641 return rc;
1642
Amir Samuelov6a22e462014-05-26 11:44:06 +03001643 rc = avc_has_perm(newsid, sbsec->sid,
1644 SECCLASS_FILESYSTEM,
1645 FILESYSTEM__ASSOCIATE, &ad);
1646 if (rc)
1647 return rc;
1648
1649 rc = pft_inode_mknod(dir, dentry, 0, 0);
1650
1651 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001652}
1653
Michael LeMay4eb582c2006-06-26 00:24:57 -07001654/* Check whether a task can create a key. */
1655static int may_create_key(u32 ksid,
1656 struct task_struct *ctx)
1657{
David Howells275bb412008-11-14 10:39:19 +11001658 u32 sid = task_sid(ctx);
Michael LeMay4eb582c2006-06-26 00:24:57 -07001659
David Howells275bb412008-11-14 10:39:19 +11001660 return avc_has_perm(sid, ksid, SECCLASS_KEY, KEY__CREATE, NULL);
Michael LeMay4eb582c2006-06-26 00:24:57 -07001661}
1662
Eric Paris828dfe12008-04-17 13:17:49 -04001663#define MAY_LINK 0
1664#define MAY_UNLINK 1
1665#define MAY_RMDIR 2
Linus Torvalds1da177e2005-04-16 15:20:36 -07001666
1667/* Check whether a task can link, unlink, or rmdir a file/directory. */
1668static int may_link(struct inode *dir,
1669 struct dentry *dentry,
1670 int kind)
1671
1672{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001673 struct inode_security_struct *dsec, *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04001674 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07001675 struct selinux_audit_data sad = {0,};
David Howells275bb412008-11-14 10:39:19 +11001676 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001677 u32 av;
1678 int rc;
1679
Linus Torvalds1da177e2005-04-16 15:20:36 -07001680 dsec = dir->i_security;
1681 isec = dentry->d_inode->i_security;
1682
Eric Parisa2694342011-04-25 13:10:27 -04001683 COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
1684 ad.u.dentry = dentry;
Eric Paris3b3b0e42012-04-03 09:37:02 -07001685 ad.selinux_audit_data = &sad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001686
1687 av = DIR__SEARCH;
1688 av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME);
David Howells275bb412008-11-14 10:39:19 +11001689 rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001690 if (rc)
1691 return rc;
1692
1693 switch (kind) {
1694 case MAY_LINK:
1695 av = FILE__LINK;
1696 break;
1697 case MAY_UNLINK:
1698 av = FILE__UNLINK;
1699 break;
1700 case MAY_RMDIR:
1701 av = DIR__RMDIR;
1702 break;
1703 default:
Eric Paris744ba352008-04-17 11:52:44 -04001704 printk(KERN_WARNING "SELinux: %s: unrecognized kind %d\n",
1705 __func__, kind);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001706 return 0;
1707 }
1708
David Howells275bb412008-11-14 10:39:19 +11001709 rc = avc_has_perm(sid, isec->sid, isec->sclass, av, &ad);
Amir Samuelov6a22e462014-05-26 11:44:06 +03001710 if (rc)
1711 return rc;
1712
1713 if (kind == MAY_UNLINK)
1714 rc = pft_inode_unlink(dir, dentry);
1715
Linus Torvalds1da177e2005-04-16 15:20:36 -07001716 return rc;
1717}
1718
1719static inline int may_rename(struct inode *old_dir,
1720 struct dentry *old_dentry,
1721 struct inode *new_dir,
1722 struct dentry *new_dentry)
1723{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001724 struct inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04001725 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07001726 struct selinux_audit_data sad = {0,};
David Howells275bb412008-11-14 10:39:19 +11001727 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001728 u32 av;
1729 int old_is_dir, new_is_dir;
1730 int rc;
1731
Linus Torvalds1da177e2005-04-16 15:20:36 -07001732 old_dsec = old_dir->i_security;
1733 old_isec = old_dentry->d_inode->i_security;
1734 old_is_dir = S_ISDIR(old_dentry->d_inode->i_mode);
1735 new_dsec = new_dir->i_security;
1736
Eric Parisa2694342011-04-25 13:10:27 -04001737 COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
Eric Paris3b3b0e42012-04-03 09:37:02 -07001738 ad.selinux_audit_data = &sad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001739
Eric Parisa2694342011-04-25 13:10:27 -04001740 ad.u.dentry = old_dentry;
David Howells275bb412008-11-14 10:39:19 +11001741 rc = avc_has_perm(sid, old_dsec->sid, SECCLASS_DIR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001742 DIR__REMOVE_NAME | DIR__SEARCH, &ad);
1743 if (rc)
1744 return rc;
David Howells275bb412008-11-14 10:39:19 +11001745 rc = avc_has_perm(sid, old_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001746 old_isec->sclass, FILE__RENAME, &ad);
1747 if (rc)
1748 return rc;
1749 if (old_is_dir && new_dir != old_dir) {
David Howells275bb412008-11-14 10:39:19 +11001750 rc = avc_has_perm(sid, old_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001751 old_isec->sclass, DIR__REPARENT, &ad);
1752 if (rc)
1753 return rc;
1754 }
1755
Eric Parisa2694342011-04-25 13:10:27 -04001756 ad.u.dentry = new_dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001757 av = DIR__ADD_NAME | DIR__SEARCH;
1758 if (new_dentry->d_inode)
1759 av |= DIR__REMOVE_NAME;
David Howells275bb412008-11-14 10:39:19 +11001760 rc = avc_has_perm(sid, new_dsec->sid, SECCLASS_DIR, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001761 if (rc)
1762 return rc;
1763 if (new_dentry->d_inode) {
1764 new_isec = new_dentry->d_inode->i_security;
1765 new_is_dir = S_ISDIR(new_dentry->d_inode->i_mode);
David Howells275bb412008-11-14 10:39:19 +11001766 rc = avc_has_perm(sid, new_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001767 new_isec->sclass,
1768 (new_is_dir ? DIR__RMDIR : FILE__UNLINK), &ad);
1769 if (rc)
1770 return rc;
1771 }
1772
1773 return 0;
1774}
1775
1776/* Check whether a task can perform a filesystem operation. */
David Howells88e67f32008-11-14 10:39:21 +11001777static int superblock_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001778 struct super_block *sb,
1779 u32 perms,
Thomas Liu2bf49692009-07-14 12:14:09 -04001780 struct common_audit_data *ad)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001781{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001782 struct superblock_security_struct *sbsec;
David Howells88e67f32008-11-14 10:39:21 +11001783 u32 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001784
Linus Torvalds1da177e2005-04-16 15:20:36 -07001785 sbsec = sb->s_security;
David Howells275bb412008-11-14 10:39:19 +11001786 return avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM, perms, ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001787}
1788
1789/* Convert a Linux mode and permission mask to an access vector. */
1790static inline u32 file_mask_to_av(int mode, int mask)
1791{
1792 u32 av = 0;
1793
Al Virodba19c62011-07-25 20:49:29 -04001794 if (!S_ISDIR(mode)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001795 if (mask & MAY_EXEC)
1796 av |= FILE__EXECUTE;
1797 if (mask & MAY_READ)
1798 av |= FILE__READ;
1799
1800 if (mask & MAY_APPEND)
1801 av |= FILE__APPEND;
1802 else if (mask & MAY_WRITE)
1803 av |= FILE__WRITE;
1804
1805 } else {
1806 if (mask & MAY_EXEC)
1807 av |= DIR__SEARCH;
1808 if (mask & MAY_WRITE)
1809 av |= DIR__WRITE;
1810 if (mask & MAY_READ)
1811 av |= DIR__READ;
1812 }
1813
1814 return av;
1815}
1816
1817/* Convert a Linux file to an access vector. */
1818static inline u32 file_to_av(struct file *file)
1819{
1820 u32 av = 0;
1821
1822 if (file->f_mode & FMODE_READ)
1823 av |= FILE__READ;
1824 if (file->f_mode & FMODE_WRITE) {
1825 if (file->f_flags & O_APPEND)
1826 av |= FILE__APPEND;
1827 else
1828 av |= FILE__WRITE;
1829 }
Stephen Smalley0794c662008-03-17 08:55:18 -04001830 if (!av) {
1831 /*
1832 * Special file opened with flags 3 for ioctl-only use.
1833 */
1834 av = FILE__IOCTL;
1835 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001836
1837 return av;
1838}
1839
Eric Paris8b6a5a32008-10-29 17:06:46 -04001840/*
1841 * Convert a file to an access vector and include the correct open
1842 * open permission.
1843 */
1844static inline u32 open_file_to_av(struct file *file)
1845{
1846 u32 av = file_to_av(file);
1847
Eric Paris49b7b8d2010-07-23 11:44:09 -04001848 if (selinux_policycap_openperm)
1849 av |= FILE__OPEN;
1850
Eric Paris8b6a5a32008-10-29 17:06:46 -04001851 return av;
1852}
1853
Linus Torvalds1da177e2005-04-16 15:20:36 -07001854/* Hook functions begin here. */
1855
Stephen Smalley48a23702012-11-05 08:15:34 -05001856static int selinux_binder_set_context_mgr(struct task_struct *mgr)
1857{
1858 u32 mysid = current_sid();
1859 u32 mgrsid = task_sid(mgr);
1860
1861 return avc_has_perm(mysid, mgrsid, SECCLASS_BINDER, BINDER__SET_CONTEXT_MGR, NULL);
1862}
1863
1864static int selinux_binder_transaction(struct task_struct *from, struct task_struct *to)
1865{
1866 u32 mysid = current_sid();
1867 u32 fromsid = task_sid(from);
1868 u32 tosid = task_sid(to);
1869 int rc;
1870
1871 if (mysid != fromsid) {
1872 rc = avc_has_perm(mysid, fromsid, SECCLASS_BINDER, BINDER__IMPERSONATE, NULL);
1873 if (rc)
1874 return rc;
1875 }
1876
1877 return avc_has_perm(fromsid, tosid, SECCLASS_BINDER, BINDER__CALL, NULL);
1878}
1879
1880static int selinux_binder_transfer_binder(struct task_struct *from, struct task_struct *to)
1881{
1882 u32 fromsid = task_sid(from);
1883 u32 tosid = task_sid(to);
1884 return avc_has_perm(fromsid, tosid, SECCLASS_BINDER, BINDER__TRANSFER, NULL);
1885}
1886
1887static int selinux_binder_transfer_file(struct task_struct *from, struct task_struct *to, struct file *file)
1888{
1889 u32 sid = task_sid(to);
1890 struct file_security_struct *fsec = file->f_security;
1891 struct inode *inode = file->f_path.dentry->d_inode;
1892 struct inode_security_struct *isec = inode->i_security;
1893 struct common_audit_data ad;
1894 struct selinux_audit_data sad = {0,};
1895 int rc;
1896
1897 COMMON_AUDIT_DATA_INIT(&ad, PATH);
1898 ad.u.path = file->f_path;
1899 ad.selinux_audit_data = &sad;
1900
1901 if (sid != fsec->sid) {
1902 rc = avc_has_perm(sid, fsec->sid,
1903 SECCLASS_FD,
1904 FD__USE,
1905 &ad);
1906 if (rc)
1907 return rc;
1908 }
1909
1910 if (unlikely(IS_PRIVATE(inode)))
1911 return 0;
1912
1913 return avc_has_perm(sid, isec->sid, isec->sclass, file_to_av(file),
1914 &ad);
1915}
1916
Ingo Molnar9e488582009-05-07 19:26:19 +10001917static int selinux_ptrace_access_check(struct task_struct *child,
David Howells5cd9c582008-08-14 11:37:28 +01001918 unsigned int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001919{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001920 int rc;
1921
Ingo Molnar9e488582009-05-07 19:26:19 +10001922 rc = cap_ptrace_access_check(child, mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001923 if (rc)
1924 return rc;
1925
Eric Paris69f594a2012-01-03 12:25:15 -05001926 if (mode & PTRACE_MODE_READ) {
David Howells275bb412008-11-14 10:39:19 +11001927 u32 sid = current_sid();
1928 u32 csid = task_sid(child);
1929 return avc_has_perm(sid, csid, SECCLASS_FILE, FILE__READ, NULL);
Stephen Smalley006ebb42008-05-19 08:32:49 -04001930 }
1931
David Howells3b11a1d2008-11-14 10:39:26 +11001932 return current_has_perm(child, PROCESS__PTRACE);
David Howells5cd9c582008-08-14 11:37:28 +01001933}
1934
1935static int selinux_ptrace_traceme(struct task_struct *parent)
1936{
1937 int rc;
1938
Eric Paris200ac532009-02-12 15:01:04 -05001939 rc = cap_ptrace_traceme(parent);
David Howells5cd9c582008-08-14 11:37:28 +01001940 if (rc)
1941 return rc;
1942
1943 return task_has_perm(parent, current, PROCESS__PTRACE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001944}
1945
1946static int selinux_capget(struct task_struct *target, kernel_cap_t *effective,
Eric Paris828dfe12008-04-17 13:17:49 -04001947 kernel_cap_t *inheritable, kernel_cap_t *permitted)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001948{
1949 int error;
1950
David Howells3b11a1d2008-11-14 10:39:26 +11001951 error = current_has_perm(target, PROCESS__GETCAP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001952 if (error)
1953 return error;
1954
Eric Paris200ac532009-02-12 15:01:04 -05001955 return cap_capget(target, effective, inheritable, permitted);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001956}
1957
David Howellsd84f4f92008-11-14 10:39:23 +11001958static int selinux_capset(struct cred *new, const struct cred *old,
1959 const kernel_cap_t *effective,
1960 const kernel_cap_t *inheritable,
1961 const kernel_cap_t *permitted)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001962{
1963 int error;
1964
Eric Paris200ac532009-02-12 15:01:04 -05001965 error = cap_capset(new, old,
David Howellsd84f4f92008-11-14 10:39:23 +11001966 effective, inheritable, permitted);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001967 if (error)
1968 return error;
1969
David Howellsd84f4f92008-11-14 10:39:23 +11001970 return cred_has_perm(old, new, PROCESS__SETCAP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001971}
1972
James Morris5626d3e2009-01-30 10:05:06 +11001973/*
1974 * (This comment used to live with the selinux_task_setuid hook,
1975 * which was removed).
1976 *
1977 * Since setuid only affects the current process, and since the SELinux
1978 * controls are not based on the Linux identity attributes, SELinux does not
1979 * need to control this operation. However, SELinux does control the use of
1980 * the CAP_SETUID and CAP_SETGID capabilities using the capable hook.
1981 */
1982
Eric Paris6a9de492012-01-03 12:25:14 -05001983static int selinux_capable(const struct cred *cred, struct user_namespace *ns,
1984 int cap, int audit)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001985{
1986 int rc;
1987
Eric Paris6a9de492012-01-03 12:25:14 -05001988 rc = cap_capable(cred, ns, cap, audit);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001989 if (rc)
1990 return rc;
1991
Eric Paris6a9de492012-01-03 12:25:14 -05001992 return cred_has_capability(cred, cap, audit);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001993}
1994
Linus Torvalds1da177e2005-04-16 15:20:36 -07001995static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb)
1996{
David Howells88e67f32008-11-14 10:39:21 +11001997 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001998 int rc = 0;
1999
2000 if (!sb)
2001 return 0;
2002
2003 switch (cmds) {
Eric Paris828dfe12008-04-17 13:17:49 -04002004 case Q_SYNC:
2005 case Q_QUOTAON:
2006 case Q_QUOTAOFF:
2007 case Q_SETINFO:
2008 case Q_SETQUOTA:
David Howells88e67f32008-11-14 10:39:21 +11002009 rc = superblock_has_perm(cred, sb, FILESYSTEM__QUOTAMOD, NULL);
Eric Paris828dfe12008-04-17 13:17:49 -04002010 break;
2011 case Q_GETFMT:
2012 case Q_GETINFO:
2013 case Q_GETQUOTA:
David Howells88e67f32008-11-14 10:39:21 +11002014 rc = superblock_has_perm(cred, sb, FILESYSTEM__QUOTAGET, NULL);
Eric Paris828dfe12008-04-17 13:17:49 -04002015 break;
2016 default:
2017 rc = 0; /* let the kernel handle invalid cmds */
2018 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002019 }
2020 return rc;
2021}
2022
2023static int selinux_quota_on(struct dentry *dentry)
2024{
David Howells88e67f32008-11-14 10:39:21 +11002025 const struct cred *cred = current_cred();
2026
Eric Paris2875fa02011-04-28 16:04:24 -04002027 return dentry_has_perm(cred, dentry, FILE__QUOTAON);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002028}
2029
Eric Paris12b30522010-11-15 18:36:29 -05002030static int selinux_syslog(int type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002031{
2032 int rc;
2033
Linus Torvalds1da177e2005-04-16 15:20:36 -07002034 switch (type) {
Kees Cookd78ca3c2010-02-03 15:37:13 -08002035 case SYSLOG_ACTION_READ_ALL: /* Read last kernel messages */
2036 case SYSLOG_ACTION_SIZE_BUFFER: /* Return size of the log buffer */
Eric Paris828dfe12008-04-17 13:17:49 -04002037 rc = task_has_system(current, SYSTEM__SYSLOG_READ);
2038 break;
Kees Cookd78ca3c2010-02-03 15:37:13 -08002039 case SYSLOG_ACTION_CONSOLE_OFF: /* Disable logging to console */
2040 case SYSLOG_ACTION_CONSOLE_ON: /* Enable logging to console */
2041 /* Set level of messages printed to console */
2042 case SYSLOG_ACTION_CONSOLE_LEVEL:
Eric Paris828dfe12008-04-17 13:17:49 -04002043 rc = task_has_system(current, SYSTEM__SYSLOG_CONSOLE);
2044 break;
Kees Cookd78ca3c2010-02-03 15:37:13 -08002045 case SYSLOG_ACTION_CLOSE: /* Close log */
2046 case SYSLOG_ACTION_OPEN: /* Open log */
2047 case SYSLOG_ACTION_READ: /* Read from log */
2048 case SYSLOG_ACTION_READ_CLEAR: /* Read/clear last kernel messages */
2049 case SYSLOG_ACTION_CLEAR: /* Clear ring buffer */
Eric Paris828dfe12008-04-17 13:17:49 -04002050 default:
2051 rc = task_has_system(current, SYSTEM__SYSLOG_MOD);
2052 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002053 }
2054 return rc;
2055}
2056
2057/*
2058 * Check that a process has enough memory to allocate a new virtual
2059 * mapping. 0 means there is enough memory for the allocation to
2060 * succeed and -ENOMEM implies there is not.
2061 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07002062 * Do not audit the selinux permission check, as this is applied to all
2063 * processes that allocate mappings.
2064 */
Alan Cox34b4e4a2007-08-22 14:01:28 -07002065static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002066{
2067 int rc, cap_sys_admin = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002068
Eric Paris6a9de492012-01-03 12:25:14 -05002069 rc = selinux_capable(current_cred(), &init_user_ns, CAP_SYS_ADMIN,
David Howells3699c532009-01-06 22:27:01 +00002070 SECURITY_CAP_NOAUDIT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002071 if (rc == 0)
2072 cap_sys_admin = 1;
2073
Alan Cox34b4e4a2007-08-22 14:01:28 -07002074 return __vm_enough_memory(mm, pages, cap_sys_admin);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002075}
2076
2077/* binprm security operations */
2078
David Howellsa6f76f22008-11-14 10:39:24 +11002079static int selinux_bprm_set_creds(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002080{
David Howellsa6f76f22008-11-14 10:39:24 +11002081 const struct task_security_struct *old_tsec;
2082 struct task_security_struct *new_tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002083 struct inode_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04002084 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07002085 struct selinux_audit_data sad = {0,};
David Howellsa6f76f22008-11-14 10:39:24 +11002086 struct inode *inode = bprm->file->f_path.dentry->d_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002087 int rc;
2088
Eric Paris200ac532009-02-12 15:01:04 -05002089 rc = cap_bprm_set_creds(bprm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002090 if (rc)
2091 return rc;
2092
David Howellsa6f76f22008-11-14 10:39:24 +11002093 /* SELinux context only depends on initial program or script and not
2094 * the script interpreter */
2095 if (bprm->cred_prepared)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002096 return 0;
2097
David Howellsa6f76f22008-11-14 10:39:24 +11002098 old_tsec = current_security();
2099 new_tsec = bprm->cred->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002100 isec = inode->i_security;
2101
2102 /* Default to the current task SID. */
David Howellsa6f76f22008-11-14 10:39:24 +11002103 new_tsec->sid = old_tsec->sid;
2104 new_tsec->osid = old_tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002105
Michael LeMay28eba5b2006-06-27 02:53:42 -07002106 /* Reset fs, key, and sock SIDs on execve. */
David Howellsa6f76f22008-11-14 10:39:24 +11002107 new_tsec->create_sid = 0;
2108 new_tsec->keycreate_sid = 0;
2109 new_tsec->sockcreate_sid = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002110
David Howellsa6f76f22008-11-14 10:39:24 +11002111 if (old_tsec->exec_sid) {
2112 new_tsec->sid = old_tsec->exec_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002113 /* Reset exec SID on execve. */
David Howellsa6f76f22008-11-14 10:39:24 +11002114 new_tsec->exec_sid = 0;
Andy Lutomirski397a85e2012-01-30 08:17:26 -08002115
2116 /*
2117 * Minimize confusion: if no_new_privs and a transition is
2118 * explicitly requested, then fail the exec.
2119 */
2120 if (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS)
2121 return -EPERM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002122 } else {
2123 /* Check for a default transition on this program. */
David Howellsa6f76f22008-11-14 10:39:24 +11002124 rc = security_transition_sid(old_tsec->sid, isec->sid,
Eric Paris652bb9b2011-02-01 11:05:40 -05002125 SECCLASS_PROCESS, NULL,
2126 &new_tsec->sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002127 if (rc)
2128 return rc;
2129 }
2130
Eric Parisf48b7392011-04-25 12:54:27 -04002131 COMMON_AUDIT_DATA_INIT(&ad, PATH);
Eric Paris3b3b0e42012-04-03 09:37:02 -07002132 ad.selinux_audit_data = &sad;
Eric Parisf48b7392011-04-25 12:54:27 -04002133 ad.u.path = bprm->file->f_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002134
Andy Lutomirski397a85e2012-01-30 08:17:26 -08002135 if ((bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) ||
2136 (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS))
David Howellsa6f76f22008-11-14 10:39:24 +11002137 new_tsec->sid = old_tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002138
David Howellsa6f76f22008-11-14 10:39:24 +11002139 if (new_tsec->sid == old_tsec->sid) {
2140 rc = avc_has_perm(old_tsec->sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002141 SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, &ad);
2142 if (rc)
2143 return rc;
2144 } else {
2145 /* Check permissions for the transition. */
David Howellsa6f76f22008-11-14 10:39:24 +11002146 rc = avc_has_perm(old_tsec->sid, new_tsec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002147 SECCLASS_PROCESS, PROCESS__TRANSITION, &ad);
2148 if (rc)
2149 return rc;
2150
David Howellsa6f76f22008-11-14 10:39:24 +11002151 rc = avc_has_perm(new_tsec->sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002152 SECCLASS_FILE, FILE__ENTRYPOINT, &ad);
2153 if (rc)
2154 return rc;
2155
David Howellsa6f76f22008-11-14 10:39:24 +11002156 /* Check for shared state */
2157 if (bprm->unsafe & LSM_UNSAFE_SHARE) {
2158 rc = avc_has_perm(old_tsec->sid, new_tsec->sid,
2159 SECCLASS_PROCESS, PROCESS__SHARE,
2160 NULL);
2161 if (rc)
2162 return -EPERM;
2163 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002164
David Howellsa6f76f22008-11-14 10:39:24 +11002165 /* Make sure that anyone attempting to ptrace over a task that
2166 * changes its SID has the appropriate permit */
2167 if (bprm->unsafe &
2168 (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) {
2169 struct task_struct *tracer;
2170 struct task_security_struct *sec;
2171 u32 ptsid = 0;
2172
2173 rcu_read_lock();
Tejun Heo06d98472011-06-17 16:50:40 +02002174 tracer = ptrace_parent(current);
David Howellsa6f76f22008-11-14 10:39:24 +11002175 if (likely(tracer != NULL)) {
2176 sec = __task_cred(tracer)->security;
2177 ptsid = sec->sid;
2178 }
2179 rcu_read_unlock();
2180
2181 if (ptsid != 0) {
2182 rc = avc_has_perm(ptsid, new_tsec->sid,
2183 SECCLASS_PROCESS,
2184 PROCESS__PTRACE, NULL);
2185 if (rc)
2186 return -EPERM;
2187 }
2188 }
2189
2190 /* Clear any possibly unsafe personality bits on exec: */
2191 bprm->per_clear |= PER_CLEAR_ON_SETID;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002192 }
2193
Linus Torvalds1da177e2005-04-16 15:20:36 -07002194 return 0;
2195}
2196
Eric Paris828dfe12008-04-17 13:17:49 -04002197static int selinux_bprm_secureexec(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002198{
Paul Moore5fb49872010-04-22 14:46:19 -04002199 const struct task_security_struct *tsec = current_security();
David Howells275bb412008-11-14 10:39:19 +11002200 u32 sid, osid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002201 int atsecure = 0;
2202
David Howells275bb412008-11-14 10:39:19 +11002203 sid = tsec->sid;
2204 osid = tsec->osid;
2205
2206 if (osid != sid) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002207 /* Enable secure mode for SIDs transitions unless
2208 the noatsecure permission is granted between
2209 the two SIDs, i.e. ahp returns 0. */
David Howells275bb412008-11-14 10:39:19 +11002210 atsecure = avc_has_perm(osid, sid,
David Howellsa6f76f22008-11-14 10:39:24 +11002211 SECCLASS_PROCESS,
2212 PROCESS__NOATSECURE, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002213 }
2214
Eric Paris200ac532009-02-12 15:01:04 -05002215 return (atsecure || cap_bprm_secureexec(bprm));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002216}
2217
Linus Torvalds1da177e2005-04-16 15:20:36 -07002218/* Derived from fs/exec.c:flush_old_files. */
David Howells745ca242008-11-14 10:39:22 +11002219static inline void flush_unauthorized_files(const struct cred *cred,
2220 struct files_struct *files)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002221{
Thomas Liu2bf49692009-07-14 12:14:09 -04002222 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07002223 struct selinux_audit_data sad = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07002224 struct file *file, *devnull = NULL;
Stephen Smalleyb20c8122006-09-25 23:32:03 -07002225 struct tty_struct *tty;
Dipankar Sarmabadf1662005-09-09 13:04:10 -07002226 struct fdtable *fdt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002227 long j = -1;
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002228 int drop_tty = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002229
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002230 tty = get_current_tty();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002231 if (tty) {
Nick Pigginee2ffa02010-08-18 04:37:35 +10002232 spin_lock(&tty_files_lock);
Eric Paris37dd0bd2008-10-31 17:40:00 -04002233 if (!list_empty(&tty->tty_files)) {
Nick Piggind996b622010-08-18 04:37:36 +10002234 struct tty_file_private *file_priv;
Eric Paris37dd0bd2008-10-31 17:40:00 -04002235 struct inode *inode;
2236
Linus Torvalds1da177e2005-04-16 15:20:36 -07002237 /* Revalidate access to controlling tty.
2238 Use inode_has_perm on the tty inode directly rather
2239 than using file_has_perm, as this particular open
2240 file may belong to another process and we are only
2241 interested in the inode-based check here. */
Nick Piggind996b622010-08-18 04:37:36 +10002242 file_priv = list_first_entry(&tty->tty_files,
2243 struct tty_file_private, list);
2244 file = file_priv->file;
Eric Paris37dd0bd2008-10-31 17:40:00 -04002245 inode = file->f_path.dentry->d_inode;
Linus Torvalds95f4efb2011-06-08 15:11:56 -07002246 if (inode_has_perm_noadp(cred, inode,
2247 FILE__READ | FILE__WRITE, 0)) {
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002248 drop_tty = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002249 }
2250 }
Nick Pigginee2ffa02010-08-18 04:37:35 +10002251 spin_unlock(&tty_files_lock);
Alan Cox452a00d2008-10-13 10:39:13 +01002252 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002253 }
Eric W. Biederman98a27ba2007-05-08 00:26:56 -07002254 /* Reset controlling tty. */
2255 if (drop_tty)
2256 no_tty();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002257
2258 /* Revalidate access to inherited open files. */
2259
Eric Parisf48b7392011-04-25 12:54:27 -04002260 COMMON_AUDIT_DATA_INIT(&ad, INODE);
Eric Paris3b3b0e42012-04-03 09:37:02 -07002261 ad.selinux_audit_data = &sad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002262
2263 spin_lock(&files->file_lock);
2264 for (;;) {
2265 unsigned long set, i;
2266 int fd;
2267
2268 j++;
Josh Boyerf17e9232012-07-25 10:40:34 -04002269 i = j * BITS_PER_LONG;
Dipankar Sarmabadf1662005-09-09 13:04:10 -07002270 fdt = files_fdtable(files);
Vadim Lobanovbbea9f62006-12-10 02:21:12 -08002271 if (i >= fdt->max_fds)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002272 break;
David Howells1fd36ad2012-02-16 17:49:54 +00002273 set = fdt->open_fds[j];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002274 if (!set)
2275 continue;
2276 spin_unlock(&files->file_lock);
Eric Paris828dfe12008-04-17 13:17:49 -04002277 for ( ; set ; i++, set >>= 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002278 if (set & 1) {
2279 file = fget(i);
2280 if (!file)
2281 continue;
David Howells88e67f32008-11-14 10:39:21 +11002282 if (file_has_perm(cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002283 file,
2284 file_to_av(file))) {
2285 sys_close(i);
2286 fd = get_unused_fd();
2287 if (fd != i) {
2288 if (fd >= 0)
2289 put_unused_fd(fd);
2290 fput(file);
2291 continue;
2292 }
2293 if (devnull) {
Nick Piggin095975d2006-01-08 01:02:19 -08002294 get_file(devnull);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002295 } else {
David Howells745ca242008-11-14 10:39:22 +11002296 devnull = dentry_open(
2297 dget(selinux_null),
2298 mntget(selinuxfs_mount),
2299 O_RDWR, cred);
Akinobu Mitafc5d81e2006-11-27 15:16:48 +09002300 if (IS_ERR(devnull)) {
2301 devnull = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002302 put_unused_fd(fd);
2303 fput(file);
2304 continue;
2305 }
2306 }
2307 fd_install(fd, devnull);
2308 }
2309 fput(file);
2310 }
2311 }
2312 spin_lock(&files->file_lock);
2313
2314 }
2315 spin_unlock(&files->file_lock);
2316}
2317
Linus Torvalds1da177e2005-04-16 15:20:36 -07002318/*
David Howellsa6f76f22008-11-14 10:39:24 +11002319 * Prepare a process for imminent new credential changes due to exec
Linus Torvalds1da177e2005-04-16 15:20:36 -07002320 */
David Howellsa6f76f22008-11-14 10:39:24 +11002321static void selinux_bprm_committing_creds(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002322{
David Howellsa6f76f22008-11-14 10:39:24 +11002323 struct task_security_struct *new_tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002324 struct rlimit *rlim, *initrlim;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002325 int rc, i;
2326
David Howellsa6f76f22008-11-14 10:39:24 +11002327 new_tsec = bprm->cred->security;
2328 if (new_tsec->sid == new_tsec->osid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002329 return;
2330
2331 /* Close files for which the new task SID is not authorized. */
David Howellsa6f76f22008-11-14 10:39:24 +11002332 flush_unauthorized_files(bprm->cred, current->files);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002333
David Howellsa6f76f22008-11-14 10:39:24 +11002334 /* Always clear parent death signal on SID transitions. */
2335 current->pdeath_signal = 0;
2336
2337 /* Check whether the new SID can inherit resource limits from the old
2338 * SID. If not, reset all soft limits to the lower of the current
2339 * task's hard limit and the init task's soft limit.
2340 *
2341 * Note that the setting of hard limits (even to lower them) can be
2342 * controlled by the setrlimit check. The inclusion of the init task's
2343 * soft limit into the computation is to avoid resetting soft limits
2344 * higher than the default soft limit for cases where the default is
2345 * lower than the hard limit, e.g. RLIMIT_CORE or RLIMIT_STACK.
2346 */
2347 rc = avc_has_perm(new_tsec->osid, new_tsec->sid, SECCLASS_PROCESS,
2348 PROCESS__RLIMITINH, NULL);
2349 if (rc) {
Oleg Nesteroveb2d55a2010-06-23 22:43:32 +02002350 /* protect against do_prlimit() */
2351 task_lock(current);
David Howellsa6f76f22008-11-14 10:39:24 +11002352 for (i = 0; i < RLIM_NLIMITS; i++) {
2353 rlim = current->signal->rlim + i;
2354 initrlim = init_task.signal->rlim + i;
2355 rlim->rlim_cur = min(rlim->rlim_max, initrlim->rlim_cur);
2356 }
Oleg Nesteroveb2d55a2010-06-23 22:43:32 +02002357 task_unlock(current);
2358 update_rlimit_cpu(current, rlimit(RLIMIT_CPU));
David Howellsa6f76f22008-11-14 10:39:24 +11002359 }
2360}
2361
2362/*
2363 * Clean up the process immediately after the installation of new credentials
2364 * due to exec
2365 */
2366static void selinux_bprm_committed_creds(struct linux_binprm *bprm)
2367{
2368 const struct task_security_struct *tsec = current_security();
2369 struct itimerval itimer;
David Howellsa6f76f22008-11-14 10:39:24 +11002370 u32 osid, sid;
2371 int rc, i;
David Howellsa6f76f22008-11-14 10:39:24 +11002372
David Howellsa6f76f22008-11-14 10:39:24 +11002373 osid = tsec->osid;
2374 sid = tsec->sid;
2375
2376 if (sid == osid)
2377 return;
2378
2379 /* Check whether the new SID can inherit signal state from the old SID.
2380 * If not, clear itimers to avoid subsequent signal generation and
2381 * flush and unblock signals.
2382 *
2383 * This must occur _after_ the task SID has been updated so that any
2384 * kill done after the flush will be checked against the new SID.
2385 */
2386 rc = avc_has_perm(osid, sid, SECCLASS_PROCESS, PROCESS__SIGINH, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002387 if (rc) {
2388 memset(&itimer, 0, sizeof itimer);
2389 for (i = 0; i < 3; i++)
2390 do_setitimer(i, &itimer, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002391 spin_lock_irq(&current->sighand->siglock);
David Howells3bcac022009-04-29 13:45:05 +01002392 if (!(current->signal->flags & SIGNAL_GROUP_EXIT)) {
2393 __flush_signals(current);
2394 flush_signal_handlers(current, 1);
2395 sigemptyset(&current->blocked);
2396 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002397 spin_unlock_irq(&current->sighand->siglock);
2398 }
2399
David Howellsa6f76f22008-11-14 10:39:24 +11002400 /* Wake up the parent if it is waiting so that it can recheck
2401 * wait permission to the new task SID. */
Oleg Nesterovecd6de32009-04-29 16:02:24 +02002402 read_lock(&tasklist_lock);
Oleg Nesterov0b7570e2009-09-23 15:56:46 -07002403 __wake_up_parent(current, current->real_parent);
Oleg Nesterovecd6de32009-04-29 16:02:24 +02002404 read_unlock(&tasklist_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002405}
2406
2407/* superblock security operations */
2408
2409static int selinux_sb_alloc_security(struct super_block *sb)
2410{
2411 return superblock_alloc_security(sb);
2412}
2413
2414static void selinux_sb_free_security(struct super_block *sb)
2415{
2416 superblock_free_security(sb);
2417}
2418
2419static inline int match_prefix(char *prefix, int plen, char *option, int olen)
2420{
2421 if (plen > olen)
2422 return 0;
2423
2424 return !memcmp(prefix, option, plen);
2425}
2426
2427static inline int selinux_option(char *option, int len)
2428{
Eric Paris832cbd92008-04-01 13:24:09 -04002429 return (match_prefix(CONTEXT_STR, sizeof(CONTEXT_STR)-1, option, len) ||
2430 match_prefix(FSCONTEXT_STR, sizeof(FSCONTEXT_STR)-1, option, len) ||
2431 match_prefix(DEFCONTEXT_STR, sizeof(DEFCONTEXT_STR)-1, option, len) ||
David P. Quigley11689d42009-01-16 09:22:03 -05002432 match_prefix(ROOTCONTEXT_STR, sizeof(ROOTCONTEXT_STR)-1, option, len) ||
2433 match_prefix(LABELSUPP_STR, sizeof(LABELSUPP_STR)-1, option, len));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002434}
2435
2436static inline void take_option(char **to, char *from, int *first, int len)
2437{
2438 if (!*first) {
2439 **to = ',';
2440 *to += 1;
Cory Olmo3528a952006-09-29 01:58:44 -07002441 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002442 *first = 0;
2443 memcpy(*to, from, len);
2444 *to += len;
2445}
2446
Eric Paris828dfe12008-04-17 13:17:49 -04002447static inline void take_selinux_option(char **to, char *from, int *first,
2448 int len)
Cory Olmo3528a952006-09-29 01:58:44 -07002449{
2450 int current_size = 0;
2451
2452 if (!*first) {
2453 **to = '|';
2454 *to += 1;
Eric Paris828dfe12008-04-17 13:17:49 -04002455 } else
Cory Olmo3528a952006-09-29 01:58:44 -07002456 *first = 0;
2457
2458 while (current_size < len) {
2459 if (*from != '"') {
2460 **to = *from;
2461 *to += 1;
2462 }
2463 from += 1;
2464 current_size += 1;
2465 }
2466}
2467
Eric Parise0007522008-03-05 10:31:54 -05002468static int selinux_sb_copy_data(char *orig, char *copy)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002469{
2470 int fnosec, fsec, rc = 0;
2471 char *in_save, *in_curr, *in_end;
2472 char *sec_curr, *nosec_save, *nosec;
Cory Olmo3528a952006-09-29 01:58:44 -07002473 int open_quote = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002474
2475 in_curr = orig;
2476 sec_curr = copy;
2477
Linus Torvalds1da177e2005-04-16 15:20:36 -07002478 nosec = (char *)get_zeroed_page(GFP_KERNEL);
2479 if (!nosec) {
2480 rc = -ENOMEM;
2481 goto out;
2482 }
2483
2484 nosec_save = nosec;
2485 fnosec = fsec = 1;
2486 in_save = in_end = orig;
2487
2488 do {
Cory Olmo3528a952006-09-29 01:58:44 -07002489 if (*in_end == '"')
2490 open_quote = !open_quote;
2491 if ((*in_end == ',' && open_quote == 0) ||
2492 *in_end == '\0') {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002493 int len = in_end - in_curr;
2494
2495 if (selinux_option(in_curr, len))
Cory Olmo3528a952006-09-29 01:58:44 -07002496 take_selinux_option(&sec_curr, in_curr, &fsec, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002497 else
2498 take_option(&nosec, in_curr, &fnosec, len);
2499
2500 in_curr = in_end + 1;
2501 }
2502 } while (*in_end++);
2503
Eric Paris6931dfc2005-06-30 02:58:51 -07002504 strcpy(in_save, nosec_save);
Gerald Schaeferda3caa22005-06-21 17:15:18 -07002505 free_page((unsigned long)nosec_save);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002506out:
2507 return rc;
2508}
2509
Eric Paris026eb162011-03-03 16:09:14 -05002510static int selinux_sb_remount(struct super_block *sb, void *data)
2511{
2512 int rc, i, *flags;
2513 struct security_mnt_opts opts;
2514 char *secdata, **mount_options;
2515 struct superblock_security_struct *sbsec = sb->s_security;
2516
2517 if (!(sbsec->flags & SE_SBINITIALIZED))
2518 return 0;
2519
2520 if (!data)
2521 return 0;
2522
2523 if (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)
2524 return 0;
2525
2526 security_init_mnt_opts(&opts);
2527 secdata = alloc_secdata();
2528 if (!secdata)
2529 return -ENOMEM;
2530 rc = selinux_sb_copy_data(data, secdata);
2531 if (rc)
2532 goto out_free_secdata;
2533
2534 rc = selinux_parse_opts_str(secdata, &opts);
2535 if (rc)
2536 goto out_free_secdata;
2537
2538 mount_options = opts.mnt_opts;
2539 flags = opts.mnt_opts_flags;
2540
2541 for (i = 0; i < opts.num_mnt_opts; i++) {
2542 u32 sid;
2543 size_t len;
2544
2545 if (flags[i] == SE_SBLABELSUPP)
2546 continue;
2547 len = strlen(mount_options[i]);
2548 rc = security_context_to_sid(mount_options[i], len, &sid);
2549 if (rc) {
2550 printk(KERN_WARNING "SELinux: security_context_to_sid"
2551 "(%s) failed for (dev %s, type %s) errno=%d\n",
2552 mount_options[i], sb->s_id, sb->s_type->name, rc);
2553 goto out_free_opts;
2554 }
2555 rc = -EINVAL;
2556 switch (flags[i]) {
2557 case FSCONTEXT_MNT:
2558 if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid, sid))
2559 goto out_bad_option;
2560 break;
2561 case CONTEXT_MNT:
2562 if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid, sid))
2563 goto out_bad_option;
2564 break;
2565 case ROOTCONTEXT_MNT: {
2566 struct inode_security_struct *root_isec;
2567 root_isec = sb->s_root->d_inode->i_security;
2568
2569 if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid, sid))
2570 goto out_bad_option;
2571 break;
2572 }
2573 case DEFCONTEXT_MNT:
2574 if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid, sid))
2575 goto out_bad_option;
2576 break;
2577 default:
2578 goto out_free_opts;
2579 }
2580 }
2581
2582 rc = 0;
2583out_free_opts:
2584 security_free_mnt_opts(&opts);
2585out_free_secdata:
2586 free_secdata(secdata);
2587 return rc;
2588out_bad_option:
2589 printk(KERN_WARNING "SELinux: unable to change security options "
2590 "during remount (dev %s, type=%s)\n", sb->s_id,
2591 sb->s_type->name);
2592 goto out_free_opts;
2593}
2594
James Morris12204e22008-12-19 10:44:42 +11002595static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002596{
David Howells88e67f32008-11-14 10:39:21 +11002597 const struct cred *cred = current_cred();
Thomas Liu2bf49692009-07-14 12:14:09 -04002598 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07002599 struct selinux_audit_data sad = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07002600 int rc;
2601
2602 rc = superblock_doinit(sb, data);
2603 if (rc)
2604 return rc;
2605
James Morris74192242008-12-19 11:41:10 +11002606 /* Allow all mounts performed by the kernel */
2607 if (flags & MS_KERNMOUNT)
2608 return 0;
2609
Eric Parisa2694342011-04-25 13:10:27 -04002610 COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
Eric Paris3b3b0e42012-04-03 09:37:02 -07002611 ad.selinux_audit_data = &sad;
Eric Parisa2694342011-04-25 13:10:27 -04002612 ad.u.dentry = sb->s_root;
David Howells88e67f32008-11-14 10:39:21 +11002613 return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002614}
2615
David Howells726c3342006-06-23 02:02:58 -07002616static int selinux_sb_statfs(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002617{
David Howells88e67f32008-11-14 10:39:21 +11002618 const struct cred *cred = current_cred();
Thomas Liu2bf49692009-07-14 12:14:09 -04002619 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07002620 struct selinux_audit_data sad = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07002621
Eric Parisa2694342011-04-25 13:10:27 -04002622 COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
Eric Paris3b3b0e42012-04-03 09:37:02 -07002623 ad.selinux_audit_data = &sad;
Eric Parisa2694342011-04-25 13:10:27 -04002624 ad.u.dentry = dentry->d_sb->s_root;
David Howells88e67f32008-11-14 10:39:21 +11002625 return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002626}
2627
Al Viroddaa16d2012-10-11 11:42:01 -04002628static int selinux_mount(const char *dev_name,
Al Virob5266eb2008-03-22 17:48:24 -04002629 struct path *path,
Al Viroddaa16d2012-10-11 11:42:01 -04002630 const char *type,
Eric Paris828dfe12008-04-17 13:17:49 -04002631 unsigned long flags,
2632 void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002633{
David Howells88e67f32008-11-14 10:39:21 +11002634 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002635
2636 if (flags & MS_REMOUNT)
Al Virod8c95842011-12-07 18:16:57 -05002637 return superblock_has_perm(cred, path->dentry->d_sb,
Eric Paris828dfe12008-04-17 13:17:49 -04002638 FILESYSTEM__REMOUNT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002639 else
Eric Paris2875fa02011-04-28 16:04:24 -04002640 return path_has_perm(cred, path, FILE__MOUNTON);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002641}
2642
2643static int selinux_umount(struct vfsmount *mnt, int flags)
2644{
David Howells88e67f32008-11-14 10:39:21 +11002645 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002646
David Howells88e67f32008-11-14 10:39:21 +11002647 return superblock_has_perm(cred, mnt->mnt_sb,
Eric Paris828dfe12008-04-17 13:17:49 -04002648 FILESYSTEM__UNMOUNT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002649}
2650
2651/* inode security operations */
2652
2653static int selinux_inode_alloc_security(struct inode *inode)
2654{
2655 return inode_alloc_security(inode);
2656}
2657
2658static void selinux_inode_free_security(struct inode *inode)
2659{
2660 inode_free_security(inode);
2661}
2662
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002663static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
Eric Paris2a7dba32011-02-01 11:05:39 -05002664 const struct qstr *qstr, char **name,
2665 void **value, size_t *len)
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002666{
Paul Moore5fb49872010-04-22 14:46:19 -04002667 const struct task_security_struct *tsec = current_security();
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002668 struct inode_security_struct *dsec;
2669 struct superblock_security_struct *sbsec;
David Howells275bb412008-11-14 10:39:19 +11002670 u32 sid, newsid, clen;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002671 int rc;
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002672 char *namep = NULL, *context;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002673
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002674 dsec = dir->i_security;
2675 sbsec = dir->i_sb->s_security;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002676
David Howells275bb412008-11-14 10:39:19 +11002677 sid = tsec->sid;
2678 newsid = tsec->create_sid;
2679
Eric Paris415103f2010-12-02 16:13:40 -05002680 if ((sbsec->flags & SE_SBINITIALIZED) &&
2681 (sbsec->behavior == SECURITY_FS_USE_MNTPOINT))
2682 newsid = sbsec->mntpoint_sid;
2683 else if (!newsid || !(sbsec->flags & SE_SBLABELSUPP)) {
David Howells275bb412008-11-14 10:39:19 +11002684 rc = security_transition_sid(sid, dsec->sid,
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002685 inode_mode_to_security_class(inode->i_mode),
Eric Paris652bb9b2011-02-01 11:05:40 -05002686 qstr, &newsid);
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002687 if (rc) {
2688 printk(KERN_WARNING "%s: "
2689 "security_transition_sid failed, rc=%d (dev=%s "
2690 "ino=%ld)\n",
Harvey Harrisondd6f9532008-03-06 10:03:59 +11002691 __func__,
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002692 -rc, inode->i_sb->s_id, inode->i_ino);
2693 return rc;
2694 }
2695 }
2696
Eric Paris296fddf2006-09-25 23:32:00 -07002697 /* Possibly defer initialization to selinux_complete_init. */
David P. Quigley0d90a7e2009-01-16 09:22:02 -05002698 if (sbsec->flags & SE_SBINITIALIZED) {
Eric Paris296fddf2006-09-25 23:32:00 -07002699 struct inode_security_struct *isec = inode->i_security;
2700 isec->sclass = inode_mode_to_security_class(inode->i_mode);
2701 isec->sid = newsid;
2702 isec->initialized = 1;
2703 }
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002704
David P. Quigleycd895962009-01-16 09:22:04 -05002705 if (!ss_initialized || !(sbsec->flags & SE_SBLABELSUPP))
Stephen Smalley25a74f32005-11-08 21:34:33 -08002706 return -EOPNOTSUPP;
2707
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002708 if (name) {
Josef Bacika02fe132008-04-04 09:35:05 +11002709 namep = kstrdup(XATTR_SELINUX_SUFFIX, GFP_NOFS);
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002710 if (!namep)
2711 return -ENOMEM;
2712 *name = namep;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002713 }
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002714
2715 if (value && len) {
Stephen Smalley12b29f32008-05-07 13:03:20 -04002716 rc = security_sid_to_context_force(newsid, &context, &clen);
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002717 if (rc) {
2718 kfree(namep);
2719 return rc;
2720 }
2721 *value = context;
2722 *len = clen;
2723 }
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002724
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002725 return 0;
2726}
2727
Al Viro4acdaf22011-07-26 01:42:34 -04002728static int selinux_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002729{
Amir Samuelov6a22e462014-05-26 11:44:06 +03002730 int ret;
2731
2732 ret = pft_inode_create(dir, dentry, mode);
2733 if (ret < 0)
2734 return ret;
2735
Linus Torvalds1da177e2005-04-16 15:20:36 -07002736 return may_create(dir, dentry, SECCLASS_FILE);
2737}
2738
Amir Samuelov6a22e462014-05-26 11:44:06 +03002739static int selinux_inode_post_create(struct inode *dir, struct dentry *dentry,
2740 umode_t mode)
2741{
2742 int ret;
2743
2744 ret = pft_inode_post_create(dir, dentry, mode);
2745
2746 return ret;
2747}
2748
Linus Torvalds1da177e2005-04-16 15:20:36 -07002749static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
2750{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002751 return may_link(dir, old_dentry, MAY_LINK);
2752}
2753
Linus Torvalds1da177e2005-04-16 15:20:36 -07002754static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry)
2755{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002756 return may_link(dir, dentry, MAY_UNLINK);
2757}
2758
2759static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry, const char *name)
2760{
2761 return may_create(dir, dentry, SECCLASS_LNK_FILE);
2762}
2763
Al Viro18bb1db2011-07-26 01:41:39 -04002764static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry, umode_t mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002765{
2766 return may_create(dir, dentry, SECCLASS_DIR);
2767}
2768
Linus Torvalds1da177e2005-04-16 15:20:36 -07002769static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry)
2770{
2771 return may_link(dir, dentry, MAY_RMDIR);
2772}
2773
Al Viro1a67aaf2011-07-26 01:52:52 -04002774static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002775{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002776 return may_create(dir, dentry, inode_mode_to_security_class(mode));
2777}
2778
Linus Torvalds1da177e2005-04-16 15:20:36 -07002779static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
Eric Paris828dfe12008-04-17 13:17:49 -04002780 struct inode *new_inode, struct dentry *new_dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002781{
Amir Samuelov6a22e462014-05-26 11:44:06 +03002782 int rc;
2783
2784 rc = pft_inode_rename(old_inode, old_dentry, new_inode, new_dentry);
2785 if (rc)
2786 return rc;
2787
Linus Torvalds1da177e2005-04-16 15:20:36 -07002788 return may_rename(old_inode, old_dentry, new_inode, new_dentry);
2789}
2790
Linus Torvalds1da177e2005-04-16 15:20:36 -07002791static int selinux_inode_readlink(struct dentry *dentry)
2792{
David Howells88e67f32008-11-14 10:39:21 +11002793 const struct cred *cred = current_cred();
2794
Eric Paris2875fa02011-04-28 16:04:24 -04002795 return dentry_has_perm(cred, dentry, FILE__READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002796}
2797
2798static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *nameidata)
2799{
David Howells88e67f32008-11-14 10:39:21 +11002800 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002801
Eric Paris2875fa02011-04-28 16:04:24 -04002802 return dentry_has_perm(cred, dentry, FILE__READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002803}
2804
Al Viroe74f71e2011-06-20 19:38:15 -04002805static int selinux_inode_permission(struct inode *inode, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002806{
David Howells88e67f32008-11-14 10:39:21 +11002807 const struct cred *cred = current_cred();
Eric Parisb782e0a2010-07-23 11:44:03 -04002808 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07002809 struct selinux_audit_data sad = {0,};
Eric Parisb782e0a2010-07-23 11:44:03 -04002810 u32 perms;
2811 bool from_access;
Al Virocf1dd1d2011-06-20 19:44:08 -04002812 unsigned flags = mask & MAY_NOT_BLOCK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002813
Eric Parisb782e0a2010-07-23 11:44:03 -04002814 from_access = mask & MAY_ACCESS;
Eric Parisd09ca732010-07-23 11:43:57 -04002815 mask &= (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND);
2816
Eric Parisb782e0a2010-07-23 11:44:03 -04002817 /* No permission to check. Existence test. */
2818 if (!mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002819 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002820
Eric Parisf48b7392011-04-25 12:54:27 -04002821 COMMON_AUDIT_DATA_INIT(&ad, INODE);
Eric Paris3b3b0e42012-04-03 09:37:02 -07002822 ad.selinux_audit_data = &sad;
Eric Parisf48b7392011-04-25 12:54:27 -04002823 ad.u.inode = inode;
Eric Parisb782e0a2010-07-23 11:44:03 -04002824
2825 if (from_access)
Eric Paris3b3b0e42012-04-03 09:37:02 -07002826 ad.selinux_audit_data->auditdeny |= FILE__AUDIT_ACCESS;
Eric Parisb782e0a2010-07-23 11:44:03 -04002827
2828 perms = file_mask_to_av(inode->i_mode, mask);
2829
Eric Paris9ade0cf2011-04-25 16:26:29 -04002830 return inode_has_perm(cred, inode, perms, &ad, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002831}
2832
2833static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
2834{
David Howells88e67f32008-11-14 10:39:21 +11002835 const struct cred *cred = current_cred();
Amerigo Wangbc6a6002009-08-20 19:29:02 -07002836 unsigned int ia_valid = iattr->ia_valid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002837
Amerigo Wangbc6a6002009-08-20 19:29:02 -07002838 /* ATTR_FORCE is just used for ATTR_KILL_S[UG]ID. */
2839 if (ia_valid & ATTR_FORCE) {
2840 ia_valid &= ~(ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_MODE |
2841 ATTR_FORCE);
2842 if (!ia_valid)
2843 return 0;
2844 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002845
Amerigo Wangbc6a6002009-08-20 19:29:02 -07002846 if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID |
2847 ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_TIMES_SET))
Eric Paris2875fa02011-04-28 16:04:24 -04002848 return dentry_has_perm(cred, dentry, FILE__SETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002849
Eric Paris2875fa02011-04-28 16:04:24 -04002850 return dentry_has_perm(cred, dentry, FILE__WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002851}
2852
2853static int selinux_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
2854{
David Howells88e67f32008-11-14 10:39:21 +11002855 const struct cred *cred = current_cred();
Eric Paris2875fa02011-04-28 16:04:24 -04002856 struct path path;
David Howells88e67f32008-11-14 10:39:21 +11002857
Eric Paris2875fa02011-04-28 16:04:24 -04002858 path.dentry = dentry;
2859 path.mnt = mnt;
2860
2861 return path_has_perm(cred, &path, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002862}
2863
David Howells8f0cfa52008-04-29 00:59:41 -07002864static int selinux_inode_setotherxattr(struct dentry *dentry, const char *name)
Serge E. Hallynb5376772007-10-16 23:31:36 -07002865{
David Howells88e67f32008-11-14 10:39:21 +11002866 const struct cred *cred = current_cred();
2867
Amir Samuelov6a22e462014-05-26 11:44:06 +03002868 if (pft_inode_set_xattr(dentry, name) < 0)
2869 return -EACCES;
2870
2871
Serge E. Hallynb5376772007-10-16 23:31:36 -07002872 if (!strncmp(name, XATTR_SECURITY_PREFIX,
2873 sizeof XATTR_SECURITY_PREFIX - 1)) {
2874 if (!strcmp(name, XATTR_NAME_CAPS)) {
2875 if (!capable(CAP_SETFCAP))
2876 return -EPERM;
2877 } else if (!capable(CAP_SYS_ADMIN)) {
2878 /* A different attribute in the security namespace.
2879 Restrict to administrator. */
2880 return -EPERM;
2881 }
2882 }
2883
2884 /* Not an attribute we recognize, so just check the
2885 ordinary setattr permission. */
Eric Paris2875fa02011-04-28 16:04:24 -04002886 return dentry_has_perm(cred, dentry, FILE__SETATTR);
Serge E. Hallynb5376772007-10-16 23:31:36 -07002887}
2888
David Howells8f0cfa52008-04-29 00:59:41 -07002889static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
2890 const void *value, size_t size, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002891{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002892 struct inode *inode = dentry->d_inode;
2893 struct inode_security_struct *isec = inode->i_security;
2894 struct superblock_security_struct *sbsec;
Thomas Liu2bf49692009-07-14 12:14:09 -04002895 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07002896 struct selinux_audit_data sad = {0,};
David Howells275bb412008-11-14 10:39:19 +11002897 u32 newsid, sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002898 int rc = 0;
2899
Serge E. Hallynb5376772007-10-16 23:31:36 -07002900 if (strcmp(name, XATTR_NAME_SELINUX))
2901 return selinux_inode_setotherxattr(dentry, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002902
2903 sbsec = inode->i_sb->s_security;
David P. Quigleycd895962009-01-16 09:22:04 -05002904 if (!(sbsec->flags & SE_SBLABELSUPP))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002905 return -EOPNOTSUPP;
2906
Serge E. Hallyn2e149672011-03-23 16:43:26 -07002907 if (!inode_owner_or_capable(inode))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002908 return -EPERM;
2909
Eric Parisa2694342011-04-25 13:10:27 -04002910 COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
Eric Paris3b3b0e42012-04-03 09:37:02 -07002911 ad.selinux_audit_data = &sad;
Eric Parisa2694342011-04-25 13:10:27 -04002912 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002913
David Howells275bb412008-11-14 10:39:19 +11002914 rc = avc_has_perm(sid, isec->sid, isec->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002915 FILE__RELABELFROM, &ad);
2916 if (rc)
2917 return rc;
2918
2919 rc = security_context_to_sid(value, size, &newsid);
Stephen Smalley12b29f32008-05-07 13:03:20 -04002920 if (rc == -EINVAL) {
2921 if (!capable(CAP_MAC_ADMIN))
2922 return rc;
2923 rc = security_context_to_sid_force(value, size, &newsid);
2924 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002925 if (rc)
2926 return rc;
2927
David Howells275bb412008-11-14 10:39:19 +11002928 rc = avc_has_perm(sid, newsid, isec->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002929 FILE__RELABELTO, &ad);
2930 if (rc)
2931 return rc;
2932
David Howells275bb412008-11-14 10:39:19 +11002933 rc = security_validate_transition(isec->sid, newsid, sid,
Eric Paris828dfe12008-04-17 13:17:49 -04002934 isec->sclass);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002935 if (rc)
2936 return rc;
2937
2938 return avc_has_perm(newsid,
2939 sbsec->sid,
2940 SECCLASS_FILESYSTEM,
2941 FILESYSTEM__ASSOCIATE,
2942 &ad);
2943}
2944
David Howells8f0cfa52008-04-29 00:59:41 -07002945static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
Eric Parisf5269712008-05-14 11:27:45 -04002946 const void *value, size_t size,
David Howells8f0cfa52008-04-29 00:59:41 -07002947 int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002948{
2949 struct inode *inode = dentry->d_inode;
2950 struct inode_security_struct *isec = inode->i_security;
2951 u32 newsid;
2952 int rc;
2953
2954 if (strcmp(name, XATTR_NAME_SELINUX)) {
2955 /* Not an attribute we recognize, so nothing to do. */
2956 return;
2957 }
2958
Stephen Smalley12b29f32008-05-07 13:03:20 -04002959 rc = security_context_to_sid_force(value, size, &newsid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002960 if (rc) {
Stephen Smalley12b29f32008-05-07 13:03:20 -04002961 printk(KERN_ERR "SELinux: unable to map context to SID"
2962 "for (%s, %lu), rc=%d\n",
2963 inode->i_sb->s_id, inode->i_ino, -rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002964 return;
2965 }
2966
2967 isec->sid = newsid;
2968 return;
2969}
2970
David Howells8f0cfa52008-04-29 00:59:41 -07002971static int selinux_inode_getxattr(struct dentry *dentry, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002972{
David Howells88e67f32008-11-14 10:39:21 +11002973 const struct cred *cred = current_cred();
2974
Eric Paris2875fa02011-04-28 16:04:24 -04002975 return dentry_has_perm(cred, dentry, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002976}
2977
Eric Paris828dfe12008-04-17 13:17:49 -04002978static int selinux_inode_listxattr(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002979{
David Howells88e67f32008-11-14 10:39:21 +11002980 const struct cred *cred = current_cred();
2981
Eric Paris2875fa02011-04-28 16:04:24 -04002982 return dentry_has_perm(cred, dentry, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002983}
2984
David Howells8f0cfa52008-04-29 00:59:41 -07002985static int selinux_inode_removexattr(struct dentry *dentry, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002986{
Serge E. Hallynb5376772007-10-16 23:31:36 -07002987 if (strcmp(name, XATTR_NAME_SELINUX))
2988 return selinux_inode_setotherxattr(dentry, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002989
2990 /* No one is allowed to remove a SELinux security label.
2991 You can change the label, but all data must be labeled. */
2992 return -EACCES;
2993}
2994
James Morrisd381d8a2005-10-30 14:59:22 -08002995/*
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04002996 * Copy the inode security context value to the user.
James Morrisd381d8a2005-10-30 14:59:22 -08002997 *
2998 * Permission check is handled by selinux_inode_getxattr hook.
2999 */
David P. Quigley42492592008-02-04 22:29:39 -08003000static int selinux_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003001{
David P. Quigley42492592008-02-04 22:29:39 -08003002 u32 size;
3003 int error;
3004 char *context = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003005 struct inode_security_struct *isec = inode->i_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003006
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00003007 if (strcmp(name, XATTR_SELINUX_SUFFIX))
3008 return -EOPNOTSUPP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003009
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04003010 /*
3011 * If the caller has CAP_MAC_ADMIN, then get the raw context
3012 * value even if it is not defined by current policy; otherwise,
3013 * use the in-core value under current policy.
3014 * Use the non-auditing forms of the permission checks since
3015 * getxattr may be called by unprivileged processes commonly
3016 * and lack of permission just means that we fall back to the
3017 * in-core context value, not a denial.
3018 */
Eric Paris6a9de492012-01-03 12:25:14 -05003019 error = selinux_capable(current_cred(), &init_user_ns, CAP_MAC_ADMIN,
David Howells3699c532009-01-06 22:27:01 +00003020 SECURITY_CAP_NOAUDIT);
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04003021 if (!error)
3022 error = security_sid_to_context_force(isec->sid, &context,
3023 &size);
3024 else
3025 error = security_sid_to_context(isec->sid, &context, &size);
David P. Quigley42492592008-02-04 22:29:39 -08003026 if (error)
3027 return error;
3028 error = size;
3029 if (alloc) {
3030 *buffer = context;
3031 goto out_nofree;
3032 }
3033 kfree(context);
3034out_nofree:
3035 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003036}
3037
3038static int selinux_inode_setsecurity(struct inode *inode, const char *name,
Eric Paris828dfe12008-04-17 13:17:49 -04003039 const void *value, size_t size, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003040{
3041 struct inode_security_struct *isec = inode->i_security;
3042 u32 newsid;
3043 int rc;
3044
3045 if (strcmp(name, XATTR_SELINUX_SUFFIX))
3046 return -EOPNOTSUPP;
3047
3048 if (!value || !size)
3049 return -EACCES;
3050
Eric Paris828dfe12008-04-17 13:17:49 -04003051 rc = security_context_to_sid((void *)value, size, &newsid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003052 if (rc)
3053 return rc;
3054
3055 isec->sid = newsid;
David P. Quigleyddd29ec2009-09-09 14:25:37 -04003056 isec->initialized = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003057 return 0;
3058}
3059
3060static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size)
3061{
3062 const int len = sizeof(XATTR_NAME_SELINUX);
3063 if (buffer && len <= buffer_size)
3064 memcpy(buffer, XATTR_NAME_SELINUX, len);
3065 return len;
3066}
3067
Ahmed S. Darwish713a04a2008-03-01 21:52:30 +02003068static void selinux_inode_getsecid(const struct inode *inode, u32 *secid)
3069{
3070 struct inode_security_struct *isec = inode->i_security;
3071 *secid = isec->sid;
3072}
3073
Linus Torvalds1da177e2005-04-16 15:20:36 -07003074/* file security operations */
3075
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003076static int selinux_revalidate_file_permission(struct file *file, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003077{
David Howells88e67f32008-11-14 10:39:21 +11003078 const struct cred *cred = current_cred();
Josef Sipek3d5ff522006-12-08 02:37:38 -08003079 struct inode *inode = file->f_path.dentry->d_inode;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003080
Linus Torvalds1da177e2005-04-16 15:20:36 -07003081 /* file_mask_to_av won't add FILE__WRITE if MAY_APPEND is set */
3082 if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE))
3083 mask |= MAY_APPEND;
3084
Paul Moore389fb802009-03-27 17:10:34 -04003085 return file_has_perm(cred, file,
3086 file_mask_to_av(inode->i_mode, mask));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003087}
3088
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003089static int selinux_file_permission(struct file *file, int mask)
3090{
Stephen Smalley20dda182009-06-22 14:54:53 -04003091 struct inode *inode = file->f_path.dentry->d_inode;
3092 struct file_security_struct *fsec = file->f_security;
3093 struct inode_security_struct *isec = inode->i_security;
3094 u32 sid = current_sid();
Amir Samuelov6a22e462014-05-26 11:44:06 +03003095 int ret;
Stephen Smalley20dda182009-06-22 14:54:53 -04003096
Paul Moore389fb802009-03-27 17:10:34 -04003097 if (!mask)
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003098 /* No permission to check. Existence test. */
3099 return 0;
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003100
Amir Samuelov6a22e462014-05-26 11:44:06 +03003101 ret = pft_file_permission(file, mask);
3102 if (ret < 0)
3103 return ret;
3104
Stephen Smalley20dda182009-06-22 14:54:53 -04003105 if (sid == fsec->sid && fsec->isid == isec->sid &&
3106 fsec->pseqno == avc_policy_seqno())
3107 /* No change since dentry_open check. */
3108 return 0;
3109
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003110 return selinux_revalidate_file_permission(file, mask);
3111}
3112
Linus Torvalds1da177e2005-04-16 15:20:36 -07003113static int selinux_file_alloc_security(struct file *file)
3114{
3115 return file_alloc_security(file);
3116}
3117
3118static void selinux_file_free_security(struct file *file)
3119{
3120 file_free_security(file);
3121}
3122
Jeff Vander Stoep581be712015-07-10 17:19:56 -04003123/*
3124 * Check whether a task has the ioctl permission and cmd
3125 * operation to an inode.
3126 */
3127int ioctl_has_perm(const struct cred *cred, struct file *file,
3128 u32 requested, u16 cmd)
3129{
3130 struct common_audit_data ad;
3131 struct file_security_struct *fsec = file->f_security;
3132 struct inode *inode = file->f_path.dentry->d_inode;
3133 struct inode_security_struct *isec = inode->i_security;
3134 struct lsm_ioctlop_audit ioctl;
3135 u32 ssid = cred_sid(cred);
3136 struct selinux_audit_data sad = {0,};
3137 int rc;
3138 u8 driver = cmd >> 8;
3139 u8 xperm = cmd & 0xff;
3140
3141 COMMON_AUDIT_DATA_INIT(&ad, IOCTL_OP);
3142 ad.u.op = &ioctl;
3143 ad.u.op->cmd = cmd;
3144 ad.selinux_audit_data = &sad;
3145 ad.u.op->path = file->f_path;
3146
3147 if (ssid != fsec->sid) {
3148 rc = avc_has_perm(ssid, fsec->sid,
3149 SECCLASS_FD,
3150 FD__USE,
3151 &ad);
3152 if (rc)
3153 goto out;
3154 }
3155
3156 if (unlikely(IS_PRIVATE(inode)))
3157 return 0;
3158
3159 rc = avc_has_extended_perms(ssid, isec->sid, isec->sclass,
3160 requested, driver, xperm, &ad);
3161out:
3162 return rc;
3163}
3164
Linus Torvalds1da177e2005-04-16 15:20:36 -07003165static int selinux_file_ioctl(struct file *file, unsigned int cmd,
3166 unsigned long arg)
3167{
David Howells88e67f32008-11-14 10:39:21 +11003168 const struct cred *cred = current_cred();
Eric Paris0b24dcb2011-02-25 15:39:20 -05003169 int error = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003170
Eric Paris0b24dcb2011-02-25 15:39:20 -05003171 switch (cmd) {
3172 case FIONREAD:
3173 /* fall through */
3174 case FIBMAP:
3175 /* fall through */
3176 case FIGETBSZ:
3177 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003178 case FS_IOC_GETFLAGS:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003179 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003180 case FS_IOC_GETVERSION:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003181 error = file_has_perm(cred, file, FILE__GETATTR);
3182 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003183
Al Viro2f99c362012-03-23 16:04:05 -04003184 case FS_IOC_SETFLAGS:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003185 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003186 case FS_IOC_SETVERSION:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003187 error = file_has_perm(cred, file, FILE__SETATTR);
3188 break;
3189
3190 /* sys_ioctl() checks */
3191 case FIONBIO:
3192 /* fall through */
3193 case FIOASYNC:
3194 error = file_has_perm(cred, file, 0);
3195 break;
3196
3197 case KDSKBENT:
3198 case KDSKBSENT:
Eric Paris6a9de492012-01-03 12:25:14 -05003199 error = cred_has_capability(cred, CAP_SYS_TTY_CONFIG,
3200 SECURITY_CAP_AUDIT);
Eric Paris0b24dcb2011-02-25 15:39:20 -05003201 break;
3202
3203 /* default case assumes that the command will go
3204 * to the file's ioctl() function.
3205 */
3206 default:
Jeff Vander Stoep581be712015-07-10 17:19:56 -04003207 error = ioctl_has_perm(cred, file, FILE__IOCTL, (u16) cmd);
Eric Paris0b24dcb2011-02-25 15:39:20 -05003208 }
3209 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003210}
3211
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003212static int default_noexec;
3213
Linus Torvalds1da177e2005-04-16 15:20:36 -07003214static int file_map_prot_check(struct file *file, unsigned long prot, int shared)
3215{
David Howells88e67f32008-11-14 10:39:21 +11003216 const struct cred *cred = current_cred();
David Howellsd84f4f92008-11-14 10:39:23 +11003217 int rc = 0;
David Howells88e67f32008-11-14 10:39:21 +11003218
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003219 if (default_noexec &&
3220 (prot & PROT_EXEC) && (!file || (!shared && (prot & PROT_WRITE)))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003221 /*
3222 * We are making executable an anonymous mapping or a
3223 * private file mapping that will also be writable.
3224 * This has an additional check.
3225 */
David Howellsd84f4f92008-11-14 10:39:23 +11003226 rc = cred_has_perm(cred, cred, PROCESS__EXECMEM);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003227 if (rc)
David Howellsd84f4f92008-11-14 10:39:23 +11003228 goto error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003229 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003230
3231 if (file) {
3232 /* read access is always possible with a mapping */
3233 u32 av = FILE__READ;
3234
3235 /* write access only matters if the mapping is shared */
3236 if (shared && (prot & PROT_WRITE))
3237 av |= FILE__WRITE;
3238
3239 if (prot & PROT_EXEC)
3240 av |= FILE__EXECUTE;
3241
David Howells88e67f32008-11-14 10:39:21 +11003242 return file_has_perm(cred, file, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003243 }
David Howellsd84f4f92008-11-14 10:39:23 +11003244
3245error:
3246 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003247}
3248
3249static int selinux_file_mmap(struct file *file, unsigned long reqprot,
Eric Parised032182007-06-28 15:55:21 -04003250 unsigned long prot, unsigned long flags,
3251 unsigned long addr, unsigned long addr_only)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003252{
Eric Parised032182007-06-28 15:55:21 -04003253 int rc = 0;
David Howells275bb412008-11-14 10:39:19 +11003254 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003255
Eric Paris84336d1a2009-07-31 12:54:05 -04003256 /*
3257 * notice that we are intentionally putting the SELinux check before
3258 * the secondary cap_file_mmap check. This is such a likely attempt
3259 * at bad behaviour/exploit that we always want to get the AVC, even
3260 * if DAC would have also denied the operation.
3261 */
Eric Parisa2551df2009-07-31 12:54:11 -04003262 if (addr < CONFIG_LSM_MMAP_MIN_ADDR) {
Eric Parised032182007-06-28 15:55:21 -04003263 rc = avc_has_perm(sid, sid, SECCLASS_MEMPROTECT,
3264 MEMPROTECT__MMAP_ZERO, NULL);
Eric Paris84336d1a2009-07-31 12:54:05 -04003265 if (rc)
3266 return rc;
3267 }
3268
3269 /* do DAC check on address space usage */
3270 rc = cap_file_mmap(file, reqprot, prot, flags, addr, addr_only);
Eric Parised032182007-06-28 15:55:21 -04003271 if (rc || addr_only)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003272 return rc;
3273
3274 if (selinux_checkreqprot)
3275 prot = reqprot;
3276
3277 return file_map_prot_check(file, prot,
3278 (flags & MAP_TYPE) == MAP_SHARED);
3279}
3280
3281static int selinux_file_mprotect(struct vm_area_struct *vma,
3282 unsigned long reqprot,
3283 unsigned long prot)
3284{
David Howells88e67f32008-11-14 10:39:21 +11003285 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003286
3287 if (selinux_checkreqprot)
3288 prot = reqprot;
3289
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003290 if (default_noexec &&
3291 (prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) {
James Morrisd541bbe2009-01-29 12:19:51 +11003292 int rc = 0;
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003293 if (vma->vm_start >= vma->vm_mm->start_brk &&
3294 vma->vm_end <= vma->vm_mm->brk) {
David Howellsd84f4f92008-11-14 10:39:23 +11003295 rc = cred_has_perm(cred, cred, PROCESS__EXECHEAP);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003296 } else if (!vma->vm_file &&
3297 vma->vm_start <= vma->vm_mm->start_stack &&
3298 vma->vm_end >= vma->vm_mm->start_stack) {
David Howells3b11a1d2008-11-14 10:39:26 +11003299 rc = current_has_perm(current, PROCESS__EXECSTACK);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003300 } else if (vma->vm_file && vma->anon_vma) {
3301 /*
3302 * We are making executable a file mapping that has
3303 * had some COW done. Since pages might have been
3304 * written, check ability to execute the possibly
3305 * modified content. This typically should only
3306 * occur for text relocations.
3307 */
David Howellsd84f4f92008-11-14 10:39:23 +11003308 rc = file_has_perm(cred, vma->vm_file, FILE__EXECMOD);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003309 }
Lorenzo Hernandez García-Hierro6b992192005-06-25 14:54:34 -07003310 if (rc)
3311 return rc;
3312 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003313
3314 return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED);
3315}
3316
3317static int selinux_file_lock(struct file *file, unsigned int cmd)
3318{
David Howells88e67f32008-11-14 10:39:21 +11003319 const struct cred *cred = current_cred();
3320
3321 return file_has_perm(cred, file, FILE__LOCK);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003322}
3323
3324static int selinux_file_fcntl(struct file *file, unsigned int cmd,
3325 unsigned long arg)
3326{
David Howells88e67f32008-11-14 10:39:21 +11003327 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003328 int err = 0;
3329
3330 switch (cmd) {
Eric Paris828dfe12008-04-17 13:17:49 -04003331 case F_SETFL:
3332 if (!file->f_path.dentry || !file->f_path.dentry->d_inode) {
3333 err = -EINVAL;
3334 break;
3335 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003336
Eric Paris828dfe12008-04-17 13:17:49 -04003337 if ((file->f_flags & O_APPEND) && !(arg & O_APPEND)) {
David Howells88e67f32008-11-14 10:39:21 +11003338 err = file_has_perm(cred, file, FILE__WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003339 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003340 }
3341 /* fall through */
3342 case F_SETOWN:
3343 case F_SETSIG:
3344 case F_GETFL:
3345 case F_GETOWN:
3346 case F_GETSIG:
3347 /* Just check FD__USE permission */
David Howells88e67f32008-11-14 10:39:21 +11003348 err = file_has_perm(cred, file, 0);
Eric Paris828dfe12008-04-17 13:17:49 -04003349 break;
3350 case F_GETLK:
3351 case F_SETLK:
3352 case F_SETLKW:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003353#if BITS_PER_LONG == 32
Eric Paris828dfe12008-04-17 13:17:49 -04003354 case F_GETLK64:
3355 case F_SETLK64:
3356 case F_SETLKW64:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003357#endif
Eric Paris828dfe12008-04-17 13:17:49 -04003358 if (!file->f_path.dentry || !file->f_path.dentry->d_inode) {
3359 err = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003360 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003361 }
David Howells88e67f32008-11-14 10:39:21 +11003362 err = file_has_perm(cred, file, FILE__LOCK);
Eric Paris828dfe12008-04-17 13:17:49 -04003363 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003364 }
3365
3366 return err;
3367}
3368
3369static int selinux_file_set_fowner(struct file *file)
3370{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003371 struct file_security_struct *fsec;
3372
Linus Torvalds1da177e2005-04-16 15:20:36 -07003373 fsec = file->f_security;
David Howells275bb412008-11-14 10:39:19 +11003374 fsec->fown_sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003375
3376 return 0;
3377}
3378
3379static int selinux_file_send_sigiotask(struct task_struct *tsk,
3380 struct fown_struct *fown, int signum)
3381{
Eric Paris828dfe12008-04-17 13:17:49 -04003382 struct file *file;
Stephen Smalley65c90bc2009-05-04 15:43:18 -04003383 u32 sid = task_sid(tsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003384 u32 perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003385 struct file_security_struct *fsec;
3386
3387 /* struct fown_struct is never outside the context of a struct file */
Eric Paris828dfe12008-04-17 13:17:49 -04003388 file = container_of(fown, struct file, f_owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003389
Linus Torvalds1da177e2005-04-16 15:20:36 -07003390 fsec = file->f_security;
3391
3392 if (!signum)
3393 perm = signal_to_av(SIGIO); /* as per send_sigio_to_task */
3394 else
3395 perm = signal_to_av(signum);
3396
David Howells275bb412008-11-14 10:39:19 +11003397 return avc_has_perm(fsec->fown_sid, sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003398 SECCLASS_PROCESS, perm, NULL);
3399}
3400
3401static int selinux_file_receive(struct file *file)
3402{
David Howells88e67f32008-11-14 10:39:21 +11003403 const struct cred *cred = current_cred();
3404
3405 return file_has_perm(cred, file, file_to_av(file));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003406}
3407
David Howells745ca242008-11-14 10:39:22 +11003408static int selinux_dentry_open(struct file *file, const struct cred *cred)
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003409{
3410 struct file_security_struct *fsec;
3411 struct inode *inode;
3412 struct inode_security_struct *isec;
Amir Samuelov6a22e462014-05-26 11:44:06 +03003413 int ret;
3414
3415 ret = pft_file_open(file, cred);
3416 if (ret < 0)
3417 return ret;
David Howellsd84f4f92008-11-14 10:39:23 +11003418
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003419 inode = file->f_path.dentry->d_inode;
3420 fsec = file->f_security;
3421 isec = inode->i_security;
3422 /*
3423 * Save inode label and policy sequence number
3424 * at open-time so that selinux_file_permission
3425 * can determine whether revalidation is necessary.
3426 * Task label is already saved in the file security
3427 * struct as its SID.
3428 */
3429 fsec->isid = isec->sid;
3430 fsec->pseqno = avc_policy_seqno();
3431 /*
3432 * Since the inode label or policy seqno may have changed
3433 * between the selinux_inode_permission check and the saving
3434 * of state above, recheck that access is still permitted.
3435 * Otherwise, access might never be revalidated against the
3436 * new inode label or new policy.
3437 * This check is not redundant - do not remove.
3438 */
Linus Torvalds95f4efb2011-06-08 15:11:56 -07003439 return inode_has_perm_noadp(cred, inode, open_file_to_av(file), 0);
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003440}
3441
Amir Samuelov6a22e462014-05-26 11:44:06 +03003442static int selinux_file_close(struct file *file)
3443{
3444 return pft_file_close(file);
3445}
3446
3447static bool selinux_allow_merge_bio(struct bio *bio1, struct bio *bio2)
3448{
3449 return pft_allow_merge_bio(bio1, bio2);
3450}
3451
Linus Torvalds1da177e2005-04-16 15:20:36 -07003452/* task security operations */
3453
3454static int selinux_task_create(unsigned long clone_flags)
3455{
David Howells3b11a1d2008-11-14 10:39:26 +11003456 return current_has_perm(current, PROCESS__FORK);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003457}
3458
David Howellsf1752ee2008-11-14 10:39:17 +11003459/*
David Howellsee18d642009-09-02 09:14:21 +01003460 * allocate the SELinux part of blank credentials
3461 */
3462static int selinux_cred_alloc_blank(struct cred *cred, gfp_t gfp)
3463{
3464 struct task_security_struct *tsec;
3465
3466 tsec = kzalloc(sizeof(struct task_security_struct), gfp);
3467 if (!tsec)
3468 return -ENOMEM;
3469
3470 cred->security = tsec;
3471 return 0;
3472}
3473
3474/*
David Howellsf1752ee2008-11-14 10:39:17 +11003475 * detach and free the LSM part of a set of credentials
3476 */
3477static void selinux_cred_free(struct cred *cred)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003478{
David Howellsf1752ee2008-11-14 10:39:17 +11003479 struct task_security_struct *tsec = cred->security;
David Howellse0e81732009-09-02 09:13:40 +01003480
Tetsuo Handa2edeaa32011-02-07 13:36:10 +00003481 /*
3482 * cred->security == NULL if security_cred_alloc_blank() or
3483 * security_prepare_creds() returned an error.
3484 */
3485 BUG_ON(cred->security && (unsigned long) cred->security < PAGE_SIZE);
David Howellse0e81732009-09-02 09:13:40 +01003486 cred->security = (void *) 0x7UL;
David Howellsf1752ee2008-11-14 10:39:17 +11003487 kfree(tsec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003488}
3489
David Howellsd84f4f92008-11-14 10:39:23 +11003490/*
3491 * prepare a new set of credentials for modification
3492 */
3493static int selinux_cred_prepare(struct cred *new, const struct cred *old,
3494 gfp_t gfp)
3495{
3496 const struct task_security_struct *old_tsec;
3497 struct task_security_struct *tsec;
3498
3499 old_tsec = old->security;
3500
3501 tsec = kmemdup(old_tsec, sizeof(struct task_security_struct), gfp);
3502 if (!tsec)
3503 return -ENOMEM;
3504
3505 new->security = tsec;
3506 return 0;
3507}
3508
3509/*
David Howellsee18d642009-09-02 09:14:21 +01003510 * transfer the SELinux data to a blank set of creds
3511 */
3512static void selinux_cred_transfer(struct cred *new, const struct cred *old)
3513{
3514 const struct task_security_struct *old_tsec = old->security;
3515 struct task_security_struct *tsec = new->security;
3516
3517 *tsec = *old_tsec;
3518}
3519
3520/*
David Howells3a3b7ce2008-11-14 10:39:28 +11003521 * set the security data for a kernel service
3522 * - all the creation contexts are set to unlabelled
3523 */
3524static int selinux_kernel_act_as(struct cred *new, u32 secid)
3525{
3526 struct task_security_struct *tsec = new->security;
3527 u32 sid = current_sid();
3528 int ret;
3529
3530 ret = avc_has_perm(sid, secid,
3531 SECCLASS_KERNEL_SERVICE,
3532 KERNEL_SERVICE__USE_AS_OVERRIDE,
3533 NULL);
3534 if (ret == 0) {
3535 tsec->sid = secid;
3536 tsec->create_sid = 0;
3537 tsec->keycreate_sid = 0;
3538 tsec->sockcreate_sid = 0;
3539 }
3540 return ret;
3541}
3542
3543/*
3544 * set the file creation context in a security record to the same as the
3545 * objective context of the specified inode
3546 */
3547static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode)
3548{
3549 struct inode_security_struct *isec = inode->i_security;
3550 struct task_security_struct *tsec = new->security;
3551 u32 sid = current_sid();
3552 int ret;
3553
3554 ret = avc_has_perm(sid, isec->sid,
3555 SECCLASS_KERNEL_SERVICE,
3556 KERNEL_SERVICE__CREATE_FILES_AS,
3557 NULL);
3558
3559 if (ret == 0)
3560 tsec->create_sid = isec->sid;
David Howellsef574712010-02-26 01:56:16 +00003561 return ret;
David Howells3a3b7ce2008-11-14 10:39:28 +11003562}
3563
Eric Parisdd8dbf22009-11-03 16:35:32 +11003564static int selinux_kernel_module_request(char *kmod_name)
Eric Paris25354c42009-08-13 09:45:03 -04003565{
Eric Parisdd8dbf22009-11-03 16:35:32 +11003566 u32 sid;
3567 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07003568 struct selinux_audit_data sad = {0,};
Eric Parisdd8dbf22009-11-03 16:35:32 +11003569
3570 sid = task_sid(current);
3571
3572 COMMON_AUDIT_DATA_INIT(&ad, KMOD);
Eric Paris3b3b0e42012-04-03 09:37:02 -07003573 ad.selinux_audit_data = &sad;
Eric Parisdd8dbf22009-11-03 16:35:32 +11003574 ad.u.kmod_name = kmod_name;
3575
3576 return avc_has_perm(sid, SECINITSID_KERNEL, SECCLASS_SYSTEM,
3577 SYSTEM__MODULE_REQUEST, &ad);
Eric Paris25354c42009-08-13 09:45:03 -04003578}
3579
Linus Torvalds1da177e2005-04-16 15:20:36 -07003580static int selinux_task_setpgid(struct task_struct *p, pid_t pgid)
3581{
David Howells3b11a1d2008-11-14 10:39:26 +11003582 return current_has_perm(p, PROCESS__SETPGID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003583}
3584
3585static int selinux_task_getpgid(struct task_struct *p)
3586{
David Howells3b11a1d2008-11-14 10:39:26 +11003587 return current_has_perm(p, PROCESS__GETPGID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003588}
3589
3590static int selinux_task_getsid(struct task_struct *p)
3591{
David Howells3b11a1d2008-11-14 10:39:26 +11003592 return current_has_perm(p, PROCESS__GETSESSION);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003593}
3594
David Quigleyf9008e42006-06-30 01:55:46 -07003595static void selinux_task_getsecid(struct task_struct *p, u32 *secid)
3596{
David Howells275bb412008-11-14 10:39:19 +11003597 *secid = task_sid(p);
David Quigleyf9008e42006-06-30 01:55:46 -07003598}
3599
Linus Torvalds1da177e2005-04-16 15:20:36 -07003600static int selinux_task_setnice(struct task_struct *p, int nice)
3601{
3602 int rc;
3603
Eric Paris200ac532009-02-12 15:01:04 -05003604 rc = cap_task_setnice(p, nice);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003605 if (rc)
3606 return rc;
3607
David Howells3b11a1d2008-11-14 10:39:26 +11003608 return current_has_perm(p, PROCESS__SETSCHED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003609}
3610
James Morris03e68062006-06-23 02:03:58 -07003611static int selinux_task_setioprio(struct task_struct *p, int ioprio)
3612{
Serge E. Hallynb5376772007-10-16 23:31:36 -07003613 int rc;
3614
Eric Paris200ac532009-02-12 15:01:04 -05003615 rc = cap_task_setioprio(p, ioprio);
Serge E. Hallynb5376772007-10-16 23:31:36 -07003616 if (rc)
3617 return rc;
3618
David Howells3b11a1d2008-11-14 10:39:26 +11003619 return current_has_perm(p, PROCESS__SETSCHED);
James Morris03e68062006-06-23 02:03:58 -07003620}
3621
David Quigleya1836a42006-06-30 01:55:49 -07003622static int selinux_task_getioprio(struct task_struct *p)
3623{
David Howells3b11a1d2008-11-14 10:39:26 +11003624 return current_has_perm(p, PROCESS__GETSCHED);
David Quigleya1836a42006-06-30 01:55:49 -07003625}
3626
Jiri Slaby8fd00b42009-08-26 18:41:16 +02003627static int selinux_task_setrlimit(struct task_struct *p, unsigned int resource,
3628 struct rlimit *new_rlim)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003629{
Jiri Slaby8fd00b42009-08-26 18:41:16 +02003630 struct rlimit *old_rlim = p->signal->rlim + resource;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003631
3632 /* Control the ability to change the hard limit (whether
3633 lowering or raising it), so that the hard limit can
3634 later be used as a safe reset point for the soft limit
David Howellsd84f4f92008-11-14 10:39:23 +11003635 upon context transitions. See selinux_bprm_committing_creds. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003636 if (old_rlim->rlim_max != new_rlim->rlim_max)
Jiri Slaby8fd00b42009-08-26 18:41:16 +02003637 return current_has_perm(p, PROCESS__SETRLIMIT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003638
3639 return 0;
3640}
3641
KOSAKI Motohirob0ae1982010-10-15 04:21:18 +09003642static int selinux_task_setscheduler(struct task_struct *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003643{
Serge E. Hallynb5376772007-10-16 23:31:36 -07003644 int rc;
3645
KOSAKI Motohirob0ae1982010-10-15 04:21:18 +09003646 rc = cap_task_setscheduler(p);
Serge E. Hallynb5376772007-10-16 23:31:36 -07003647 if (rc)
3648 return rc;
3649
David Howells3b11a1d2008-11-14 10:39:26 +11003650 return current_has_perm(p, PROCESS__SETSCHED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003651}
3652
3653static int selinux_task_getscheduler(struct task_struct *p)
3654{
David Howells3b11a1d2008-11-14 10:39:26 +11003655 return current_has_perm(p, PROCESS__GETSCHED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003656}
3657
David Quigley35601542006-06-23 02:04:01 -07003658static int selinux_task_movememory(struct task_struct *p)
3659{
David Howells3b11a1d2008-11-14 10:39:26 +11003660 return current_has_perm(p, PROCESS__SETSCHED);
David Quigley35601542006-06-23 02:04:01 -07003661}
3662
David Quigleyf9008e42006-06-30 01:55:46 -07003663static int selinux_task_kill(struct task_struct *p, struct siginfo *info,
3664 int sig, u32 secid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003665{
3666 u32 perm;
3667 int rc;
3668
Linus Torvalds1da177e2005-04-16 15:20:36 -07003669 if (!sig)
3670 perm = PROCESS__SIGNULL; /* null signal; existence test */
3671 else
3672 perm = signal_to_av(sig);
David Quigleyf9008e42006-06-30 01:55:46 -07003673 if (secid)
David Howells275bb412008-11-14 10:39:19 +11003674 rc = avc_has_perm(secid, task_sid(p),
3675 SECCLASS_PROCESS, perm, NULL);
David Quigleyf9008e42006-06-30 01:55:46 -07003676 else
David Howells3b11a1d2008-11-14 10:39:26 +11003677 rc = current_has_perm(p, perm);
David Quigleyf9008e42006-06-30 01:55:46 -07003678 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003679}
3680
Linus Torvalds1da177e2005-04-16 15:20:36 -07003681static int selinux_task_wait(struct task_struct *p)
3682{
Eric Paris8a535142007-10-22 16:10:31 -04003683 return task_has_perm(p, current, PROCESS__SIGCHLD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003684}
3685
Linus Torvalds1da177e2005-04-16 15:20:36 -07003686static void selinux_task_to_inode(struct task_struct *p,
3687 struct inode *inode)
3688{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003689 struct inode_security_struct *isec = inode->i_security;
David Howells275bb412008-11-14 10:39:19 +11003690 u32 sid = task_sid(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003691
David Howells275bb412008-11-14 10:39:19 +11003692 isec->sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003693 isec->initialized = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003694}
3695
Linus Torvalds1da177e2005-04-16 15:20:36 -07003696/* Returns error only if unable to parse addresses */
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003697static int selinux_parse_skb_ipv4(struct sk_buff *skb,
Thomas Liu2bf49692009-07-14 12:14:09 -04003698 struct common_audit_data *ad, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003699{
3700 int offset, ihlen, ret = -EINVAL;
3701 struct iphdr _iph, *ih;
3702
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03003703 offset = skb_network_offset(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003704 ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph);
3705 if (ih == NULL)
3706 goto out;
3707
3708 ihlen = ih->ihl * 4;
3709 if (ihlen < sizeof(_iph))
3710 goto out;
3711
Eric Paris48c62af2012-04-02 13:15:44 -04003712 ad->u.net->v4info.saddr = ih->saddr;
3713 ad->u.net->v4info.daddr = ih->daddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003714 ret = 0;
3715
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003716 if (proto)
3717 *proto = ih->protocol;
3718
Linus Torvalds1da177e2005-04-16 15:20:36 -07003719 switch (ih->protocol) {
Eric Paris828dfe12008-04-17 13:17:49 -04003720 case IPPROTO_TCP: {
3721 struct tcphdr _tcph, *th;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003722
Eric Paris828dfe12008-04-17 13:17:49 -04003723 if (ntohs(ih->frag_off) & IP_OFFSET)
3724 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003725
3726 offset += ihlen;
3727 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
3728 if (th == NULL)
3729 break;
3730
Eric Paris48c62af2012-04-02 13:15:44 -04003731 ad->u.net->sport = th->source;
3732 ad->u.net->dport = th->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003733 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003734 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003735
Eric Paris828dfe12008-04-17 13:17:49 -04003736 case IPPROTO_UDP: {
3737 struct udphdr _udph, *uh;
3738
3739 if (ntohs(ih->frag_off) & IP_OFFSET)
3740 break;
3741
3742 offset += ihlen;
3743 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
3744 if (uh == NULL)
3745 break;
3746
Eric Paris48c62af2012-04-02 13:15:44 -04003747 ad->u.net->sport = uh->source;
3748 ad->u.net->dport = uh->dest;
Eric Paris828dfe12008-04-17 13:17:49 -04003749 break;
3750 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003751
James Morris2ee92d42006-11-13 16:09:01 -08003752 case IPPROTO_DCCP: {
3753 struct dccp_hdr _dccph, *dh;
3754
3755 if (ntohs(ih->frag_off) & IP_OFFSET)
3756 break;
3757
3758 offset += ihlen;
3759 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
3760 if (dh == NULL)
3761 break;
3762
Eric Paris48c62af2012-04-02 13:15:44 -04003763 ad->u.net->sport = dh->dccph_sport;
3764 ad->u.net->dport = dh->dccph_dport;
James Morris2ee92d42006-11-13 16:09:01 -08003765 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003766 }
James Morris2ee92d42006-11-13 16:09:01 -08003767
Eric Paris828dfe12008-04-17 13:17:49 -04003768 default:
3769 break;
3770 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003771out:
3772 return ret;
3773}
3774
3775#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
3776
3777/* Returns error only if unable to parse addresses */
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003778static int selinux_parse_skb_ipv6(struct sk_buff *skb,
Thomas Liu2bf49692009-07-14 12:14:09 -04003779 struct common_audit_data *ad, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003780{
3781 u8 nexthdr;
3782 int ret = -EINVAL, offset;
3783 struct ipv6hdr _ipv6h, *ip6;
Jesse Gross75f28112011-11-30 17:05:51 -08003784 __be16 frag_off;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003785
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03003786 offset = skb_network_offset(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003787 ip6 = skb_header_pointer(skb, offset, sizeof(_ipv6h), &_ipv6h);
3788 if (ip6 == NULL)
3789 goto out;
3790
Eric Paris48c62af2012-04-02 13:15:44 -04003791 ad->u.net->v6info.saddr = ip6->saddr;
3792 ad->u.net->v6info.daddr = ip6->daddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003793 ret = 0;
3794
3795 nexthdr = ip6->nexthdr;
3796 offset += sizeof(_ipv6h);
Jesse Gross75f28112011-11-30 17:05:51 -08003797 offset = ipv6_skip_exthdr(skb, offset, &nexthdr, &frag_off);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003798 if (offset < 0)
3799 goto out;
3800
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003801 if (proto)
3802 *proto = nexthdr;
3803
Linus Torvalds1da177e2005-04-16 15:20:36 -07003804 switch (nexthdr) {
3805 case IPPROTO_TCP: {
Eric Paris828dfe12008-04-17 13:17:49 -04003806 struct tcphdr _tcph, *th;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003807
3808 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
3809 if (th == NULL)
3810 break;
3811
Eric Paris48c62af2012-04-02 13:15:44 -04003812 ad->u.net->sport = th->source;
3813 ad->u.net->dport = th->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003814 break;
3815 }
3816
3817 case IPPROTO_UDP: {
3818 struct udphdr _udph, *uh;
3819
3820 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
3821 if (uh == NULL)
3822 break;
3823
Eric Paris48c62af2012-04-02 13:15:44 -04003824 ad->u.net->sport = uh->source;
3825 ad->u.net->dport = uh->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003826 break;
3827 }
3828
James Morris2ee92d42006-11-13 16:09:01 -08003829 case IPPROTO_DCCP: {
3830 struct dccp_hdr _dccph, *dh;
3831
3832 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
3833 if (dh == NULL)
3834 break;
3835
Eric Paris48c62af2012-04-02 13:15:44 -04003836 ad->u.net->sport = dh->dccph_sport;
3837 ad->u.net->dport = dh->dccph_dport;
James Morris2ee92d42006-11-13 16:09:01 -08003838 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003839 }
James Morris2ee92d42006-11-13 16:09:01 -08003840
Linus Torvalds1da177e2005-04-16 15:20:36 -07003841 /* includes fragments */
3842 default:
3843 break;
3844 }
3845out:
3846 return ret;
3847}
3848
3849#endif /* IPV6 */
3850
Thomas Liu2bf49692009-07-14 12:14:09 -04003851static int selinux_parse_skb(struct sk_buff *skb, struct common_audit_data *ad,
David Howellscf9481e2008-07-27 21:31:07 +10003852 char **_addrp, int src, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003853{
David Howellscf9481e2008-07-27 21:31:07 +10003854 char *addrp;
3855 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003856
Eric Paris48c62af2012-04-02 13:15:44 -04003857 switch (ad->u.net->family) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003858 case PF_INET:
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003859 ret = selinux_parse_skb_ipv4(skb, ad, proto);
David Howellscf9481e2008-07-27 21:31:07 +10003860 if (ret)
3861 goto parse_error;
Eric Paris48c62af2012-04-02 13:15:44 -04003862 addrp = (char *)(src ? &ad->u.net->v4info.saddr :
3863 &ad->u.net->v4info.daddr);
David Howellscf9481e2008-07-27 21:31:07 +10003864 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003865
3866#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
3867 case PF_INET6:
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003868 ret = selinux_parse_skb_ipv6(skb, ad, proto);
David Howellscf9481e2008-07-27 21:31:07 +10003869 if (ret)
3870 goto parse_error;
Eric Paris48c62af2012-04-02 13:15:44 -04003871 addrp = (char *)(src ? &ad->u.net->v6info.saddr :
3872 &ad->u.net->v6info.daddr);
David Howellscf9481e2008-07-27 21:31:07 +10003873 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003874#endif /* IPV6 */
3875 default:
David Howellscf9481e2008-07-27 21:31:07 +10003876 addrp = NULL;
3877 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003878 }
3879
David Howellscf9481e2008-07-27 21:31:07 +10003880parse_error:
3881 printk(KERN_WARNING
3882 "SELinux: failure in selinux_parse_skb(),"
3883 " unable to parse packet\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003884 return ret;
David Howellscf9481e2008-07-27 21:31:07 +10003885
3886okay:
3887 if (_addrp)
3888 *_addrp = addrp;
3889 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003890}
3891
Paul Moore4f6a9932007-03-01 14:35:22 -05003892/**
Paul Moore220deb92008-01-29 08:38:23 -05003893 * selinux_skb_peerlbl_sid - Determine the peer label of a packet
Paul Moore4f6a9932007-03-01 14:35:22 -05003894 * @skb: the packet
Paul Moore75e22912008-01-29 08:38:04 -05003895 * @family: protocol family
Paul Moore220deb92008-01-29 08:38:23 -05003896 * @sid: the packet's peer label SID
Paul Moore4f6a9932007-03-01 14:35:22 -05003897 *
3898 * Description:
Paul Moore220deb92008-01-29 08:38:23 -05003899 * Check the various different forms of network peer labeling and determine
3900 * the peer label/SID for the packet; most of the magic actually occurs in
3901 * the security server function security_net_peersid_cmp(). The function
3902 * returns zero if the value in @sid is valid (although it may be SECSID_NULL)
3903 * or -EACCES if @sid is invalid due to inconsistencies with the different
3904 * peer labels.
Paul Moore4f6a9932007-03-01 14:35:22 -05003905 *
3906 */
Paul Moore220deb92008-01-29 08:38:23 -05003907static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)
Paul Moore4f6a9932007-03-01 14:35:22 -05003908{
Paul Moore71f1cb02008-01-29 08:51:16 -05003909 int err;
Paul Moore4f6a9932007-03-01 14:35:22 -05003910 u32 xfrm_sid;
3911 u32 nlbl_sid;
Paul Moore220deb92008-01-29 08:38:23 -05003912 u32 nlbl_type;
Paul Moore4f6a9932007-03-01 14:35:22 -05003913
3914 selinux_skb_xfrm_sid(skb, &xfrm_sid);
Paul Moore5dbe1eb2008-01-29 08:44:18 -05003915 selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid);
Paul Moore220deb92008-01-29 08:38:23 -05003916
Paul Moore71f1cb02008-01-29 08:51:16 -05003917 err = security_net_peersid_resolve(nlbl_sid, nlbl_type, xfrm_sid, sid);
3918 if (unlikely(err)) {
3919 printk(KERN_WARNING
3920 "SELinux: failure in selinux_skb_peerlbl_sid(),"
3921 " unable to determine packet's peer label\n");
Paul Moore220deb92008-01-29 08:38:23 -05003922 return -EACCES;
Paul Moore71f1cb02008-01-29 08:51:16 -05003923 }
Paul Moore220deb92008-01-29 08:38:23 -05003924
3925 return 0;
Paul Moore4f6a9932007-03-01 14:35:22 -05003926}
3927
Linus Torvalds1da177e2005-04-16 15:20:36 -07003928/* socket security operations */
Paul Moored4f2d972010-04-22 14:46:18 -04003929
Harry Ciao2ad18bd2011-03-02 13:32:34 +08003930static int socket_sockcreate_sid(const struct task_security_struct *tsec,
3931 u16 secclass, u32 *socksid)
Paul Moored4f2d972010-04-22 14:46:18 -04003932{
Harry Ciao2ad18bd2011-03-02 13:32:34 +08003933 if (tsec->sockcreate_sid > SECSID_NULL) {
3934 *socksid = tsec->sockcreate_sid;
3935 return 0;
3936 }
3937
3938 return security_transition_sid(tsec->sid, tsec->sid, secclass, NULL,
3939 socksid);
Paul Moored4f2d972010-04-22 14:46:18 -04003940}
3941
Paul Moore253bfae2010-04-22 14:46:19 -04003942static int sock_has_perm(struct task_struct *task, struct sock *sk, u32 perms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003943{
Paul Moore253bfae2010-04-22 14:46:19 -04003944 struct sk_security_struct *sksec = sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04003945 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07003946 struct selinux_audit_data sad = {0,};
Eric Paris48c62af2012-04-02 13:15:44 -04003947 struct lsm_network_audit net = {0,};
Paul Moore253bfae2010-04-22 14:46:19 -04003948 u32 tsid = task_sid(task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003949
Satya Durga Srinivasu Prabhala90280652013-09-24 15:23:48 -07003950 if (unlikely(!sksec)) {
3951 pr_warn("SELinux: sksec is NULL, socket is already freed\n");
3952 return -EINVAL;
3953 }
3954
Paul Moore253bfae2010-04-22 14:46:19 -04003955 if (sksec->sid == SECINITSID_KERNEL)
3956 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003957
Thomas Liu2bf49692009-07-14 12:14:09 -04003958 COMMON_AUDIT_DATA_INIT(&ad, NET);
Eric Paris3b3b0e42012-04-03 09:37:02 -07003959 ad.selinux_audit_data = &sad;
Eric Paris48c62af2012-04-02 13:15:44 -04003960 ad.u.net = &net;
3961 ad.u.net->sk = sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003962
Paul Moore253bfae2010-04-22 14:46:19 -04003963 return avc_has_perm(tsid, sksec->sid, sksec->sclass, perms, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003964}
3965
3966static int selinux_socket_create(int family, int type,
3967 int protocol, int kern)
3968{
Paul Moore5fb49872010-04-22 14:46:19 -04003969 const struct task_security_struct *tsec = current_security();
Paul Moored4f2d972010-04-22 14:46:18 -04003970 u32 newsid;
David Howells275bb412008-11-14 10:39:19 +11003971 u16 secclass;
Harry Ciao2ad18bd2011-03-02 13:32:34 +08003972 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003973
3974 if (kern)
Paul Moored4f2d972010-04-22 14:46:18 -04003975 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003976
David Howells275bb412008-11-14 10:39:19 +11003977 secclass = socket_type_to_security_class(family, type, protocol);
Harry Ciao2ad18bd2011-03-02 13:32:34 +08003978 rc = socket_sockcreate_sid(tsec, secclass, &newsid);
3979 if (rc)
3980 return rc;
3981
Paul Moored4f2d972010-04-22 14:46:18 -04003982 return avc_has_perm(tsec->sid, newsid, secclass, SOCKET__CREATE, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003983}
3984
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07003985static int selinux_socket_post_create(struct socket *sock, int family,
3986 int type, int protocol, int kern)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003987{
Paul Moore5fb49872010-04-22 14:46:19 -04003988 const struct task_security_struct *tsec = current_security();
Paul Moored4f2d972010-04-22 14:46:18 -04003989 struct inode_security_struct *isec = SOCK_INODE(sock)->i_security;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07003990 struct sk_security_struct *sksec;
David Howells275bb412008-11-14 10:39:19 +11003991 int err = 0;
3992
Harry Ciao2ad18bd2011-03-02 13:32:34 +08003993 isec->sclass = socket_type_to_security_class(family, type, protocol);
3994
David Howells275bb412008-11-14 10:39:19 +11003995 if (kern)
3996 isec->sid = SECINITSID_KERNEL;
Harry Ciao2ad18bd2011-03-02 13:32:34 +08003997 else {
3998 err = socket_sockcreate_sid(tsec, isec->sclass, &(isec->sid));
3999 if (err)
4000 return err;
4001 }
David Howells275bb412008-11-14 10:39:19 +11004002
Linus Torvalds1da177e2005-04-16 15:20:36 -07004003 isec->initialized = 1;
4004
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004005 if (sock->sk) {
4006 sksec = sock->sk->sk_security;
4007 sksec->sid = isec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05004008 sksec->sclass = isec->sclass;
Paul Moore389fb802009-03-27 17:10:34 -04004009 err = selinux_netlbl_socket_post_create(sock->sk, family);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004010 }
4011
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07004012 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004013}
4014
4015/* Range of port numbers used to automatically bind.
4016 Need to determine whether we should perform a name_bind
4017 permission check between the socket and the port number. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004018
4019static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen)
4020{
Paul Moore253bfae2010-04-22 14:46:19 -04004021 struct sock *sk = sock->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004022 u16 family;
4023 int err;
4024
Paul Moore253bfae2010-04-22 14:46:19 -04004025 err = sock_has_perm(current, sk, SOCKET__BIND);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004026 if (err)
4027 goto out;
4028
4029 /*
4030 * If PF_INET or PF_INET6, check name_bind permission for the port.
James Morris13402582005-09-30 14:24:34 -04004031 * Multiple address binding for SCTP is not supported yet: we just
4032 * check the first address now.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004033 */
Paul Moore253bfae2010-04-22 14:46:19 -04004034 family = sk->sk_family;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004035 if (family == PF_INET || family == PF_INET6) {
4036 char *addrp;
Paul Moore253bfae2010-04-22 14:46:19 -04004037 struct sk_security_struct *sksec = sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004038 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07004039 struct selinux_audit_data sad = {0,};
Eric Paris48c62af2012-04-02 13:15:44 -04004040 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004041 struct sockaddr_in *addr4 = NULL;
4042 struct sockaddr_in6 *addr6 = NULL;
4043 unsigned short snum;
James Morrise399f982008-06-12 01:39:58 +10004044 u32 sid, node_perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004045
Linus Torvalds1da177e2005-04-16 15:20:36 -07004046 if (family == PF_INET) {
4047 addr4 = (struct sockaddr_in *)address;
4048 snum = ntohs(addr4->sin_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004049 addrp = (char *)&addr4->sin_addr.s_addr;
4050 } else {
4051 addr6 = (struct sockaddr_in6 *)address;
4052 snum = ntohs(addr6->sin6_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004053 addrp = (char *)&addr6->sin6_addr.s6_addr;
4054 }
4055
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004056 if (snum) {
4057 int low, high;
4058
4059 inet_get_local_port_range(&low, &high);
4060
4061 if (snum < max(PROT_SOCK, low) || snum > high) {
Paul Moore3e112172008-04-10 10:48:14 -04004062 err = sel_netport_sid(sk->sk_protocol,
4063 snum, &sid);
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004064 if (err)
4065 goto out;
Thomas Liu2bf49692009-07-14 12:14:09 -04004066 COMMON_AUDIT_DATA_INIT(&ad, NET);
Eric Paris3b3b0e42012-04-03 09:37:02 -07004067 ad.selinux_audit_data = &sad;
Eric Paris48c62af2012-04-02 13:15:44 -04004068 ad.u.net = &net;
4069 ad.u.net->sport = htons(snum);
4070 ad.u.net->family = family;
Paul Moore253bfae2010-04-22 14:46:19 -04004071 err = avc_has_perm(sksec->sid, sid,
4072 sksec->sclass,
Stephen Hemminger227b60f2007-10-10 17:30:46 -07004073 SOCKET__NAME_BIND, &ad);
4074 if (err)
4075 goto out;
4076 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004077 }
Eric Paris828dfe12008-04-17 13:17:49 -04004078
Paul Moore253bfae2010-04-22 14:46:19 -04004079 switch (sksec->sclass) {
James Morris13402582005-09-30 14:24:34 -04004080 case SECCLASS_TCP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004081 node_perm = TCP_SOCKET__NODE_BIND;
4082 break;
Eric Paris828dfe12008-04-17 13:17:49 -04004083
James Morris13402582005-09-30 14:24:34 -04004084 case SECCLASS_UDP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004085 node_perm = UDP_SOCKET__NODE_BIND;
4086 break;
James Morris2ee92d42006-11-13 16:09:01 -08004087
4088 case SECCLASS_DCCP_SOCKET:
4089 node_perm = DCCP_SOCKET__NODE_BIND;
4090 break;
4091
Linus Torvalds1da177e2005-04-16 15:20:36 -07004092 default:
4093 node_perm = RAWIP_SOCKET__NODE_BIND;
4094 break;
4095 }
Eric Paris828dfe12008-04-17 13:17:49 -04004096
Paul Moore224dfbd2008-01-29 08:38:13 -05004097 err = sel_netnode_sid(addrp, family, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004098 if (err)
4099 goto out;
Eric Paris828dfe12008-04-17 13:17:49 -04004100
Thomas Liu2bf49692009-07-14 12:14:09 -04004101 COMMON_AUDIT_DATA_INIT(&ad, NET);
Eric Paris3b3b0e42012-04-03 09:37:02 -07004102 ad.selinux_audit_data = &sad;
Eric Paris48c62af2012-04-02 13:15:44 -04004103 ad.u.net = &net;
4104 ad.u.net->sport = htons(snum);
4105 ad.u.net->family = family;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004106
4107 if (family == PF_INET)
Eric Paris48c62af2012-04-02 13:15:44 -04004108 ad.u.net->v4info.saddr = addr4->sin_addr.s_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004109 else
Eric Paris48c62af2012-04-02 13:15:44 -04004110 ad.u.net->v6info.saddr = addr6->sin6_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004111
Paul Moore253bfae2010-04-22 14:46:19 -04004112 err = avc_has_perm(sksec->sid, sid,
4113 sksec->sclass, node_perm, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004114 if (err)
4115 goto out;
4116 }
4117out:
4118 return err;
4119}
4120
4121static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen)
4122{
Paul Moore014ab192008-10-10 10:16:33 -04004123 struct sock *sk = sock->sk;
Paul Moore253bfae2010-04-22 14:46:19 -04004124 struct sk_security_struct *sksec = sk->sk_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004125 int err;
4126
Paul Moore253bfae2010-04-22 14:46:19 -04004127 err = sock_has_perm(current, sk, SOCKET__CONNECT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004128 if (err)
4129 return err;
4130
4131 /*
James Morris2ee92d42006-11-13 16:09:01 -08004132 * If a TCP or DCCP socket, check name_connect permission for the port.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004133 */
Paul Moore253bfae2010-04-22 14:46:19 -04004134 if (sksec->sclass == SECCLASS_TCP_SOCKET ||
4135 sksec->sclass == SECCLASS_DCCP_SOCKET) {
Thomas Liu2bf49692009-07-14 12:14:09 -04004136 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07004137 struct selinux_audit_data sad = {0,};
Eric Paris48c62af2012-04-02 13:15:44 -04004138 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004139 struct sockaddr_in *addr4 = NULL;
4140 struct sockaddr_in6 *addr6 = NULL;
4141 unsigned short snum;
James Morris2ee92d42006-11-13 16:09:01 -08004142 u32 sid, perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004143
4144 if (sk->sk_family == PF_INET) {
4145 addr4 = (struct sockaddr_in *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07004146 if (addrlen < sizeof(struct sockaddr_in))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004147 return -EINVAL;
4148 snum = ntohs(addr4->sin_port);
4149 } else {
4150 addr6 = (struct sockaddr_in6 *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07004151 if (addrlen < SIN6_LEN_RFC2133)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004152 return -EINVAL;
4153 snum = ntohs(addr6->sin6_port);
4154 }
4155
Paul Moore3e112172008-04-10 10:48:14 -04004156 err = sel_netport_sid(sk->sk_protocol, snum, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004157 if (err)
4158 goto out;
4159
Paul Moore253bfae2010-04-22 14:46:19 -04004160 perm = (sksec->sclass == SECCLASS_TCP_SOCKET) ?
James Morris2ee92d42006-11-13 16:09:01 -08004161 TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT;
4162
Thomas Liu2bf49692009-07-14 12:14:09 -04004163 COMMON_AUDIT_DATA_INIT(&ad, NET);
Eric Paris3b3b0e42012-04-03 09:37:02 -07004164 ad.selinux_audit_data = &sad;
Eric Paris48c62af2012-04-02 13:15:44 -04004165 ad.u.net = &net;
4166 ad.u.net->dport = htons(snum);
4167 ad.u.net->family = sk->sk_family;
Paul Moore253bfae2010-04-22 14:46:19 -04004168 err = avc_has_perm(sksec->sid, sid, sksec->sclass, perm, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004169 if (err)
4170 goto out;
4171 }
4172
Paul Moore014ab192008-10-10 10:16:33 -04004173 err = selinux_netlbl_socket_connect(sk, address);
4174
Linus Torvalds1da177e2005-04-16 15:20:36 -07004175out:
4176 return err;
4177}
4178
4179static int selinux_socket_listen(struct socket *sock, int backlog)
4180{
Paul Moore253bfae2010-04-22 14:46:19 -04004181 return sock_has_perm(current, sock->sk, SOCKET__LISTEN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004182}
4183
4184static int selinux_socket_accept(struct socket *sock, struct socket *newsock)
4185{
4186 int err;
4187 struct inode_security_struct *isec;
4188 struct inode_security_struct *newisec;
4189
Paul Moore253bfae2010-04-22 14:46:19 -04004190 err = sock_has_perm(current, sock->sk, SOCKET__ACCEPT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004191 if (err)
4192 return err;
4193
4194 newisec = SOCK_INODE(newsock)->i_security;
4195
4196 isec = SOCK_INODE(sock)->i_security;
4197 newisec->sclass = isec->sclass;
4198 newisec->sid = isec->sid;
4199 newisec->initialized = 1;
4200
4201 return 0;
4202}
4203
4204static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg,
Eric Paris828dfe12008-04-17 13:17:49 -04004205 int size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004206{
Paul Moore253bfae2010-04-22 14:46:19 -04004207 return sock_has_perm(current, sock->sk, SOCKET__WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004208}
4209
4210static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg,
4211 int size, int flags)
4212{
Paul Moore253bfae2010-04-22 14:46:19 -04004213 return sock_has_perm(current, sock->sk, SOCKET__READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004214}
4215
4216static int selinux_socket_getsockname(struct socket *sock)
4217{
Paul Moore253bfae2010-04-22 14:46:19 -04004218 return sock_has_perm(current, sock->sk, SOCKET__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004219}
4220
4221static int selinux_socket_getpeername(struct socket *sock)
4222{
Paul Moore253bfae2010-04-22 14:46:19 -04004223 return sock_has_perm(current, sock->sk, SOCKET__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004224}
4225
Eric Paris828dfe12008-04-17 13:17:49 -04004226static int selinux_socket_setsockopt(struct socket *sock, int level, int optname)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004227{
Paul Mooref8687af2006-10-30 15:22:15 -08004228 int err;
4229
Paul Moore253bfae2010-04-22 14:46:19 -04004230 err = sock_has_perm(current, sock->sk, SOCKET__SETOPT);
Paul Mooref8687af2006-10-30 15:22:15 -08004231 if (err)
4232 return err;
4233
4234 return selinux_netlbl_socket_setsockopt(sock, level, optname);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004235}
4236
4237static int selinux_socket_getsockopt(struct socket *sock, int level,
4238 int optname)
4239{
Paul Moore253bfae2010-04-22 14:46:19 -04004240 return sock_has_perm(current, sock->sk, SOCKET__GETOPT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004241}
4242
4243static int selinux_socket_shutdown(struct socket *sock, int how)
4244{
Paul Moore253bfae2010-04-22 14:46:19 -04004245 return sock_has_perm(current, sock->sk, SOCKET__SHUTDOWN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004246}
4247
David S. Miller3610cda2011-01-05 15:38:53 -08004248static int selinux_socket_unix_stream_connect(struct sock *sock,
4249 struct sock *other,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004250 struct sock *newsk)
4251{
David S. Miller3610cda2011-01-05 15:38:53 -08004252 struct sk_security_struct *sksec_sock = sock->sk_security;
4253 struct sk_security_struct *sksec_other = other->sk_security;
Paul Moore4d1e2452010-04-22 14:46:18 -04004254 struct sk_security_struct *sksec_new = newsk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004255 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07004256 struct selinux_audit_data sad = {0,};
Eric Paris48c62af2012-04-02 13:15:44 -04004257 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004258 int err;
4259
Thomas Liu2bf49692009-07-14 12:14:09 -04004260 COMMON_AUDIT_DATA_INIT(&ad, NET);
Eric Paris3b3b0e42012-04-03 09:37:02 -07004261 ad.selinux_audit_data = &sad;
Eric Paris48c62af2012-04-02 13:15:44 -04004262 ad.u.net = &net;
4263 ad.u.net->sk = other;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004264
Paul Moore4d1e2452010-04-22 14:46:18 -04004265 err = avc_has_perm(sksec_sock->sid, sksec_other->sid,
4266 sksec_other->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004267 UNIX_STREAM_SOCKET__CONNECTTO, &ad);
4268 if (err)
4269 return err;
4270
Linus Torvalds1da177e2005-04-16 15:20:36 -07004271 /* server child socket */
Paul Moore4d1e2452010-04-22 14:46:18 -04004272 sksec_new->peer_sid = sksec_sock->sid;
4273 err = security_sid_mls_copy(sksec_other->sid, sksec_sock->sid,
4274 &sksec_new->sid);
4275 if (err)
4276 return err;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004277
Paul Moore4d1e2452010-04-22 14:46:18 -04004278 /* connecting socket */
4279 sksec_sock->peer_sid = sksec_new->sid;
4280
4281 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004282}
4283
4284static int selinux_socket_unix_may_send(struct socket *sock,
4285 struct socket *other)
4286{
Paul Moore253bfae2010-04-22 14:46:19 -04004287 struct sk_security_struct *ssec = sock->sk->sk_security;
4288 struct sk_security_struct *osec = other->sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004289 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07004290 struct selinux_audit_data sad = {0,};
Eric Paris48c62af2012-04-02 13:15:44 -04004291 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004292
Thomas Liu2bf49692009-07-14 12:14:09 -04004293 COMMON_AUDIT_DATA_INIT(&ad, NET);
Eric Paris3b3b0e42012-04-03 09:37:02 -07004294 ad.selinux_audit_data = &sad;
Eric Paris48c62af2012-04-02 13:15:44 -04004295 ad.u.net = &net;
4296 ad.u.net->sk = other->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004297
Paul Moore253bfae2010-04-22 14:46:19 -04004298 return avc_has_perm(ssec->sid, osec->sid, osec->sclass, SOCKET__SENDTO,
4299 &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004300}
4301
Paul Mooreeffad8d2008-01-29 08:49:27 -05004302static int selinux_inet_sys_rcv_skb(int ifindex, char *addrp, u16 family,
4303 u32 peer_sid,
Thomas Liu2bf49692009-07-14 12:14:09 -04004304 struct common_audit_data *ad)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004305{
4306 int err;
4307 u32 if_sid;
4308 u32 node_sid;
4309
4310 err = sel_netif_sid(ifindex, &if_sid);
4311 if (err)
4312 return err;
4313 err = avc_has_perm(peer_sid, if_sid,
4314 SECCLASS_NETIF, NETIF__INGRESS, ad);
4315 if (err)
4316 return err;
4317
4318 err = sel_netnode_sid(addrp, family, &node_sid);
4319 if (err)
4320 return err;
4321 return avc_has_perm(peer_sid, node_sid,
4322 SECCLASS_NODE, NODE__RECVFROM, ad);
4323}
4324
Paul Moore220deb92008-01-29 08:38:23 -05004325static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
Paul Moored8395c82008-10-10 10:16:30 -04004326 u16 family)
Paul Moore220deb92008-01-29 08:38:23 -05004327{
Paul Moore277d3422008-12-31 12:54:11 -05004328 int err = 0;
Paul Moore220deb92008-01-29 08:38:23 -05004329 struct sk_security_struct *sksec = sk->sk_security;
Paul Moore220deb92008-01-29 08:38:23 -05004330 u32 sk_sid = sksec->sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04004331 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07004332 struct selinux_audit_data sad = {0,};
Eric Paris48c62af2012-04-02 13:15:44 -04004333 struct lsm_network_audit net = {0,};
Paul Moored8395c82008-10-10 10:16:30 -04004334 char *addrp;
4335
Thomas Liu2bf49692009-07-14 12:14:09 -04004336 COMMON_AUDIT_DATA_INIT(&ad, NET);
Eric Paris3b3b0e42012-04-03 09:37:02 -07004337 ad.selinux_audit_data = &sad;
Eric Paris48c62af2012-04-02 13:15:44 -04004338 ad.u.net = &net;
4339 ad.u.net->netif = skb->skb_iif;
4340 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04004341 err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
4342 if (err)
4343 return err;
Paul Moore220deb92008-01-29 08:38:23 -05004344
Paul Moore58bfbb52009-03-27 17:10:41 -04004345 if (selinux_secmark_enabled()) {
Paul Moore220deb92008-01-29 08:38:23 -05004346 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
Paul Moored8395c82008-10-10 10:16:30 -04004347 PACKET__RECV, &ad);
Paul Moore58bfbb52009-03-27 17:10:41 -04004348 if (err)
4349 return err;
4350 }
Paul Moore220deb92008-01-29 08:38:23 -05004351
Steffen Klassertb9679a72011-02-23 12:55:21 +01004352 err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, &ad);
4353 if (err)
4354 return err;
4355 err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, &ad);
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004356
James Morris4e5ab4c2006-06-09 00:33:33 -07004357 return err;
4358}
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004359
James Morris4e5ab4c2006-06-09 00:33:33 -07004360static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
4361{
Paul Moore220deb92008-01-29 08:38:23 -05004362 int err;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004363 struct sk_security_struct *sksec = sk->sk_security;
Paul Moore220deb92008-01-29 08:38:23 -05004364 u16 family = sk->sk_family;
4365 u32 sk_sid = sksec->sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04004366 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07004367 struct selinux_audit_data sad = {0,};
Eric Paris48c62af2012-04-02 13:15:44 -04004368 struct lsm_network_audit net = {0,};
Paul Moore220deb92008-01-29 08:38:23 -05004369 char *addrp;
Paul Moored8395c82008-10-10 10:16:30 -04004370 u8 secmark_active;
4371 u8 peerlbl_active;
James Morris4e5ab4c2006-06-09 00:33:33 -07004372
James Morris4e5ab4c2006-06-09 00:33:33 -07004373 if (family != PF_INET && family != PF_INET6)
Paul Moore220deb92008-01-29 08:38:23 -05004374 return 0;
James Morris4e5ab4c2006-06-09 00:33:33 -07004375
4376 /* Handle mapped IPv4 packets arriving via IPv6 sockets */
Al Viro87fcd702006-12-04 22:00:55 +00004377 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
James Morris4e5ab4c2006-06-09 00:33:33 -07004378 family = PF_INET;
4379
Paul Moored8395c82008-10-10 10:16:30 -04004380 /* If any sort of compatibility mode is enabled then handoff processing
4381 * to the selinux_sock_rcv_skb_compat() function to deal with the
4382 * special handling. We do this in an attempt to keep this function
4383 * as fast and as clean as possible. */
Paul Moore58bfbb52009-03-27 17:10:41 -04004384 if (!selinux_policycap_netpeer)
Paul Moored8395c82008-10-10 10:16:30 -04004385 return selinux_sock_rcv_skb_compat(sk, skb, family);
4386
4387 secmark_active = selinux_secmark_enabled();
4388 peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled();
4389 if (!secmark_active && !peerlbl_active)
4390 return 0;
4391
Thomas Liu2bf49692009-07-14 12:14:09 -04004392 COMMON_AUDIT_DATA_INIT(&ad, NET);
Eric Paris3b3b0e42012-04-03 09:37:02 -07004393 ad.selinux_audit_data = &sad;
Eric Paris48c62af2012-04-02 13:15:44 -04004394 ad.u.net = &net;
4395 ad.u.net->netif = skb->skb_iif;
4396 ad.u.net->family = family;
Paul Moore224dfbd2008-01-29 08:38:13 -05004397 err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
James Morris4e5ab4c2006-06-09 00:33:33 -07004398 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05004399 return err;
James Morris4e5ab4c2006-06-09 00:33:33 -07004400
Paul Moored8395c82008-10-10 10:16:30 -04004401 if (peerlbl_active) {
Paul Moored621d352008-01-29 08:43:36 -05004402 u32 peer_sid;
4403
4404 err = selinux_skb_peerlbl_sid(skb, family, &peer_sid);
4405 if (err)
4406 return err;
Eric Dumazet8964be42009-11-20 15:35:04 -08004407 err = selinux_inet_sys_rcv_skb(skb->skb_iif, addrp, family,
Paul Mooreeffad8d2008-01-29 08:49:27 -05004408 peer_sid, &ad);
Paul Mooredfaebe92008-10-10 10:16:31 -04004409 if (err) {
4410 selinux_netlbl_err(skb, err, 0);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004411 return err;
Paul Mooredfaebe92008-10-10 10:16:31 -04004412 }
Paul Moored621d352008-01-29 08:43:36 -05004413 err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER,
4414 PEER__RECV, &ad);
Paul Mooredfaebe92008-10-10 10:16:31 -04004415 if (err)
4416 selinux_netlbl_err(skb, err, 0);
Paul Moored621d352008-01-29 08:43:36 -05004417 }
4418
Paul Moored8395c82008-10-10 10:16:30 -04004419 if (secmark_active) {
Paul Mooreeffad8d2008-01-29 08:49:27 -05004420 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
4421 PACKET__RECV, &ad);
4422 if (err)
4423 return err;
4424 }
4425
Paul Moored621d352008-01-29 08:43:36 -05004426 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004427}
4428
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004429static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *optval,
4430 int __user *optlen, unsigned len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004431{
4432 int err = 0;
4433 char *scontext;
4434 u32 scontext_len;
Paul Moore253bfae2010-04-22 14:46:19 -04004435 struct sk_security_struct *sksec = sock->sk->sk_security;
Paul Moore3de4bab2006-11-17 17:38:54 -05004436 u32 peer_sid = SECSID_NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004437
Paul Moore253bfae2010-04-22 14:46:19 -04004438 if (sksec->sclass == SECCLASS_UNIX_STREAM_SOCKET ||
4439 sksec->sclass == SECCLASS_TCP_SOCKET)
Eric Parisdd3e7832010-04-07 15:08:46 -04004440 peer_sid = sksec->peer_sid;
Paul Moore253bfae2010-04-22 14:46:19 -04004441 if (peer_sid == SECSID_NULL)
4442 return -ENOPROTOOPT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004443
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004444 err = security_sid_to_context(peer_sid, &scontext, &scontext_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004445 if (err)
Paul Moore253bfae2010-04-22 14:46:19 -04004446 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004447
4448 if (scontext_len > len) {
4449 err = -ERANGE;
4450 goto out_len;
4451 }
4452
4453 if (copy_to_user(optval, scontext, scontext_len))
4454 err = -EFAULT;
4455
4456out_len:
4457 if (put_user(scontext_len, optlen))
4458 err = -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004459 kfree(scontext);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004460 return err;
4461}
4462
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004463static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid)
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004464{
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004465 u32 peer_secid = SECSID_NULL;
Paul Moore75e22912008-01-29 08:38:04 -05004466 u16 family;
Catherine Zhang877ce7c2006-06-29 12:27:47 -07004467
Paul Mooreaa862902008-10-10 10:16:29 -04004468 if (skb && skb->protocol == htons(ETH_P_IP))
4469 family = PF_INET;
4470 else if (skb && skb->protocol == htons(ETH_P_IPV6))
4471 family = PF_INET6;
4472 else if (sock)
Paul Moore75e22912008-01-29 08:38:04 -05004473 family = sock->sk->sk_family;
Paul Moore75e22912008-01-29 08:38:04 -05004474 else
4475 goto out;
4476
4477 if (sock && family == PF_UNIX)
Ahmed S. Darwish713a04a2008-03-01 21:52:30 +02004478 selinux_inode_getsecid(SOCK_INODE(sock), &peer_secid);
Paul Moore3de4bab2006-11-17 17:38:54 -05004479 else if (skb)
Paul Moore220deb92008-01-29 08:38:23 -05004480 selinux_skb_peerlbl_sid(skb, family, &peer_secid);
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004481
Paul Moore75e22912008-01-29 08:38:04 -05004482out:
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004483 *secid = peer_secid;
Paul Moore75e22912008-01-29 08:38:04 -05004484 if (peer_secid == SECSID_NULL)
4485 return -EINVAL;
4486 return 0;
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004487}
4488
Al Viro7d877f32005-10-21 03:20:43 -04004489static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004490{
Paul Moore84914b72010-04-22 14:46:18 -04004491 struct sk_security_struct *sksec;
4492
4493 sksec = kzalloc(sizeof(*sksec), priority);
4494 if (!sksec)
4495 return -ENOMEM;
4496
4497 sksec->peer_sid = SECINITSID_UNLABELED;
4498 sksec->sid = SECINITSID_UNLABELED;
4499 selinux_netlbl_sk_security_reset(sksec);
4500 sk->sk_security = sksec;
4501
4502 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004503}
4504
4505static void selinux_sk_free_security(struct sock *sk)
4506{
Paul Moore84914b72010-04-22 14:46:18 -04004507 struct sk_security_struct *sksec = sk->sk_security;
4508
4509 sk->sk_security = NULL;
4510 selinux_netlbl_sk_security_free(sksec);
4511 kfree(sksec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004512}
4513
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004514static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk)
4515{
Eric Parisdd3e7832010-04-07 15:08:46 -04004516 struct sk_security_struct *sksec = sk->sk_security;
4517 struct sk_security_struct *newsksec = newsk->sk_security;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004518
Eric Parisdd3e7832010-04-07 15:08:46 -04004519 newsksec->sid = sksec->sid;
4520 newsksec->peer_sid = sksec->peer_sid;
4521 newsksec->sclass = sksec->sclass;
Paul Moore99f59ed2006-08-29 17:53:48 -07004522
Eric Parisdd3e7832010-04-07 15:08:46 -04004523 selinux_netlbl_sk_security_reset(newsksec);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004524}
4525
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004526static void selinux_sk_getsecid(struct sock *sk, u32 *secid)
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004527{
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004528 if (!sk)
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004529 *secid = SECINITSID_ANY_SOCKET;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004530 else {
4531 struct sk_security_struct *sksec = sk->sk_security;
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004532
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004533 *secid = sksec->sid;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004534 }
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004535}
4536
Eric Paris828dfe12008-04-17 13:17:49 -04004537static void selinux_sock_graft(struct sock *sk, struct socket *parent)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004538{
4539 struct inode_security_struct *isec = SOCK_INODE(parent)->i_security;
4540 struct sk_security_struct *sksec = sk->sk_security;
4541
David Woodhouse2148ccc2006-09-29 15:50:25 -07004542 if (sk->sk_family == PF_INET || sk->sk_family == PF_INET6 ||
4543 sk->sk_family == PF_UNIX)
4544 isec->sid = sksec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05004545 sksec->sclass = isec->sclass;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004546}
4547
Adrian Bunk9a673e52006-08-15 00:03:53 -07004548static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
4549 struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004550{
4551 struct sk_security_struct *sksec = sk->sk_security;
4552 int err;
Paul Mooreaa862902008-10-10 10:16:29 -04004553 u16 family = sk->sk_family;
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07004554 u32 newsid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004555 u32 peersid;
4556
Paul Mooreaa862902008-10-10 10:16:29 -04004557 /* handle mapped IPv4 packets arriving via IPv6 sockets */
4558 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
4559 family = PF_INET;
4560
4561 err = selinux_skb_peerlbl_sid(skb, family, &peersid);
Paul Moore220deb92008-01-29 08:38:23 -05004562 if (err)
4563 return err;
Venkat Yekkiralaa51c64f2006-07-27 22:01:34 -07004564 if (peersid == SECSID_NULL) {
4565 req->secid = sksec->sid;
Paul Moore3de4bab2006-11-17 17:38:54 -05004566 req->peer_secid = SECSID_NULL;
Paul Moore389fb802009-03-27 17:10:34 -04004567 } else {
4568 err = security_sid_mls_copy(sksec->sid, peersid, &newsid);
4569 if (err)
4570 return err;
4571 req->secid = newsid;
4572 req->peer_secid = peersid;
Venkat Yekkiralaa51c64f2006-07-27 22:01:34 -07004573 }
4574
Paul Moore389fb802009-03-27 17:10:34 -04004575 return selinux_netlbl_inet_conn_request(req, family);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004576}
4577
Adrian Bunk9a673e52006-08-15 00:03:53 -07004578static void selinux_inet_csk_clone(struct sock *newsk,
4579 const struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004580{
4581 struct sk_security_struct *newsksec = newsk->sk_security;
4582
4583 newsksec->sid = req->secid;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004584 newsksec->peer_sid = req->peer_secid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004585 /* NOTE: Ideally, we should also get the isec->sid for the
4586 new socket in sync, but we don't have the isec available yet.
4587 So we will wait until sock_graft to do it, by which
4588 time it will have been created and available. */
Paul Moore99f59ed2006-08-29 17:53:48 -07004589
Paul Moore9f2ad662006-11-17 17:38:53 -05004590 /* We don't need to take any sort of lock here as we are the only
4591 * thread with access to newsksec */
Paul Moore389fb802009-03-27 17:10:34 -04004592 selinux_netlbl_inet_csk_clone(newsk, req->rsk_ops->family);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004593}
4594
Paul Moore014ab192008-10-10 10:16:33 -04004595static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb)
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004596{
Paul Mooreaa862902008-10-10 10:16:29 -04004597 u16 family = sk->sk_family;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004598 struct sk_security_struct *sksec = sk->sk_security;
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 selinux_skb_peerlbl_sid(skb, family, &sksec->peer_sid);
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004605}
4606
Eric Paris2606fd12010-10-13 16:24:41 -04004607static int selinux_secmark_relabel_packet(u32 sid)
4608{
4609 const struct task_security_struct *__tsec;
4610 u32 tsid;
4611
4612 __tsec = current_security();
4613 tsid = __tsec->sid;
4614
4615 return avc_has_perm(tsid, sid, SECCLASS_PACKET, PACKET__RELABELTO, NULL);
4616}
4617
4618static void selinux_secmark_refcount_inc(void)
4619{
4620 atomic_inc(&selinux_secmark_refcount);
4621}
4622
4623static void selinux_secmark_refcount_dec(void)
4624{
4625 atomic_dec(&selinux_secmark_refcount);
4626}
4627
Adrian Bunk9a673e52006-08-15 00:03:53 -07004628static void selinux_req_classify_flow(const struct request_sock *req,
4629 struct flowi *fl)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004630{
David S. Miller1d28f422011-03-12 00:29:39 -05004631 fl->flowi_secid = req->secid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004632}
4633
Paul Mooreed6d76e2009-08-28 18:12:49 -04004634static int selinux_tun_dev_create(void)
4635{
4636 u32 sid = current_sid();
4637
4638 /* we aren't taking into account the "sockcreate" SID since the socket
4639 * that is being created here is not a socket in the traditional sense,
4640 * instead it is a private sock, accessible only to the kernel, and
4641 * representing a wide range of network traffic spanning multiple
4642 * connections unlike traditional sockets - check the TUN driver to
4643 * get a better understanding of why this socket is special */
4644
4645 return avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET, TUN_SOCKET__CREATE,
4646 NULL);
4647}
4648
4649static void selinux_tun_dev_post_create(struct sock *sk)
4650{
4651 struct sk_security_struct *sksec = sk->sk_security;
4652
4653 /* we don't currently perform any NetLabel based labeling here and it
4654 * isn't clear that we would want to do so anyway; while we could apply
4655 * labeling without the support of the TUN user the resulting labeled
4656 * traffic from the other end of the connection would almost certainly
4657 * cause confusion to the TUN user that had no idea network labeling
4658 * protocols were being used */
4659
4660 /* see the comments in selinux_tun_dev_create() about why we don't use
4661 * the sockcreate SID here */
4662
4663 sksec->sid = current_sid();
4664 sksec->sclass = SECCLASS_TUN_SOCKET;
4665}
4666
4667static int selinux_tun_dev_attach(struct sock *sk)
4668{
4669 struct sk_security_struct *sksec = sk->sk_security;
4670 u32 sid = current_sid();
4671 int err;
4672
4673 err = avc_has_perm(sid, sksec->sid, SECCLASS_TUN_SOCKET,
4674 TUN_SOCKET__RELABELFROM, NULL);
4675 if (err)
4676 return err;
4677 err = avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET,
4678 TUN_SOCKET__RELABELTO, NULL);
4679 if (err)
4680 return err;
4681
4682 sksec->sid = sid;
4683
4684 return 0;
4685}
4686
Linus Torvalds1da177e2005-04-16 15:20:36 -07004687static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
4688{
4689 int err = 0;
4690 u32 perm;
4691 struct nlmsghdr *nlh;
Paul Moore253bfae2010-04-22 14:46:19 -04004692 struct sk_security_struct *sksec = sk->sk_security;
Eric Paris828dfe12008-04-17 13:17:49 -04004693
Linus Torvalds1da177e2005-04-16 15:20:36 -07004694 if (skb->len < NLMSG_SPACE(0)) {
4695 err = -EINVAL;
4696 goto out;
4697 }
Arnaldo Carvalho de Melob529ccf2007-04-25 19:08:35 -07004698 nlh = nlmsg_hdr(skb);
Eric Paris828dfe12008-04-17 13:17:49 -04004699
Paul Moore253bfae2010-04-22 14:46:19 -04004700 err = selinux_nlmsg_lookup(sksec->sclass, nlh->nlmsg_type, &perm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004701 if (err) {
4702 if (err == -EINVAL) {
David Woodhouse9ad9ad32005-06-22 15:04:33 +01004703 audit_log(current->audit_context, GFP_KERNEL, AUDIT_SELINUX_ERR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004704 "SELinux: unrecognized netlink message"
4705 " type=%hu for sclass=%hu\n",
Paul Moore253bfae2010-04-22 14:46:19 -04004706 nlh->nlmsg_type, sksec->sclass);
Eric Paris39c9aed2008-11-05 09:34:42 -05004707 if (!selinux_enforcing || security_get_allow_unknown())
Linus Torvalds1da177e2005-04-16 15:20:36 -07004708 err = 0;
4709 }
4710
4711 /* Ignore */
4712 if (err == -ENOENT)
4713 err = 0;
4714 goto out;
4715 }
4716
Paul Moore253bfae2010-04-22 14:46:19 -04004717 err = sock_has_perm(current, sk, perm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004718out:
4719 return err;
4720}
4721
4722#ifdef CONFIG_NETFILTER
4723
Paul Mooreeffad8d2008-01-29 08:49:27 -05004724static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex,
4725 u16 family)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004726{
Paul Mooredfaebe92008-10-10 10:16:31 -04004727 int err;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004728 char *addrp;
4729 u32 peer_sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04004730 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07004731 struct selinux_audit_data sad = {0,};
Eric Paris48c62af2012-04-02 13:15:44 -04004732 struct lsm_network_audit net = {0,};
Paul Mooreeffad8d2008-01-29 08:49:27 -05004733 u8 secmark_active;
Paul Moore948bf852008-10-10 10:16:32 -04004734 u8 netlbl_active;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004735 u8 peerlbl_active;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004736
Paul Mooreeffad8d2008-01-29 08:49:27 -05004737 if (!selinux_policycap_netpeer)
4738 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004739
Paul Mooreeffad8d2008-01-29 08:49:27 -05004740 secmark_active = selinux_secmark_enabled();
Paul Moore948bf852008-10-10 10:16:32 -04004741 netlbl_active = netlbl_enabled();
4742 peerlbl_active = netlbl_active || selinux_xfrm_enabled();
Paul Mooreeffad8d2008-01-29 08:49:27 -05004743 if (!secmark_active && !peerlbl_active)
4744 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004745
Paul Moored8395c82008-10-10 10:16:30 -04004746 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0)
4747 return NF_DROP;
4748
Thomas Liu2bf49692009-07-14 12:14:09 -04004749 COMMON_AUDIT_DATA_INIT(&ad, NET);
Eric Paris3b3b0e42012-04-03 09:37:02 -07004750 ad.selinux_audit_data = &sad;
Eric Paris48c62af2012-04-02 13:15:44 -04004751 ad.u.net = &net;
4752 ad.u.net->netif = ifindex;
4753 ad.u.net->family = family;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004754 if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0)
4755 return NF_DROP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004756
Paul Mooredfaebe92008-10-10 10:16:31 -04004757 if (peerlbl_active) {
4758 err = selinux_inet_sys_rcv_skb(ifindex, addrp, family,
4759 peer_sid, &ad);
4760 if (err) {
4761 selinux_netlbl_err(skb, err, 1);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004762 return NF_DROP;
Paul Mooredfaebe92008-10-10 10:16:31 -04004763 }
4764 }
Paul Mooreeffad8d2008-01-29 08:49:27 -05004765
4766 if (secmark_active)
4767 if (avc_has_perm(peer_sid, skb->secmark,
4768 SECCLASS_PACKET, PACKET__FORWARD_IN, &ad))
4769 return NF_DROP;
4770
Paul Moore948bf852008-10-10 10:16:32 -04004771 if (netlbl_active)
4772 /* we do this in the FORWARD path and not the POST_ROUTING
4773 * path because we want to make sure we apply the necessary
4774 * labeling before IPsec is applied so we can leverage AH
4775 * protection */
4776 if (selinux_netlbl_skbuff_setsid(skb, family, peer_sid) != 0)
4777 return NF_DROP;
4778
Paul Mooreeffad8d2008-01-29 08:49:27 -05004779 return NF_ACCEPT;
4780}
4781
4782static unsigned int selinux_ipv4_forward(unsigned int hooknum,
4783 struct sk_buff *skb,
4784 const struct net_device *in,
4785 const struct net_device *out,
4786 int (*okfn)(struct sk_buff *))
4787{
4788 return selinux_ip_forward(skb, in->ifindex, PF_INET);
4789}
4790
4791#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
4792static unsigned int selinux_ipv6_forward(unsigned int hooknum,
4793 struct sk_buff *skb,
4794 const struct net_device *in,
4795 const struct net_device *out,
4796 int (*okfn)(struct sk_buff *))
4797{
4798 return selinux_ip_forward(skb, in->ifindex, PF_INET6);
4799}
4800#endif /* IPV6 */
4801
Paul Moore948bf852008-10-10 10:16:32 -04004802static unsigned int selinux_ip_output(struct sk_buff *skb,
4803 u16 family)
4804{
4805 u32 sid;
4806
4807 if (!netlbl_enabled())
4808 return NF_ACCEPT;
4809
4810 /* we do this in the LOCAL_OUT path and not the POST_ROUTING path
4811 * because we want to make sure we apply the necessary labeling
4812 * before IPsec is applied so we can leverage AH protection */
4813 if (skb->sk) {
4814 struct sk_security_struct *sksec = skb->sk->sk_security;
4815 sid = sksec->sid;
4816 } else
4817 sid = SECINITSID_KERNEL;
4818 if (selinux_netlbl_skbuff_setsid(skb, family, sid) != 0)
4819 return NF_DROP;
4820
4821 return NF_ACCEPT;
4822}
4823
4824static unsigned int selinux_ipv4_output(unsigned int hooknum,
4825 struct sk_buff *skb,
4826 const struct net_device *in,
4827 const struct net_device *out,
4828 int (*okfn)(struct sk_buff *))
4829{
4830 return selinux_ip_output(skb, PF_INET);
4831}
4832
Paul Mooreeffad8d2008-01-29 08:49:27 -05004833static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
4834 int ifindex,
Paul Moored8395c82008-10-10 10:16:30 -04004835 u16 family)
James Morris4e5ab4c2006-06-09 00:33:33 -07004836{
Paul Mooreeffad8d2008-01-29 08:49:27 -05004837 struct sock *sk = skb->sk;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004838 struct sk_security_struct *sksec;
Thomas Liu2bf49692009-07-14 12:14:09 -04004839 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07004840 struct selinux_audit_data sad = {0,};
Eric Paris48c62af2012-04-02 13:15:44 -04004841 struct lsm_network_audit net = {0,};
Paul Moored8395c82008-10-10 10:16:30 -04004842 char *addrp;
4843 u8 proto;
James Morris4e5ab4c2006-06-09 00:33:33 -07004844
Paul Mooreeffad8d2008-01-29 08:49:27 -05004845 if (sk == NULL)
4846 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004847 sksec = sk->sk_security;
James Morris4e5ab4c2006-06-09 00:33:33 -07004848
Thomas Liu2bf49692009-07-14 12:14:09 -04004849 COMMON_AUDIT_DATA_INIT(&ad, NET);
Eric Paris3b3b0e42012-04-03 09:37:02 -07004850 ad.selinux_audit_data = &sad;
Eric Paris48c62af2012-04-02 13:15:44 -04004851 ad.u.net = &net;
4852 ad.u.net->netif = ifindex;
4853 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04004854 if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto))
4855 return NF_DROP;
4856
Paul Moore58bfbb52009-03-27 17:10:41 -04004857 if (selinux_secmark_enabled())
Paul Mooreeffad8d2008-01-29 08:49:27 -05004858 if (avc_has_perm(sksec->sid, skb->secmark,
Paul Moored8395c82008-10-10 10:16:30 -04004859 SECCLASS_PACKET, PACKET__SEND, &ad))
Eric Paris2fe66ec2010-11-23 06:28:08 +00004860 return NF_DROP_ERR(-ECONNREFUSED);
James Morris4e5ab4c2006-06-09 00:33:33 -07004861
Steffen Klassertb9679a72011-02-23 12:55:21 +01004862 if (selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto))
4863 return NF_DROP_ERR(-ECONNREFUSED);
James Morris4e5ab4c2006-06-09 00:33:33 -07004864
Paul Mooreeffad8d2008-01-29 08:49:27 -05004865 return NF_ACCEPT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004866}
4867
Paul Mooreeffad8d2008-01-29 08:49:27 -05004868static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
4869 u16 family)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004870{
Paul Mooreeffad8d2008-01-29 08:49:27 -05004871 u32 secmark_perm;
4872 u32 peer_sid;
4873 struct sock *sk;
Thomas Liu2bf49692009-07-14 12:14:09 -04004874 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07004875 struct selinux_audit_data sad = {0,};
Eric Paris48c62af2012-04-02 13:15:44 -04004876 struct lsm_network_audit net = {0,};
Paul Mooreeffad8d2008-01-29 08:49:27 -05004877 char *addrp;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004878 u8 secmark_active;
4879 u8 peerlbl_active;
4880
Paul Mooreeffad8d2008-01-29 08:49:27 -05004881 /* If any sort of compatibility mode is enabled then handoff processing
4882 * to the selinux_ip_postroute_compat() function to deal with the
4883 * special handling. We do this in an attempt to keep this function
4884 * as fast and as clean as possible. */
Paul Moore58bfbb52009-03-27 17:10:41 -04004885 if (!selinux_policycap_netpeer)
Paul Moored8395c82008-10-10 10:16:30 -04004886 return selinux_ip_postroute_compat(skb, ifindex, family);
Alexey Dobriyandef8b4f2008-10-28 13:24:06 -07004887#ifdef CONFIG_XFRM
Paul Mooreeffad8d2008-01-29 08:49:27 -05004888 /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec
4889 * packet transformation so allow the packet to pass without any checks
4890 * since we'll have another chance to perform access control checks
4891 * when the packet is on it's final way out.
4892 * NOTE: there appear to be some IPv6 multicast cases where skb->dst
4893 * is NULL, in this case go ahead and apply access control. */
Eric Dumazetadf30902009-06-02 05:19:30 +00004894 if (skb_dst(skb) != NULL && skb_dst(skb)->xfrm != NULL)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004895 return NF_ACCEPT;
Alexey Dobriyandef8b4f2008-10-28 13:24:06 -07004896#endif
Paul Mooreeffad8d2008-01-29 08:49:27 -05004897 secmark_active = selinux_secmark_enabled();
4898 peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled();
4899 if (!secmark_active && !peerlbl_active)
4900 return NF_ACCEPT;
4901
Paul Moored8395c82008-10-10 10:16:30 -04004902 /* if the packet is being forwarded then get the peer label from the
4903 * packet itself; otherwise check to see if it is from a local
4904 * application or the kernel, if from an application get the peer label
4905 * from the sending socket, otherwise use the kernel's sid */
Paul Mooreeffad8d2008-01-29 08:49:27 -05004906 sk = skb->sk;
Paul Moored8395c82008-10-10 10:16:30 -04004907 if (sk == NULL) {
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01004908 if (skb->skb_iif) {
4909 secmark_perm = PACKET__FORWARD_OUT;
Paul Moored8395c82008-10-10 10:16:30 -04004910 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00004911 return NF_DROP;
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01004912 } else {
4913 secmark_perm = PACKET__SEND;
Paul Moored8395c82008-10-10 10:16:30 -04004914 peer_sid = SECINITSID_KERNEL;
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01004915 }
Paul Moored8395c82008-10-10 10:16:30 -04004916 } else {
Paul Mooreeffad8d2008-01-29 08:49:27 -05004917 struct sk_security_struct *sksec = sk->sk_security;
4918 peer_sid = sksec->sid;
4919 secmark_perm = PACKET__SEND;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004920 }
4921
Thomas Liu2bf49692009-07-14 12:14:09 -04004922 COMMON_AUDIT_DATA_INIT(&ad, NET);
Eric Paris3b3b0e42012-04-03 09:37:02 -07004923 ad.selinux_audit_data = &sad;
Eric Paris48c62af2012-04-02 13:15:44 -04004924 ad.u.net = &net;
4925 ad.u.net->netif = ifindex;
4926 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04004927 if (selinux_parse_skb(skb, &ad, &addrp, 0, NULL))
Eric Paris04f6d702010-11-23 06:28:02 +00004928 return NF_DROP;
Paul Moored8395c82008-10-10 10:16:30 -04004929
Paul Mooreeffad8d2008-01-29 08:49:27 -05004930 if (secmark_active)
4931 if (avc_has_perm(peer_sid, skb->secmark,
4932 SECCLASS_PACKET, secmark_perm, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00004933 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004934
4935 if (peerlbl_active) {
4936 u32 if_sid;
4937 u32 node_sid;
4938
4939 if (sel_netif_sid(ifindex, &if_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00004940 return NF_DROP;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004941 if (avc_has_perm(peer_sid, if_sid,
4942 SECCLASS_NETIF, NETIF__EGRESS, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00004943 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004944
4945 if (sel_netnode_sid(addrp, family, &node_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00004946 return NF_DROP;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004947 if (avc_has_perm(peer_sid, node_sid,
4948 SECCLASS_NODE, NODE__SENDTO, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00004949 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004950 }
4951
4952 return NF_ACCEPT;
4953}
4954
4955static unsigned int selinux_ipv4_postroute(unsigned int hooknum,
4956 struct sk_buff *skb,
4957 const struct net_device *in,
4958 const struct net_device *out,
4959 int (*okfn)(struct sk_buff *))
4960{
4961 return selinux_ip_postroute(skb, out->ifindex, PF_INET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004962}
4963
4964#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004965static unsigned int selinux_ipv6_postroute(unsigned int hooknum,
4966 struct sk_buff *skb,
4967 const struct net_device *in,
4968 const struct net_device *out,
4969 int (*okfn)(struct sk_buff *))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004970{
Paul Mooreeffad8d2008-01-29 08:49:27 -05004971 return selinux_ip_postroute(skb, out->ifindex, PF_INET6);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004972}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004973#endif /* IPV6 */
4974
4975#endif /* CONFIG_NETFILTER */
4976
Linus Torvalds1da177e2005-04-16 15:20:36 -07004977static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb)
4978{
Linus Torvalds1da177e2005-04-16 15:20:36 -07004979 int err;
4980
Eric Paris200ac532009-02-12 15:01:04 -05004981 err = cap_netlink_send(sk, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004982 if (err)
4983 return err;
4984
Stephen Smalley941fc5b2009-10-01 14:48:23 -04004985 return selinux_nlmsg_perm(sk, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004986}
4987
Linus Torvalds1da177e2005-04-16 15:20:36 -07004988static int ipc_alloc_security(struct task_struct *task,
4989 struct kern_ipc_perm *perm,
4990 u16 sclass)
4991{
Linus Torvalds1da177e2005-04-16 15:20:36 -07004992 struct ipc_security_struct *isec;
David Howells275bb412008-11-14 10:39:19 +11004993 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004994
James Morris89d155e2005-10-30 14:59:21 -08004995 isec = kzalloc(sizeof(struct ipc_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004996 if (!isec)
4997 return -ENOMEM;
4998
David Howells275bb412008-11-14 10:39:19 +11004999 sid = task_sid(task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005000 isec->sclass = sclass;
David Howells275bb412008-11-14 10:39:19 +11005001 isec->sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005002 perm->security = isec;
5003
5004 return 0;
5005}
5006
5007static void ipc_free_security(struct kern_ipc_perm *perm)
5008{
5009 struct ipc_security_struct *isec = perm->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005010 perm->security = NULL;
5011 kfree(isec);
5012}
5013
5014static int msg_msg_alloc_security(struct msg_msg *msg)
5015{
5016 struct msg_security_struct *msec;
5017
James Morris89d155e2005-10-30 14:59:21 -08005018 msec = kzalloc(sizeof(struct msg_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005019 if (!msec)
5020 return -ENOMEM;
5021
Linus Torvalds1da177e2005-04-16 15:20:36 -07005022 msec->sid = SECINITSID_UNLABELED;
5023 msg->security = msec;
5024
5025 return 0;
5026}
5027
5028static void msg_msg_free_security(struct msg_msg *msg)
5029{
5030 struct msg_security_struct *msec = msg->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005031
5032 msg->security = NULL;
5033 kfree(msec);
5034}
5035
5036static int ipc_has_perm(struct kern_ipc_perm *ipc_perms,
Stephen Smalley6af963f2005-05-01 08:58:39 -07005037 u32 perms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005038{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005039 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005040 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07005041 struct selinux_audit_data sad = {0,};
David Howells275bb412008-11-14 10:39:19 +11005042 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005043
Linus Torvalds1da177e2005-04-16 15:20:36 -07005044 isec = ipc_perms->security;
5045
Thomas Liu2bf49692009-07-14 12:14:09 -04005046 COMMON_AUDIT_DATA_INIT(&ad, IPC);
Eric Paris3b3b0e42012-04-03 09:37:02 -07005047 ad.selinux_audit_data = &sad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005048 ad.u.ipc_id = ipc_perms->key;
5049
David Howells275bb412008-11-14 10:39:19 +11005050 return avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005051}
5052
5053static int selinux_msg_msg_alloc_security(struct msg_msg *msg)
5054{
5055 return msg_msg_alloc_security(msg);
5056}
5057
5058static void selinux_msg_msg_free_security(struct msg_msg *msg)
5059{
5060 msg_msg_free_security(msg);
5061}
5062
5063/* message queue security operations */
5064static int selinux_msg_queue_alloc_security(struct msg_queue *msq)
5065{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005066 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005067 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07005068 struct selinux_audit_data sad = {0,};
David Howells275bb412008-11-14 10:39:19 +11005069 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005070 int rc;
5071
5072 rc = ipc_alloc_security(current, &msq->q_perm, SECCLASS_MSGQ);
5073 if (rc)
5074 return rc;
5075
Linus Torvalds1da177e2005-04-16 15:20:36 -07005076 isec = msq->q_perm.security;
5077
Thomas Liu2bf49692009-07-14 12:14:09 -04005078 COMMON_AUDIT_DATA_INIT(&ad, IPC);
Eric Paris3b3b0e42012-04-03 09:37:02 -07005079 ad.selinux_audit_data = &sad;
Eric Paris828dfe12008-04-17 13:17:49 -04005080 ad.u.ipc_id = msq->q_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005081
David Howells275bb412008-11-14 10:39:19 +11005082 rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005083 MSGQ__CREATE, &ad);
5084 if (rc) {
5085 ipc_free_security(&msq->q_perm);
5086 return rc;
5087 }
5088 return 0;
5089}
5090
5091static void selinux_msg_queue_free_security(struct msg_queue *msq)
5092{
5093 ipc_free_security(&msq->q_perm);
5094}
5095
5096static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg)
5097{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005098 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005099 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07005100 struct selinux_audit_data sad = {0,};
David Howells275bb412008-11-14 10:39:19 +11005101 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005102
Linus Torvalds1da177e2005-04-16 15:20:36 -07005103 isec = msq->q_perm.security;
5104
Thomas Liu2bf49692009-07-14 12:14:09 -04005105 COMMON_AUDIT_DATA_INIT(&ad, IPC);
Eric Paris3b3b0e42012-04-03 09:37:02 -07005106 ad.selinux_audit_data = &sad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005107 ad.u.ipc_id = msq->q_perm.key;
5108
David Howells275bb412008-11-14 10:39:19 +11005109 return avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005110 MSGQ__ASSOCIATE, &ad);
5111}
5112
5113static int selinux_msg_queue_msgctl(struct msg_queue *msq, int cmd)
5114{
5115 int err;
5116 int perms;
5117
Eric Paris828dfe12008-04-17 13:17:49 -04005118 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005119 case IPC_INFO:
5120 case MSG_INFO:
5121 /* No specific object, just general system-wide information. */
5122 return task_has_system(current, SYSTEM__IPC_INFO);
5123 case IPC_STAT:
5124 case MSG_STAT:
5125 perms = MSGQ__GETATTR | MSGQ__ASSOCIATE;
5126 break;
5127 case IPC_SET:
5128 perms = MSGQ__SETATTR;
5129 break;
5130 case IPC_RMID:
5131 perms = MSGQ__DESTROY;
5132 break;
5133 default:
5134 return 0;
5135 }
5136
Stephen Smalley6af963f2005-05-01 08:58:39 -07005137 err = ipc_has_perm(&msq->q_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005138 return err;
5139}
5140
5141static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, int msqflg)
5142{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005143 struct ipc_security_struct *isec;
5144 struct msg_security_struct *msec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005145 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07005146 struct selinux_audit_data sad = {0,};
David Howells275bb412008-11-14 10:39:19 +11005147 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005148 int rc;
5149
Linus Torvalds1da177e2005-04-16 15:20:36 -07005150 isec = msq->q_perm.security;
5151 msec = msg->security;
5152
5153 /*
5154 * First time through, need to assign label to the message
5155 */
5156 if (msec->sid == SECINITSID_UNLABELED) {
5157 /*
5158 * Compute new sid based on current process and
5159 * message queue this message will be stored in
5160 */
David Howells275bb412008-11-14 10:39:19 +11005161 rc = security_transition_sid(sid, isec->sid, SECCLASS_MSG,
Eric Paris652bb9b2011-02-01 11:05:40 -05005162 NULL, &msec->sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005163 if (rc)
5164 return rc;
5165 }
5166
Thomas Liu2bf49692009-07-14 12:14:09 -04005167 COMMON_AUDIT_DATA_INIT(&ad, IPC);
Eric Paris3b3b0e42012-04-03 09:37:02 -07005168 ad.selinux_audit_data = &sad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005169 ad.u.ipc_id = msq->q_perm.key;
5170
5171 /* Can this process write to the queue? */
David Howells275bb412008-11-14 10:39:19 +11005172 rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005173 MSGQ__WRITE, &ad);
5174 if (!rc)
5175 /* Can this process send the message */
David Howells275bb412008-11-14 10:39:19 +11005176 rc = avc_has_perm(sid, msec->sid, SECCLASS_MSG,
5177 MSG__SEND, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005178 if (!rc)
5179 /* Can the message be put in the queue? */
David Howells275bb412008-11-14 10:39:19 +11005180 rc = avc_has_perm(msec->sid, isec->sid, SECCLASS_MSGQ,
5181 MSGQ__ENQUEUE, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005182
5183 return rc;
5184}
5185
5186static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
5187 struct task_struct *target,
5188 long type, int mode)
5189{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005190 struct ipc_security_struct *isec;
5191 struct msg_security_struct *msec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005192 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07005193 struct selinux_audit_data sad = {0,};
David Howells275bb412008-11-14 10:39:19 +11005194 u32 sid = task_sid(target);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005195 int rc;
5196
Linus Torvalds1da177e2005-04-16 15:20:36 -07005197 isec = msq->q_perm.security;
5198 msec = msg->security;
5199
Thomas Liu2bf49692009-07-14 12:14:09 -04005200 COMMON_AUDIT_DATA_INIT(&ad, IPC);
Eric Paris3b3b0e42012-04-03 09:37:02 -07005201 ad.selinux_audit_data = &sad;
Eric Paris828dfe12008-04-17 13:17:49 -04005202 ad.u.ipc_id = msq->q_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005203
David Howells275bb412008-11-14 10:39:19 +11005204 rc = avc_has_perm(sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005205 SECCLASS_MSGQ, MSGQ__READ, &ad);
5206 if (!rc)
David Howells275bb412008-11-14 10:39:19 +11005207 rc = avc_has_perm(sid, msec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005208 SECCLASS_MSG, MSG__RECEIVE, &ad);
5209 return rc;
5210}
5211
5212/* Shared Memory security operations */
5213static int selinux_shm_alloc_security(struct shmid_kernel *shp)
5214{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005215 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005216 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07005217 struct selinux_audit_data sad = {0,};
David Howells275bb412008-11-14 10:39:19 +11005218 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005219 int rc;
5220
5221 rc = ipc_alloc_security(current, &shp->shm_perm, SECCLASS_SHM);
5222 if (rc)
5223 return rc;
5224
Linus Torvalds1da177e2005-04-16 15:20:36 -07005225 isec = shp->shm_perm.security;
5226
Thomas Liu2bf49692009-07-14 12:14:09 -04005227 COMMON_AUDIT_DATA_INIT(&ad, IPC);
Eric Paris3b3b0e42012-04-03 09:37:02 -07005228 ad.selinux_audit_data = &sad;
Eric Paris828dfe12008-04-17 13:17:49 -04005229 ad.u.ipc_id = shp->shm_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005230
David Howells275bb412008-11-14 10:39:19 +11005231 rc = avc_has_perm(sid, isec->sid, SECCLASS_SHM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005232 SHM__CREATE, &ad);
5233 if (rc) {
5234 ipc_free_security(&shp->shm_perm);
5235 return rc;
5236 }
5237 return 0;
5238}
5239
5240static void selinux_shm_free_security(struct shmid_kernel *shp)
5241{
5242 ipc_free_security(&shp->shm_perm);
5243}
5244
5245static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg)
5246{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005247 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005248 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07005249 struct selinux_audit_data sad = {0,};
David Howells275bb412008-11-14 10:39:19 +11005250 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005251
Linus Torvalds1da177e2005-04-16 15:20:36 -07005252 isec = shp->shm_perm.security;
5253
Thomas Liu2bf49692009-07-14 12:14:09 -04005254 COMMON_AUDIT_DATA_INIT(&ad, IPC);
Eric Paris3b3b0e42012-04-03 09:37:02 -07005255 ad.selinux_audit_data = &sad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005256 ad.u.ipc_id = shp->shm_perm.key;
5257
David Howells275bb412008-11-14 10:39:19 +11005258 return avc_has_perm(sid, isec->sid, SECCLASS_SHM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005259 SHM__ASSOCIATE, &ad);
5260}
5261
5262/* Note, at this point, shp is locked down */
5263static int selinux_shm_shmctl(struct shmid_kernel *shp, int cmd)
5264{
5265 int perms;
5266 int err;
5267
Eric Paris828dfe12008-04-17 13:17:49 -04005268 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005269 case IPC_INFO:
5270 case SHM_INFO:
5271 /* No specific object, just general system-wide information. */
5272 return task_has_system(current, SYSTEM__IPC_INFO);
5273 case IPC_STAT:
5274 case SHM_STAT:
5275 perms = SHM__GETATTR | SHM__ASSOCIATE;
5276 break;
5277 case IPC_SET:
5278 perms = SHM__SETATTR;
5279 break;
5280 case SHM_LOCK:
5281 case SHM_UNLOCK:
5282 perms = SHM__LOCK;
5283 break;
5284 case IPC_RMID:
5285 perms = SHM__DESTROY;
5286 break;
5287 default:
5288 return 0;
5289 }
5290
Stephen Smalley6af963f2005-05-01 08:58:39 -07005291 err = ipc_has_perm(&shp->shm_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005292 return err;
5293}
5294
5295static int selinux_shm_shmat(struct shmid_kernel *shp,
5296 char __user *shmaddr, int shmflg)
5297{
5298 u32 perms;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005299
5300 if (shmflg & SHM_RDONLY)
5301 perms = SHM__READ;
5302 else
5303 perms = SHM__READ | SHM__WRITE;
5304
Stephen Smalley6af963f2005-05-01 08:58:39 -07005305 return ipc_has_perm(&shp->shm_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005306}
5307
5308/* Semaphore security operations */
5309static int selinux_sem_alloc_security(struct sem_array *sma)
5310{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005311 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005312 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07005313 struct selinux_audit_data sad = {0,};
David Howells275bb412008-11-14 10:39:19 +11005314 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005315 int rc;
5316
5317 rc = ipc_alloc_security(current, &sma->sem_perm, SECCLASS_SEM);
5318 if (rc)
5319 return rc;
5320
Linus Torvalds1da177e2005-04-16 15:20:36 -07005321 isec = sma->sem_perm.security;
5322
Thomas Liu2bf49692009-07-14 12:14:09 -04005323 COMMON_AUDIT_DATA_INIT(&ad, IPC);
Eric Paris3b3b0e42012-04-03 09:37:02 -07005324 ad.selinux_audit_data = &sad;
Eric Paris828dfe12008-04-17 13:17:49 -04005325 ad.u.ipc_id = sma->sem_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005326
David Howells275bb412008-11-14 10:39:19 +11005327 rc = avc_has_perm(sid, isec->sid, SECCLASS_SEM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005328 SEM__CREATE, &ad);
5329 if (rc) {
5330 ipc_free_security(&sma->sem_perm);
5331 return rc;
5332 }
5333 return 0;
5334}
5335
5336static void selinux_sem_free_security(struct sem_array *sma)
5337{
5338 ipc_free_security(&sma->sem_perm);
5339}
5340
5341static int selinux_sem_associate(struct sem_array *sma, int semflg)
5342{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005343 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005344 struct common_audit_data ad;
Eric Paris3b3b0e42012-04-03 09:37:02 -07005345 struct selinux_audit_data sad = {0,};
David Howells275bb412008-11-14 10:39:19 +11005346 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005347
Linus Torvalds1da177e2005-04-16 15:20:36 -07005348 isec = sma->sem_perm.security;
5349
Thomas Liu2bf49692009-07-14 12:14:09 -04005350 COMMON_AUDIT_DATA_INIT(&ad, IPC);
Eric Paris3b3b0e42012-04-03 09:37:02 -07005351 ad.selinux_audit_data = &sad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005352 ad.u.ipc_id = sma->sem_perm.key;
5353
David Howells275bb412008-11-14 10:39:19 +11005354 return avc_has_perm(sid, isec->sid, SECCLASS_SEM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005355 SEM__ASSOCIATE, &ad);
5356}
5357
5358/* Note, at this point, sma is locked down */
5359static int selinux_sem_semctl(struct sem_array *sma, int cmd)
5360{
5361 int err;
5362 u32 perms;
5363
Eric Paris828dfe12008-04-17 13:17:49 -04005364 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005365 case IPC_INFO:
5366 case SEM_INFO:
5367 /* No specific object, just general system-wide information. */
5368 return task_has_system(current, SYSTEM__IPC_INFO);
5369 case GETPID:
5370 case GETNCNT:
5371 case GETZCNT:
5372 perms = SEM__GETATTR;
5373 break;
5374 case GETVAL:
5375 case GETALL:
5376 perms = SEM__READ;
5377 break;
5378 case SETVAL:
5379 case SETALL:
5380 perms = SEM__WRITE;
5381 break;
5382 case IPC_RMID:
5383 perms = SEM__DESTROY;
5384 break;
5385 case IPC_SET:
5386 perms = SEM__SETATTR;
5387 break;
5388 case IPC_STAT:
5389 case SEM_STAT:
5390 perms = SEM__GETATTR | SEM__ASSOCIATE;
5391 break;
5392 default:
5393 return 0;
5394 }
5395
Stephen Smalley6af963f2005-05-01 08:58:39 -07005396 err = ipc_has_perm(&sma->sem_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005397 return err;
5398}
5399
5400static int selinux_sem_semop(struct sem_array *sma,
5401 struct sembuf *sops, unsigned nsops, int alter)
5402{
5403 u32 perms;
5404
5405 if (alter)
5406 perms = SEM__READ | SEM__WRITE;
5407 else
5408 perms = SEM__READ;
5409
Stephen Smalley6af963f2005-05-01 08:58:39 -07005410 return ipc_has_perm(&sma->sem_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005411}
5412
5413static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
5414{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005415 u32 av = 0;
5416
Linus Torvalds1da177e2005-04-16 15:20:36 -07005417 av = 0;
5418 if (flag & S_IRUGO)
5419 av |= IPC__UNIX_READ;
5420 if (flag & S_IWUGO)
5421 av |= IPC__UNIX_WRITE;
5422
5423 if (av == 0)
5424 return 0;
5425
Stephen Smalley6af963f2005-05-01 08:58:39 -07005426 return ipc_has_perm(ipcp, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005427}
5428
Ahmed S. Darwish713a04a2008-03-01 21:52:30 +02005429static void selinux_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
5430{
5431 struct ipc_security_struct *isec = ipcp->security;
5432 *secid = isec->sid;
5433}
5434
Eric Paris828dfe12008-04-17 13:17:49 -04005435static void selinux_d_instantiate(struct dentry *dentry, struct inode *inode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005436{
5437 if (inode)
5438 inode_doinit_with_dentry(inode, dentry);
5439}
5440
5441static int selinux_getprocattr(struct task_struct *p,
Al Viro04ff9702007-03-12 16:17:58 +00005442 char *name, char **value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005443{
David Howells275bb412008-11-14 10:39:19 +11005444 const struct task_security_struct *__tsec;
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00005445 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005446 int error;
Al Viro04ff9702007-03-12 16:17:58 +00005447 unsigned len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005448
5449 if (current != p) {
David Howells3b11a1d2008-11-14 10:39:26 +11005450 error = current_has_perm(p, PROCESS__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005451 if (error)
5452 return error;
5453 }
5454
David Howells275bb412008-11-14 10:39:19 +11005455 rcu_read_lock();
5456 __tsec = __task_cred(p)->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005457
5458 if (!strcmp(name, "current"))
David Howells275bb412008-11-14 10:39:19 +11005459 sid = __tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005460 else if (!strcmp(name, "prev"))
David Howells275bb412008-11-14 10:39:19 +11005461 sid = __tsec->osid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005462 else if (!strcmp(name, "exec"))
David Howells275bb412008-11-14 10:39:19 +11005463 sid = __tsec->exec_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005464 else if (!strcmp(name, "fscreate"))
David Howells275bb412008-11-14 10:39:19 +11005465 sid = __tsec->create_sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005466 else if (!strcmp(name, "keycreate"))
David Howells275bb412008-11-14 10:39:19 +11005467 sid = __tsec->keycreate_sid;
Eric Paris42c3e032006-06-26 00:26:03 -07005468 else if (!strcmp(name, "sockcreate"))
David Howells275bb412008-11-14 10:39:19 +11005469 sid = __tsec->sockcreate_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005470 else
David Howells275bb412008-11-14 10:39:19 +11005471 goto invalid;
5472 rcu_read_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005473
5474 if (!sid)
5475 return 0;
5476
Al Viro04ff9702007-03-12 16:17:58 +00005477 error = security_sid_to_context(sid, value, &len);
5478 if (error)
5479 return error;
5480 return len;
David Howells275bb412008-11-14 10:39:19 +11005481
5482invalid:
5483 rcu_read_unlock();
5484 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005485}
5486
5487static int selinux_setprocattr(struct task_struct *p,
5488 char *name, void *value, size_t size)
5489{
5490 struct task_security_struct *tsec;
Roland McGrath03563572008-03-26 15:46:39 -07005491 struct task_struct *tracer;
David Howellsd84f4f92008-11-14 10:39:23 +11005492 struct cred *new;
5493 u32 sid = 0, ptsid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005494 int error;
5495 char *str = value;
5496
5497 if (current != p) {
5498 /* SELinux only allows a process to change its own
5499 security attributes. */
5500 return -EACCES;
5501 }
5502
5503 /*
5504 * Basic control over ability to set these attributes at all.
5505 * current == p, but we'll pass them separately in case the
5506 * above restriction is ever removed.
5507 */
5508 if (!strcmp(name, "exec"))
David Howells3b11a1d2008-11-14 10:39:26 +11005509 error = current_has_perm(p, PROCESS__SETEXEC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005510 else if (!strcmp(name, "fscreate"))
David Howells3b11a1d2008-11-14 10:39:26 +11005511 error = current_has_perm(p, PROCESS__SETFSCREATE);
Michael LeMay4eb582c2006-06-26 00:24:57 -07005512 else if (!strcmp(name, "keycreate"))
David Howells3b11a1d2008-11-14 10:39:26 +11005513 error = current_has_perm(p, PROCESS__SETKEYCREATE);
Eric Paris42c3e032006-06-26 00:26:03 -07005514 else if (!strcmp(name, "sockcreate"))
David Howells3b11a1d2008-11-14 10:39:26 +11005515 error = current_has_perm(p, PROCESS__SETSOCKCREATE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005516 else if (!strcmp(name, "current"))
David Howells3b11a1d2008-11-14 10:39:26 +11005517 error = current_has_perm(p, PROCESS__SETCURRENT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005518 else
5519 error = -EINVAL;
5520 if (error)
5521 return error;
5522
5523 /* Obtain a SID for the context, if one was specified. */
Stephen Smalleye44b57e2017-01-31 11:54:04 -05005524 if (size && str[0] && str[0] != '\n') {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005525 if (str[size-1] == '\n') {
5526 str[size-1] = 0;
5527 size--;
5528 }
5529 error = security_context_to_sid(value, size, &sid);
Stephen Smalley12b29f32008-05-07 13:03:20 -04005530 if (error == -EINVAL && !strcmp(name, "fscreate")) {
5531 if (!capable(CAP_MAC_ADMIN))
5532 return error;
5533 error = security_context_to_sid_force(value, size,
5534 &sid);
5535 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005536 if (error)
5537 return error;
5538 }
5539
David Howellsd84f4f92008-11-14 10:39:23 +11005540 new = prepare_creds();
5541 if (!new)
5542 return -ENOMEM;
5543
Linus Torvalds1da177e2005-04-16 15:20:36 -07005544 /* Permission checking based on the specified context is
5545 performed during the actual operation (execve,
5546 open/mkdir/...), when we know the full context of the
David Howellsd84f4f92008-11-14 10:39:23 +11005547 operation. See selinux_bprm_set_creds for the execve
Linus Torvalds1da177e2005-04-16 15:20:36 -07005548 checks and may_create for the file creation checks. The
5549 operation will then fail if the context is not permitted. */
David Howellsd84f4f92008-11-14 10:39:23 +11005550 tsec = new->security;
5551 if (!strcmp(name, "exec")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005552 tsec->exec_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005553 } else if (!strcmp(name, "fscreate")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005554 tsec->create_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005555 } else if (!strcmp(name, "keycreate")) {
Michael LeMay4eb582c2006-06-26 00:24:57 -07005556 error = may_create_key(sid, p);
5557 if (error)
David Howellsd84f4f92008-11-14 10:39:23 +11005558 goto abort_change;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005559 tsec->keycreate_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005560 } else if (!strcmp(name, "sockcreate")) {
Eric Paris42c3e032006-06-26 00:26:03 -07005561 tsec->sockcreate_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005562 } else if (!strcmp(name, "current")) {
5563 error = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005564 if (sid == 0)
David Howellsd84f4f92008-11-14 10:39:23 +11005565 goto abort_change;
KaiGai Koheid9250de2008-08-28 16:35:57 +09005566
David Howellsd84f4f92008-11-14 10:39:23 +11005567 /* Only allow single threaded processes to change context */
5568 error = -EPERM;
Oleg Nesterov5bb459b2009-07-10 03:48:23 +02005569 if (!current_is_single_threaded()) {
David Howellsd84f4f92008-11-14 10:39:23 +11005570 error = security_bounded_transition(tsec->sid, sid);
5571 if (error)
5572 goto abort_change;
Eric Paris828dfe12008-04-17 13:17:49 -04005573 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005574
5575 /* Check permissions for the transition. */
5576 error = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS,
Eric Paris828dfe12008-04-17 13:17:49 -04005577 PROCESS__DYNTRANSITION, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005578 if (error)
David Howellsd84f4f92008-11-14 10:39:23 +11005579 goto abort_change;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005580
5581 /* Check for ptracing, and update the task SID if ok.
5582 Otherwise, leave SID unchanged and fail. */
David Howellsd84f4f92008-11-14 10:39:23 +11005583 ptsid = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005584 task_lock(p);
Tejun Heo06d98472011-06-17 16:50:40 +02005585 tracer = ptrace_parent(p);
David Howellsd84f4f92008-11-14 10:39:23 +11005586 if (tracer)
5587 ptsid = task_sid(tracer);
5588 task_unlock(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005589
David Howellsd84f4f92008-11-14 10:39:23 +11005590 if (tracer) {
5591 error = avc_has_perm(ptsid, sid, SECCLASS_PROCESS,
5592 PROCESS__PTRACE, NULL);
5593 if (error)
5594 goto abort_change;
5595 }
5596
5597 tsec->sid = sid;
5598 } else {
5599 error = -EINVAL;
5600 goto abort_change;
5601 }
5602
5603 commit_creds(new);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005604 return size;
David Howellsd84f4f92008-11-14 10:39:23 +11005605
5606abort_change:
5607 abort_creds(new);
5608 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005609}
5610
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005611static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
5612{
5613 return security_sid_to_context(secid, secdata, seclen);
5614}
5615
David Howells7bf570d2008-04-29 20:52:51 +01005616static int selinux_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
David Howells63cb3442008-01-15 23:47:35 +00005617{
5618 return security_context_to_sid(secdata, seclen, secid);
5619}
5620
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005621static void selinux_release_secctx(char *secdata, u32 seclen)
5622{
Paul Moore088999e2007-08-01 11:12:58 -04005623 kfree(secdata);
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005624}
5625
David P. Quigley1ee65e32009-09-03 14:25:57 -04005626/*
5627 * called with inode->i_mutex locked
5628 */
5629static int selinux_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen)
5630{
5631 return selinux_inode_setsecurity(inode, XATTR_SELINUX_SUFFIX, ctx, ctxlen, 0);
5632}
5633
5634/*
5635 * called with inode->i_mutex locked
5636 */
5637static int selinux_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen)
5638{
5639 return __vfs_setxattr_noperm(dentry, XATTR_NAME_SELINUX, ctx, ctxlen, 0);
5640}
5641
5642static int selinux_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen)
5643{
5644 int len = 0;
5645 len = selinux_inode_getsecurity(inode, XATTR_SELINUX_SUFFIX,
5646 ctx, true);
5647 if (len < 0)
5648 return len;
5649 *ctxlen = len;
5650 return 0;
5651}
Michael LeMayd7200242006-06-22 14:47:17 -07005652#ifdef CONFIG_KEYS
5653
David Howellsd84f4f92008-11-14 10:39:23 +11005654static int selinux_key_alloc(struct key *k, const struct cred *cred,
David Howells7e047ef2006-06-26 00:24:50 -07005655 unsigned long flags)
Michael LeMayd7200242006-06-22 14:47:17 -07005656{
David Howellsd84f4f92008-11-14 10:39:23 +11005657 const struct task_security_struct *tsec;
Michael LeMayd7200242006-06-22 14:47:17 -07005658 struct key_security_struct *ksec;
5659
5660 ksec = kzalloc(sizeof(struct key_security_struct), GFP_KERNEL);
5661 if (!ksec)
5662 return -ENOMEM;
5663
David Howellsd84f4f92008-11-14 10:39:23 +11005664 tsec = cred->security;
5665 if (tsec->keycreate_sid)
5666 ksec->sid = tsec->keycreate_sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005667 else
David Howellsd84f4f92008-11-14 10:39:23 +11005668 ksec->sid = tsec->sid;
Michael LeMayd7200242006-06-22 14:47:17 -07005669
David Howells275bb412008-11-14 10:39:19 +11005670 k->security = ksec;
Michael LeMayd7200242006-06-22 14:47:17 -07005671 return 0;
5672}
5673
5674static void selinux_key_free(struct key *k)
5675{
5676 struct key_security_struct *ksec = k->security;
5677
5678 k->security = NULL;
5679 kfree(ksec);
5680}
5681
5682static int selinux_key_permission(key_ref_t key_ref,
David Howellsd84f4f92008-11-14 10:39:23 +11005683 const struct cred *cred,
5684 key_perm_t perm)
Michael LeMayd7200242006-06-22 14:47:17 -07005685{
5686 struct key *key;
Michael LeMayd7200242006-06-22 14:47:17 -07005687 struct key_security_struct *ksec;
David Howells275bb412008-11-14 10:39:19 +11005688 u32 sid;
Michael LeMayd7200242006-06-22 14:47:17 -07005689
5690 /* if no specific permissions are requested, we skip the
5691 permission check. No serious, additional covert channels
5692 appear to be created. */
5693 if (perm == 0)
5694 return 0;
5695
David Howellsd84f4f92008-11-14 10:39:23 +11005696 sid = cred_sid(cred);
David Howells275bb412008-11-14 10:39:19 +11005697
5698 key = key_ref_to_ptr(key_ref);
5699 ksec = key->security;
5700
5701 return avc_has_perm(sid, ksec->sid, SECCLASS_KEY, perm, NULL);
Michael LeMayd7200242006-06-22 14:47:17 -07005702}
5703
David Howells70a5bb72008-04-29 01:01:26 -07005704static int selinux_key_getsecurity(struct key *key, char **_buffer)
5705{
5706 struct key_security_struct *ksec = key->security;
5707 char *context = NULL;
5708 unsigned len;
5709 int rc;
5710
5711 rc = security_sid_to_context(ksec->sid, &context, &len);
5712 if (!rc)
5713 rc = len;
5714 *_buffer = context;
5715 return rc;
5716}
5717
Michael LeMayd7200242006-06-22 14:47:17 -07005718#endif
5719
Linus Torvalds1da177e2005-04-16 15:20:36 -07005720static struct security_operations selinux_ops = {
Ahmed S. Darwish076c54c2008-03-06 18:09:10 +02005721 .name = "selinux",
5722
Stephen Smalley48a23702012-11-05 08:15:34 -05005723 .binder_set_context_mgr = selinux_binder_set_context_mgr,
5724 .binder_transaction = selinux_binder_transaction,
5725 .binder_transfer_binder = selinux_binder_transfer_binder,
5726 .binder_transfer_file = selinux_binder_transfer_file,
5727
Ingo Molnar9e488582009-05-07 19:26:19 +10005728 .ptrace_access_check = selinux_ptrace_access_check,
David Howells5cd9c582008-08-14 11:37:28 +01005729 .ptrace_traceme = selinux_ptrace_traceme,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005730 .capget = selinux_capget,
David Howellsd84f4f92008-11-14 10:39:23 +11005731 .capset = selinux_capset,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005732 .capable = selinux_capable,
5733 .quotactl = selinux_quotactl,
5734 .quota_on = selinux_quota_on,
5735 .syslog = selinux_syslog,
5736 .vm_enough_memory = selinux_vm_enough_memory,
5737
5738 .netlink_send = selinux_netlink_send,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005739
David Howellsa6f76f22008-11-14 10:39:24 +11005740 .bprm_set_creds = selinux_bprm_set_creds,
David Howellsa6f76f22008-11-14 10:39:24 +11005741 .bprm_committing_creds = selinux_bprm_committing_creds,
5742 .bprm_committed_creds = selinux_bprm_committed_creds,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005743 .bprm_secureexec = selinux_bprm_secureexec,
5744
5745 .sb_alloc_security = selinux_sb_alloc_security,
5746 .sb_free_security = selinux_sb_free_security,
5747 .sb_copy_data = selinux_sb_copy_data,
Eric Paris026eb162011-03-03 16:09:14 -05005748 .sb_remount = selinux_sb_remount,
Eric Paris828dfe12008-04-17 13:17:49 -04005749 .sb_kern_mount = selinux_sb_kern_mount,
Eric Paris2069f452008-07-04 09:47:13 +10005750 .sb_show_options = selinux_sb_show_options,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005751 .sb_statfs = selinux_sb_statfs,
5752 .sb_mount = selinux_mount,
5753 .sb_umount = selinux_umount,
Eric Parisc9180a52007-11-30 13:00:35 -05005754 .sb_set_mnt_opts = selinux_set_mnt_opts,
Eric Paris828dfe12008-04-17 13:17:49 -04005755 .sb_clone_mnt_opts = selinux_sb_clone_mnt_opts,
Eric Parise0007522008-03-05 10:31:54 -05005756 .sb_parse_opts_str = selinux_parse_opts_str,
5757
Linus Torvalds1da177e2005-04-16 15:20:36 -07005758
5759 .inode_alloc_security = selinux_inode_alloc_security,
5760 .inode_free_security = selinux_inode_free_security,
Stephen Smalley5e41ff92005-09-09 13:01:35 -07005761 .inode_init_security = selinux_inode_init_security,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005762 .inode_create = selinux_inode_create,
Amir Samuelov6a22e462014-05-26 11:44:06 +03005763 .inode_post_create = selinux_inode_post_create,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005764 .inode_link = selinux_inode_link,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005765 .inode_unlink = selinux_inode_unlink,
5766 .inode_symlink = selinux_inode_symlink,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005767 .inode_mkdir = selinux_inode_mkdir,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005768 .inode_rmdir = selinux_inode_rmdir,
5769 .inode_mknod = selinux_inode_mknod,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005770 .inode_rename = selinux_inode_rename,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005771 .inode_readlink = selinux_inode_readlink,
5772 .inode_follow_link = selinux_inode_follow_link,
5773 .inode_permission = selinux_inode_permission,
5774 .inode_setattr = selinux_inode_setattr,
5775 .inode_getattr = selinux_inode_getattr,
5776 .inode_setxattr = selinux_inode_setxattr,
5777 .inode_post_setxattr = selinux_inode_post_setxattr,
5778 .inode_getxattr = selinux_inode_getxattr,
5779 .inode_listxattr = selinux_inode_listxattr,
5780 .inode_removexattr = selinux_inode_removexattr,
Eric Paris828dfe12008-04-17 13:17:49 -04005781 .inode_getsecurity = selinux_inode_getsecurity,
5782 .inode_setsecurity = selinux_inode_setsecurity,
5783 .inode_listsecurity = selinux_inode_listsecurity,
Eric Parisf5269712008-05-14 11:27:45 -04005784 .inode_getsecid = selinux_inode_getsecid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005785
5786 .file_permission = selinux_file_permission,
5787 .file_alloc_security = selinux_file_alloc_security,
5788 .file_free_security = selinux_file_free_security,
5789 .file_ioctl = selinux_file_ioctl,
5790 .file_mmap = selinux_file_mmap,
5791 .file_mprotect = selinux_file_mprotect,
5792 .file_lock = selinux_file_lock,
5793 .file_fcntl = selinux_file_fcntl,
5794 .file_set_fowner = selinux_file_set_fowner,
5795 .file_send_sigiotask = selinux_file_send_sigiotask,
5796 .file_receive = selinux_file_receive,
5797
Eric Paris828dfe12008-04-17 13:17:49 -04005798 .dentry_open = selinux_dentry_open,
Amir Samuelov6a22e462014-05-26 11:44:06 +03005799 .file_close = selinux_file_close,
5800 .allow_merge_bio = selinux_allow_merge_bio,
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09005801
Linus Torvalds1da177e2005-04-16 15:20:36 -07005802 .task_create = selinux_task_create,
David Howellsee18d642009-09-02 09:14:21 +01005803 .cred_alloc_blank = selinux_cred_alloc_blank,
David Howellsf1752ee2008-11-14 10:39:17 +11005804 .cred_free = selinux_cred_free,
David Howellsd84f4f92008-11-14 10:39:23 +11005805 .cred_prepare = selinux_cred_prepare,
David Howellsee18d642009-09-02 09:14:21 +01005806 .cred_transfer = selinux_cred_transfer,
David Howells3a3b7ce2008-11-14 10:39:28 +11005807 .kernel_act_as = selinux_kernel_act_as,
5808 .kernel_create_files_as = selinux_kernel_create_files_as,
Eric Paris25354c42009-08-13 09:45:03 -04005809 .kernel_module_request = selinux_kernel_module_request,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005810 .task_setpgid = selinux_task_setpgid,
5811 .task_getpgid = selinux_task_getpgid,
Eric Paris828dfe12008-04-17 13:17:49 -04005812 .task_getsid = selinux_task_getsid,
David Quigleyf9008e42006-06-30 01:55:46 -07005813 .task_getsecid = selinux_task_getsecid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005814 .task_setnice = selinux_task_setnice,
James Morris03e68062006-06-23 02:03:58 -07005815 .task_setioprio = selinux_task_setioprio,
David Quigleya1836a42006-06-30 01:55:49 -07005816 .task_getioprio = selinux_task_getioprio,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005817 .task_setrlimit = selinux_task_setrlimit,
5818 .task_setscheduler = selinux_task_setscheduler,
5819 .task_getscheduler = selinux_task_getscheduler,
David Quigley35601542006-06-23 02:04:01 -07005820 .task_movememory = selinux_task_movememory,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005821 .task_kill = selinux_task_kill,
5822 .task_wait = selinux_task_wait,
Eric Paris828dfe12008-04-17 13:17:49 -04005823 .task_to_inode = selinux_task_to_inode,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005824
5825 .ipc_permission = selinux_ipc_permission,
Eric Parisf5269712008-05-14 11:27:45 -04005826 .ipc_getsecid = selinux_ipc_getsecid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005827
5828 .msg_msg_alloc_security = selinux_msg_msg_alloc_security,
5829 .msg_msg_free_security = selinux_msg_msg_free_security,
5830
5831 .msg_queue_alloc_security = selinux_msg_queue_alloc_security,
5832 .msg_queue_free_security = selinux_msg_queue_free_security,
5833 .msg_queue_associate = selinux_msg_queue_associate,
5834 .msg_queue_msgctl = selinux_msg_queue_msgctl,
5835 .msg_queue_msgsnd = selinux_msg_queue_msgsnd,
5836 .msg_queue_msgrcv = selinux_msg_queue_msgrcv,
5837
5838 .shm_alloc_security = selinux_shm_alloc_security,
5839 .shm_free_security = selinux_shm_free_security,
5840 .shm_associate = selinux_shm_associate,
5841 .shm_shmctl = selinux_shm_shmctl,
5842 .shm_shmat = selinux_shm_shmat,
5843
Eric Paris828dfe12008-04-17 13:17:49 -04005844 .sem_alloc_security = selinux_sem_alloc_security,
5845 .sem_free_security = selinux_sem_free_security,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005846 .sem_associate = selinux_sem_associate,
5847 .sem_semctl = selinux_sem_semctl,
5848 .sem_semop = selinux_sem_semop,
5849
Eric Paris828dfe12008-04-17 13:17:49 -04005850 .d_instantiate = selinux_d_instantiate,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005851
Eric Paris828dfe12008-04-17 13:17:49 -04005852 .getprocattr = selinux_getprocattr,
5853 .setprocattr = selinux_setprocattr,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005854
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005855 .secid_to_secctx = selinux_secid_to_secctx,
David Howells63cb3442008-01-15 23:47:35 +00005856 .secctx_to_secid = selinux_secctx_to_secid,
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005857 .release_secctx = selinux_release_secctx,
David P. Quigley1ee65e32009-09-03 14:25:57 -04005858 .inode_notifysecctx = selinux_inode_notifysecctx,
5859 .inode_setsecctx = selinux_inode_setsecctx,
5860 .inode_getsecctx = selinux_inode_getsecctx,
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005861
Eric Paris828dfe12008-04-17 13:17:49 -04005862 .unix_stream_connect = selinux_socket_unix_stream_connect,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005863 .unix_may_send = selinux_socket_unix_may_send,
5864
5865 .socket_create = selinux_socket_create,
5866 .socket_post_create = selinux_socket_post_create,
5867 .socket_bind = selinux_socket_bind,
5868 .socket_connect = selinux_socket_connect,
5869 .socket_listen = selinux_socket_listen,
5870 .socket_accept = selinux_socket_accept,
5871 .socket_sendmsg = selinux_socket_sendmsg,
5872 .socket_recvmsg = selinux_socket_recvmsg,
5873 .socket_getsockname = selinux_socket_getsockname,
5874 .socket_getpeername = selinux_socket_getpeername,
5875 .socket_getsockopt = selinux_socket_getsockopt,
5876 .socket_setsockopt = selinux_socket_setsockopt,
5877 .socket_shutdown = selinux_socket_shutdown,
5878 .socket_sock_rcv_skb = selinux_socket_sock_rcv_skb,
Catherine Zhang2c7946a2006-03-20 22:41:23 -08005879 .socket_getpeersec_stream = selinux_socket_getpeersec_stream,
5880 .socket_getpeersec_dgram = selinux_socket_getpeersec_dgram,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005881 .sk_alloc_security = selinux_sk_alloc_security,
5882 .sk_free_security = selinux_sk_free_security,
Venkat Yekkirala892c1412006-08-04 23:08:56 -07005883 .sk_clone_security = selinux_sk_clone_security,
Eric Paris828dfe12008-04-17 13:17:49 -04005884 .sk_getsecid = selinux_sk_getsecid,
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005885 .sock_graft = selinux_sock_graft,
5886 .inet_conn_request = selinux_inet_conn_request,
5887 .inet_csk_clone = selinux_inet_csk_clone,
Venkat Yekkirala6b877692006-11-08 17:04:09 -06005888 .inet_conn_established = selinux_inet_conn_established,
Eric Paris2606fd12010-10-13 16:24:41 -04005889 .secmark_relabel_packet = selinux_secmark_relabel_packet,
5890 .secmark_refcount_inc = selinux_secmark_refcount_inc,
5891 .secmark_refcount_dec = selinux_secmark_refcount_dec,
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005892 .req_classify_flow = selinux_req_classify_flow,
Paul Mooreed6d76e2009-08-28 18:12:49 -04005893 .tun_dev_create = selinux_tun_dev_create,
5894 .tun_dev_post_create = selinux_tun_dev_post_create,
5895 .tun_dev_attach = selinux_tun_dev_attach,
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005896
5897#ifdef CONFIG_SECURITY_NETWORK_XFRM
5898 .xfrm_policy_alloc_security = selinux_xfrm_policy_alloc,
5899 .xfrm_policy_clone_security = selinux_xfrm_policy_clone,
5900 .xfrm_policy_free_security = selinux_xfrm_policy_free,
Catherine Zhangc8c05a82006-06-08 23:39:49 -07005901 .xfrm_policy_delete_security = selinux_xfrm_policy_delete,
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005902 .xfrm_state_alloc_security = selinux_xfrm_state_alloc,
5903 .xfrm_state_free_security = selinux_xfrm_state_free,
Catherine Zhangc8c05a82006-06-08 23:39:49 -07005904 .xfrm_state_delete_security = selinux_xfrm_state_delete,
Eric Paris828dfe12008-04-17 13:17:49 -04005905 .xfrm_policy_lookup = selinux_xfrm_policy_lookup,
Venkat Yekkiralae0d1caa2006-07-24 23:29:07 -07005906 .xfrm_state_pol_flow_match = selinux_xfrm_state_pol_flow_match,
Venkat Yekkiralae0d1caa2006-07-24 23:29:07 -07005907 .xfrm_decode_session = selinux_xfrm_decode_session,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005908#endif
Michael LeMayd7200242006-06-22 14:47:17 -07005909
5910#ifdef CONFIG_KEYS
Eric Paris828dfe12008-04-17 13:17:49 -04005911 .key_alloc = selinux_key_alloc,
5912 .key_free = selinux_key_free,
5913 .key_permission = selinux_key_permission,
David Howells70a5bb72008-04-29 01:01:26 -07005914 .key_getsecurity = selinux_key_getsecurity,
Michael LeMayd7200242006-06-22 14:47:17 -07005915#endif
Ahmed S. Darwish9d57a7f2008-03-01 22:03:14 +02005916
5917#ifdef CONFIG_AUDIT
5918 .audit_rule_init = selinux_audit_rule_init,
5919 .audit_rule_known = selinux_audit_rule_known,
5920 .audit_rule_match = selinux_audit_rule_match,
5921 .audit_rule_free = selinux_audit_rule_free,
5922#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07005923};
5924
5925static __init int selinux_init(void)
5926{
Ahmed S. Darwish076c54c2008-03-06 18:09:10 +02005927 if (!security_module_enable(&selinux_ops)) {
5928 selinux_enabled = 0;
5929 return 0;
5930 }
5931
Linus Torvalds1da177e2005-04-16 15:20:36 -07005932 if (!selinux_enabled) {
5933 printk(KERN_INFO "SELinux: Disabled at boot.\n");
5934 return 0;
5935 }
5936
5937 printk(KERN_INFO "SELinux: Initializing.\n");
5938
5939 /* Set the security state for the initial task. */
David Howellsd84f4f92008-11-14 10:39:23 +11005940 cred_init_security();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005941
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04005942 default_noexec = !(VM_DATA_DEFAULT_FLAGS & VM_EXEC);
5943
James Morris7cae7e22006-03-22 00:09:22 -08005944 sel_inode_cache = kmem_cache_create("selinux_inode_security",
5945 sizeof(struct inode_security_struct),
Paul Mundt20c2df82007-07-20 10:11:58 +09005946 0, SLAB_PANIC, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005947 avc_init();
5948
Eric Paris828dfe12008-04-17 13:17:49 -04005949 if (register_security(&selinux_ops))
Linus Torvalds1da177e2005-04-16 15:20:36 -07005950 panic("SELinux: Unable to register with kernel.\n");
5951
Eric Paris828dfe12008-04-17 13:17:49 -04005952 if (selinux_enforcing)
Eric Parisfadcdb42007-02-22 18:11:31 -05005953 printk(KERN_DEBUG "SELinux: Starting in enforcing mode\n");
Eric Paris828dfe12008-04-17 13:17:49 -04005954 else
Eric Parisfadcdb42007-02-22 18:11:31 -05005955 printk(KERN_DEBUG "SELinux: Starting in permissive mode\n");
Michael LeMayd7200242006-06-22 14:47:17 -07005956
Linus Torvalds1da177e2005-04-16 15:20:36 -07005957 return 0;
5958}
5959
Al Viroe8c26252010-03-23 06:36:54 -04005960static void delayed_superblock_init(struct super_block *sb, void *unused)
5961{
5962 superblock_doinit(sb, NULL);
5963}
5964
Linus Torvalds1da177e2005-04-16 15:20:36 -07005965void selinux_complete_init(void)
5966{
Eric Parisfadcdb42007-02-22 18:11:31 -05005967 printk(KERN_DEBUG "SELinux: Completing initialization.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005968
5969 /* Set up any superblocks initialized prior to the policy load. */
Eric Parisfadcdb42007-02-22 18:11:31 -05005970 printk(KERN_DEBUG "SELinux: Setting up existing superblocks.\n");
Al Viroe8c26252010-03-23 06:36:54 -04005971 iterate_supers(delayed_superblock_init, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005972}
5973
5974/* SELinux requires early initialization in order to label
5975 all processes and objects when they are created. */
5976security_initcall(selinux_init);
5977
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08005978#if defined(CONFIG_NETFILTER)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005979
Paul Mooreeffad8d2008-01-29 08:49:27 -05005980static struct nf_hook_ops selinux_ipv4_ops[] = {
5981 {
5982 .hook = selinux_ipv4_postroute,
5983 .owner = THIS_MODULE,
5984 .pf = PF_INET,
5985 .hooknum = NF_INET_POST_ROUTING,
5986 .priority = NF_IP_PRI_SELINUX_LAST,
5987 },
5988 {
5989 .hook = selinux_ipv4_forward,
5990 .owner = THIS_MODULE,
5991 .pf = PF_INET,
5992 .hooknum = NF_INET_FORWARD,
5993 .priority = NF_IP_PRI_SELINUX_FIRST,
Paul Moore948bf852008-10-10 10:16:32 -04005994 },
5995 {
5996 .hook = selinux_ipv4_output,
5997 .owner = THIS_MODULE,
5998 .pf = PF_INET,
5999 .hooknum = NF_INET_LOCAL_OUT,
6000 .priority = NF_IP_PRI_SELINUX_FIRST,
Paul Mooreeffad8d2008-01-29 08:49:27 -05006001 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006002};
6003
6004#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
6005
Paul Mooreeffad8d2008-01-29 08:49:27 -05006006static struct nf_hook_ops selinux_ipv6_ops[] = {
6007 {
6008 .hook = selinux_ipv6_postroute,
6009 .owner = THIS_MODULE,
6010 .pf = PF_INET6,
6011 .hooknum = NF_INET_POST_ROUTING,
6012 .priority = NF_IP6_PRI_SELINUX_LAST,
6013 },
6014 {
6015 .hook = selinux_ipv6_forward,
6016 .owner = THIS_MODULE,
6017 .pf = PF_INET6,
6018 .hooknum = NF_INET_FORWARD,
6019 .priority = NF_IP6_PRI_SELINUX_FIRST,
6020 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006021};
6022
6023#endif /* IPV6 */
6024
6025static int __init selinux_nf_ip_init(void)
6026{
6027 int err = 0;
6028
6029 if (!selinux_enabled)
6030 goto out;
Eric Parisfadcdb42007-02-22 18:11:31 -05006031
6032 printk(KERN_DEBUG "SELinux: Registering netfilter hooks\n");
6033
Alexey Dobriyan6c5a9d22008-07-26 17:48:15 -07006034 err = nf_register_hooks(selinux_ipv4_ops, ARRAY_SIZE(selinux_ipv4_ops));
6035 if (err)
6036 panic("SELinux: nf_register_hooks for IPv4: error %d\n", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006037
6038#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Alexey Dobriyan6c5a9d22008-07-26 17:48:15 -07006039 err = nf_register_hooks(selinux_ipv6_ops, ARRAY_SIZE(selinux_ipv6_ops));
6040 if (err)
6041 panic("SELinux: nf_register_hooks for IPv6: error %d\n", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006042#endif /* IPV6 */
Trent Jaegerd28d1e02005-12-13 23:12:40 -08006043
Linus Torvalds1da177e2005-04-16 15:20:36 -07006044out:
6045 return err;
6046}
6047
6048__initcall(selinux_nf_ip_init);
6049
6050#ifdef CONFIG_SECURITY_SELINUX_DISABLE
6051static void selinux_nf_ip_exit(void)
6052{
Eric Parisfadcdb42007-02-22 18:11:31 -05006053 printk(KERN_DEBUG "SELinux: Unregistering netfilter hooks\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07006054
Alexey Dobriyan6c5a9d22008-07-26 17:48:15 -07006055 nf_unregister_hooks(selinux_ipv4_ops, ARRAY_SIZE(selinux_ipv4_ops));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006056#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Alexey Dobriyan6c5a9d22008-07-26 17:48:15 -07006057 nf_unregister_hooks(selinux_ipv6_ops, ARRAY_SIZE(selinux_ipv6_ops));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006058#endif /* IPV6 */
6059}
6060#endif
6061
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08006062#else /* CONFIG_NETFILTER */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006063
6064#ifdef CONFIG_SECURITY_SELINUX_DISABLE
6065#define selinux_nf_ip_exit()
6066#endif
6067
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08006068#endif /* CONFIG_NETFILTER */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006069
6070#ifdef CONFIG_SECURITY_SELINUX_DISABLE
Eric Paris828dfe12008-04-17 13:17:49 -04006071static int selinux_disabled;
6072
Linus Torvalds1da177e2005-04-16 15:20:36 -07006073int selinux_disable(void)
6074{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006075 if (ss_initialized) {
6076 /* Not permitted after initial policy load. */
6077 return -EINVAL;
6078 }
6079
6080 if (selinux_disabled) {
6081 /* Only do this once. */
6082 return -EINVAL;
6083 }
6084
6085 printk(KERN_INFO "SELinux: Disabled at runtime.\n");
6086
6087 selinux_disabled = 1;
Stephen Smalley30d55282006-05-03 10:52:36 -04006088 selinux_enabled = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006089
wzt.wzt@gmail.com189b3b12010-02-23 23:15:28 +08006090 reset_security_ops();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006091
Eric Parisaf8ff042009-09-20 21:23:01 -04006092 /* Try to destroy the avc node cache */
6093 avc_disable();
6094
Linus Torvalds1da177e2005-04-16 15:20:36 -07006095 /* Unregister netfilter hooks. */
6096 selinux_nf_ip_exit();
6097
6098 /* Unregister selinuxfs. */
6099 exit_sel_fs();
6100
6101 return 0;
6102}
6103#endif