blob: f3b54466a0378bae4004289170bdac49c00b8b08 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * NSA Security-Enhanced Linux (SELinux) security module
3 *
4 * This file contains the SELinux hook function implementations.
5 *
6 * Authors: Stephen Smalley, <sds@epoch.ncsc.mil>
Eric Paris828dfe12008-04-17 13:17:49 -04007 * Chris Vance, <cvance@nai.com>
8 * Wayne Salamon, <wsalamon@nai.com>
9 * James Morris <jmorris@redhat.com>
Linus Torvalds1da177e2005-04-16 15:20:36 -070010 *
11 * Copyright (C) 2001,2002 Networks Associates Technology, Inc.
Eric Paris2069f452008-07-04 09:47:13 +100012 * Copyright (C) 2003-2008 Red Hat, Inc., James Morris <jmorris@redhat.com>
13 * Eric Paris <eparis@redhat.com>
Linus Torvalds1da177e2005-04-16 15:20:36 -070014 * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
Eric Paris828dfe12008-04-17 13:17:49 -040015 * <dgoeddel@trustedcs.com>
Paul Mooreed6d76e2009-08-28 18:12:49 -040016 * Copyright (C) 2006, 2007, 2009 Hewlett-Packard Development Company, L.P.
Paul Moore82c21bf2011-08-01 11:10:33 +000017 * Paul Moore <paul@paul-moore.com>
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +090018 * Copyright (C) 2007 Hitachi Software Engineering Co., Ltd.
Eric Paris828dfe12008-04-17 13:17:49 -040019 * Yuichi Nakamura <ynakam@hitachisoft.jp>
Linus Torvalds1da177e2005-04-16 15:20:36 -070020 *
21 * This program is free software; you can redistribute it and/or modify
22 * it under the terms of the GNU General Public License version 2,
Eric Paris828dfe12008-04-17 13:17:49 -040023 * as published by the Free Software Foundation.
Linus Torvalds1da177e2005-04-16 15:20:36 -070024 */
25
Linus Torvalds1da177e2005-04-16 15:20:36 -070026#include <linux/init.h>
Eric Paris0b24dcb2011-02-25 15:39:20 -050027#include <linux/kd.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070028#include <linux/kernel.h>
Roland McGrath0d094ef2008-07-25 19:45:49 -070029#include <linux/tracehook.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070030#include <linux/errno.h>
31#include <linux/sched.h>
32#include <linux/security.h>
33#include <linux/xattr.h>
34#include <linux/capability.h>
35#include <linux/unistd.h>
36#include <linux/mm.h>
37#include <linux/mman.h>
38#include <linux/slab.h>
39#include <linux/pagemap.h>
Eric Paris0b24dcb2011-02-25 15:39:20 -050040#include <linux/proc_fs.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070041#include <linux/swap.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070042#include <linux/spinlock.h>
43#include <linux/syscalls.h>
Eric Paris2a7dba32011-02-01 11:05:39 -050044#include <linux/dcache.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070045#include <linux/file.h>
Al Viro9f3acc32008-04-24 07:44:08 -040046#include <linux/fdtable.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070047#include <linux/namei.h>
48#include <linux/mount.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070049#include <linux/netfilter_ipv4.h>
50#include <linux/netfilter_ipv6.h>
51#include <linux/tty.h>
52#include <net/icmp.h>
Stephen Hemminger227b60f2007-10-10 17:30:46 -070053#include <net/ip.h> /* for local_port_range[] */
Eric Dumazetca10b9e2013-04-08 17:58:11 +000054#include <net/sock.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070055#include <net/tcp.h> /* struct or_callable used in sock_rcv_skb */
Paul Moore220deb92008-01-29 08:38:23 -050056#include <net/net_namespace.h>
Paul Moored621d352008-01-29 08:43:36 -050057#include <net/netlabel.h>
Eric Parisf5269712008-05-14 11:27:45 -040058#include <linux/uaccess.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070059#include <asm/ioctls.h>
Arun Sharma600634972011-07-26 16:09:06 -070060#include <linux/atomic.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070061#include <linux/bitops.h>
62#include <linux/interrupt.h>
63#include <linux/netdevice.h> /* for network interface checks */
Hong zhi guo77954982013-03-27 06:49:35 +000064#include <net/netlink.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070065#include <linux/tcp.h>
66#include <linux/udp.h>
James Morris2ee92d42006-11-13 16:09:01 -080067#include <linux/dccp.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070068#include <linux/quota.h>
69#include <linux/un.h> /* for Unix socket types */
70#include <net/af_unix.h> /* for Unix socket types */
71#include <linux/parser.h>
72#include <linux/nfs_mount.h>
73#include <net/ipv6.h>
74#include <linux/hugetlb.h>
75#include <linux/personality.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070076#include <linux/audit.h>
Eric Paris6931dfc2005-06-30 02:58:51 -070077#include <linux/string.h>
Catherine Zhang877ce7c2006-06-29 12:27:47 -070078#include <linux/selinux.h>
Eric Paris23970742006-09-25 23:32:01 -070079#include <linux/mutex.h>
Frank Mayharf06febc2008-09-12 09:54:39 -070080#include <linux/posix-timers.h>
Kees Cook00234592010-02-03 15:36:43 -080081#include <linux/syslog.h>
Serge E. Hallyn34867402011-03-23 16:43:17 -070082#include <linux/user_namespace.h>
Paul Gortmaker44fc7ea2011-05-26 20:52:10 -040083#include <linux/export.h>
Al Viro40401532012-02-13 03:58:52 +000084#include <linux/msg.h>
85#include <linux/shm.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070086
87#include "avc.h"
88#include "objsec.h"
89#include "netif.h"
Paul Moore224dfbd2008-01-29 08:38:13 -050090#include "netnode.h"
Paul Moore3e112172008-04-10 10:48:14 -040091#include "netport.h"
Trent Jaegerd28d1e02005-12-13 23:12:40 -080092#include "xfrm.h"
Paul Moorec60475b2007-02-28 15:14:23 -050093#include "netlabel.h"
Ahmed S. Darwish9d57a7f2008-03-01 22:03:14 +020094#include "audit.h"
James Morris7b98a582011-08-30 12:52:32 +100095#include "avc_ss.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070096
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
David P. Quigleyddd29ec2009-09-09 14:25:37 -0400405 /* Special handling for sysfs. Is genfs but also has setxattr handler*/
406 if (strncmp(sb->s_type->name, "sysfs", sizeof("sysfs")) == 0)
407 sbsec->flags |= SE_SBLABELSUPP;
408
Linus Torvalds1da177e2005-04-16 15:20:36 -0700409 /* Initialize the root inode. */
Eric Parisc9180a52007-11-30 13:00:35 -0500410 rc = inode_doinit_with_dentry(root_inode, root);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700411
412 /* Initialize any other inodes associated with the superblock, e.g.
413 inodes created prior to initial policy load or inodes created
414 during get_sb by a pseudo filesystem that directly
415 populates itself. */
416 spin_lock(&sbsec->isec_lock);
417next_inode:
418 if (!list_empty(&sbsec->isec_head)) {
419 struct inode_security_struct *isec =
420 list_entry(sbsec->isec_head.next,
Eric Parisc9180a52007-11-30 13:00:35 -0500421 struct inode_security_struct, list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422 struct inode *inode = isec->inode;
423 spin_unlock(&sbsec->isec_lock);
424 inode = igrab(inode);
425 if (inode) {
Eric Parisc9180a52007-11-30 13:00:35 -0500426 if (!IS_PRIVATE(inode))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700427 inode_doinit(inode);
428 iput(inode);
429 }
430 spin_lock(&sbsec->isec_lock);
431 list_del_init(&isec->list);
432 goto next_inode;
433 }
434 spin_unlock(&sbsec->isec_lock);
435out:
Eric Parisc9180a52007-11-30 13:00:35 -0500436 return rc;
437}
438
439/*
440 * This function should allow an FS to ask what it's mount security
441 * options were so it can use those later for submounts, displaying
442 * mount options, or whatever.
443 */
444static int selinux_get_mnt_opts(const struct super_block *sb,
Eric Parise0007522008-03-05 10:31:54 -0500445 struct security_mnt_opts *opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500446{
447 int rc = 0, i;
448 struct superblock_security_struct *sbsec = sb->s_security;
449 char *context = NULL;
450 u32 len;
451 char tmp;
452
Eric Parise0007522008-03-05 10:31:54 -0500453 security_init_mnt_opts(opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500454
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500455 if (!(sbsec->flags & SE_SBINITIALIZED))
Eric Parisc9180a52007-11-30 13:00:35 -0500456 return -EINVAL;
457
458 if (!ss_initialized)
459 return -EINVAL;
460
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500461 tmp = sbsec->flags & SE_MNTMASK;
Eric Parisc9180a52007-11-30 13:00:35 -0500462 /* count the number of mount options for this sb */
463 for (i = 0; i < 8; i++) {
464 if (tmp & 0x01)
Eric Parise0007522008-03-05 10:31:54 -0500465 opts->num_mnt_opts++;
Eric Parisc9180a52007-11-30 13:00:35 -0500466 tmp >>= 1;
467 }
David P. Quigley11689d42009-01-16 09:22:03 -0500468 /* Check if the Label support flag is set */
469 if (sbsec->flags & SE_SBLABELSUPP)
470 opts->num_mnt_opts++;
Eric Parisc9180a52007-11-30 13:00:35 -0500471
Eric Parise0007522008-03-05 10:31:54 -0500472 opts->mnt_opts = kcalloc(opts->num_mnt_opts, sizeof(char *), GFP_ATOMIC);
473 if (!opts->mnt_opts) {
Eric Parisc9180a52007-11-30 13:00:35 -0500474 rc = -ENOMEM;
475 goto out_free;
476 }
477
Eric Parise0007522008-03-05 10:31:54 -0500478 opts->mnt_opts_flags = kcalloc(opts->num_mnt_opts, sizeof(int), GFP_ATOMIC);
479 if (!opts->mnt_opts_flags) {
Eric Parisc9180a52007-11-30 13:00:35 -0500480 rc = -ENOMEM;
481 goto out_free;
482 }
483
484 i = 0;
485 if (sbsec->flags & FSCONTEXT_MNT) {
486 rc = security_sid_to_context(sbsec->sid, &context, &len);
487 if (rc)
488 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500489 opts->mnt_opts[i] = context;
490 opts->mnt_opts_flags[i++] = FSCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500491 }
492 if (sbsec->flags & CONTEXT_MNT) {
493 rc = security_sid_to_context(sbsec->mntpoint_sid, &context, &len);
494 if (rc)
495 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500496 opts->mnt_opts[i] = context;
497 opts->mnt_opts_flags[i++] = CONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500498 }
499 if (sbsec->flags & DEFCONTEXT_MNT) {
500 rc = security_sid_to_context(sbsec->def_sid, &context, &len);
501 if (rc)
502 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500503 opts->mnt_opts[i] = context;
504 opts->mnt_opts_flags[i++] = DEFCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500505 }
506 if (sbsec->flags & ROOTCONTEXT_MNT) {
507 struct inode *root = sbsec->sb->s_root->d_inode;
508 struct inode_security_struct *isec = root->i_security;
509
510 rc = security_sid_to_context(isec->sid, &context, &len);
511 if (rc)
512 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500513 opts->mnt_opts[i] = context;
514 opts->mnt_opts_flags[i++] = ROOTCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500515 }
David P. Quigley11689d42009-01-16 09:22:03 -0500516 if (sbsec->flags & SE_SBLABELSUPP) {
517 opts->mnt_opts[i] = NULL;
518 opts->mnt_opts_flags[i++] = SE_SBLABELSUPP;
519 }
Eric Parisc9180a52007-11-30 13:00:35 -0500520
Eric Parise0007522008-03-05 10:31:54 -0500521 BUG_ON(i != opts->num_mnt_opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500522
523 return 0;
524
525out_free:
Eric Parise0007522008-03-05 10:31:54 -0500526 security_free_mnt_opts(opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500527 return rc;
528}
529
530static int bad_option(struct superblock_security_struct *sbsec, char flag,
531 u32 old_sid, u32 new_sid)
532{
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500533 char mnt_flags = sbsec->flags & SE_MNTMASK;
534
Eric Parisc9180a52007-11-30 13:00:35 -0500535 /* check if the old mount command had the same options */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500536 if (sbsec->flags & SE_SBINITIALIZED)
Eric Parisc9180a52007-11-30 13:00:35 -0500537 if (!(sbsec->flags & flag) ||
538 (old_sid != new_sid))
539 return 1;
540
541 /* check if we were passed the same options twice,
542 * aka someone passed context=a,context=b
543 */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500544 if (!(sbsec->flags & SE_SBINITIALIZED))
545 if (mnt_flags & flag)
Eric Parisc9180a52007-11-30 13:00:35 -0500546 return 1;
547 return 0;
548}
Eric Parise0007522008-03-05 10:31:54 -0500549
Eric Parisc9180a52007-11-30 13:00:35 -0500550/*
551 * Allow filesystems with binary mount data to explicitly set mount point
552 * labeling information.
553 */
Eric Parise0007522008-03-05 10:31:54 -0500554static int selinux_set_mnt_opts(struct super_block *sb,
David Quigley649f6e72013-05-22 12:50:36 -0400555 struct security_mnt_opts *opts,
556 unsigned long kern_flags,
557 unsigned long *set_kern_flags)
Eric Parisc9180a52007-11-30 13:00:35 -0500558{
David Howells275bb412008-11-14 10:39:19 +1100559 const struct cred *cred = current_cred();
Eric Parisc9180a52007-11-30 13:00:35 -0500560 int rc = 0, i;
Eric Parisc9180a52007-11-30 13:00:35 -0500561 struct superblock_security_struct *sbsec = sb->s_security;
562 const char *name = sb->s_type->name;
James Morris089be432008-07-15 18:32:49 +1000563 struct inode *inode = sbsec->sb->s_root->d_inode;
564 struct inode_security_struct *root_isec = inode->i_security;
Eric Parisc9180a52007-11-30 13:00:35 -0500565 u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0;
566 u32 defcontext_sid = 0;
Eric Parise0007522008-03-05 10:31:54 -0500567 char **mount_options = opts->mnt_opts;
568 int *flags = opts->mnt_opts_flags;
569 int num_opts = opts->num_mnt_opts;
Eric Parisc9180a52007-11-30 13:00:35 -0500570
571 mutex_lock(&sbsec->lock);
572
573 if (!ss_initialized) {
574 if (!num_opts) {
575 /* Defer initialization until selinux_complete_init,
576 after the initial policy is loaded and the security
577 server is ready to handle calls. */
Eric Parisc9180a52007-11-30 13:00:35 -0500578 goto out;
579 }
580 rc = -EINVAL;
Eric Paris744ba352008-04-17 11:52:44 -0400581 printk(KERN_WARNING "SELinux: Unable to set superblock options "
582 "before the security server is initialized\n");
Eric Parisc9180a52007-11-30 13:00:35 -0500583 goto out;
584 }
David Quigley649f6e72013-05-22 12:50:36 -0400585 if (kern_flags && !set_kern_flags) {
586 /* Specifying internal flags without providing a place to
587 * place the results is not allowed */
588 rc = -EINVAL;
589 goto out;
590 }
Eric Parisc9180a52007-11-30 13:00:35 -0500591
592 /*
Eric Parise0007522008-03-05 10:31:54 -0500593 * Binary mount data FS will come through this function twice. Once
594 * from an explicit call and once from the generic calls from the vfs.
595 * Since the generic VFS calls will not contain any security mount data
596 * we need to skip the double mount verification.
597 *
598 * This does open a hole in which we will not notice if the first
599 * mount using this sb set explict options and a second mount using
600 * this sb does not set any security options. (The first options
601 * will be used for both mounts)
602 */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500603 if ((sbsec->flags & SE_SBINITIALIZED) && (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)
Eric Parise0007522008-03-05 10:31:54 -0500604 && (num_opts == 0))
Eric Parisf5269712008-05-14 11:27:45 -0400605 goto out;
Eric Parise0007522008-03-05 10:31:54 -0500606
607 /*
Eric Parisc9180a52007-11-30 13:00:35 -0500608 * parse the mount options, check if they are valid sids.
609 * also check if someone is trying to mount the same sb more
610 * than once with different security options.
611 */
612 for (i = 0; i < num_opts; i++) {
613 u32 sid;
David P. Quigley11689d42009-01-16 09:22:03 -0500614
615 if (flags[i] == SE_SBLABELSUPP)
616 continue;
Eric Parisc9180a52007-11-30 13:00:35 -0500617 rc = security_context_to_sid(mount_options[i],
618 strlen(mount_options[i]), &sid);
619 if (rc) {
620 printk(KERN_WARNING "SELinux: security_context_to_sid"
621 "(%s) failed for (dev %s, type %s) errno=%d\n",
622 mount_options[i], sb->s_id, name, rc);
623 goto out;
624 }
625 switch (flags[i]) {
626 case FSCONTEXT_MNT:
627 fscontext_sid = sid;
628
629 if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid,
630 fscontext_sid))
631 goto out_double_mount;
632
633 sbsec->flags |= FSCONTEXT_MNT;
634 break;
635 case CONTEXT_MNT:
636 context_sid = sid;
637
638 if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid,
639 context_sid))
640 goto out_double_mount;
641
642 sbsec->flags |= CONTEXT_MNT;
643 break;
644 case ROOTCONTEXT_MNT:
645 rootcontext_sid = sid;
646
647 if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid,
648 rootcontext_sid))
649 goto out_double_mount;
650
651 sbsec->flags |= ROOTCONTEXT_MNT;
652
653 break;
654 case DEFCONTEXT_MNT:
655 defcontext_sid = sid;
656
657 if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid,
658 defcontext_sid))
659 goto out_double_mount;
660
661 sbsec->flags |= DEFCONTEXT_MNT;
662
663 break;
664 default:
665 rc = -EINVAL;
666 goto out;
667 }
668 }
669
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500670 if (sbsec->flags & SE_SBINITIALIZED) {
Eric Parisc9180a52007-11-30 13:00:35 -0500671 /* previously mounted with options, but not on this attempt? */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500672 if ((sbsec->flags & SE_MNTMASK) && !num_opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500673 goto out_double_mount;
674 rc = 0;
675 goto out;
676 }
677
James Morris089be432008-07-15 18:32:49 +1000678 if (strcmp(sb->s_type->name, "proc") == 0)
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500679 sbsec->flags |= SE_SBPROC;
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
Jeff Layton094f7b62013-04-01 08:14:24 -0400762static int selinux_cmp_sb_context(const struct super_block *oldsb,
763 const struct super_block *newsb)
764{
765 struct superblock_security_struct *old = oldsb->s_security;
766 struct superblock_security_struct *new = newsb->s_security;
767 char oldflags = old->flags & SE_MNTMASK;
768 char newflags = new->flags & SE_MNTMASK;
769
770 if (oldflags != newflags)
771 goto mismatch;
772 if ((oldflags & FSCONTEXT_MNT) && old->sid != new->sid)
773 goto mismatch;
774 if ((oldflags & CONTEXT_MNT) && old->mntpoint_sid != new->mntpoint_sid)
775 goto mismatch;
776 if ((oldflags & DEFCONTEXT_MNT) && old->def_sid != new->def_sid)
777 goto mismatch;
778 if (oldflags & ROOTCONTEXT_MNT) {
779 struct inode_security_struct *oldroot = oldsb->s_root->d_inode->i_security;
780 struct inode_security_struct *newroot = newsb->s_root->d_inode->i_security;
781 if (oldroot->sid != newroot->sid)
782 goto mismatch;
783 }
784 return 0;
785mismatch:
786 printk(KERN_WARNING "SELinux: mount invalid. Same superblock, "
787 "different security settings for (dev %s, "
788 "type %s)\n", newsb->s_id, newsb->s_type->name);
789 return -EBUSY;
790}
791
792static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
Eric Parisc9180a52007-11-30 13:00:35 -0500793 struct super_block *newsb)
794{
795 const struct superblock_security_struct *oldsbsec = oldsb->s_security;
796 struct superblock_security_struct *newsbsec = newsb->s_security;
797
798 int set_fscontext = (oldsbsec->flags & FSCONTEXT_MNT);
799 int set_context = (oldsbsec->flags & CONTEXT_MNT);
800 int set_rootcontext = (oldsbsec->flags & ROOTCONTEXT_MNT);
801
Eric Paris0f5e6422008-04-21 16:24:11 -0400802 /*
803 * if the parent was able to be mounted it clearly had no special lsm
Al Viroe8c26252010-03-23 06:36:54 -0400804 * mount options. thus we can safely deal with this superblock later
Eric Paris0f5e6422008-04-21 16:24:11 -0400805 */
Al Viroe8c26252010-03-23 06:36:54 -0400806 if (!ss_initialized)
Jeff Layton094f7b62013-04-01 08:14:24 -0400807 return 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500808
Eric Parisc9180a52007-11-30 13:00:35 -0500809 /* how can we clone if the old one wasn't set up?? */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500810 BUG_ON(!(oldsbsec->flags & SE_SBINITIALIZED));
Eric Parisc9180a52007-11-30 13:00:35 -0500811
Jeff Layton094f7b62013-04-01 08:14:24 -0400812 /* if fs is reusing a sb, make sure that the contexts match */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500813 if (newsbsec->flags & SE_SBINITIALIZED)
Jeff Layton094f7b62013-04-01 08:14:24 -0400814 return selinux_cmp_sb_context(oldsb, newsb);
Eric Paris5a552612008-04-09 14:08:35 -0400815
Eric Parisc9180a52007-11-30 13:00:35 -0500816 mutex_lock(&newsbsec->lock);
817
818 newsbsec->flags = oldsbsec->flags;
819
820 newsbsec->sid = oldsbsec->sid;
821 newsbsec->def_sid = oldsbsec->def_sid;
822 newsbsec->behavior = oldsbsec->behavior;
823
824 if (set_context) {
825 u32 sid = oldsbsec->mntpoint_sid;
826
827 if (!set_fscontext)
828 newsbsec->sid = sid;
829 if (!set_rootcontext) {
830 struct inode *newinode = newsb->s_root->d_inode;
831 struct inode_security_struct *newisec = newinode->i_security;
832 newisec->sid = sid;
833 }
834 newsbsec->mntpoint_sid = sid;
835 }
836 if (set_rootcontext) {
837 const struct inode *oldinode = oldsb->s_root->d_inode;
838 const struct inode_security_struct *oldisec = oldinode->i_security;
839 struct inode *newinode = newsb->s_root->d_inode;
840 struct inode_security_struct *newisec = newinode->i_security;
841
842 newisec->sid = oldisec->sid;
843 }
844
845 sb_finish_set_opts(newsb);
846 mutex_unlock(&newsbsec->lock);
Jeff Layton094f7b62013-04-01 08:14:24 -0400847 return 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500848}
849
Adrian Bunk2e1479d2008-03-17 22:29:23 +0200850static int selinux_parse_opts_str(char *options,
851 struct security_mnt_opts *opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500852{
Eric Parise0007522008-03-05 10:31:54 -0500853 char *p;
Eric Parisc9180a52007-11-30 13:00:35 -0500854 char *context = NULL, *defcontext = NULL;
855 char *fscontext = NULL, *rootcontext = NULL;
Eric Parise0007522008-03-05 10:31:54 -0500856 int rc, num_mnt_opts = 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500857
Eric Parise0007522008-03-05 10:31:54 -0500858 opts->num_mnt_opts = 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500859
860 /* Standard string-based options. */
861 while ((p = strsep(&options, "|")) != NULL) {
862 int token;
863 substring_t args[MAX_OPT_ARGS];
864
865 if (!*p)
866 continue;
867
868 token = match_token(p, tokens, args);
869
870 switch (token) {
871 case Opt_context:
872 if (context || defcontext) {
873 rc = -EINVAL;
874 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
875 goto out_err;
876 }
877 context = match_strdup(&args[0]);
878 if (!context) {
879 rc = -ENOMEM;
880 goto out_err;
881 }
882 break;
883
884 case Opt_fscontext:
885 if (fscontext) {
886 rc = -EINVAL;
887 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
888 goto out_err;
889 }
890 fscontext = match_strdup(&args[0]);
891 if (!fscontext) {
892 rc = -ENOMEM;
893 goto out_err;
894 }
895 break;
896
897 case Opt_rootcontext:
898 if (rootcontext) {
899 rc = -EINVAL;
900 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
901 goto out_err;
902 }
903 rootcontext = match_strdup(&args[0]);
904 if (!rootcontext) {
905 rc = -ENOMEM;
906 goto out_err;
907 }
908 break;
909
910 case Opt_defcontext:
911 if (context || defcontext) {
912 rc = -EINVAL;
913 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
914 goto out_err;
915 }
916 defcontext = match_strdup(&args[0]);
917 if (!defcontext) {
918 rc = -ENOMEM;
919 goto out_err;
920 }
921 break;
David P. Quigley11689d42009-01-16 09:22:03 -0500922 case Opt_labelsupport:
923 break;
Eric Parisc9180a52007-11-30 13:00:35 -0500924 default:
925 rc = -EINVAL;
926 printk(KERN_WARNING "SELinux: unknown mount option\n");
927 goto out_err;
928
929 }
930 }
931
Eric Parise0007522008-03-05 10:31:54 -0500932 rc = -ENOMEM;
933 opts->mnt_opts = kcalloc(NUM_SEL_MNT_OPTS, sizeof(char *), GFP_ATOMIC);
934 if (!opts->mnt_opts)
935 goto out_err;
936
937 opts->mnt_opts_flags = kcalloc(NUM_SEL_MNT_OPTS, sizeof(int), GFP_ATOMIC);
938 if (!opts->mnt_opts_flags) {
939 kfree(opts->mnt_opts);
940 goto out_err;
Eric Parisc9180a52007-11-30 13:00:35 -0500941 }
942
Eric Parise0007522008-03-05 10:31:54 -0500943 if (fscontext) {
944 opts->mnt_opts[num_mnt_opts] = fscontext;
945 opts->mnt_opts_flags[num_mnt_opts++] = FSCONTEXT_MNT;
946 }
947 if (context) {
948 opts->mnt_opts[num_mnt_opts] = context;
949 opts->mnt_opts_flags[num_mnt_opts++] = CONTEXT_MNT;
950 }
951 if (rootcontext) {
952 opts->mnt_opts[num_mnt_opts] = rootcontext;
953 opts->mnt_opts_flags[num_mnt_opts++] = ROOTCONTEXT_MNT;
954 }
955 if (defcontext) {
956 opts->mnt_opts[num_mnt_opts] = defcontext;
957 opts->mnt_opts_flags[num_mnt_opts++] = DEFCONTEXT_MNT;
958 }
959
960 opts->num_mnt_opts = num_mnt_opts;
961 return 0;
962
Eric Parisc9180a52007-11-30 13:00:35 -0500963out_err:
964 kfree(context);
965 kfree(defcontext);
966 kfree(fscontext);
967 kfree(rootcontext);
968 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700969}
Eric Parise0007522008-03-05 10:31:54 -0500970/*
971 * string mount options parsing and call set the sbsec
972 */
973static int superblock_doinit(struct super_block *sb, void *data)
974{
975 int rc = 0;
976 char *options = data;
977 struct security_mnt_opts opts;
978
979 security_init_mnt_opts(&opts);
980
981 if (!data)
982 goto out;
983
984 BUG_ON(sb->s_type->fs_flags & FS_BINARY_MOUNTDATA);
985
986 rc = selinux_parse_opts_str(options, &opts);
987 if (rc)
988 goto out_err;
989
990out:
David Quigley649f6e72013-05-22 12:50:36 -0400991 rc = selinux_set_mnt_opts(sb, &opts, 0, NULL);
Eric Parise0007522008-03-05 10:31:54 -0500992
993out_err:
994 security_free_mnt_opts(&opts);
995 return rc;
996}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700997
Adrian Bunk3583a712008-07-22 20:21:23 +0300998static void selinux_write_opts(struct seq_file *m,
999 struct security_mnt_opts *opts)
Eric Paris2069f452008-07-04 09:47:13 +10001000{
1001 int i;
1002 char *prefix;
1003
1004 for (i = 0; i < opts->num_mnt_opts; i++) {
David P. Quigley11689d42009-01-16 09:22:03 -05001005 char *has_comma;
1006
1007 if (opts->mnt_opts[i])
1008 has_comma = strchr(opts->mnt_opts[i], ',');
1009 else
1010 has_comma = NULL;
Eric Paris2069f452008-07-04 09:47:13 +10001011
1012 switch (opts->mnt_opts_flags[i]) {
1013 case CONTEXT_MNT:
1014 prefix = CONTEXT_STR;
1015 break;
1016 case FSCONTEXT_MNT:
1017 prefix = FSCONTEXT_STR;
1018 break;
1019 case ROOTCONTEXT_MNT:
1020 prefix = ROOTCONTEXT_STR;
1021 break;
1022 case DEFCONTEXT_MNT:
1023 prefix = DEFCONTEXT_STR;
1024 break;
David P. Quigley11689d42009-01-16 09:22:03 -05001025 case SE_SBLABELSUPP:
1026 seq_putc(m, ',');
1027 seq_puts(m, LABELSUPP_STR);
1028 continue;
Eric Paris2069f452008-07-04 09:47:13 +10001029 default:
1030 BUG();
Eric Parisa35c6c82011-04-20 10:21:28 -04001031 return;
Eric Paris2069f452008-07-04 09:47:13 +10001032 };
1033 /* we need a comma before each option */
1034 seq_putc(m, ',');
1035 seq_puts(m, prefix);
1036 if (has_comma)
1037 seq_putc(m, '\"');
1038 seq_puts(m, opts->mnt_opts[i]);
1039 if (has_comma)
1040 seq_putc(m, '\"');
1041 }
1042}
1043
1044static int selinux_sb_show_options(struct seq_file *m, struct super_block *sb)
1045{
1046 struct security_mnt_opts opts;
1047 int rc;
1048
1049 rc = selinux_get_mnt_opts(sb, &opts);
Eric Paris383795c2008-07-29 17:07:26 -04001050 if (rc) {
1051 /* before policy load we may get EINVAL, don't show anything */
1052 if (rc == -EINVAL)
1053 rc = 0;
Eric Paris2069f452008-07-04 09:47:13 +10001054 return rc;
Eric Paris383795c2008-07-29 17:07:26 -04001055 }
Eric Paris2069f452008-07-04 09:47:13 +10001056
1057 selinux_write_opts(m, &opts);
1058
1059 security_free_mnt_opts(&opts);
1060
1061 return rc;
1062}
1063
Linus Torvalds1da177e2005-04-16 15:20:36 -07001064static inline u16 inode_mode_to_security_class(umode_t mode)
1065{
1066 switch (mode & S_IFMT) {
1067 case S_IFSOCK:
1068 return SECCLASS_SOCK_FILE;
1069 case S_IFLNK:
1070 return SECCLASS_LNK_FILE;
1071 case S_IFREG:
1072 return SECCLASS_FILE;
1073 case S_IFBLK:
1074 return SECCLASS_BLK_FILE;
1075 case S_IFDIR:
1076 return SECCLASS_DIR;
1077 case S_IFCHR:
1078 return SECCLASS_CHR_FILE;
1079 case S_IFIFO:
1080 return SECCLASS_FIFO_FILE;
1081
1082 }
1083
1084 return SECCLASS_FILE;
1085}
1086
James Morris13402582005-09-30 14:24:34 -04001087static inline int default_protocol_stream(int protocol)
1088{
1089 return (protocol == IPPROTO_IP || protocol == IPPROTO_TCP);
1090}
1091
1092static inline int default_protocol_dgram(int protocol)
1093{
1094 return (protocol == IPPROTO_IP || protocol == IPPROTO_UDP);
1095}
1096
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097static inline u16 socket_type_to_security_class(int family, int type, int protocol)
1098{
1099 switch (family) {
1100 case PF_UNIX:
1101 switch (type) {
1102 case SOCK_STREAM:
1103 case SOCK_SEQPACKET:
1104 return SECCLASS_UNIX_STREAM_SOCKET;
1105 case SOCK_DGRAM:
1106 return SECCLASS_UNIX_DGRAM_SOCKET;
1107 }
1108 break;
1109 case PF_INET:
1110 case PF_INET6:
1111 switch (type) {
1112 case SOCK_STREAM:
James Morris13402582005-09-30 14:24:34 -04001113 if (default_protocol_stream(protocol))
1114 return SECCLASS_TCP_SOCKET;
1115 else
1116 return SECCLASS_RAWIP_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001117 case SOCK_DGRAM:
James Morris13402582005-09-30 14:24:34 -04001118 if (default_protocol_dgram(protocol))
1119 return SECCLASS_UDP_SOCKET;
1120 else
1121 return SECCLASS_RAWIP_SOCKET;
James Morris2ee92d42006-11-13 16:09:01 -08001122 case SOCK_DCCP:
1123 return SECCLASS_DCCP_SOCKET;
James Morris13402582005-09-30 14:24:34 -04001124 default:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001125 return SECCLASS_RAWIP_SOCKET;
1126 }
1127 break;
1128 case PF_NETLINK:
1129 switch (protocol) {
1130 case NETLINK_ROUTE:
1131 return SECCLASS_NETLINK_ROUTE_SOCKET;
1132 case NETLINK_FIREWALL:
1133 return SECCLASS_NETLINK_FIREWALL_SOCKET;
Pavel Emelyanov7f1fb602011-12-06 07:56:43 +00001134 case NETLINK_SOCK_DIAG:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001135 return SECCLASS_NETLINK_TCPDIAG_SOCKET;
1136 case NETLINK_NFLOG:
1137 return SECCLASS_NETLINK_NFLOG_SOCKET;
1138 case NETLINK_XFRM:
1139 return SECCLASS_NETLINK_XFRM_SOCKET;
1140 case NETLINK_SELINUX:
1141 return SECCLASS_NETLINK_SELINUX_SOCKET;
1142 case NETLINK_AUDIT:
1143 return SECCLASS_NETLINK_AUDIT_SOCKET;
1144 case NETLINK_IP6_FW:
1145 return SECCLASS_NETLINK_IP6FW_SOCKET;
1146 case NETLINK_DNRTMSG:
1147 return SECCLASS_NETLINK_DNRT_SOCKET;
James Morris0c9b7942005-04-16 15:24:13 -07001148 case NETLINK_KOBJECT_UEVENT:
1149 return SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001150 default:
1151 return SECCLASS_NETLINK_SOCKET;
1152 }
1153 case PF_PACKET:
1154 return SECCLASS_PACKET_SOCKET;
1155 case PF_KEY:
1156 return SECCLASS_KEY_SOCKET;
Christopher J. PeBenito3e3ff152006-06-09 00:25:03 -07001157 case PF_APPLETALK:
1158 return SECCLASS_APPLETALK_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001159 }
1160
1161 return SECCLASS_SOCKET;
1162}
1163
1164#ifdef CONFIG_PROC_FS
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001165static int selinux_proc_get_sid(struct dentry *dentry,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001166 u16 tclass,
1167 u32 *sid)
1168{
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001169 int rc;
1170 char *buffer, *path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001171
Eric Paris828dfe12008-04-17 13:17:49 -04001172 buffer = (char *)__get_free_page(GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001173 if (!buffer)
1174 return -ENOMEM;
1175
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001176 path = dentry_path_raw(dentry, buffer, PAGE_SIZE);
1177 if (IS_ERR(path))
1178 rc = PTR_ERR(path);
1179 else {
1180 /* each process gets a /proc/PID/ entry. Strip off the
1181 * PID part to get a valid selinux labeling.
1182 * e.g. /proc/1/net/rpc/nfs -> /net/rpc/nfs */
1183 while (path[1] >= '0' && path[1] <= '9') {
1184 path[1] = '/';
1185 path++;
1186 }
1187 rc = security_genfs_sid("proc", path, tclass, sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001189 free_page((unsigned long)buffer);
1190 return rc;
1191}
1192#else
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001193static int selinux_proc_get_sid(struct dentry *dentry,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001194 u16 tclass,
1195 u32 *sid)
1196{
1197 return -EINVAL;
1198}
1199#endif
1200
1201/* The inode's security attributes must be initialized before first use. */
1202static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry)
1203{
1204 struct superblock_security_struct *sbsec = NULL;
1205 struct inode_security_struct *isec = inode->i_security;
1206 u32 sid;
1207 struct dentry *dentry;
1208#define INITCONTEXTLEN 255
1209 char *context = NULL;
1210 unsigned len = 0;
1211 int rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001212
1213 if (isec->initialized)
1214 goto out;
1215
Eric Paris23970742006-09-25 23:32:01 -07001216 mutex_lock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001217 if (isec->initialized)
Eric Paris23970742006-09-25 23:32:01 -07001218 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001219
1220 sbsec = inode->i_sb->s_security;
David P. Quigley0d90a7e2009-01-16 09:22:02 -05001221 if (!(sbsec->flags & SE_SBINITIALIZED)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001222 /* Defer initialization until selinux_complete_init,
1223 after the initial policy is loaded and the security
1224 server is ready to handle calls. */
1225 spin_lock(&sbsec->isec_lock);
1226 if (list_empty(&isec->list))
1227 list_add(&isec->list, &sbsec->isec_head);
1228 spin_unlock(&sbsec->isec_lock);
Eric Paris23970742006-09-25 23:32:01 -07001229 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001230 }
1231
1232 switch (sbsec->behavior) {
1233 case SECURITY_FS_USE_XATTR:
1234 if (!inode->i_op->getxattr) {
1235 isec->sid = sbsec->def_sid;
1236 break;
1237 }
1238
1239 /* Need a dentry, since the xattr API requires one.
1240 Life would be simpler if we could just pass the inode. */
1241 if (opt_dentry) {
1242 /* Called from d_instantiate or d_splice_alias. */
1243 dentry = dget(opt_dentry);
1244 } else {
1245 /* Called from selinux_complete_init, try to find a dentry. */
1246 dentry = d_find_alias(inode);
1247 }
1248 if (!dentry) {
Eric Parisdf7f54c2009-03-09 14:35:58 -04001249 /*
1250 * this is can be hit on boot when a file is accessed
1251 * before the policy is loaded. When we load policy we
1252 * may find inodes that have no dentry on the
1253 * sbsec->isec_head list. No reason to complain as these
1254 * will get fixed up the next time we go through
1255 * inode_doinit with a dentry, before these inodes could
1256 * be used again by userspace.
1257 */
Eric Paris23970742006-09-25 23:32:01 -07001258 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001259 }
1260
1261 len = INITCONTEXTLEN;
Eric Paris4cb912f2009-02-12 14:50:05 -05001262 context = kmalloc(len+1, GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001263 if (!context) {
1264 rc = -ENOMEM;
1265 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001266 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001267 }
Eric Paris4cb912f2009-02-12 14:50:05 -05001268 context[len] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001269 rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX,
1270 context, len);
1271 if (rc == -ERANGE) {
James Morris314dabb2009-08-10 22:00:13 +10001272 kfree(context);
1273
Linus Torvalds1da177e2005-04-16 15:20:36 -07001274 /* Need a larger buffer. Query for the right size. */
1275 rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX,
1276 NULL, 0);
1277 if (rc < 0) {
1278 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001279 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001280 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001281 len = rc;
Eric Paris4cb912f2009-02-12 14:50:05 -05001282 context = kmalloc(len+1, GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001283 if (!context) {
1284 rc = -ENOMEM;
1285 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001286 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001287 }
Eric Paris4cb912f2009-02-12 14:50:05 -05001288 context[len] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001289 rc = inode->i_op->getxattr(dentry,
1290 XATTR_NAME_SELINUX,
1291 context, len);
1292 }
1293 dput(dentry);
1294 if (rc < 0) {
1295 if (rc != -ENODATA) {
Eric Paris744ba352008-04-17 11:52:44 -04001296 printk(KERN_WARNING "SELinux: %s: getxattr returned "
Harvey Harrisondd6f9532008-03-06 10:03:59 +11001297 "%d for dev=%s ino=%ld\n", __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001298 -rc, inode->i_sb->s_id, inode->i_ino);
1299 kfree(context);
Eric Paris23970742006-09-25 23:32:01 -07001300 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001301 }
1302 /* Map ENODATA to the default file SID */
1303 sid = sbsec->def_sid;
1304 rc = 0;
1305 } else {
James Morrisf5c1d5b2005-07-28 01:07:37 -07001306 rc = security_context_to_sid_default(context, rc, &sid,
Stephen Smalley869ab512008-04-04 08:46:05 -04001307 sbsec->def_sid,
1308 GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001309 if (rc) {
Eric Paris4ba0a8a2009-02-12 15:01:10 -05001310 char *dev = inode->i_sb->s_id;
1311 unsigned long ino = inode->i_ino;
1312
1313 if (rc == -EINVAL) {
1314 if (printk_ratelimit())
1315 printk(KERN_NOTICE "SELinux: inode=%lu on dev=%s was found to have an invalid "
1316 "context=%s. This indicates you may need to relabel the inode or the "
1317 "filesystem in question.\n", ino, dev, context);
1318 } else {
1319 printk(KERN_WARNING "SELinux: %s: context_to_sid(%s) "
1320 "returned %d for dev=%s ino=%ld\n",
1321 __func__, context, -rc, dev, ino);
1322 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001323 kfree(context);
1324 /* Leave with the unlabeled SID */
1325 rc = 0;
1326 break;
1327 }
1328 }
1329 kfree(context);
1330 isec->sid = sid;
1331 break;
1332 case SECURITY_FS_USE_TASK:
1333 isec->sid = isec->task_sid;
1334 break;
1335 case SECURITY_FS_USE_TRANS:
1336 /* Default to the fs SID. */
1337 isec->sid = sbsec->sid;
1338
1339 /* Try to obtain a transition SID. */
1340 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Eric Paris652bb9b2011-02-01 11:05:40 -05001341 rc = security_transition_sid(isec->task_sid, sbsec->sid,
1342 isec->sclass, NULL, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001343 if (rc)
Eric Paris23970742006-09-25 23:32:01 -07001344 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001345 isec->sid = sid;
1346 break;
Eric Parisc312feb2006-07-10 04:43:53 -07001347 case SECURITY_FS_USE_MNTPOINT:
1348 isec->sid = sbsec->mntpoint_sid;
1349 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001350 default:
Eric Parisc312feb2006-07-10 04:43:53 -07001351 /* Default to the fs superblock SID. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001352 isec->sid = sbsec->sid;
1353
David P. Quigley0d90a7e2009-01-16 09:22:02 -05001354 if ((sbsec->flags & SE_SBPROC) && !S_ISLNK(inode->i_mode)) {
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001355 if (opt_dentry) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001356 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001357 rc = selinux_proc_get_sid(opt_dentry,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001358 isec->sclass,
1359 &sid);
1360 if (rc)
Eric Paris23970742006-09-25 23:32:01 -07001361 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001362 isec->sid = sid;
1363 }
1364 }
1365 break;
1366 }
1367
1368 isec->initialized = 1;
1369
Eric Paris23970742006-09-25 23:32:01 -07001370out_unlock:
1371 mutex_unlock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001372out:
1373 if (isec->sclass == SECCLASS_FILE)
1374 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001375 return rc;
1376}
1377
1378/* Convert a Linux signal to an access vector. */
1379static inline u32 signal_to_av(int sig)
1380{
1381 u32 perm = 0;
1382
1383 switch (sig) {
1384 case SIGCHLD:
1385 /* Commonly granted from child to parent. */
1386 perm = PROCESS__SIGCHLD;
1387 break;
1388 case SIGKILL:
1389 /* Cannot be caught or ignored */
1390 perm = PROCESS__SIGKILL;
1391 break;
1392 case SIGSTOP:
1393 /* Cannot be caught or ignored */
1394 perm = PROCESS__SIGSTOP;
1395 break;
1396 default:
1397 /* All other signals. */
1398 perm = PROCESS__SIGNAL;
1399 break;
1400 }
1401
1402 return perm;
1403}
1404
David Howells275bb412008-11-14 10:39:19 +11001405/*
David Howellsd84f4f92008-11-14 10:39:23 +11001406 * Check permission between a pair of credentials
1407 * fork check, ptrace check, etc.
1408 */
1409static int cred_has_perm(const struct cred *actor,
1410 const struct cred *target,
1411 u32 perms)
1412{
1413 u32 asid = cred_sid(actor), tsid = cred_sid(target);
1414
1415 return avc_has_perm(asid, tsid, SECCLASS_PROCESS, perms, NULL);
1416}
1417
1418/*
David Howells88e67f32008-11-14 10:39:21 +11001419 * Check permission between a pair of tasks, e.g. signal checks,
David Howells275bb412008-11-14 10:39:19 +11001420 * fork check, ptrace check, etc.
1421 * tsk1 is the actor and tsk2 is the target
David Howells3b11a1d2008-11-14 10:39:26 +11001422 * - this uses the default subjective creds of tsk1
David Howells275bb412008-11-14 10:39:19 +11001423 */
1424static int task_has_perm(const struct task_struct *tsk1,
1425 const struct task_struct *tsk2,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001426 u32 perms)
1427{
David Howells275bb412008-11-14 10:39:19 +11001428 const struct task_security_struct *__tsec1, *__tsec2;
1429 u32 sid1, sid2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001430
David Howells275bb412008-11-14 10:39:19 +11001431 rcu_read_lock();
1432 __tsec1 = __task_cred(tsk1)->security; sid1 = __tsec1->sid;
1433 __tsec2 = __task_cred(tsk2)->security; sid2 = __tsec2->sid;
1434 rcu_read_unlock();
1435 return avc_has_perm(sid1, sid2, SECCLASS_PROCESS, perms, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001436}
1437
David Howells3b11a1d2008-11-14 10:39:26 +11001438/*
1439 * Check permission between current and another task, e.g. signal checks,
1440 * fork check, ptrace check, etc.
1441 * current is the actor and tsk2 is the target
1442 * - this uses current's subjective creds
1443 */
1444static int current_has_perm(const struct task_struct *tsk,
1445 u32 perms)
1446{
1447 u32 sid, tsid;
1448
1449 sid = current_sid();
1450 tsid = task_sid(tsk);
1451 return avc_has_perm(sid, tsid, SECCLASS_PROCESS, perms, NULL);
1452}
1453
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001454#if CAP_LAST_CAP > 63
1455#error Fix SELinux to handle capabilities > 63.
1456#endif
1457
Linus Torvalds1da177e2005-04-16 15:20:36 -07001458/* Check whether a task is allowed to use a capability. */
Eric Paris6a9de492012-01-03 12:25:14 -05001459static int cred_has_capability(const struct cred *cred,
Eric Paris06112162008-11-11 22:02:50 +11001460 int cap, int audit)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001461{
Thomas Liu2bf49692009-07-14 12:14:09 -04001462 struct common_audit_data ad;
Eric Paris06112162008-11-11 22:02:50 +11001463 struct av_decision avd;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001464 u16 sclass;
David Howells3699c532009-01-06 22:27:01 +00001465 u32 sid = cred_sid(cred);
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001466 u32 av = CAP_TO_MASK(cap);
Eric Paris06112162008-11-11 22:02:50 +11001467 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468
Eric Paris50c205f2012-04-04 15:01:43 -04001469 ad.type = LSM_AUDIT_DATA_CAP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001470 ad.u.cap = cap;
1471
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001472 switch (CAP_TO_INDEX(cap)) {
1473 case 0:
1474 sclass = SECCLASS_CAPABILITY;
1475 break;
1476 case 1:
1477 sclass = SECCLASS_CAPABILITY2;
1478 break;
1479 default:
1480 printk(KERN_ERR
1481 "SELinux: out of range capability %d\n", cap);
1482 BUG();
Eric Parisa35c6c82011-04-20 10:21:28 -04001483 return -EINVAL;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001484 }
Eric Paris06112162008-11-11 22:02:50 +11001485
David Howells275bb412008-11-14 10:39:19 +11001486 rc = avc_has_perm_noaudit(sid, sid, sclass, av, 0, &avd);
Eric Paris9ade0cf2011-04-25 16:26:29 -04001487 if (audit == SECURITY_CAP_AUDIT) {
1488 int rc2 = avc_audit(sid, sid, sclass, av, &avd, rc, &ad, 0);
1489 if (rc2)
1490 return rc2;
1491 }
Eric Paris06112162008-11-11 22:02:50 +11001492 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001493}
1494
1495/* Check whether a task is allowed to use a system operation. */
1496static int task_has_system(struct task_struct *tsk,
1497 u32 perms)
1498{
David Howells275bb412008-11-14 10:39:19 +11001499 u32 sid = task_sid(tsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001500
David Howells275bb412008-11-14 10:39:19 +11001501 return avc_has_perm(sid, SECINITSID_KERNEL,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001502 SECCLASS_SYSTEM, perms, NULL);
1503}
1504
1505/* Check whether a task has a particular permission to an inode.
1506 The 'adp' parameter is optional and allows other audit
1507 data to be passed (e.g. the dentry). */
David Howells88e67f32008-11-14 10:39:21 +11001508static int inode_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001509 struct inode *inode,
1510 u32 perms,
Eric Paris9ade0cf2011-04-25 16:26:29 -04001511 struct common_audit_data *adp,
1512 unsigned flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001513{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001514 struct inode_security_struct *isec;
David Howells275bb412008-11-14 10:39:19 +11001515 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001516
David Howellse0e81732009-09-02 09:13:40 +01001517 validate_creds(cred);
1518
Eric Paris828dfe12008-04-17 13:17:49 -04001519 if (unlikely(IS_PRIVATE(inode)))
Stephen Smalleybbaca6c2007-02-14 00:34:16 -08001520 return 0;
1521
David Howells88e67f32008-11-14 10:39:21 +11001522 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001523 isec = inode->i_security;
1524
Eric Paris9ade0cf2011-04-25 16:26:29 -04001525 return avc_has_perm_flags(sid, isec->sid, isec->sclass, perms, adp, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001526}
1527
1528/* 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;
David Howells88e67f32008-11-14 10:39:21 +11001537
Eric Paris50c205f2012-04-04 15:01:43 -04001538 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Paris2875fa02011-04-28 16:04:24 -04001539 ad.u.dentry = dentry;
1540 return inode_has_perm(cred, inode, av, &ad, 0);
1541}
1542
1543/* Same as inode_has_perm, but pass explicit audit data containing
1544 the path to help the auditing code to more easily generate the
1545 pathname if needed. */
1546static inline int path_has_perm(const struct cred *cred,
1547 struct path *path,
1548 u32 av)
1549{
1550 struct inode *inode = path->dentry->d_inode;
1551 struct common_audit_data ad;
1552
Eric Paris50c205f2012-04-04 15:01:43 -04001553 ad.type = LSM_AUDIT_DATA_PATH;
Eric Paris2875fa02011-04-28 16:04:24 -04001554 ad.u.path = *path;
Eric Paris9ade0cf2011-04-25 16:26:29 -04001555 return inode_has_perm(cred, inode, av, &ad, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001556}
1557
1558/* Check whether a task can use an open file descriptor to
1559 access an inode in a given way. Check access to the
1560 descriptor itself, and then use dentry_has_perm to
1561 check a particular permission to the file.
1562 Access to the descriptor is implicitly granted if it
1563 has the same SID as the process. If av is zero, then
1564 access to the file is not checked, e.g. for cases
1565 where only the descriptor is affected like seek. */
David Howells88e67f32008-11-14 10:39:21 +11001566static int file_has_perm(const struct cred *cred,
1567 struct file *file,
1568 u32 av)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001569{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001570 struct file_security_struct *fsec = file->f_security;
Al Viro496ad9a2013-01-23 17:07:38 -05001571 struct inode *inode = file_inode(file);
Thomas Liu2bf49692009-07-14 12:14:09 -04001572 struct common_audit_data ad;
David Howells88e67f32008-11-14 10:39:21 +11001573 u32 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001574 int rc;
1575
Eric Paris50c205f2012-04-04 15:01:43 -04001576 ad.type = LSM_AUDIT_DATA_PATH;
Eric Parisf48b7392011-04-25 12:54:27 -04001577 ad.u.path = file->f_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001578
David Howells275bb412008-11-14 10:39:19 +11001579 if (sid != fsec->sid) {
1580 rc = avc_has_perm(sid, fsec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001581 SECCLASS_FD,
1582 FD__USE,
1583 &ad);
1584 if (rc)
David Howells88e67f32008-11-14 10:39:21 +11001585 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001586 }
1587
1588 /* av is zero if only checking access to the descriptor. */
David Howells88e67f32008-11-14 10:39:21 +11001589 rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001590 if (av)
Eric Paris9ade0cf2011-04-25 16:26:29 -04001591 rc = inode_has_perm(cred, inode, av, &ad, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001592
David Howells88e67f32008-11-14 10:39:21 +11001593out:
1594 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001595}
1596
1597/* Check whether a task can create a file. */
1598static int may_create(struct inode *dir,
1599 struct dentry *dentry,
1600 u16 tclass)
1601{
Paul Moore5fb49872010-04-22 14:46:19 -04001602 const struct task_security_struct *tsec = current_security();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001603 struct inode_security_struct *dsec;
1604 struct superblock_security_struct *sbsec;
David Howells275bb412008-11-14 10:39:19 +11001605 u32 sid, newsid;
Thomas Liu2bf49692009-07-14 12:14:09 -04001606 struct common_audit_data ad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001607 int rc;
1608
Linus Torvalds1da177e2005-04-16 15:20:36 -07001609 dsec = dir->i_security;
1610 sbsec = dir->i_sb->s_security;
1611
David Howells275bb412008-11-14 10:39:19 +11001612 sid = tsec->sid;
1613 newsid = tsec->create_sid;
1614
Eric Paris50c205f2012-04-04 15:01:43 -04001615 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04001616 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001617
David Howells275bb412008-11-14 10:39:19 +11001618 rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001619 DIR__ADD_NAME | DIR__SEARCH,
1620 &ad);
1621 if (rc)
1622 return rc;
1623
David P. Quigleycd895962009-01-16 09:22:04 -05001624 if (!newsid || !(sbsec->flags & SE_SBLABELSUPP)) {
Eric Pariscb1e9222011-04-28 15:11:21 -04001625 rc = security_transition_sid(sid, dsec->sid, tclass,
1626 &dentry->d_name, &newsid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001627 if (rc)
1628 return rc;
1629 }
1630
David Howells275bb412008-11-14 10:39:19 +11001631 rc = avc_has_perm(sid, newsid, tclass, FILE__CREATE, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001632 if (rc)
1633 return rc;
1634
1635 return avc_has_perm(newsid, sbsec->sid,
1636 SECCLASS_FILESYSTEM,
1637 FILESYSTEM__ASSOCIATE, &ad);
1638}
1639
Michael LeMay4eb582c2006-06-26 00:24:57 -07001640/* Check whether a task can create a key. */
1641static int may_create_key(u32 ksid,
1642 struct task_struct *ctx)
1643{
David Howells275bb412008-11-14 10:39:19 +11001644 u32 sid = task_sid(ctx);
Michael LeMay4eb582c2006-06-26 00:24:57 -07001645
David Howells275bb412008-11-14 10:39:19 +11001646 return avc_has_perm(sid, ksid, SECCLASS_KEY, KEY__CREATE, NULL);
Michael LeMay4eb582c2006-06-26 00:24:57 -07001647}
1648
Eric Paris828dfe12008-04-17 13:17:49 -04001649#define MAY_LINK 0
1650#define MAY_UNLINK 1
1651#define MAY_RMDIR 2
Linus Torvalds1da177e2005-04-16 15:20:36 -07001652
1653/* Check whether a task can link, unlink, or rmdir a file/directory. */
1654static int may_link(struct inode *dir,
1655 struct dentry *dentry,
1656 int kind)
1657
1658{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001659 struct inode_security_struct *dsec, *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04001660 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11001661 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001662 u32 av;
1663 int rc;
1664
Linus Torvalds1da177e2005-04-16 15:20:36 -07001665 dsec = dir->i_security;
1666 isec = dentry->d_inode->i_security;
1667
Eric Paris50c205f2012-04-04 15:01:43 -04001668 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04001669 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001670
1671 av = DIR__SEARCH;
1672 av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME);
David Howells275bb412008-11-14 10:39:19 +11001673 rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001674 if (rc)
1675 return rc;
1676
1677 switch (kind) {
1678 case MAY_LINK:
1679 av = FILE__LINK;
1680 break;
1681 case MAY_UNLINK:
1682 av = FILE__UNLINK;
1683 break;
1684 case MAY_RMDIR:
1685 av = DIR__RMDIR;
1686 break;
1687 default:
Eric Paris744ba352008-04-17 11:52:44 -04001688 printk(KERN_WARNING "SELinux: %s: unrecognized kind %d\n",
1689 __func__, kind);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001690 return 0;
1691 }
1692
David Howells275bb412008-11-14 10:39:19 +11001693 rc = avc_has_perm(sid, isec->sid, isec->sclass, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001694 return rc;
1695}
1696
1697static inline int may_rename(struct inode *old_dir,
1698 struct dentry *old_dentry,
1699 struct inode *new_dir,
1700 struct dentry *new_dentry)
1701{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001702 struct inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04001703 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11001704 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001705 u32 av;
1706 int old_is_dir, new_is_dir;
1707 int rc;
1708
Linus Torvalds1da177e2005-04-16 15:20:36 -07001709 old_dsec = old_dir->i_security;
1710 old_isec = old_dentry->d_inode->i_security;
1711 old_is_dir = S_ISDIR(old_dentry->d_inode->i_mode);
1712 new_dsec = new_dir->i_security;
1713
Eric Paris50c205f2012-04-04 15:01:43 -04001714 ad.type = LSM_AUDIT_DATA_DENTRY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001715
Eric Parisa2694342011-04-25 13:10:27 -04001716 ad.u.dentry = old_dentry;
David Howells275bb412008-11-14 10:39:19 +11001717 rc = avc_has_perm(sid, old_dsec->sid, SECCLASS_DIR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001718 DIR__REMOVE_NAME | DIR__SEARCH, &ad);
1719 if (rc)
1720 return rc;
David Howells275bb412008-11-14 10:39:19 +11001721 rc = avc_has_perm(sid, old_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001722 old_isec->sclass, FILE__RENAME, &ad);
1723 if (rc)
1724 return rc;
1725 if (old_is_dir && new_dir != old_dir) {
David Howells275bb412008-11-14 10:39:19 +11001726 rc = avc_has_perm(sid, old_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001727 old_isec->sclass, DIR__REPARENT, &ad);
1728 if (rc)
1729 return rc;
1730 }
1731
Eric Parisa2694342011-04-25 13:10:27 -04001732 ad.u.dentry = new_dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001733 av = DIR__ADD_NAME | DIR__SEARCH;
1734 if (new_dentry->d_inode)
1735 av |= DIR__REMOVE_NAME;
David Howells275bb412008-11-14 10:39:19 +11001736 rc = avc_has_perm(sid, new_dsec->sid, SECCLASS_DIR, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001737 if (rc)
1738 return rc;
1739 if (new_dentry->d_inode) {
1740 new_isec = new_dentry->d_inode->i_security;
1741 new_is_dir = S_ISDIR(new_dentry->d_inode->i_mode);
David Howells275bb412008-11-14 10:39:19 +11001742 rc = avc_has_perm(sid, new_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001743 new_isec->sclass,
1744 (new_is_dir ? DIR__RMDIR : FILE__UNLINK), &ad);
1745 if (rc)
1746 return rc;
1747 }
1748
1749 return 0;
1750}
1751
1752/* Check whether a task can perform a filesystem operation. */
David Howells88e67f32008-11-14 10:39:21 +11001753static int superblock_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001754 struct super_block *sb,
1755 u32 perms,
Thomas Liu2bf49692009-07-14 12:14:09 -04001756 struct common_audit_data *ad)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001757{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001758 struct superblock_security_struct *sbsec;
David Howells88e67f32008-11-14 10:39:21 +11001759 u32 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001760
Linus Torvalds1da177e2005-04-16 15:20:36 -07001761 sbsec = sb->s_security;
David Howells275bb412008-11-14 10:39:19 +11001762 return avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM, perms, ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001763}
1764
1765/* Convert a Linux mode and permission mask to an access vector. */
1766static inline u32 file_mask_to_av(int mode, int mask)
1767{
1768 u32 av = 0;
1769
Al Virodba19c62011-07-25 20:49:29 -04001770 if (!S_ISDIR(mode)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001771 if (mask & MAY_EXEC)
1772 av |= FILE__EXECUTE;
1773 if (mask & MAY_READ)
1774 av |= FILE__READ;
1775
1776 if (mask & MAY_APPEND)
1777 av |= FILE__APPEND;
1778 else if (mask & MAY_WRITE)
1779 av |= FILE__WRITE;
1780
1781 } else {
1782 if (mask & MAY_EXEC)
1783 av |= DIR__SEARCH;
1784 if (mask & MAY_WRITE)
1785 av |= DIR__WRITE;
1786 if (mask & MAY_READ)
1787 av |= DIR__READ;
1788 }
1789
1790 return av;
1791}
1792
1793/* Convert a Linux file to an access vector. */
1794static inline u32 file_to_av(struct file *file)
1795{
1796 u32 av = 0;
1797
1798 if (file->f_mode & FMODE_READ)
1799 av |= FILE__READ;
1800 if (file->f_mode & FMODE_WRITE) {
1801 if (file->f_flags & O_APPEND)
1802 av |= FILE__APPEND;
1803 else
1804 av |= FILE__WRITE;
1805 }
Stephen Smalley0794c662008-03-17 08:55:18 -04001806 if (!av) {
1807 /*
1808 * Special file opened with flags 3 for ioctl-only use.
1809 */
1810 av = FILE__IOCTL;
1811 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001812
1813 return av;
1814}
1815
Eric Paris8b6a5a32008-10-29 17:06:46 -04001816/*
1817 * Convert a file to an access vector and include the correct open
1818 * open permission.
1819 */
1820static inline u32 open_file_to_av(struct file *file)
1821{
1822 u32 av = file_to_av(file);
1823
Eric Paris49b7b8d2010-07-23 11:44:09 -04001824 if (selinux_policycap_openperm)
1825 av |= FILE__OPEN;
1826
Eric Paris8b6a5a32008-10-29 17:06:46 -04001827 return av;
1828}
1829
Linus Torvalds1da177e2005-04-16 15:20:36 -07001830/* Hook functions begin here. */
1831
Ingo Molnar9e488582009-05-07 19:26:19 +10001832static int selinux_ptrace_access_check(struct task_struct *child,
David Howells5cd9c582008-08-14 11:37:28 +01001833 unsigned int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001834{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001835 int rc;
1836
Ingo Molnar9e488582009-05-07 19:26:19 +10001837 rc = cap_ptrace_access_check(child, mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001838 if (rc)
1839 return rc;
1840
Eric Paris69f594a2012-01-03 12:25:15 -05001841 if (mode & PTRACE_MODE_READ) {
David Howells275bb412008-11-14 10:39:19 +11001842 u32 sid = current_sid();
1843 u32 csid = task_sid(child);
1844 return avc_has_perm(sid, csid, SECCLASS_FILE, FILE__READ, NULL);
Stephen Smalley006ebb42008-05-19 08:32:49 -04001845 }
1846
David Howells3b11a1d2008-11-14 10:39:26 +11001847 return current_has_perm(child, PROCESS__PTRACE);
David Howells5cd9c582008-08-14 11:37:28 +01001848}
1849
1850static int selinux_ptrace_traceme(struct task_struct *parent)
1851{
1852 int rc;
1853
Eric Paris200ac532009-02-12 15:01:04 -05001854 rc = cap_ptrace_traceme(parent);
David Howells5cd9c582008-08-14 11:37:28 +01001855 if (rc)
1856 return rc;
1857
1858 return task_has_perm(parent, current, PROCESS__PTRACE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001859}
1860
1861static int selinux_capget(struct task_struct *target, kernel_cap_t *effective,
Eric Paris828dfe12008-04-17 13:17:49 -04001862 kernel_cap_t *inheritable, kernel_cap_t *permitted)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001863{
1864 int error;
1865
David Howells3b11a1d2008-11-14 10:39:26 +11001866 error = current_has_perm(target, PROCESS__GETCAP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001867 if (error)
1868 return error;
1869
Eric Paris200ac532009-02-12 15:01:04 -05001870 return cap_capget(target, effective, inheritable, permitted);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001871}
1872
David Howellsd84f4f92008-11-14 10:39:23 +11001873static int selinux_capset(struct cred *new, const struct cred *old,
1874 const kernel_cap_t *effective,
1875 const kernel_cap_t *inheritable,
1876 const kernel_cap_t *permitted)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001877{
1878 int error;
1879
Eric Paris200ac532009-02-12 15:01:04 -05001880 error = cap_capset(new, old,
David Howellsd84f4f92008-11-14 10:39:23 +11001881 effective, inheritable, permitted);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001882 if (error)
1883 return error;
1884
David Howellsd84f4f92008-11-14 10:39:23 +11001885 return cred_has_perm(old, new, PROCESS__SETCAP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001886}
1887
James Morris5626d3e2009-01-30 10:05:06 +11001888/*
1889 * (This comment used to live with the selinux_task_setuid hook,
1890 * which was removed).
1891 *
1892 * Since setuid only affects the current process, and since the SELinux
1893 * controls are not based on the Linux identity attributes, SELinux does not
1894 * need to control this operation. However, SELinux does control the use of
1895 * the CAP_SETUID and CAP_SETGID capabilities using the capable hook.
1896 */
1897
Eric Paris6a9de492012-01-03 12:25:14 -05001898static int selinux_capable(const struct cred *cred, struct user_namespace *ns,
1899 int cap, int audit)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001900{
1901 int rc;
1902
Eric Paris6a9de492012-01-03 12:25:14 -05001903 rc = cap_capable(cred, ns, cap, audit);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001904 if (rc)
1905 return rc;
1906
Eric Paris6a9de492012-01-03 12:25:14 -05001907 return cred_has_capability(cred, cap, audit);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001908}
1909
Linus Torvalds1da177e2005-04-16 15:20:36 -07001910static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb)
1911{
David Howells88e67f32008-11-14 10:39:21 +11001912 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001913 int rc = 0;
1914
1915 if (!sb)
1916 return 0;
1917
1918 switch (cmds) {
Eric Paris828dfe12008-04-17 13:17:49 -04001919 case Q_SYNC:
1920 case Q_QUOTAON:
1921 case Q_QUOTAOFF:
1922 case Q_SETINFO:
1923 case Q_SETQUOTA:
David Howells88e67f32008-11-14 10:39:21 +11001924 rc = superblock_has_perm(cred, sb, FILESYSTEM__QUOTAMOD, NULL);
Eric Paris828dfe12008-04-17 13:17:49 -04001925 break;
1926 case Q_GETFMT:
1927 case Q_GETINFO:
1928 case Q_GETQUOTA:
David Howells88e67f32008-11-14 10:39:21 +11001929 rc = superblock_has_perm(cred, sb, FILESYSTEM__QUOTAGET, NULL);
Eric Paris828dfe12008-04-17 13:17:49 -04001930 break;
1931 default:
1932 rc = 0; /* let the kernel handle invalid cmds */
1933 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001934 }
1935 return rc;
1936}
1937
1938static int selinux_quota_on(struct dentry *dentry)
1939{
David Howells88e67f32008-11-14 10:39:21 +11001940 const struct cred *cred = current_cred();
1941
Eric Paris2875fa02011-04-28 16:04:24 -04001942 return dentry_has_perm(cred, dentry, FILE__QUOTAON);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001943}
1944
Eric Paris12b30522010-11-15 18:36:29 -05001945static int selinux_syslog(int type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001946{
1947 int rc;
1948
Linus Torvalds1da177e2005-04-16 15:20:36 -07001949 switch (type) {
Kees Cookd78ca3c2010-02-03 15:37:13 -08001950 case SYSLOG_ACTION_READ_ALL: /* Read last kernel messages */
1951 case SYSLOG_ACTION_SIZE_BUFFER: /* Return size of the log buffer */
Eric Paris828dfe12008-04-17 13:17:49 -04001952 rc = task_has_system(current, SYSTEM__SYSLOG_READ);
1953 break;
Kees Cookd78ca3c2010-02-03 15:37:13 -08001954 case SYSLOG_ACTION_CONSOLE_OFF: /* Disable logging to console */
1955 case SYSLOG_ACTION_CONSOLE_ON: /* Enable logging to console */
1956 /* Set level of messages printed to console */
1957 case SYSLOG_ACTION_CONSOLE_LEVEL:
Eric Paris828dfe12008-04-17 13:17:49 -04001958 rc = task_has_system(current, SYSTEM__SYSLOG_CONSOLE);
1959 break;
Kees Cookd78ca3c2010-02-03 15:37:13 -08001960 case SYSLOG_ACTION_CLOSE: /* Close log */
1961 case SYSLOG_ACTION_OPEN: /* Open log */
1962 case SYSLOG_ACTION_READ: /* Read from log */
1963 case SYSLOG_ACTION_READ_CLEAR: /* Read/clear last kernel messages */
1964 case SYSLOG_ACTION_CLEAR: /* Clear ring buffer */
Eric Paris828dfe12008-04-17 13:17:49 -04001965 default:
1966 rc = task_has_system(current, SYSTEM__SYSLOG_MOD);
1967 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001968 }
1969 return rc;
1970}
1971
1972/*
1973 * Check that a process has enough memory to allocate a new virtual
1974 * mapping. 0 means there is enough memory for the allocation to
1975 * succeed and -ENOMEM implies there is not.
1976 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07001977 * Do not audit the selinux permission check, as this is applied to all
1978 * processes that allocate mappings.
1979 */
Alan Cox34b4e4a2007-08-22 14:01:28 -07001980static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001981{
1982 int rc, cap_sys_admin = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001983
Eric Paris6a9de492012-01-03 12:25:14 -05001984 rc = selinux_capable(current_cred(), &init_user_ns, CAP_SYS_ADMIN,
David Howells3699c532009-01-06 22:27:01 +00001985 SECURITY_CAP_NOAUDIT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001986 if (rc == 0)
1987 cap_sys_admin = 1;
1988
Alan Cox34b4e4a2007-08-22 14:01:28 -07001989 return __vm_enough_memory(mm, pages, cap_sys_admin);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001990}
1991
1992/* binprm security operations */
1993
David Howellsa6f76f22008-11-14 10:39:24 +11001994static int selinux_bprm_set_creds(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001995{
David Howellsa6f76f22008-11-14 10:39:24 +11001996 const struct task_security_struct *old_tsec;
1997 struct task_security_struct *new_tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001998 struct inode_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04001999 struct common_audit_data ad;
Al Viro496ad9a2013-01-23 17:07:38 -05002000 struct inode *inode = file_inode(bprm->file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002001 int rc;
2002
Eric Paris200ac532009-02-12 15:01:04 -05002003 rc = cap_bprm_set_creds(bprm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002004 if (rc)
2005 return rc;
2006
David Howellsa6f76f22008-11-14 10:39:24 +11002007 /* SELinux context only depends on initial program or script and not
2008 * the script interpreter */
2009 if (bprm->cred_prepared)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002010 return 0;
2011
David Howellsa6f76f22008-11-14 10:39:24 +11002012 old_tsec = current_security();
2013 new_tsec = bprm->cred->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002014 isec = inode->i_security;
2015
2016 /* Default to the current task SID. */
David Howellsa6f76f22008-11-14 10:39:24 +11002017 new_tsec->sid = old_tsec->sid;
2018 new_tsec->osid = old_tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002019
Michael LeMay28eba5b2006-06-27 02:53:42 -07002020 /* Reset fs, key, and sock SIDs on execve. */
David Howellsa6f76f22008-11-14 10:39:24 +11002021 new_tsec->create_sid = 0;
2022 new_tsec->keycreate_sid = 0;
2023 new_tsec->sockcreate_sid = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002024
David Howellsa6f76f22008-11-14 10:39:24 +11002025 if (old_tsec->exec_sid) {
2026 new_tsec->sid = old_tsec->exec_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002027 /* Reset exec SID on execve. */
David Howellsa6f76f22008-11-14 10:39:24 +11002028 new_tsec->exec_sid = 0;
Andy Lutomirski259e5e62012-04-12 16:47:50 -05002029
2030 /*
2031 * Minimize confusion: if no_new_privs and a transition is
2032 * explicitly requested, then fail the exec.
2033 */
2034 if (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS)
2035 return -EPERM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002036 } else {
2037 /* Check for a default transition on this program. */
David Howellsa6f76f22008-11-14 10:39:24 +11002038 rc = security_transition_sid(old_tsec->sid, isec->sid,
Eric Paris652bb9b2011-02-01 11:05:40 -05002039 SECCLASS_PROCESS, NULL,
2040 &new_tsec->sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002041 if (rc)
2042 return rc;
2043 }
2044
Eric Paris50c205f2012-04-04 15:01:43 -04002045 ad.type = LSM_AUDIT_DATA_PATH;
Eric Parisf48b7392011-04-25 12:54:27 -04002046 ad.u.path = bprm->file->f_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002047
Andy Lutomirski259e5e62012-04-12 16:47:50 -05002048 if ((bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) ||
2049 (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS))
David Howellsa6f76f22008-11-14 10:39:24 +11002050 new_tsec->sid = old_tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002051
David Howellsa6f76f22008-11-14 10:39:24 +11002052 if (new_tsec->sid == old_tsec->sid) {
2053 rc = avc_has_perm(old_tsec->sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002054 SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, &ad);
2055 if (rc)
2056 return rc;
2057 } else {
2058 /* Check permissions for the transition. */
David Howellsa6f76f22008-11-14 10:39:24 +11002059 rc = avc_has_perm(old_tsec->sid, new_tsec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002060 SECCLASS_PROCESS, PROCESS__TRANSITION, &ad);
2061 if (rc)
2062 return rc;
2063
David Howellsa6f76f22008-11-14 10:39:24 +11002064 rc = avc_has_perm(new_tsec->sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002065 SECCLASS_FILE, FILE__ENTRYPOINT, &ad);
2066 if (rc)
2067 return rc;
2068
David Howellsa6f76f22008-11-14 10:39:24 +11002069 /* Check for shared state */
2070 if (bprm->unsafe & LSM_UNSAFE_SHARE) {
2071 rc = avc_has_perm(old_tsec->sid, new_tsec->sid,
2072 SECCLASS_PROCESS, PROCESS__SHARE,
2073 NULL);
2074 if (rc)
2075 return -EPERM;
2076 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002077
David Howellsa6f76f22008-11-14 10:39:24 +11002078 /* Make sure that anyone attempting to ptrace over a task that
2079 * changes its SID has the appropriate permit */
2080 if (bprm->unsafe &
2081 (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) {
2082 struct task_struct *tracer;
2083 struct task_security_struct *sec;
2084 u32 ptsid = 0;
2085
2086 rcu_read_lock();
Tejun Heo06d98472011-06-17 16:50:40 +02002087 tracer = ptrace_parent(current);
David Howellsa6f76f22008-11-14 10:39:24 +11002088 if (likely(tracer != NULL)) {
2089 sec = __task_cred(tracer)->security;
2090 ptsid = sec->sid;
2091 }
2092 rcu_read_unlock();
2093
2094 if (ptsid != 0) {
2095 rc = avc_has_perm(ptsid, new_tsec->sid,
2096 SECCLASS_PROCESS,
2097 PROCESS__PTRACE, NULL);
2098 if (rc)
2099 return -EPERM;
2100 }
2101 }
2102
2103 /* Clear any possibly unsafe personality bits on exec: */
2104 bprm->per_clear |= PER_CLEAR_ON_SETID;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002105 }
2106
Linus Torvalds1da177e2005-04-16 15:20:36 -07002107 return 0;
2108}
2109
Eric Paris828dfe12008-04-17 13:17:49 -04002110static int selinux_bprm_secureexec(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002111{
Paul Moore5fb49872010-04-22 14:46:19 -04002112 const struct task_security_struct *tsec = current_security();
David Howells275bb412008-11-14 10:39:19 +11002113 u32 sid, osid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002114 int atsecure = 0;
2115
David Howells275bb412008-11-14 10:39:19 +11002116 sid = tsec->sid;
2117 osid = tsec->osid;
2118
2119 if (osid != sid) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002120 /* Enable secure mode for SIDs transitions unless
2121 the noatsecure permission is granted between
2122 the two SIDs, i.e. ahp returns 0. */
David Howells275bb412008-11-14 10:39:19 +11002123 atsecure = avc_has_perm(osid, sid,
David Howellsa6f76f22008-11-14 10:39:24 +11002124 SECCLASS_PROCESS,
2125 PROCESS__NOATSECURE, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002126 }
2127
Eric Paris200ac532009-02-12 15:01:04 -05002128 return (atsecure || cap_bprm_secureexec(bprm));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002129}
2130
Al Viroc3c073f2012-08-21 22:32:06 -04002131static int match_file(const void *p, struct file *file, unsigned fd)
2132{
2133 return file_has_perm(p, file, file_to_av(file)) ? fd + 1 : 0;
2134}
2135
Linus Torvalds1da177e2005-04-16 15:20:36 -07002136/* Derived from fs/exec.c:flush_old_files. */
David Howells745ca242008-11-14 10:39:22 +11002137static inline void flush_unauthorized_files(const struct cred *cred,
2138 struct files_struct *files)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002139{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002140 struct file *file, *devnull = NULL;
Stephen Smalleyb20c8122006-09-25 23:32:03 -07002141 struct tty_struct *tty;
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002142 int drop_tty = 0;
Al Viroc3c073f2012-08-21 22:32:06 -04002143 unsigned n;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002144
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002145 tty = get_current_tty();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002146 if (tty) {
Nick Pigginee2ffa02010-08-18 04:37:35 +10002147 spin_lock(&tty_files_lock);
Eric Paris37dd0bd2008-10-31 17:40:00 -04002148 if (!list_empty(&tty->tty_files)) {
Nick Piggind996b622010-08-18 04:37:36 +10002149 struct tty_file_private *file_priv;
Eric Paris37dd0bd2008-10-31 17:40:00 -04002150
Linus Torvalds1da177e2005-04-16 15:20:36 -07002151 /* Revalidate access to controlling tty.
Eric Paris602a8dd2012-04-04 15:01:42 -04002152 Use path_has_perm on the tty path directly rather
Linus Torvalds1da177e2005-04-16 15:20:36 -07002153 than using file_has_perm, as this particular open
2154 file may belong to another process and we are only
2155 interested in the inode-based check here. */
Nick Piggind996b622010-08-18 04:37:36 +10002156 file_priv = list_first_entry(&tty->tty_files,
2157 struct tty_file_private, list);
2158 file = file_priv->file;
Eric Paris602a8dd2012-04-04 15:01:42 -04002159 if (path_has_perm(cred, &file->f_path, FILE__READ | FILE__WRITE))
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002160 drop_tty = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002161 }
Nick Pigginee2ffa02010-08-18 04:37:35 +10002162 spin_unlock(&tty_files_lock);
Alan Cox452a00d2008-10-13 10:39:13 +01002163 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002164 }
Eric W. Biederman98a27ba2007-05-08 00:26:56 -07002165 /* Reset controlling tty. */
2166 if (drop_tty)
2167 no_tty();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002168
2169 /* Revalidate access to inherited open files. */
Al Viroc3c073f2012-08-21 22:32:06 -04002170 n = iterate_fd(files, 0, match_file, cred);
2171 if (!n) /* none found? */
2172 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002173
Al Viroc3c073f2012-08-21 22:32:06 -04002174 devnull = dentry_open(&selinux_null, O_RDWR, cred);
Al Viro45525b22012-10-16 13:30:07 -04002175 if (IS_ERR(devnull))
2176 devnull = NULL;
2177 /* replace all the matching ones with this */
2178 do {
2179 replace_fd(n - 1, devnull, 0);
2180 } while ((n = iterate_fd(files, n, match_file, cred)) != 0);
2181 if (devnull)
Al Viroc3c073f2012-08-21 22:32:06 -04002182 fput(devnull);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002183}
2184
Linus Torvalds1da177e2005-04-16 15:20:36 -07002185/*
David Howellsa6f76f22008-11-14 10:39:24 +11002186 * Prepare a process for imminent new credential changes due to exec
Linus Torvalds1da177e2005-04-16 15:20:36 -07002187 */
David Howellsa6f76f22008-11-14 10:39:24 +11002188static void selinux_bprm_committing_creds(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002189{
David Howellsa6f76f22008-11-14 10:39:24 +11002190 struct task_security_struct *new_tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002191 struct rlimit *rlim, *initrlim;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002192 int rc, i;
2193
David Howellsa6f76f22008-11-14 10:39:24 +11002194 new_tsec = bprm->cred->security;
2195 if (new_tsec->sid == new_tsec->osid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002196 return;
2197
2198 /* Close files for which the new task SID is not authorized. */
David Howellsa6f76f22008-11-14 10:39:24 +11002199 flush_unauthorized_files(bprm->cred, current->files);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002200
David Howellsa6f76f22008-11-14 10:39:24 +11002201 /* Always clear parent death signal on SID transitions. */
2202 current->pdeath_signal = 0;
2203
2204 /* Check whether the new SID can inherit resource limits from the old
2205 * SID. If not, reset all soft limits to the lower of the current
2206 * task's hard limit and the init task's soft limit.
2207 *
2208 * Note that the setting of hard limits (even to lower them) can be
2209 * controlled by the setrlimit check. The inclusion of the init task's
2210 * soft limit into the computation is to avoid resetting soft limits
2211 * higher than the default soft limit for cases where the default is
2212 * lower than the hard limit, e.g. RLIMIT_CORE or RLIMIT_STACK.
2213 */
2214 rc = avc_has_perm(new_tsec->osid, new_tsec->sid, SECCLASS_PROCESS,
2215 PROCESS__RLIMITINH, NULL);
2216 if (rc) {
Oleg Nesteroveb2d55a2010-06-23 22:43:32 +02002217 /* protect against do_prlimit() */
2218 task_lock(current);
David Howellsa6f76f22008-11-14 10:39:24 +11002219 for (i = 0; i < RLIM_NLIMITS; i++) {
2220 rlim = current->signal->rlim + i;
2221 initrlim = init_task.signal->rlim + i;
2222 rlim->rlim_cur = min(rlim->rlim_max, initrlim->rlim_cur);
2223 }
Oleg Nesteroveb2d55a2010-06-23 22:43:32 +02002224 task_unlock(current);
2225 update_rlimit_cpu(current, rlimit(RLIMIT_CPU));
David Howellsa6f76f22008-11-14 10:39:24 +11002226 }
2227}
2228
2229/*
2230 * Clean up the process immediately after the installation of new credentials
2231 * due to exec
2232 */
2233static void selinux_bprm_committed_creds(struct linux_binprm *bprm)
2234{
2235 const struct task_security_struct *tsec = current_security();
2236 struct itimerval itimer;
David Howellsa6f76f22008-11-14 10:39:24 +11002237 u32 osid, sid;
2238 int rc, i;
David Howellsa6f76f22008-11-14 10:39:24 +11002239
David Howellsa6f76f22008-11-14 10:39:24 +11002240 osid = tsec->osid;
2241 sid = tsec->sid;
2242
2243 if (sid == osid)
2244 return;
2245
2246 /* Check whether the new SID can inherit signal state from the old SID.
2247 * If not, clear itimers to avoid subsequent signal generation and
2248 * flush and unblock signals.
2249 *
2250 * This must occur _after_ the task SID has been updated so that any
2251 * kill done after the flush will be checked against the new SID.
2252 */
2253 rc = avc_has_perm(osid, sid, SECCLASS_PROCESS, PROCESS__SIGINH, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002254 if (rc) {
2255 memset(&itimer, 0, sizeof itimer);
2256 for (i = 0; i < 3; i++)
2257 do_setitimer(i, &itimer, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002258 spin_lock_irq(&current->sighand->siglock);
David Howells3bcac022009-04-29 13:45:05 +01002259 if (!(current->signal->flags & SIGNAL_GROUP_EXIT)) {
2260 __flush_signals(current);
2261 flush_signal_handlers(current, 1);
2262 sigemptyset(&current->blocked);
2263 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002264 spin_unlock_irq(&current->sighand->siglock);
2265 }
2266
David Howellsa6f76f22008-11-14 10:39:24 +11002267 /* Wake up the parent if it is waiting so that it can recheck
2268 * wait permission to the new task SID. */
Oleg Nesterovecd6de32009-04-29 16:02:24 +02002269 read_lock(&tasklist_lock);
Oleg Nesterov0b7570e2009-09-23 15:56:46 -07002270 __wake_up_parent(current, current->real_parent);
Oleg Nesterovecd6de32009-04-29 16:02:24 +02002271 read_unlock(&tasklist_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002272}
2273
2274/* superblock security operations */
2275
2276static int selinux_sb_alloc_security(struct super_block *sb)
2277{
2278 return superblock_alloc_security(sb);
2279}
2280
2281static void selinux_sb_free_security(struct super_block *sb)
2282{
2283 superblock_free_security(sb);
2284}
2285
2286static inline int match_prefix(char *prefix, int plen, char *option, int olen)
2287{
2288 if (plen > olen)
2289 return 0;
2290
2291 return !memcmp(prefix, option, plen);
2292}
2293
2294static inline int selinux_option(char *option, int len)
2295{
Eric Paris832cbd92008-04-01 13:24:09 -04002296 return (match_prefix(CONTEXT_STR, sizeof(CONTEXT_STR)-1, option, len) ||
2297 match_prefix(FSCONTEXT_STR, sizeof(FSCONTEXT_STR)-1, option, len) ||
2298 match_prefix(DEFCONTEXT_STR, sizeof(DEFCONTEXT_STR)-1, option, len) ||
David P. Quigley11689d42009-01-16 09:22:03 -05002299 match_prefix(ROOTCONTEXT_STR, sizeof(ROOTCONTEXT_STR)-1, option, len) ||
2300 match_prefix(LABELSUPP_STR, sizeof(LABELSUPP_STR)-1, option, len));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002301}
2302
2303static inline void take_option(char **to, char *from, int *first, int len)
2304{
2305 if (!*first) {
2306 **to = ',';
2307 *to += 1;
Cory Olmo3528a952006-09-29 01:58:44 -07002308 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002309 *first = 0;
2310 memcpy(*to, from, len);
2311 *to += len;
2312}
2313
Eric Paris828dfe12008-04-17 13:17:49 -04002314static inline void take_selinux_option(char **to, char *from, int *first,
2315 int len)
Cory Olmo3528a952006-09-29 01:58:44 -07002316{
2317 int current_size = 0;
2318
2319 if (!*first) {
2320 **to = '|';
2321 *to += 1;
Eric Paris828dfe12008-04-17 13:17:49 -04002322 } else
Cory Olmo3528a952006-09-29 01:58:44 -07002323 *first = 0;
2324
2325 while (current_size < len) {
2326 if (*from != '"') {
2327 **to = *from;
2328 *to += 1;
2329 }
2330 from += 1;
2331 current_size += 1;
2332 }
2333}
2334
Eric Parise0007522008-03-05 10:31:54 -05002335static int selinux_sb_copy_data(char *orig, char *copy)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002336{
2337 int fnosec, fsec, rc = 0;
2338 char *in_save, *in_curr, *in_end;
2339 char *sec_curr, *nosec_save, *nosec;
Cory Olmo3528a952006-09-29 01:58:44 -07002340 int open_quote = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002341
2342 in_curr = orig;
2343 sec_curr = copy;
2344
Linus Torvalds1da177e2005-04-16 15:20:36 -07002345 nosec = (char *)get_zeroed_page(GFP_KERNEL);
2346 if (!nosec) {
2347 rc = -ENOMEM;
2348 goto out;
2349 }
2350
2351 nosec_save = nosec;
2352 fnosec = fsec = 1;
2353 in_save = in_end = orig;
2354
2355 do {
Cory Olmo3528a952006-09-29 01:58:44 -07002356 if (*in_end == '"')
2357 open_quote = !open_quote;
2358 if ((*in_end == ',' && open_quote == 0) ||
2359 *in_end == '\0') {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002360 int len = in_end - in_curr;
2361
2362 if (selinux_option(in_curr, len))
Cory Olmo3528a952006-09-29 01:58:44 -07002363 take_selinux_option(&sec_curr, in_curr, &fsec, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002364 else
2365 take_option(&nosec, in_curr, &fnosec, len);
2366
2367 in_curr = in_end + 1;
2368 }
2369 } while (*in_end++);
2370
Eric Paris6931dfc2005-06-30 02:58:51 -07002371 strcpy(in_save, nosec_save);
Gerald Schaeferda3caa22005-06-21 17:15:18 -07002372 free_page((unsigned long)nosec_save);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002373out:
2374 return rc;
2375}
2376
Eric Paris026eb162011-03-03 16:09:14 -05002377static int selinux_sb_remount(struct super_block *sb, void *data)
2378{
2379 int rc, i, *flags;
2380 struct security_mnt_opts opts;
2381 char *secdata, **mount_options;
2382 struct superblock_security_struct *sbsec = sb->s_security;
2383
2384 if (!(sbsec->flags & SE_SBINITIALIZED))
2385 return 0;
2386
2387 if (!data)
2388 return 0;
2389
2390 if (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)
2391 return 0;
2392
2393 security_init_mnt_opts(&opts);
2394 secdata = alloc_secdata();
2395 if (!secdata)
2396 return -ENOMEM;
2397 rc = selinux_sb_copy_data(data, secdata);
2398 if (rc)
2399 goto out_free_secdata;
2400
2401 rc = selinux_parse_opts_str(secdata, &opts);
2402 if (rc)
2403 goto out_free_secdata;
2404
2405 mount_options = opts.mnt_opts;
2406 flags = opts.mnt_opts_flags;
2407
2408 for (i = 0; i < opts.num_mnt_opts; i++) {
2409 u32 sid;
2410 size_t len;
2411
2412 if (flags[i] == SE_SBLABELSUPP)
2413 continue;
2414 len = strlen(mount_options[i]);
2415 rc = security_context_to_sid(mount_options[i], len, &sid);
2416 if (rc) {
2417 printk(KERN_WARNING "SELinux: security_context_to_sid"
2418 "(%s) failed for (dev %s, type %s) errno=%d\n",
2419 mount_options[i], sb->s_id, sb->s_type->name, rc);
2420 goto out_free_opts;
2421 }
2422 rc = -EINVAL;
2423 switch (flags[i]) {
2424 case FSCONTEXT_MNT:
2425 if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid, sid))
2426 goto out_bad_option;
2427 break;
2428 case CONTEXT_MNT:
2429 if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid, sid))
2430 goto out_bad_option;
2431 break;
2432 case ROOTCONTEXT_MNT: {
2433 struct inode_security_struct *root_isec;
2434 root_isec = sb->s_root->d_inode->i_security;
2435
2436 if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid, sid))
2437 goto out_bad_option;
2438 break;
2439 }
2440 case DEFCONTEXT_MNT:
2441 if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid, sid))
2442 goto out_bad_option;
2443 break;
2444 default:
2445 goto out_free_opts;
2446 }
2447 }
2448
2449 rc = 0;
2450out_free_opts:
2451 security_free_mnt_opts(&opts);
2452out_free_secdata:
2453 free_secdata(secdata);
2454 return rc;
2455out_bad_option:
2456 printk(KERN_WARNING "SELinux: unable to change security options "
2457 "during remount (dev %s, type=%s)\n", sb->s_id,
2458 sb->s_type->name);
2459 goto out_free_opts;
2460}
2461
James Morris12204e22008-12-19 10:44:42 +11002462static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002463{
David Howells88e67f32008-11-14 10:39:21 +11002464 const struct cred *cred = current_cred();
Thomas Liu2bf49692009-07-14 12:14:09 -04002465 struct common_audit_data ad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002466 int rc;
2467
2468 rc = superblock_doinit(sb, data);
2469 if (rc)
2470 return rc;
2471
James Morris74192242008-12-19 11:41:10 +11002472 /* Allow all mounts performed by the kernel */
2473 if (flags & MS_KERNMOUNT)
2474 return 0;
2475
Eric Paris50c205f2012-04-04 15:01:43 -04002476 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04002477 ad.u.dentry = sb->s_root;
David Howells88e67f32008-11-14 10:39:21 +11002478 return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002479}
2480
David Howells726c3342006-06-23 02:02:58 -07002481static int selinux_sb_statfs(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002482{
David Howells88e67f32008-11-14 10:39:21 +11002483 const struct cred *cred = current_cred();
Thomas Liu2bf49692009-07-14 12:14:09 -04002484 struct common_audit_data ad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002485
Eric Paris50c205f2012-04-04 15:01:43 -04002486 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04002487 ad.u.dentry = dentry->d_sb->s_root;
David Howells88e67f32008-11-14 10:39:21 +11002488 return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002489}
2490
Al Viro808d4e32012-10-11 11:42:01 -04002491static int selinux_mount(const char *dev_name,
Al Virob5266eb2008-03-22 17:48:24 -04002492 struct path *path,
Al Viro808d4e32012-10-11 11:42:01 -04002493 const char *type,
Eric Paris828dfe12008-04-17 13:17:49 -04002494 unsigned long flags,
2495 void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002496{
David Howells88e67f32008-11-14 10:39:21 +11002497 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002498
2499 if (flags & MS_REMOUNT)
Al Virod8c95842011-12-07 18:16:57 -05002500 return superblock_has_perm(cred, path->dentry->d_sb,
Eric Paris828dfe12008-04-17 13:17:49 -04002501 FILESYSTEM__REMOUNT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002502 else
Eric Paris2875fa02011-04-28 16:04:24 -04002503 return path_has_perm(cred, path, FILE__MOUNTON);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002504}
2505
2506static int selinux_umount(struct vfsmount *mnt, int flags)
2507{
David Howells88e67f32008-11-14 10:39:21 +11002508 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002509
David Howells88e67f32008-11-14 10:39:21 +11002510 return superblock_has_perm(cred, mnt->mnt_sb,
Eric Paris828dfe12008-04-17 13:17:49 -04002511 FILESYSTEM__UNMOUNT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002512}
2513
2514/* inode security operations */
2515
2516static int selinux_inode_alloc_security(struct inode *inode)
2517{
2518 return inode_alloc_security(inode);
2519}
2520
2521static void selinux_inode_free_security(struct inode *inode)
2522{
2523 inode_free_security(inode);
2524}
2525
David Quigleyd47be3d2013-05-22 12:50:34 -04002526static int selinux_dentry_init_security(struct dentry *dentry, int mode,
2527 struct qstr *name, void **ctx,
2528 u32 *ctxlen)
2529{
2530 const struct cred *cred = current_cred();
2531 struct task_security_struct *tsec;
2532 struct inode_security_struct *dsec;
2533 struct superblock_security_struct *sbsec;
2534 struct inode *dir = dentry->d_parent->d_inode;
2535 u32 newsid;
2536 int rc;
2537
2538 tsec = cred->security;
2539 dsec = dir->i_security;
2540 sbsec = dir->i_sb->s_security;
2541
2542 if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) {
2543 newsid = tsec->create_sid;
2544 } else {
2545 rc = security_transition_sid(tsec->sid, dsec->sid,
2546 inode_mode_to_security_class(mode),
2547 name,
2548 &newsid);
2549 if (rc) {
2550 printk(KERN_WARNING
2551 "%s: security_transition_sid failed, rc=%d\n",
2552 __func__, -rc);
2553 return rc;
2554 }
2555 }
2556
2557 return security_sid_to_context(newsid, (char **)ctx, ctxlen);
2558}
2559
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002560static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
Eric Paris2a7dba32011-02-01 11:05:39 -05002561 const struct qstr *qstr, char **name,
2562 void **value, size_t *len)
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002563{
Paul Moore5fb49872010-04-22 14:46:19 -04002564 const struct task_security_struct *tsec = current_security();
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002565 struct inode_security_struct *dsec;
2566 struct superblock_security_struct *sbsec;
David Howells275bb412008-11-14 10:39:19 +11002567 u32 sid, newsid, clen;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002568 int rc;
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002569 char *namep = NULL, *context;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002570
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002571 dsec = dir->i_security;
2572 sbsec = dir->i_sb->s_security;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002573
David Howells275bb412008-11-14 10:39:19 +11002574 sid = tsec->sid;
2575 newsid = tsec->create_sid;
2576
Eric Paris415103f2010-12-02 16:13:40 -05002577 if ((sbsec->flags & SE_SBINITIALIZED) &&
2578 (sbsec->behavior == SECURITY_FS_USE_MNTPOINT))
2579 newsid = sbsec->mntpoint_sid;
2580 else if (!newsid || !(sbsec->flags & SE_SBLABELSUPP)) {
David Howells275bb412008-11-14 10:39:19 +11002581 rc = security_transition_sid(sid, dsec->sid,
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002582 inode_mode_to_security_class(inode->i_mode),
Eric Paris652bb9b2011-02-01 11:05:40 -05002583 qstr, &newsid);
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002584 if (rc) {
2585 printk(KERN_WARNING "%s: "
2586 "security_transition_sid failed, rc=%d (dev=%s "
2587 "ino=%ld)\n",
Harvey Harrisondd6f9532008-03-06 10:03:59 +11002588 __func__,
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002589 -rc, inode->i_sb->s_id, inode->i_ino);
2590 return rc;
2591 }
2592 }
2593
Eric Paris296fddf2006-09-25 23:32:00 -07002594 /* Possibly defer initialization to selinux_complete_init. */
David P. Quigley0d90a7e2009-01-16 09:22:02 -05002595 if (sbsec->flags & SE_SBINITIALIZED) {
Eric Paris296fddf2006-09-25 23:32:00 -07002596 struct inode_security_struct *isec = inode->i_security;
2597 isec->sclass = inode_mode_to_security_class(inode->i_mode);
2598 isec->sid = newsid;
2599 isec->initialized = 1;
2600 }
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002601
David P. Quigleycd895962009-01-16 09:22:04 -05002602 if (!ss_initialized || !(sbsec->flags & SE_SBLABELSUPP))
Stephen Smalley25a74f32005-11-08 21:34:33 -08002603 return -EOPNOTSUPP;
2604
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002605 if (name) {
Josef Bacika02fe132008-04-04 09:35:05 +11002606 namep = kstrdup(XATTR_SELINUX_SUFFIX, GFP_NOFS);
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002607 if (!namep)
2608 return -ENOMEM;
2609 *name = namep;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002610 }
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002611
2612 if (value && len) {
Stephen Smalley12b29f32008-05-07 13:03:20 -04002613 rc = security_sid_to_context_force(newsid, &context, &clen);
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002614 if (rc) {
2615 kfree(namep);
2616 return rc;
2617 }
2618 *value = context;
2619 *len = clen;
2620 }
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002621
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002622 return 0;
2623}
2624
Al Viro4acdaf22011-07-26 01:42:34 -04002625static int selinux_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002626{
2627 return may_create(dir, dentry, SECCLASS_FILE);
2628}
2629
Linus Torvalds1da177e2005-04-16 15:20:36 -07002630static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
2631{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002632 return may_link(dir, old_dentry, MAY_LINK);
2633}
2634
Linus Torvalds1da177e2005-04-16 15:20:36 -07002635static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry)
2636{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002637 return may_link(dir, dentry, MAY_UNLINK);
2638}
2639
2640static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry, const char *name)
2641{
2642 return may_create(dir, dentry, SECCLASS_LNK_FILE);
2643}
2644
Al Viro18bb1db2011-07-26 01:41:39 -04002645static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry, umode_t mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002646{
2647 return may_create(dir, dentry, SECCLASS_DIR);
2648}
2649
Linus Torvalds1da177e2005-04-16 15:20:36 -07002650static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry)
2651{
2652 return may_link(dir, dentry, MAY_RMDIR);
2653}
2654
Al Viro1a67aaf2011-07-26 01:52:52 -04002655static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002656{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002657 return may_create(dir, dentry, inode_mode_to_security_class(mode));
2658}
2659
Linus Torvalds1da177e2005-04-16 15:20:36 -07002660static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
Eric Paris828dfe12008-04-17 13:17:49 -04002661 struct inode *new_inode, struct dentry *new_dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002662{
2663 return may_rename(old_inode, old_dentry, new_inode, new_dentry);
2664}
2665
Linus Torvalds1da177e2005-04-16 15:20:36 -07002666static int selinux_inode_readlink(struct dentry *dentry)
2667{
David Howells88e67f32008-11-14 10:39:21 +11002668 const struct cred *cred = current_cred();
2669
Eric Paris2875fa02011-04-28 16:04:24 -04002670 return dentry_has_perm(cred, dentry, FILE__READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002671}
2672
2673static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *nameidata)
2674{
David Howells88e67f32008-11-14 10:39:21 +11002675 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002676
Eric Paris2875fa02011-04-28 16:04:24 -04002677 return dentry_has_perm(cred, dentry, FILE__READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002678}
2679
Eric Parisd4cf970d2012-04-04 15:01:42 -04002680static noinline int audit_inode_permission(struct inode *inode,
2681 u32 perms, u32 audited, u32 denied,
2682 unsigned flags)
2683{
2684 struct common_audit_data ad;
Eric Parisd4cf970d2012-04-04 15:01:42 -04002685 struct inode_security_struct *isec = inode->i_security;
2686 int rc;
2687
Eric Paris50c205f2012-04-04 15:01:43 -04002688 ad.type = LSM_AUDIT_DATA_INODE;
Eric Parisd4cf970d2012-04-04 15:01:42 -04002689 ad.u.inode = inode;
2690
2691 rc = slow_avc_audit(current_sid(), isec->sid, isec->sclass, perms,
2692 audited, denied, &ad, flags);
2693 if (rc)
2694 return rc;
2695 return 0;
2696}
2697
Al Viroe74f71e2011-06-20 19:38:15 -04002698static int selinux_inode_permission(struct inode *inode, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002699{
David Howells88e67f32008-11-14 10:39:21 +11002700 const struct cred *cred = current_cred();
Eric Parisb782e0a2010-07-23 11:44:03 -04002701 u32 perms;
2702 bool from_access;
Al Virocf1dd1d2011-06-20 19:44:08 -04002703 unsigned flags = mask & MAY_NOT_BLOCK;
Eric Paris2e334052012-04-04 15:01:42 -04002704 struct inode_security_struct *isec;
2705 u32 sid;
2706 struct av_decision avd;
2707 int rc, rc2;
2708 u32 audited, denied;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002709
Eric Parisb782e0a2010-07-23 11:44:03 -04002710 from_access = mask & MAY_ACCESS;
Eric Parisd09ca732010-07-23 11:43:57 -04002711 mask &= (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND);
2712
Eric Parisb782e0a2010-07-23 11:44:03 -04002713 /* No permission to check. Existence test. */
2714 if (!mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002715 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002716
Eric Paris2e334052012-04-04 15:01:42 -04002717 validate_creds(cred);
Eric Parisb782e0a2010-07-23 11:44:03 -04002718
Eric Paris2e334052012-04-04 15:01:42 -04002719 if (unlikely(IS_PRIVATE(inode)))
2720 return 0;
Eric Parisb782e0a2010-07-23 11:44:03 -04002721
2722 perms = file_mask_to_av(inode->i_mode, mask);
2723
Eric Paris2e334052012-04-04 15:01:42 -04002724 sid = cred_sid(cred);
2725 isec = inode->i_security;
2726
2727 rc = avc_has_perm_noaudit(sid, isec->sid, isec->sclass, perms, 0, &avd);
2728 audited = avc_audit_required(perms, &avd, rc,
2729 from_access ? FILE__AUDIT_ACCESS : 0,
2730 &denied);
2731 if (likely(!audited))
2732 return rc;
2733
Eric Parisd4cf970d2012-04-04 15:01:42 -04002734 rc2 = audit_inode_permission(inode, perms, audited, denied, flags);
Eric Paris2e334052012-04-04 15:01:42 -04002735 if (rc2)
2736 return rc2;
2737 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002738}
2739
2740static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
2741{
David Howells88e67f32008-11-14 10:39:21 +11002742 const struct cred *cred = current_cred();
Amerigo Wangbc6a6002009-08-20 19:29:02 -07002743 unsigned int ia_valid = iattr->ia_valid;
Eric Paris95dbf732012-04-04 13:45:34 -04002744 __u32 av = FILE__WRITE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002745
Amerigo Wangbc6a6002009-08-20 19:29:02 -07002746 /* ATTR_FORCE is just used for ATTR_KILL_S[UG]ID. */
2747 if (ia_valid & ATTR_FORCE) {
2748 ia_valid &= ~(ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_MODE |
2749 ATTR_FORCE);
2750 if (!ia_valid)
2751 return 0;
2752 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002753
Amerigo Wangbc6a6002009-08-20 19:29:02 -07002754 if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID |
2755 ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_TIMES_SET))
Eric Paris2875fa02011-04-28 16:04:24 -04002756 return dentry_has_perm(cred, dentry, FILE__SETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002757
Eric Paris3d2195c2012-07-06 14:13:30 -04002758 if (selinux_policycap_openperm && (ia_valid & ATTR_SIZE))
Eric Paris95dbf732012-04-04 13:45:34 -04002759 av |= FILE__OPEN;
2760
2761 return dentry_has_perm(cred, dentry, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002762}
2763
2764static int selinux_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
2765{
David Howells88e67f32008-11-14 10:39:21 +11002766 const struct cred *cred = current_cred();
Eric Paris2875fa02011-04-28 16:04:24 -04002767 struct path path;
David Howells88e67f32008-11-14 10:39:21 +11002768
Eric Paris2875fa02011-04-28 16:04:24 -04002769 path.dentry = dentry;
2770 path.mnt = mnt;
2771
2772 return path_has_perm(cred, &path, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002773}
2774
David Howells8f0cfa52008-04-29 00:59:41 -07002775static int selinux_inode_setotherxattr(struct dentry *dentry, const char *name)
Serge E. Hallynb5376772007-10-16 23:31:36 -07002776{
David Howells88e67f32008-11-14 10:39:21 +11002777 const struct cred *cred = current_cred();
2778
Serge E. Hallynb5376772007-10-16 23:31:36 -07002779 if (!strncmp(name, XATTR_SECURITY_PREFIX,
2780 sizeof XATTR_SECURITY_PREFIX - 1)) {
2781 if (!strcmp(name, XATTR_NAME_CAPS)) {
2782 if (!capable(CAP_SETFCAP))
2783 return -EPERM;
2784 } else if (!capable(CAP_SYS_ADMIN)) {
2785 /* A different attribute in the security namespace.
2786 Restrict to administrator. */
2787 return -EPERM;
2788 }
2789 }
2790
2791 /* Not an attribute we recognize, so just check the
2792 ordinary setattr permission. */
Eric Paris2875fa02011-04-28 16:04:24 -04002793 return dentry_has_perm(cred, dentry, FILE__SETATTR);
Serge E. Hallynb5376772007-10-16 23:31:36 -07002794}
2795
David Howells8f0cfa52008-04-29 00:59:41 -07002796static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
2797 const void *value, size_t size, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002798{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002799 struct inode *inode = dentry->d_inode;
2800 struct inode_security_struct *isec = inode->i_security;
2801 struct superblock_security_struct *sbsec;
Thomas Liu2bf49692009-07-14 12:14:09 -04002802 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11002803 u32 newsid, sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002804 int rc = 0;
2805
Serge E. Hallynb5376772007-10-16 23:31:36 -07002806 if (strcmp(name, XATTR_NAME_SELINUX))
2807 return selinux_inode_setotherxattr(dentry, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002808
2809 sbsec = inode->i_sb->s_security;
David P. Quigleycd895962009-01-16 09:22:04 -05002810 if (!(sbsec->flags & SE_SBLABELSUPP))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002811 return -EOPNOTSUPP;
2812
Serge E. Hallyn2e149672011-03-23 16:43:26 -07002813 if (!inode_owner_or_capable(inode))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002814 return -EPERM;
2815
Eric Paris50c205f2012-04-04 15:01:43 -04002816 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04002817 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002818
David Howells275bb412008-11-14 10:39:19 +11002819 rc = avc_has_perm(sid, isec->sid, isec->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002820 FILE__RELABELFROM, &ad);
2821 if (rc)
2822 return rc;
2823
2824 rc = security_context_to_sid(value, size, &newsid);
Stephen Smalley12b29f32008-05-07 13:03:20 -04002825 if (rc == -EINVAL) {
Eric Parisd6ea83e2012-04-04 13:45:49 -04002826 if (!capable(CAP_MAC_ADMIN)) {
2827 struct audit_buffer *ab;
2828 size_t audit_size;
2829 const char *str;
2830
2831 /* We strip a nul only if it is at the end, otherwise the
2832 * context contains a nul and we should audit that */
Al Viroe3fea3f2012-06-09 08:15:16 +01002833 if (value) {
2834 str = value;
2835 if (str[size - 1] == '\0')
2836 audit_size = size - 1;
2837 else
2838 audit_size = size;
2839 } else {
2840 str = "";
2841 audit_size = 0;
2842 }
Eric Parisd6ea83e2012-04-04 13:45:49 -04002843 ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR);
2844 audit_log_format(ab, "op=setxattr invalid_context=");
2845 audit_log_n_untrustedstring(ab, value, audit_size);
2846 audit_log_end(ab);
2847
Stephen Smalley12b29f32008-05-07 13:03:20 -04002848 return rc;
Eric Parisd6ea83e2012-04-04 13:45:49 -04002849 }
Stephen Smalley12b29f32008-05-07 13:03:20 -04002850 rc = security_context_to_sid_force(value, size, &newsid);
2851 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002852 if (rc)
2853 return rc;
2854
David Howells275bb412008-11-14 10:39:19 +11002855 rc = avc_has_perm(sid, newsid, isec->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002856 FILE__RELABELTO, &ad);
2857 if (rc)
2858 return rc;
2859
David Howells275bb412008-11-14 10:39:19 +11002860 rc = security_validate_transition(isec->sid, newsid, sid,
Eric Paris828dfe12008-04-17 13:17:49 -04002861 isec->sclass);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002862 if (rc)
2863 return rc;
2864
2865 return avc_has_perm(newsid,
2866 sbsec->sid,
2867 SECCLASS_FILESYSTEM,
2868 FILESYSTEM__ASSOCIATE,
2869 &ad);
2870}
2871
David Howells8f0cfa52008-04-29 00:59:41 -07002872static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
Eric Parisf5269712008-05-14 11:27:45 -04002873 const void *value, size_t size,
David Howells8f0cfa52008-04-29 00:59:41 -07002874 int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002875{
2876 struct inode *inode = dentry->d_inode;
2877 struct inode_security_struct *isec = inode->i_security;
2878 u32 newsid;
2879 int rc;
2880
2881 if (strcmp(name, XATTR_NAME_SELINUX)) {
2882 /* Not an attribute we recognize, so nothing to do. */
2883 return;
2884 }
2885
Stephen Smalley12b29f32008-05-07 13:03:20 -04002886 rc = security_context_to_sid_force(value, size, &newsid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002887 if (rc) {
Stephen Smalley12b29f32008-05-07 13:03:20 -04002888 printk(KERN_ERR "SELinux: unable to map context to SID"
2889 "for (%s, %lu), rc=%d\n",
2890 inode->i_sb->s_id, inode->i_ino, -rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002891 return;
2892 }
2893
2894 isec->sid = newsid;
2895 return;
2896}
2897
David Howells8f0cfa52008-04-29 00:59:41 -07002898static int selinux_inode_getxattr(struct dentry *dentry, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002899{
David Howells88e67f32008-11-14 10:39:21 +11002900 const struct cred *cred = current_cred();
2901
Eric Paris2875fa02011-04-28 16:04:24 -04002902 return dentry_has_perm(cred, dentry, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002903}
2904
Eric Paris828dfe12008-04-17 13:17:49 -04002905static int selinux_inode_listxattr(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002906{
David Howells88e67f32008-11-14 10:39:21 +11002907 const struct cred *cred = current_cred();
2908
Eric Paris2875fa02011-04-28 16:04:24 -04002909 return dentry_has_perm(cred, dentry, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002910}
2911
David Howells8f0cfa52008-04-29 00:59:41 -07002912static int selinux_inode_removexattr(struct dentry *dentry, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002913{
Serge E. Hallynb5376772007-10-16 23:31:36 -07002914 if (strcmp(name, XATTR_NAME_SELINUX))
2915 return selinux_inode_setotherxattr(dentry, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002916
2917 /* No one is allowed to remove a SELinux security label.
2918 You can change the label, but all data must be labeled. */
2919 return -EACCES;
2920}
2921
James Morrisd381d8a2005-10-30 14:59:22 -08002922/*
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04002923 * Copy the inode security context value to the user.
James Morrisd381d8a2005-10-30 14:59:22 -08002924 *
2925 * Permission check is handled by selinux_inode_getxattr hook.
2926 */
David P. Quigley42492592008-02-04 22:29:39 -08002927static int selinux_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002928{
David P. Quigley42492592008-02-04 22:29:39 -08002929 u32 size;
2930 int error;
2931 char *context = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002932 struct inode_security_struct *isec = inode->i_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002933
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00002934 if (strcmp(name, XATTR_SELINUX_SUFFIX))
2935 return -EOPNOTSUPP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002936
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04002937 /*
2938 * If the caller has CAP_MAC_ADMIN, then get the raw context
2939 * value even if it is not defined by current policy; otherwise,
2940 * use the in-core value under current policy.
2941 * Use the non-auditing forms of the permission checks since
2942 * getxattr may be called by unprivileged processes commonly
2943 * and lack of permission just means that we fall back to the
2944 * in-core context value, not a denial.
2945 */
Eric Paris6a9de492012-01-03 12:25:14 -05002946 error = selinux_capable(current_cred(), &init_user_ns, CAP_MAC_ADMIN,
David Howells3699c532009-01-06 22:27:01 +00002947 SECURITY_CAP_NOAUDIT);
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04002948 if (!error)
2949 error = security_sid_to_context_force(isec->sid, &context,
2950 &size);
2951 else
2952 error = security_sid_to_context(isec->sid, &context, &size);
David P. Quigley42492592008-02-04 22:29:39 -08002953 if (error)
2954 return error;
2955 error = size;
2956 if (alloc) {
2957 *buffer = context;
2958 goto out_nofree;
2959 }
2960 kfree(context);
2961out_nofree:
2962 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002963}
2964
2965static int selinux_inode_setsecurity(struct inode *inode, const char *name,
Eric Paris828dfe12008-04-17 13:17:49 -04002966 const void *value, size_t size, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002967{
2968 struct inode_security_struct *isec = inode->i_security;
2969 u32 newsid;
2970 int rc;
2971
2972 if (strcmp(name, XATTR_SELINUX_SUFFIX))
2973 return -EOPNOTSUPP;
2974
2975 if (!value || !size)
2976 return -EACCES;
2977
Eric Paris828dfe12008-04-17 13:17:49 -04002978 rc = security_context_to_sid((void *)value, size, &newsid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002979 if (rc)
2980 return rc;
2981
2982 isec->sid = newsid;
David P. Quigleyddd29ec2009-09-09 14:25:37 -04002983 isec->initialized = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002984 return 0;
2985}
2986
2987static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size)
2988{
2989 const int len = sizeof(XATTR_NAME_SELINUX);
2990 if (buffer && len <= buffer_size)
2991 memcpy(buffer, XATTR_NAME_SELINUX, len);
2992 return len;
2993}
2994
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02002995static void selinux_inode_getsecid(const struct inode *inode, u32 *secid)
2996{
2997 struct inode_security_struct *isec = inode->i_security;
2998 *secid = isec->sid;
2999}
3000
Linus Torvalds1da177e2005-04-16 15:20:36 -07003001/* file security operations */
3002
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003003static int selinux_revalidate_file_permission(struct file *file, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003004{
David Howells88e67f32008-11-14 10:39:21 +11003005 const struct cred *cred = current_cred();
Al Viro496ad9a2013-01-23 17:07:38 -05003006 struct inode *inode = file_inode(file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003007
Linus Torvalds1da177e2005-04-16 15:20:36 -07003008 /* file_mask_to_av won't add FILE__WRITE if MAY_APPEND is set */
3009 if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE))
3010 mask |= MAY_APPEND;
3011
Paul Moore389fb8002009-03-27 17:10:34 -04003012 return file_has_perm(cred, file,
3013 file_mask_to_av(inode->i_mode, mask));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003014}
3015
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003016static int selinux_file_permission(struct file *file, int mask)
3017{
Al Viro496ad9a2013-01-23 17:07:38 -05003018 struct inode *inode = file_inode(file);
Stephen Smalley20dda182009-06-22 14:54:53 -04003019 struct file_security_struct *fsec = file->f_security;
3020 struct inode_security_struct *isec = inode->i_security;
3021 u32 sid = current_sid();
3022
Paul Moore389fb8002009-03-27 17:10:34 -04003023 if (!mask)
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003024 /* No permission to check. Existence test. */
3025 return 0;
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003026
Stephen Smalley20dda182009-06-22 14:54:53 -04003027 if (sid == fsec->sid && fsec->isid == isec->sid &&
3028 fsec->pseqno == avc_policy_seqno())
Eric Paris83d49852012-04-04 13:45:40 -04003029 /* No change since file_open check. */
Stephen Smalley20dda182009-06-22 14:54:53 -04003030 return 0;
3031
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003032 return selinux_revalidate_file_permission(file, mask);
3033}
3034
Linus Torvalds1da177e2005-04-16 15:20:36 -07003035static int selinux_file_alloc_security(struct file *file)
3036{
3037 return file_alloc_security(file);
3038}
3039
3040static void selinux_file_free_security(struct file *file)
3041{
3042 file_free_security(file);
3043}
3044
3045static int selinux_file_ioctl(struct file *file, unsigned int cmd,
3046 unsigned long arg)
3047{
David Howells88e67f32008-11-14 10:39:21 +11003048 const struct cred *cred = current_cred();
Eric Paris0b24dcb2011-02-25 15:39:20 -05003049 int error = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003050
Eric Paris0b24dcb2011-02-25 15:39:20 -05003051 switch (cmd) {
3052 case FIONREAD:
3053 /* fall through */
3054 case FIBMAP:
3055 /* fall through */
3056 case FIGETBSZ:
3057 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003058 case FS_IOC_GETFLAGS:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003059 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003060 case FS_IOC_GETVERSION:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003061 error = file_has_perm(cred, file, FILE__GETATTR);
3062 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003063
Al Viro2f99c362012-03-23 16:04:05 -04003064 case FS_IOC_SETFLAGS:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003065 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003066 case FS_IOC_SETVERSION:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003067 error = file_has_perm(cred, file, FILE__SETATTR);
3068 break;
3069
3070 /* sys_ioctl() checks */
3071 case FIONBIO:
3072 /* fall through */
3073 case FIOASYNC:
3074 error = file_has_perm(cred, file, 0);
3075 break;
3076
3077 case KDSKBENT:
3078 case KDSKBSENT:
Eric Paris6a9de492012-01-03 12:25:14 -05003079 error = cred_has_capability(cred, CAP_SYS_TTY_CONFIG,
3080 SECURITY_CAP_AUDIT);
Eric Paris0b24dcb2011-02-25 15:39:20 -05003081 break;
3082
3083 /* default case assumes that the command will go
3084 * to the file's ioctl() function.
3085 */
3086 default:
3087 error = file_has_perm(cred, file, FILE__IOCTL);
3088 }
3089 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003090}
3091
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003092static int default_noexec;
3093
Linus Torvalds1da177e2005-04-16 15:20:36 -07003094static int file_map_prot_check(struct file *file, unsigned long prot, int shared)
3095{
David Howells88e67f32008-11-14 10:39:21 +11003096 const struct cred *cred = current_cred();
David Howellsd84f4f92008-11-14 10:39:23 +11003097 int rc = 0;
David Howells88e67f32008-11-14 10:39:21 +11003098
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003099 if (default_noexec &&
3100 (prot & PROT_EXEC) && (!file || (!shared && (prot & PROT_WRITE)))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003101 /*
3102 * We are making executable an anonymous mapping or a
3103 * private file mapping that will also be writable.
3104 * This has an additional check.
3105 */
David Howellsd84f4f92008-11-14 10:39:23 +11003106 rc = cred_has_perm(cred, cred, PROCESS__EXECMEM);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003107 if (rc)
David Howellsd84f4f92008-11-14 10:39:23 +11003108 goto error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003109 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003110
3111 if (file) {
3112 /* read access is always possible with a mapping */
3113 u32 av = FILE__READ;
3114
3115 /* write access only matters if the mapping is shared */
3116 if (shared && (prot & PROT_WRITE))
3117 av |= FILE__WRITE;
3118
3119 if (prot & PROT_EXEC)
3120 av |= FILE__EXECUTE;
3121
David Howells88e67f32008-11-14 10:39:21 +11003122 return file_has_perm(cred, file, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003123 }
David Howellsd84f4f92008-11-14 10:39:23 +11003124
3125error:
3126 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003127}
3128
Al Viroe5467852012-05-30 13:30:51 -04003129static int selinux_mmap_addr(unsigned long addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003130{
Eric Parised032182007-06-28 15:55:21 -04003131 int rc = 0;
David Howells275bb412008-11-14 10:39:19 +11003132 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003133
Eric Paris84336d1a2009-07-31 12:54:05 -04003134 /*
3135 * notice that we are intentionally putting the SELinux check before
3136 * the secondary cap_file_mmap check. This is such a likely attempt
3137 * at bad behaviour/exploit that we always want to get the AVC, even
3138 * if DAC would have also denied the operation.
3139 */
Eric Parisa2551df2009-07-31 12:54:11 -04003140 if (addr < CONFIG_LSM_MMAP_MIN_ADDR) {
Eric Parised032182007-06-28 15:55:21 -04003141 rc = avc_has_perm(sid, sid, SECCLASS_MEMPROTECT,
3142 MEMPROTECT__MMAP_ZERO, NULL);
Eric Paris84336d1a2009-07-31 12:54:05 -04003143 if (rc)
3144 return rc;
3145 }
3146
3147 /* do DAC check on address space usage */
Al Viroe5467852012-05-30 13:30:51 -04003148 return cap_mmap_addr(addr);
3149}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003150
Al Viroe5467852012-05-30 13:30:51 -04003151static int selinux_mmap_file(struct file *file, unsigned long reqprot,
3152 unsigned long prot, unsigned long flags)
3153{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003154 if (selinux_checkreqprot)
3155 prot = reqprot;
3156
3157 return file_map_prot_check(file, prot,
3158 (flags & MAP_TYPE) == MAP_SHARED);
3159}
3160
3161static int selinux_file_mprotect(struct vm_area_struct *vma,
3162 unsigned long reqprot,
3163 unsigned long prot)
3164{
David Howells88e67f32008-11-14 10:39:21 +11003165 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003166
3167 if (selinux_checkreqprot)
3168 prot = reqprot;
3169
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003170 if (default_noexec &&
3171 (prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) {
James Morrisd541bbe2009-01-29 12:19:51 +11003172 int rc = 0;
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003173 if (vma->vm_start >= vma->vm_mm->start_brk &&
3174 vma->vm_end <= vma->vm_mm->brk) {
David Howellsd84f4f92008-11-14 10:39:23 +11003175 rc = cred_has_perm(cred, cred, PROCESS__EXECHEAP);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003176 } else if (!vma->vm_file &&
3177 vma->vm_start <= vma->vm_mm->start_stack &&
3178 vma->vm_end >= vma->vm_mm->start_stack) {
David Howells3b11a1d2008-11-14 10:39:26 +11003179 rc = current_has_perm(current, PROCESS__EXECSTACK);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003180 } else if (vma->vm_file && vma->anon_vma) {
3181 /*
3182 * We are making executable a file mapping that has
3183 * had some COW done. Since pages might have been
3184 * written, check ability to execute the possibly
3185 * modified content. This typically should only
3186 * occur for text relocations.
3187 */
David Howellsd84f4f92008-11-14 10:39:23 +11003188 rc = file_has_perm(cred, vma->vm_file, FILE__EXECMOD);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003189 }
Lorenzo Hernandez García-Hierro6b992192005-06-25 14:54:34 -07003190 if (rc)
3191 return rc;
3192 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003193
3194 return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED);
3195}
3196
3197static int selinux_file_lock(struct file *file, unsigned int cmd)
3198{
David Howells88e67f32008-11-14 10:39:21 +11003199 const struct cred *cred = current_cred();
3200
3201 return file_has_perm(cred, file, FILE__LOCK);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003202}
3203
3204static int selinux_file_fcntl(struct file *file, unsigned int cmd,
3205 unsigned long arg)
3206{
David Howells88e67f32008-11-14 10:39:21 +11003207 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003208 int err = 0;
3209
3210 switch (cmd) {
Eric Paris828dfe12008-04-17 13:17:49 -04003211 case F_SETFL:
Eric Paris828dfe12008-04-17 13:17:49 -04003212 if ((file->f_flags & O_APPEND) && !(arg & O_APPEND)) {
David Howells88e67f32008-11-14 10:39:21 +11003213 err = file_has_perm(cred, file, FILE__WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003214 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003215 }
3216 /* fall through */
3217 case F_SETOWN:
3218 case F_SETSIG:
3219 case F_GETFL:
3220 case F_GETOWN:
3221 case F_GETSIG:
Cyrill Gorcunov1d151c32012-07-30 14:43:00 -07003222 case F_GETOWNER_UIDS:
Eric Paris828dfe12008-04-17 13:17:49 -04003223 /* Just check FD__USE permission */
David Howells88e67f32008-11-14 10:39:21 +11003224 err = file_has_perm(cred, file, 0);
Eric Paris828dfe12008-04-17 13:17:49 -04003225 break;
3226 case F_GETLK:
3227 case F_SETLK:
3228 case F_SETLKW:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003229#if BITS_PER_LONG == 32
Eric Paris828dfe12008-04-17 13:17:49 -04003230 case F_GETLK64:
3231 case F_SETLK64:
3232 case F_SETLKW64:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003233#endif
David Howells88e67f32008-11-14 10:39:21 +11003234 err = file_has_perm(cred, file, FILE__LOCK);
Eric Paris828dfe12008-04-17 13:17:49 -04003235 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003236 }
3237
3238 return err;
3239}
3240
3241static int selinux_file_set_fowner(struct file *file)
3242{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003243 struct file_security_struct *fsec;
3244
Linus Torvalds1da177e2005-04-16 15:20:36 -07003245 fsec = file->f_security;
David Howells275bb412008-11-14 10:39:19 +11003246 fsec->fown_sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003247
3248 return 0;
3249}
3250
3251static int selinux_file_send_sigiotask(struct task_struct *tsk,
3252 struct fown_struct *fown, int signum)
3253{
Eric Paris828dfe12008-04-17 13:17:49 -04003254 struct file *file;
Stephen Smalley65c90bc2009-05-04 15:43:18 -04003255 u32 sid = task_sid(tsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003256 u32 perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003257 struct file_security_struct *fsec;
3258
3259 /* struct fown_struct is never outside the context of a struct file */
Eric Paris828dfe12008-04-17 13:17:49 -04003260 file = container_of(fown, struct file, f_owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003261
Linus Torvalds1da177e2005-04-16 15:20:36 -07003262 fsec = file->f_security;
3263
3264 if (!signum)
3265 perm = signal_to_av(SIGIO); /* as per send_sigio_to_task */
3266 else
3267 perm = signal_to_av(signum);
3268
David Howells275bb412008-11-14 10:39:19 +11003269 return avc_has_perm(fsec->fown_sid, sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003270 SECCLASS_PROCESS, perm, NULL);
3271}
3272
3273static int selinux_file_receive(struct file *file)
3274{
David Howells88e67f32008-11-14 10:39:21 +11003275 const struct cred *cred = current_cred();
3276
3277 return file_has_perm(cred, file, file_to_av(file));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003278}
3279
Eric Paris83d49852012-04-04 13:45:40 -04003280static int selinux_file_open(struct file *file, const struct cred *cred)
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003281{
3282 struct file_security_struct *fsec;
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003283 struct inode_security_struct *isec;
David Howellsd84f4f92008-11-14 10:39:23 +11003284
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003285 fsec = file->f_security;
Al Viro496ad9a2013-01-23 17:07:38 -05003286 isec = file_inode(file)->i_security;
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003287 /*
3288 * Save inode label and policy sequence number
3289 * at open-time so that selinux_file_permission
3290 * can determine whether revalidation is necessary.
3291 * Task label is already saved in the file security
3292 * struct as its SID.
3293 */
3294 fsec->isid = isec->sid;
3295 fsec->pseqno = avc_policy_seqno();
3296 /*
3297 * Since the inode label or policy seqno may have changed
3298 * between the selinux_inode_permission check and the saving
3299 * of state above, recheck that access is still permitted.
3300 * Otherwise, access might never be revalidated against the
3301 * new inode label or new policy.
3302 * This check is not redundant - do not remove.
3303 */
Eric Paris602a8dd2012-04-04 15:01:42 -04003304 return path_has_perm(cred, &file->f_path, open_file_to_av(file));
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003305}
3306
Linus Torvalds1da177e2005-04-16 15:20:36 -07003307/* task security operations */
3308
3309static int selinux_task_create(unsigned long clone_flags)
3310{
David Howells3b11a1d2008-11-14 10:39:26 +11003311 return current_has_perm(current, PROCESS__FORK);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003312}
3313
David Howellsf1752ee2008-11-14 10:39:17 +11003314/*
David Howellsee18d642009-09-02 09:14:21 +01003315 * allocate the SELinux part of blank credentials
3316 */
3317static int selinux_cred_alloc_blank(struct cred *cred, gfp_t gfp)
3318{
3319 struct task_security_struct *tsec;
3320
3321 tsec = kzalloc(sizeof(struct task_security_struct), gfp);
3322 if (!tsec)
3323 return -ENOMEM;
3324
3325 cred->security = tsec;
3326 return 0;
3327}
3328
3329/*
David Howellsf1752ee2008-11-14 10:39:17 +11003330 * detach and free the LSM part of a set of credentials
3331 */
3332static void selinux_cred_free(struct cred *cred)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003333{
David Howellsf1752ee2008-11-14 10:39:17 +11003334 struct task_security_struct *tsec = cred->security;
David Howellse0e81732009-09-02 09:13:40 +01003335
Tetsuo Handa2edeaa32011-02-07 13:36:10 +00003336 /*
3337 * cred->security == NULL if security_cred_alloc_blank() or
3338 * security_prepare_creds() returned an error.
3339 */
3340 BUG_ON(cred->security && (unsigned long) cred->security < PAGE_SIZE);
David Howellse0e81732009-09-02 09:13:40 +01003341 cred->security = (void *) 0x7UL;
David Howellsf1752ee2008-11-14 10:39:17 +11003342 kfree(tsec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003343}
3344
David Howellsd84f4f92008-11-14 10:39:23 +11003345/*
3346 * prepare a new set of credentials for modification
3347 */
3348static int selinux_cred_prepare(struct cred *new, const struct cred *old,
3349 gfp_t gfp)
3350{
3351 const struct task_security_struct *old_tsec;
3352 struct task_security_struct *tsec;
3353
3354 old_tsec = old->security;
3355
3356 tsec = kmemdup(old_tsec, sizeof(struct task_security_struct), gfp);
3357 if (!tsec)
3358 return -ENOMEM;
3359
3360 new->security = tsec;
3361 return 0;
3362}
3363
3364/*
David Howellsee18d642009-09-02 09:14:21 +01003365 * transfer the SELinux data to a blank set of creds
3366 */
3367static void selinux_cred_transfer(struct cred *new, const struct cred *old)
3368{
3369 const struct task_security_struct *old_tsec = old->security;
3370 struct task_security_struct *tsec = new->security;
3371
3372 *tsec = *old_tsec;
3373}
3374
3375/*
David Howells3a3b7ce2008-11-14 10:39:28 +11003376 * set the security data for a kernel service
3377 * - all the creation contexts are set to unlabelled
3378 */
3379static int selinux_kernel_act_as(struct cred *new, u32 secid)
3380{
3381 struct task_security_struct *tsec = new->security;
3382 u32 sid = current_sid();
3383 int ret;
3384
3385 ret = avc_has_perm(sid, secid,
3386 SECCLASS_KERNEL_SERVICE,
3387 KERNEL_SERVICE__USE_AS_OVERRIDE,
3388 NULL);
3389 if (ret == 0) {
3390 tsec->sid = secid;
3391 tsec->create_sid = 0;
3392 tsec->keycreate_sid = 0;
3393 tsec->sockcreate_sid = 0;
3394 }
3395 return ret;
3396}
3397
3398/*
3399 * set the file creation context in a security record to the same as the
3400 * objective context of the specified inode
3401 */
3402static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode)
3403{
3404 struct inode_security_struct *isec = inode->i_security;
3405 struct task_security_struct *tsec = new->security;
3406 u32 sid = current_sid();
3407 int ret;
3408
3409 ret = avc_has_perm(sid, isec->sid,
3410 SECCLASS_KERNEL_SERVICE,
3411 KERNEL_SERVICE__CREATE_FILES_AS,
3412 NULL);
3413
3414 if (ret == 0)
3415 tsec->create_sid = isec->sid;
David Howellsef574712010-02-26 01:56:16 +00003416 return ret;
David Howells3a3b7ce2008-11-14 10:39:28 +11003417}
3418
Eric Parisdd8dbf22009-11-03 16:35:32 +11003419static int selinux_kernel_module_request(char *kmod_name)
Eric Paris25354c42009-08-13 09:45:03 -04003420{
Eric Parisdd8dbf22009-11-03 16:35:32 +11003421 u32 sid;
3422 struct common_audit_data ad;
3423
3424 sid = task_sid(current);
3425
Eric Paris50c205f2012-04-04 15:01:43 -04003426 ad.type = LSM_AUDIT_DATA_KMOD;
Eric Parisdd8dbf22009-11-03 16:35:32 +11003427 ad.u.kmod_name = kmod_name;
3428
3429 return avc_has_perm(sid, SECINITSID_KERNEL, SECCLASS_SYSTEM,
3430 SYSTEM__MODULE_REQUEST, &ad);
Eric Paris25354c42009-08-13 09:45:03 -04003431}
3432
Linus Torvalds1da177e2005-04-16 15:20:36 -07003433static int selinux_task_setpgid(struct task_struct *p, pid_t pgid)
3434{
David Howells3b11a1d2008-11-14 10:39:26 +11003435 return current_has_perm(p, PROCESS__SETPGID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003436}
3437
3438static int selinux_task_getpgid(struct task_struct *p)
3439{
David Howells3b11a1d2008-11-14 10:39:26 +11003440 return current_has_perm(p, PROCESS__GETPGID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003441}
3442
3443static int selinux_task_getsid(struct task_struct *p)
3444{
David Howells3b11a1d2008-11-14 10:39:26 +11003445 return current_has_perm(p, PROCESS__GETSESSION);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003446}
3447
David Quigleyf9008e42006-06-30 01:55:46 -07003448static void selinux_task_getsecid(struct task_struct *p, u32 *secid)
3449{
David Howells275bb412008-11-14 10:39:19 +11003450 *secid = task_sid(p);
David Quigleyf9008e42006-06-30 01:55:46 -07003451}
3452
Linus Torvalds1da177e2005-04-16 15:20:36 -07003453static int selinux_task_setnice(struct task_struct *p, int nice)
3454{
3455 int rc;
3456
Eric Paris200ac532009-02-12 15:01:04 -05003457 rc = cap_task_setnice(p, nice);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003458 if (rc)
3459 return rc;
3460
David Howells3b11a1d2008-11-14 10:39:26 +11003461 return current_has_perm(p, PROCESS__SETSCHED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003462}
3463
James Morris03e68062006-06-23 02:03:58 -07003464static int selinux_task_setioprio(struct task_struct *p, int ioprio)
3465{
Serge E. Hallynb5376772007-10-16 23:31:36 -07003466 int rc;
3467
Eric Paris200ac532009-02-12 15:01:04 -05003468 rc = cap_task_setioprio(p, ioprio);
Serge E. Hallynb5376772007-10-16 23:31:36 -07003469 if (rc)
3470 return rc;
3471
David Howells3b11a1d2008-11-14 10:39:26 +11003472 return current_has_perm(p, PROCESS__SETSCHED);
James Morris03e68062006-06-23 02:03:58 -07003473}
3474
David Quigleya1836a42006-06-30 01:55:49 -07003475static int selinux_task_getioprio(struct task_struct *p)
3476{
David Howells3b11a1d2008-11-14 10:39:26 +11003477 return current_has_perm(p, PROCESS__GETSCHED);
David Quigleya1836a42006-06-30 01:55:49 -07003478}
3479
Jiri Slaby8fd00b42009-08-26 18:41:16 +02003480static int selinux_task_setrlimit(struct task_struct *p, unsigned int resource,
3481 struct rlimit *new_rlim)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003482{
Jiri Slaby8fd00b42009-08-26 18:41:16 +02003483 struct rlimit *old_rlim = p->signal->rlim + resource;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003484
3485 /* Control the ability to change the hard limit (whether
3486 lowering or raising it), so that the hard limit can
3487 later be used as a safe reset point for the soft limit
David Howellsd84f4f92008-11-14 10:39:23 +11003488 upon context transitions. See selinux_bprm_committing_creds. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003489 if (old_rlim->rlim_max != new_rlim->rlim_max)
Jiri Slaby8fd00b42009-08-26 18:41:16 +02003490 return current_has_perm(p, PROCESS__SETRLIMIT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003491
3492 return 0;
3493}
3494
KOSAKI Motohirob0ae1982010-10-15 04:21:18 +09003495static int selinux_task_setscheduler(struct task_struct *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003496{
Serge E. Hallynb5376772007-10-16 23:31:36 -07003497 int rc;
3498
KOSAKI Motohirob0ae1982010-10-15 04:21:18 +09003499 rc = cap_task_setscheduler(p);
Serge E. Hallynb5376772007-10-16 23:31:36 -07003500 if (rc)
3501 return rc;
3502
David Howells3b11a1d2008-11-14 10:39:26 +11003503 return current_has_perm(p, PROCESS__SETSCHED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003504}
3505
3506static int selinux_task_getscheduler(struct task_struct *p)
3507{
David Howells3b11a1d2008-11-14 10:39:26 +11003508 return current_has_perm(p, PROCESS__GETSCHED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003509}
3510
David Quigley35601542006-06-23 02:04:01 -07003511static int selinux_task_movememory(struct task_struct *p)
3512{
David Howells3b11a1d2008-11-14 10:39:26 +11003513 return current_has_perm(p, PROCESS__SETSCHED);
David Quigley35601542006-06-23 02:04:01 -07003514}
3515
David Quigleyf9008e42006-06-30 01:55:46 -07003516static int selinux_task_kill(struct task_struct *p, struct siginfo *info,
3517 int sig, u32 secid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003518{
3519 u32 perm;
3520 int rc;
3521
Linus Torvalds1da177e2005-04-16 15:20:36 -07003522 if (!sig)
3523 perm = PROCESS__SIGNULL; /* null signal; existence test */
3524 else
3525 perm = signal_to_av(sig);
David Quigleyf9008e42006-06-30 01:55:46 -07003526 if (secid)
David Howells275bb412008-11-14 10:39:19 +11003527 rc = avc_has_perm(secid, task_sid(p),
3528 SECCLASS_PROCESS, perm, NULL);
David Quigleyf9008e42006-06-30 01:55:46 -07003529 else
David Howells3b11a1d2008-11-14 10:39:26 +11003530 rc = current_has_perm(p, perm);
David Quigleyf9008e42006-06-30 01:55:46 -07003531 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003532}
3533
Linus Torvalds1da177e2005-04-16 15:20:36 -07003534static int selinux_task_wait(struct task_struct *p)
3535{
Eric Paris8a535142007-10-22 16:10:31 -04003536 return task_has_perm(p, current, PROCESS__SIGCHLD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003537}
3538
Linus Torvalds1da177e2005-04-16 15:20:36 -07003539static void selinux_task_to_inode(struct task_struct *p,
3540 struct inode *inode)
3541{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003542 struct inode_security_struct *isec = inode->i_security;
David Howells275bb412008-11-14 10:39:19 +11003543 u32 sid = task_sid(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003544
David Howells275bb412008-11-14 10:39:19 +11003545 isec->sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003546 isec->initialized = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003547}
3548
Linus Torvalds1da177e2005-04-16 15:20:36 -07003549/* Returns error only if unable to parse addresses */
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003550static int selinux_parse_skb_ipv4(struct sk_buff *skb,
Thomas Liu2bf49692009-07-14 12:14:09 -04003551 struct common_audit_data *ad, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003552{
3553 int offset, ihlen, ret = -EINVAL;
3554 struct iphdr _iph, *ih;
3555
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03003556 offset = skb_network_offset(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003557 ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph);
3558 if (ih == NULL)
3559 goto out;
3560
3561 ihlen = ih->ihl * 4;
3562 if (ihlen < sizeof(_iph))
3563 goto out;
3564
Eric Paris48c62af2012-04-02 13:15:44 -04003565 ad->u.net->v4info.saddr = ih->saddr;
3566 ad->u.net->v4info.daddr = ih->daddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003567 ret = 0;
3568
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003569 if (proto)
3570 *proto = ih->protocol;
3571
Linus Torvalds1da177e2005-04-16 15:20:36 -07003572 switch (ih->protocol) {
Eric Paris828dfe12008-04-17 13:17:49 -04003573 case IPPROTO_TCP: {
3574 struct tcphdr _tcph, *th;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003575
Eric Paris828dfe12008-04-17 13:17:49 -04003576 if (ntohs(ih->frag_off) & IP_OFFSET)
3577 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003578
3579 offset += ihlen;
3580 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
3581 if (th == NULL)
3582 break;
3583
Eric Paris48c62af2012-04-02 13:15:44 -04003584 ad->u.net->sport = th->source;
3585 ad->u.net->dport = th->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003586 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003587 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003588
Eric Paris828dfe12008-04-17 13:17:49 -04003589 case IPPROTO_UDP: {
3590 struct udphdr _udph, *uh;
3591
3592 if (ntohs(ih->frag_off) & IP_OFFSET)
3593 break;
3594
3595 offset += ihlen;
3596 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
3597 if (uh == NULL)
3598 break;
3599
Eric Paris48c62af2012-04-02 13:15:44 -04003600 ad->u.net->sport = uh->source;
3601 ad->u.net->dport = uh->dest;
Eric Paris828dfe12008-04-17 13:17:49 -04003602 break;
3603 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003604
James Morris2ee92d42006-11-13 16:09:01 -08003605 case IPPROTO_DCCP: {
3606 struct dccp_hdr _dccph, *dh;
3607
3608 if (ntohs(ih->frag_off) & IP_OFFSET)
3609 break;
3610
3611 offset += ihlen;
3612 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
3613 if (dh == NULL)
3614 break;
3615
Eric Paris48c62af2012-04-02 13:15:44 -04003616 ad->u.net->sport = dh->dccph_sport;
3617 ad->u.net->dport = dh->dccph_dport;
James Morris2ee92d42006-11-13 16:09:01 -08003618 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003619 }
James Morris2ee92d42006-11-13 16:09:01 -08003620
Eric Paris828dfe12008-04-17 13:17:49 -04003621 default:
3622 break;
3623 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003624out:
3625 return ret;
3626}
3627
3628#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
3629
3630/* Returns error only if unable to parse addresses */
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003631static int selinux_parse_skb_ipv6(struct sk_buff *skb,
Thomas Liu2bf49692009-07-14 12:14:09 -04003632 struct common_audit_data *ad, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003633{
3634 u8 nexthdr;
3635 int ret = -EINVAL, offset;
3636 struct ipv6hdr _ipv6h, *ip6;
Jesse Gross75f28112011-11-30 17:05:51 -08003637 __be16 frag_off;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003638
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03003639 offset = skb_network_offset(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003640 ip6 = skb_header_pointer(skb, offset, sizeof(_ipv6h), &_ipv6h);
3641 if (ip6 == NULL)
3642 goto out;
3643
Eric Paris48c62af2012-04-02 13:15:44 -04003644 ad->u.net->v6info.saddr = ip6->saddr;
3645 ad->u.net->v6info.daddr = ip6->daddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003646 ret = 0;
3647
3648 nexthdr = ip6->nexthdr;
3649 offset += sizeof(_ipv6h);
Jesse Gross75f28112011-11-30 17:05:51 -08003650 offset = ipv6_skip_exthdr(skb, offset, &nexthdr, &frag_off);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003651 if (offset < 0)
3652 goto out;
3653
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003654 if (proto)
3655 *proto = nexthdr;
3656
Linus Torvalds1da177e2005-04-16 15:20:36 -07003657 switch (nexthdr) {
3658 case IPPROTO_TCP: {
Eric Paris828dfe12008-04-17 13:17:49 -04003659 struct tcphdr _tcph, *th;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003660
3661 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
3662 if (th == NULL)
3663 break;
3664
Eric Paris48c62af2012-04-02 13:15:44 -04003665 ad->u.net->sport = th->source;
3666 ad->u.net->dport = th->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003667 break;
3668 }
3669
3670 case IPPROTO_UDP: {
3671 struct udphdr _udph, *uh;
3672
3673 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
3674 if (uh == NULL)
3675 break;
3676
Eric Paris48c62af2012-04-02 13:15:44 -04003677 ad->u.net->sport = uh->source;
3678 ad->u.net->dport = uh->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003679 break;
3680 }
3681
James Morris2ee92d42006-11-13 16:09:01 -08003682 case IPPROTO_DCCP: {
3683 struct dccp_hdr _dccph, *dh;
3684
3685 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
3686 if (dh == NULL)
3687 break;
3688
Eric Paris48c62af2012-04-02 13:15:44 -04003689 ad->u.net->sport = dh->dccph_sport;
3690 ad->u.net->dport = dh->dccph_dport;
James Morris2ee92d42006-11-13 16:09:01 -08003691 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003692 }
James Morris2ee92d42006-11-13 16:09:01 -08003693
Linus Torvalds1da177e2005-04-16 15:20:36 -07003694 /* includes fragments */
3695 default:
3696 break;
3697 }
3698out:
3699 return ret;
3700}
3701
3702#endif /* IPV6 */
3703
Thomas Liu2bf49692009-07-14 12:14:09 -04003704static int selinux_parse_skb(struct sk_buff *skb, struct common_audit_data *ad,
David Howellscf9481e2008-07-27 21:31:07 +10003705 char **_addrp, int src, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003706{
David Howellscf9481e2008-07-27 21:31:07 +10003707 char *addrp;
3708 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003709
Eric Paris48c62af2012-04-02 13:15:44 -04003710 switch (ad->u.net->family) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003711 case PF_INET:
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003712 ret = selinux_parse_skb_ipv4(skb, ad, proto);
David Howellscf9481e2008-07-27 21:31:07 +10003713 if (ret)
3714 goto parse_error;
Eric Paris48c62af2012-04-02 13:15:44 -04003715 addrp = (char *)(src ? &ad->u.net->v4info.saddr :
3716 &ad->u.net->v4info.daddr);
David Howellscf9481e2008-07-27 21:31:07 +10003717 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003718
3719#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
3720 case PF_INET6:
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003721 ret = selinux_parse_skb_ipv6(skb, ad, proto);
David Howellscf9481e2008-07-27 21:31:07 +10003722 if (ret)
3723 goto parse_error;
Eric Paris48c62af2012-04-02 13:15:44 -04003724 addrp = (char *)(src ? &ad->u.net->v6info.saddr :
3725 &ad->u.net->v6info.daddr);
David Howellscf9481e2008-07-27 21:31:07 +10003726 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003727#endif /* IPV6 */
3728 default:
David Howellscf9481e2008-07-27 21:31:07 +10003729 addrp = NULL;
3730 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003731 }
3732
David Howellscf9481e2008-07-27 21:31:07 +10003733parse_error:
3734 printk(KERN_WARNING
3735 "SELinux: failure in selinux_parse_skb(),"
3736 " unable to parse packet\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003737 return ret;
David Howellscf9481e2008-07-27 21:31:07 +10003738
3739okay:
3740 if (_addrp)
3741 *_addrp = addrp;
3742 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003743}
3744
Paul Moore4f6a9932007-03-01 14:35:22 -05003745/**
Paul Moore220deb92008-01-29 08:38:23 -05003746 * selinux_skb_peerlbl_sid - Determine the peer label of a packet
Paul Moore4f6a9932007-03-01 14:35:22 -05003747 * @skb: the packet
Paul Moore75e22912008-01-29 08:38:04 -05003748 * @family: protocol family
Paul Moore220deb92008-01-29 08:38:23 -05003749 * @sid: the packet's peer label SID
Paul Moore4f6a9932007-03-01 14:35:22 -05003750 *
3751 * Description:
Paul Moore220deb92008-01-29 08:38:23 -05003752 * Check the various different forms of network peer labeling and determine
3753 * the peer label/SID for the packet; most of the magic actually occurs in
3754 * the security server function security_net_peersid_cmp(). The function
3755 * returns zero if the value in @sid is valid (although it may be SECSID_NULL)
3756 * or -EACCES if @sid is invalid due to inconsistencies with the different
3757 * peer labels.
Paul Moore4f6a9932007-03-01 14:35:22 -05003758 *
3759 */
Paul Moore220deb92008-01-29 08:38:23 -05003760static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)
Paul Moore4f6a9932007-03-01 14:35:22 -05003761{
Paul Moore71f1cb02008-01-29 08:51:16 -05003762 int err;
Paul Moore4f6a9932007-03-01 14:35:22 -05003763 u32 xfrm_sid;
3764 u32 nlbl_sid;
Paul Moore220deb92008-01-29 08:38:23 -05003765 u32 nlbl_type;
Paul Moore4f6a9932007-03-01 14:35:22 -05003766
3767 selinux_skb_xfrm_sid(skb, &xfrm_sid);
Paul Moore5dbe1eb2008-01-29 08:44:18 -05003768 selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid);
Paul Moore220deb92008-01-29 08:38:23 -05003769
Paul Moore71f1cb02008-01-29 08:51:16 -05003770 err = security_net_peersid_resolve(nlbl_sid, nlbl_type, xfrm_sid, sid);
3771 if (unlikely(err)) {
3772 printk(KERN_WARNING
3773 "SELinux: failure in selinux_skb_peerlbl_sid(),"
3774 " unable to determine packet's peer label\n");
Paul Moore220deb92008-01-29 08:38:23 -05003775 return -EACCES;
Paul Moore71f1cb02008-01-29 08:51:16 -05003776 }
Paul Moore220deb92008-01-29 08:38:23 -05003777
3778 return 0;
Paul Moore4f6a9932007-03-01 14:35:22 -05003779}
3780
Linus Torvalds1da177e2005-04-16 15:20:36 -07003781/* socket security operations */
Paul Moored4f2d972010-04-22 14:46:18 -04003782
Harry Ciao2ad18bd2011-03-02 13:32:34 +08003783static int socket_sockcreate_sid(const struct task_security_struct *tsec,
3784 u16 secclass, u32 *socksid)
Paul Moored4f2d972010-04-22 14:46:18 -04003785{
Harry Ciao2ad18bd2011-03-02 13:32:34 +08003786 if (tsec->sockcreate_sid > SECSID_NULL) {
3787 *socksid = tsec->sockcreate_sid;
3788 return 0;
3789 }
3790
3791 return security_transition_sid(tsec->sid, tsec->sid, secclass, NULL,
3792 socksid);
Paul Moored4f2d972010-04-22 14:46:18 -04003793}
3794
Paul Moore253bfae2010-04-22 14:46:19 -04003795static int sock_has_perm(struct task_struct *task, struct sock *sk, u32 perms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003796{
Paul Moore253bfae2010-04-22 14:46:19 -04003797 struct sk_security_struct *sksec = sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04003798 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04003799 struct lsm_network_audit net = {0,};
Paul Moore253bfae2010-04-22 14:46:19 -04003800 u32 tsid = task_sid(task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003801
Paul Moore253bfae2010-04-22 14:46:19 -04003802 if (sksec->sid == SECINITSID_KERNEL)
3803 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003804
Eric Paris50c205f2012-04-04 15:01:43 -04003805 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04003806 ad.u.net = &net;
3807 ad.u.net->sk = sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003808
Paul Moore253bfae2010-04-22 14:46:19 -04003809 return avc_has_perm(tsid, sksec->sid, sksec->sclass, perms, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003810}
3811
3812static int selinux_socket_create(int family, int type,
3813 int protocol, int kern)
3814{
Paul Moore5fb49872010-04-22 14:46:19 -04003815 const struct task_security_struct *tsec = current_security();
Paul Moored4f2d972010-04-22 14:46:18 -04003816 u32 newsid;
David Howells275bb412008-11-14 10:39:19 +11003817 u16 secclass;
Harry Ciao2ad18bd2011-03-02 13:32:34 +08003818 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003819
3820 if (kern)
Paul Moored4f2d972010-04-22 14:46:18 -04003821 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003822
David Howells275bb412008-11-14 10:39:19 +11003823 secclass = socket_type_to_security_class(family, type, protocol);
Harry Ciao2ad18bd2011-03-02 13:32:34 +08003824 rc = socket_sockcreate_sid(tsec, secclass, &newsid);
3825 if (rc)
3826 return rc;
3827
Paul Moored4f2d972010-04-22 14:46:18 -04003828 return avc_has_perm(tsec->sid, newsid, secclass, SOCKET__CREATE, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003829}
3830
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07003831static int selinux_socket_post_create(struct socket *sock, int family,
3832 int type, int protocol, int kern)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003833{
Paul Moore5fb49872010-04-22 14:46:19 -04003834 const struct task_security_struct *tsec = current_security();
Paul Moored4f2d972010-04-22 14:46:18 -04003835 struct inode_security_struct *isec = SOCK_INODE(sock)->i_security;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07003836 struct sk_security_struct *sksec;
David Howells275bb412008-11-14 10:39:19 +11003837 int err = 0;
3838
Harry Ciao2ad18bd2011-03-02 13:32:34 +08003839 isec->sclass = socket_type_to_security_class(family, type, protocol);
3840
David Howells275bb412008-11-14 10:39:19 +11003841 if (kern)
3842 isec->sid = SECINITSID_KERNEL;
Harry Ciao2ad18bd2011-03-02 13:32:34 +08003843 else {
3844 err = socket_sockcreate_sid(tsec, isec->sclass, &(isec->sid));
3845 if (err)
3846 return err;
3847 }
David Howells275bb412008-11-14 10:39:19 +11003848
Linus Torvalds1da177e2005-04-16 15:20:36 -07003849 isec->initialized = 1;
3850
Venkat Yekkirala892c1412006-08-04 23:08:56 -07003851 if (sock->sk) {
3852 sksec = sock->sk->sk_security;
3853 sksec->sid = isec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05003854 sksec->sclass = isec->sclass;
Paul Moore389fb8002009-03-27 17:10:34 -04003855 err = selinux_netlbl_socket_post_create(sock->sk, family);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07003856 }
3857
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07003858 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003859}
3860
3861/* Range of port numbers used to automatically bind.
3862 Need to determine whether we should perform a name_bind
3863 permission check between the socket and the port number. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003864
3865static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen)
3866{
Paul Moore253bfae2010-04-22 14:46:19 -04003867 struct sock *sk = sock->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003868 u16 family;
3869 int err;
3870
Paul Moore253bfae2010-04-22 14:46:19 -04003871 err = sock_has_perm(current, sk, SOCKET__BIND);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003872 if (err)
3873 goto out;
3874
3875 /*
3876 * If PF_INET or PF_INET6, check name_bind permission for the port.
James Morris13402582005-09-30 14:24:34 -04003877 * Multiple address binding for SCTP is not supported yet: we just
3878 * check the first address now.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003879 */
Paul Moore253bfae2010-04-22 14:46:19 -04003880 family = sk->sk_family;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003881 if (family == PF_INET || family == PF_INET6) {
3882 char *addrp;
Paul Moore253bfae2010-04-22 14:46:19 -04003883 struct sk_security_struct *sksec = sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04003884 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04003885 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07003886 struct sockaddr_in *addr4 = NULL;
3887 struct sockaddr_in6 *addr6 = NULL;
3888 unsigned short snum;
James Morrise399f982008-06-12 01:39:58 +10003889 u32 sid, node_perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003890
Linus Torvalds1da177e2005-04-16 15:20:36 -07003891 if (family == PF_INET) {
3892 addr4 = (struct sockaddr_in *)address;
3893 snum = ntohs(addr4->sin_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003894 addrp = (char *)&addr4->sin_addr.s_addr;
3895 } else {
3896 addr6 = (struct sockaddr_in6 *)address;
3897 snum = ntohs(addr6->sin6_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003898 addrp = (char *)&addr6->sin6_addr.s6_addr;
3899 }
3900
Stephen Hemminger227b60f2007-10-10 17:30:46 -07003901 if (snum) {
3902 int low, high;
3903
3904 inet_get_local_port_range(&low, &high);
3905
3906 if (snum < max(PROT_SOCK, low) || snum > high) {
Paul Moore3e112172008-04-10 10:48:14 -04003907 err = sel_netport_sid(sk->sk_protocol,
3908 snum, &sid);
Stephen Hemminger227b60f2007-10-10 17:30:46 -07003909 if (err)
3910 goto out;
Eric Paris50c205f2012-04-04 15:01:43 -04003911 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04003912 ad.u.net = &net;
3913 ad.u.net->sport = htons(snum);
3914 ad.u.net->family = family;
Paul Moore253bfae2010-04-22 14:46:19 -04003915 err = avc_has_perm(sksec->sid, sid,
3916 sksec->sclass,
Stephen Hemminger227b60f2007-10-10 17:30:46 -07003917 SOCKET__NAME_BIND, &ad);
3918 if (err)
3919 goto out;
3920 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003921 }
Eric Paris828dfe12008-04-17 13:17:49 -04003922
Paul Moore253bfae2010-04-22 14:46:19 -04003923 switch (sksec->sclass) {
James Morris13402582005-09-30 14:24:34 -04003924 case SECCLASS_TCP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003925 node_perm = TCP_SOCKET__NODE_BIND;
3926 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003927
James Morris13402582005-09-30 14:24:34 -04003928 case SECCLASS_UDP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003929 node_perm = UDP_SOCKET__NODE_BIND;
3930 break;
James Morris2ee92d42006-11-13 16:09:01 -08003931
3932 case SECCLASS_DCCP_SOCKET:
3933 node_perm = DCCP_SOCKET__NODE_BIND;
3934 break;
3935
Linus Torvalds1da177e2005-04-16 15:20:36 -07003936 default:
3937 node_perm = RAWIP_SOCKET__NODE_BIND;
3938 break;
3939 }
Eric Paris828dfe12008-04-17 13:17:49 -04003940
Paul Moore224dfbd2008-01-29 08:38:13 -05003941 err = sel_netnode_sid(addrp, family, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003942 if (err)
3943 goto out;
Eric Paris828dfe12008-04-17 13:17:49 -04003944
Eric Paris50c205f2012-04-04 15:01:43 -04003945 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04003946 ad.u.net = &net;
3947 ad.u.net->sport = htons(snum);
3948 ad.u.net->family = family;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003949
3950 if (family == PF_INET)
Eric Paris48c62af2012-04-02 13:15:44 -04003951 ad.u.net->v4info.saddr = addr4->sin_addr.s_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003952 else
Eric Paris48c62af2012-04-02 13:15:44 -04003953 ad.u.net->v6info.saddr = addr6->sin6_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003954
Paul Moore253bfae2010-04-22 14:46:19 -04003955 err = avc_has_perm(sksec->sid, sid,
3956 sksec->sclass, node_perm, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003957 if (err)
3958 goto out;
3959 }
3960out:
3961 return err;
3962}
3963
3964static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen)
3965{
Paul Moore014ab192008-10-10 10:16:33 -04003966 struct sock *sk = sock->sk;
Paul Moore253bfae2010-04-22 14:46:19 -04003967 struct sk_security_struct *sksec = sk->sk_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003968 int err;
3969
Paul Moore253bfae2010-04-22 14:46:19 -04003970 err = sock_has_perm(current, sk, SOCKET__CONNECT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003971 if (err)
3972 return err;
3973
3974 /*
James Morris2ee92d42006-11-13 16:09:01 -08003975 * If a TCP or DCCP socket, check name_connect permission for the port.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003976 */
Paul Moore253bfae2010-04-22 14:46:19 -04003977 if (sksec->sclass == SECCLASS_TCP_SOCKET ||
3978 sksec->sclass == SECCLASS_DCCP_SOCKET) {
Thomas Liu2bf49692009-07-14 12:14:09 -04003979 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04003980 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07003981 struct sockaddr_in *addr4 = NULL;
3982 struct sockaddr_in6 *addr6 = NULL;
3983 unsigned short snum;
James Morris2ee92d42006-11-13 16:09:01 -08003984 u32 sid, perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003985
3986 if (sk->sk_family == PF_INET) {
3987 addr4 = (struct sockaddr_in *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07003988 if (addrlen < sizeof(struct sockaddr_in))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003989 return -EINVAL;
3990 snum = ntohs(addr4->sin_port);
3991 } else {
3992 addr6 = (struct sockaddr_in6 *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07003993 if (addrlen < SIN6_LEN_RFC2133)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003994 return -EINVAL;
3995 snum = ntohs(addr6->sin6_port);
3996 }
3997
Paul Moore3e112172008-04-10 10:48:14 -04003998 err = sel_netport_sid(sk->sk_protocol, snum, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003999 if (err)
4000 goto out;
4001
Paul Moore253bfae2010-04-22 14:46:19 -04004002 perm = (sksec->sclass == SECCLASS_TCP_SOCKET) ?
James Morris2ee92d42006-11-13 16:09:01 -08004003 TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT;
4004
Eric Paris50c205f2012-04-04 15:01:43 -04004005 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004006 ad.u.net = &net;
4007 ad.u.net->dport = htons(snum);
4008 ad.u.net->family = sk->sk_family;
Paul Moore253bfae2010-04-22 14:46:19 -04004009 err = avc_has_perm(sksec->sid, sid, sksec->sclass, perm, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004010 if (err)
4011 goto out;
4012 }
4013
Paul Moore014ab192008-10-10 10:16:33 -04004014 err = selinux_netlbl_socket_connect(sk, address);
4015
Linus Torvalds1da177e2005-04-16 15:20:36 -07004016out:
4017 return err;
4018}
4019
4020static int selinux_socket_listen(struct socket *sock, int backlog)
4021{
Paul Moore253bfae2010-04-22 14:46:19 -04004022 return sock_has_perm(current, sock->sk, SOCKET__LISTEN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004023}
4024
4025static int selinux_socket_accept(struct socket *sock, struct socket *newsock)
4026{
4027 int err;
4028 struct inode_security_struct *isec;
4029 struct inode_security_struct *newisec;
4030
Paul Moore253bfae2010-04-22 14:46:19 -04004031 err = sock_has_perm(current, sock->sk, SOCKET__ACCEPT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004032 if (err)
4033 return err;
4034
4035 newisec = SOCK_INODE(newsock)->i_security;
4036
4037 isec = SOCK_INODE(sock)->i_security;
4038 newisec->sclass = isec->sclass;
4039 newisec->sid = isec->sid;
4040 newisec->initialized = 1;
4041
4042 return 0;
4043}
4044
4045static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg,
Eric Paris828dfe12008-04-17 13:17:49 -04004046 int size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004047{
Paul Moore253bfae2010-04-22 14:46:19 -04004048 return sock_has_perm(current, sock->sk, SOCKET__WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004049}
4050
4051static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg,
4052 int size, int flags)
4053{
Paul Moore253bfae2010-04-22 14:46:19 -04004054 return sock_has_perm(current, sock->sk, SOCKET__READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004055}
4056
4057static int selinux_socket_getsockname(struct socket *sock)
4058{
Paul Moore253bfae2010-04-22 14:46:19 -04004059 return sock_has_perm(current, sock->sk, SOCKET__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004060}
4061
4062static int selinux_socket_getpeername(struct socket *sock)
4063{
Paul Moore253bfae2010-04-22 14:46:19 -04004064 return sock_has_perm(current, sock->sk, SOCKET__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004065}
4066
Eric Paris828dfe12008-04-17 13:17:49 -04004067static int selinux_socket_setsockopt(struct socket *sock, int level, int optname)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004068{
Paul Mooref8687af2006-10-30 15:22:15 -08004069 int err;
4070
Paul Moore253bfae2010-04-22 14:46:19 -04004071 err = sock_has_perm(current, sock->sk, SOCKET__SETOPT);
Paul Mooref8687af2006-10-30 15:22:15 -08004072 if (err)
4073 return err;
4074
4075 return selinux_netlbl_socket_setsockopt(sock, level, optname);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004076}
4077
4078static int selinux_socket_getsockopt(struct socket *sock, int level,
4079 int optname)
4080{
Paul Moore253bfae2010-04-22 14:46:19 -04004081 return sock_has_perm(current, sock->sk, SOCKET__GETOPT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004082}
4083
4084static int selinux_socket_shutdown(struct socket *sock, int how)
4085{
Paul Moore253bfae2010-04-22 14:46:19 -04004086 return sock_has_perm(current, sock->sk, SOCKET__SHUTDOWN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004087}
4088
David S. Miller3610cda2011-01-05 15:38:53 -08004089static int selinux_socket_unix_stream_connect(struct sock *sock,
4090 struct sock *other,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004091 struct sock *newsk)
4092{
David S. Miller3610cda2011-01-05 15:38:53 -08004093 struct sk_security_struct *sksec_sock = sock->sk_security;
4094 struct sk_security_struct *sksec_other = other->sk_security;
Paul Moore4d1e2452010-04-22 14:46:18 -04004095 struct sk_security_struct *sksec_new = newsk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004096 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004097 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004098 int err;
4099
Eric Paris50c205f2012-04-04 15:01:43 -04004100 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004101 ad.u.net = &net;
4102 ad.u.net->sk = other;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004103
Paul Moore4d1e2452010-04-22 14:46:18 -04004104 err = avc_has_perm(sksec_sock->sid, sksec_other->sid,
4105 sksec_other->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004106 UNIX_STREAM_SOCKET__CONNECTTO, &ad);
4107 if (err)
4108 return err;
4109
Linus Torvalds1da177e2005-04-16 15:20:36 -07004110 /* server child socket */
Paul Moore4d1e2452010-04-22 14:46:18 -04004111 sksec_new->peer_sid = sksec_sock->sid;
4112 err = security_sid_mls_copy(sksec_other->sid, sksec_sock->sid,
4113 &sksec_new->sid);
4114 if (err)
4115 return err;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004116
Paul Moore4d1e2452010-04-22 14:46:18 -04004117 /* connecting socket */
4118 sksec_sock->peer_sid = sksec_new->sid;
4119
4120 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004121}
4122
4123static int selinux_socket_unix_may_send(struct socket *sock,
4124 struct socket *other)
4125{
Paul Moore253bfae2010-04-22 14:46:19 -04004126 struct sk_security_struct *ssec = sock->sk->sk_security;
4127 struct sk_security_struct *osec = other->sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004128 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004129 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004130
Eric Paris50c205f2012-04-04 15:01:43 -04004131 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004132 ad.u.net = &net;
4133 ad.u.net->sk = other->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004134
Paul Moore253bfae2010-04-22 14:46:19 -04004135 return avc_has_perm(ssec->sid, osec->sid, osec->sclass, SOCKET__SENDTO,
4136 &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004137}
4138
Paul Mooreeffad8d2008-01-29 08:49:27 -05004139static int selinux_inet_sys_rcv_skb(int ifindex, char *addrp, u16 family,
4140 u32 peer_sid,
Thomas Liu2bf49692009-07-14 12:14:09 -04004141 struct common_audit_data *ad)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004142{
4143 int err;
4144 u32 if_sid;
4145 u32 node_sid;
4146
4147 err = sel_netif_sid(ifindex, &if_sid);
4148 if (err)
4149 return err;
4150 err = avc_has_perm(peer_sid, if_sid,
4151 SECCLASS_NETIF, NETIF__INGRESS, ad);
4152 if (err)
4153 return err;
4154
4155 err = sel_netnode_sid(addrp, family, &node_sid);
4156 if (err)
4157 return err;
4158 return avc_has_perm(peer_sid, node_sid,
4159 SECCLASS_NODE, NODE__RECVFROM, ad);
4160}
4161
Paul Moore220deb92008-01-29 08:38:23 -05004162static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
Paul Moored8395c82008-10-10 10:16:30 -04004163 u16 family)
Paul Moore220deb92008-01-29 08:38:23 -05004164{
Paul Moore277d3422008-12-31 12:54:11 -05004165 int err = 0;
Paul Moore220deb92008-01-29 08:38:23 -05004166 struct sk_security_struct *sksec = sk->sk_security;
Paul Moore220deb92008-01-29 08:38:23 -05004167 u32 sk_sid = sksec->sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04004168 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004169 struct lsm_network_audit net = {0,};
Paul Moored8395c82008-10-10 10:16:30 -04004170 char *addrp;
4171
Eric Paris50c205f2012-04-04 15:01:43 -04004172 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004173 ad.u.net = &net;
4174 ad.u.net->netif = skb->skb_iif;
4175 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04004176 err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
4177 if (err)
4178 return err;
Paul Moore220deb92008-01-29 08:38:23 -05004179
Paul Moore58bfbb52009-03-27 17:10:41 -04004180 if (selinux_secmark_enabled()) {
Paul Moore220deb92008-01-29 08:38:23 -05004181 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
Paul Moored8395c82008-10-10 10:16:30 -04004182 PACKET__RECV, &ad);
Paul Moore58bfbb52009-03-27 17:10:41 -04004183 if (err)
4184 return err;
4185 }
Paul Moore220deb92008-01-29 08:38:23 -05004186
Steffen Klassertb9679a72011-02-23 12:55:21 +01004187 err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, &ad);
4188 if (err)
4189 return err;
4190 err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, &ad);
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004191
James Morris4e5ab4c2006-06-09 00:33:33 -07004192 return err;
4193}
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004194
James Morris4e5ab4c2006-06-09 00:33:33 -07004195static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
4196{
Paul Moore220deb92008-01-29 08:38:23 -05004197 int err;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004198 struct sk_security_struct *sksec = sk->sk_security;
Paul Moore220deb92008-01-29 08:38:23 -05004199 u16 family = sk->sk_family;
4200 u32 sk_sid = sksec->sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04004201 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004202 struct lsm_network_audit net = {0,};
Paul Moore220deb92008-01-29 08:38:23 -05004203 char *addrp;
Paul Moored8395c82008-10-10 10:16:30 -04004204 u8 secmark_active;
4205 u8 peerlbl_active;
James Morris4e5ab4c2006-06-09 00:33:33 -07004206
James Morris4e5ab4c2006-06-09 00:33:33 -07004207 if (family != PF_INET && family != PF_INET6)
Paul Moore220deb92008-01-29 08:38:23 -05004208 return 0;
James Morris4e5ab4c2006-06-09 00:33:33 -07004209
4210 /* Handle mapped IPv4 packets arriving via IPv6 sockets */
Al Viro87fcd702006-12-04 22:00:55 +00004211 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
James Morris4e5ab4c2006-06-09 00:33:33 -07004212 family = PF_INET;
4213
Paul Moored8395c82008-10-10 10:16:30 -04004214 /* If any sort of compatibility mode is enabled then handoff processing
4215 * to the selinux_sock_rcv_skb_compat() function to deal with the
4216 * special handling. We do this in an attempt to keep this function
4217 * as fast and as clean as possible. */
Paul Moore58bfbb52009-03-27 17:10:41 -04004218 if (!selinux_policycap_netpeer)
Paul Moored8395c82008-10-10 10:16:30 -04004219 return selinux_sock_rcv_skb_compat(sk, skb, family);
4220
4221 secmark_active = selinux_secmark_enabled();
4222 peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled();
4223 if (!secmark_active && !peerlbl_active)
4224 return 0;
4225
Eric Paris50c205f2012-04-04 15:01:43 -04004226 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004227 ad.u.net = &net;
4228 ad.u.net->netif = skb->skb_iif;
4229 ad.u.net->family = family;
Paul Moore224dfbd2008-01-29 08:38:13 -05004230 err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
James Morris4e5ab4c2006-06-09 00:33:33 -07004231 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05004232 return err;
James Morris4e5ab4c2006-06-09 00:33:33 -07004233
Paul Moored8395c82008-10-10 10:16:30 -04004234 if (peerlbl_active) {
Paul Moored621d352008-01-29 08:43:36 -05004235 u32 peer_sid;
4236
4237 err = selinux_skb_peerlbl_sid(skb, family, &peer_sid);
4238 if (err)
4239 return err;
Eric Dumazet8964be42009-11-20 15:35:04 -08004240 err = selinux_inet_sys_rcv_skb(skb->skb_iif, addrp, family,
Paul Mooreeffad8d2008-01-29 08:49:27 -05004241 peer_sid, &ad);
Paul Mooredfaebe92008-10-10 10:16:31 -04004242 if (err) {
4243 selinux_netlbl_err(skb, err, 0);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004244 return err;
Paul Mooredfaebe92008-10-10 10:16:31 -04004245 }
Paul Moored621d352008-01-29 08:43:36 -05004246 err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER,
4247 PEER__RECV, &ad);
Paul Mooredfaebe92008-10-10 10:16:31 -04004248 if (err)
4249 selinux_netlbl_err(skb, err, 0);
Paul Moored621d352008-01-29 08:43:36 -05004250 }
4251
Paul Moored8395c82008-10-10 10:16:30 -04004252 if (secmark_active) {
Paul Mooreeffad8d2008-01-29 08:49:27 -05004253 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
4254 PACKET__RECV, &ad);
4255 if (err)
4256 return err;
4257 }
4258
Paul Moored621d352008-01-29 08:43:36 -05004259 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004260}
4261
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004262static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *optval,
4263 int __user *optlen, unsigned len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004264{
4265 int err = 0;
4266 char *scontext;
4267 u32 scontext_len;
Paul Moore253bfae2010-04-22 14:46:19 -04004268 struct sk_security_struct *sksec = sock->sk->sk_security;
Paul Moore3de4bab2006-11-17 17:38:54 -05004269 u32 peer_sid = SECSID_NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004270
Paul Moore253bfae2010-04-22 14:46:19 -04004271 if (sksec->sclass == SECCLASS_UNIX_STREAM_SOCKET ||
4272 sksec->sclass == SECCLASS_TCP_SOCKET)
Eric Parisdd3e7832010-04-07 15:08:46 -04004273 peer_sid = sksec->peer_sid;
Paul Moore253bfae2010-04-22 14:46:19 -04004274 if (peer_sid == SECSID_NULL)
4275 return -ENOPROTOOPT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004276
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004277 err = security_sid_to_context(peer_sid, &scontext, &scontext_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004278 if (err)
Paul Moore253bfae2010-04-22 14:46:19 -04004279 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004280
4281 if (scontext_len > len) {
4282 err = -ERANGE;
4283 goto out_len;
4284 }
4285
4286 if (copy_to_user(optval, scontext, scontext_len))
4287 err = -EFAULT;
4288
4289out_len:
4290 if (put_user(scontext_len, optlen))
4291 err = -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004292 kfree(scontext);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004293 return err;
4294}
4295
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004296static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid)
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004297{
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004298 u32 peer_secid = SECSID_NULL;
Paul Moore75e22912008-01-29 08:38:04 -05004299 u16 family;
Catherine Zhang877ce7c2006-06-29 12:27:47 -07004300
Paul Mooreaa862902008-10-10 10:16:29 -04004301 if (skb && skb->protocol == htons(ETH_P_IP))
4302 family = PF_INET;
4303 else if (skb && skb->protocol == htons(ETH_P_IPV6))
4304 family = PF_INET6;
4305 else if (sock)
Paul Moore75e22912008-01-29 08:38:04 -05004306 family = sock->sk->sk_family;
Paul Moore75e22912008-01-29 08:38:04 -05004307 else
4308 goto out;
4309
4310 if (sock && family == PF_UNIX)
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02004311 selinux_inode_getsecid(SOCK_INODE(sock), &peer_secid);
Paul Moore3de4bab2006-11-17 17:38:54 -05004312 else if (skb)
Paul Moore220deb92008-01-29 08:38:23 -05004313 selinux_skb_peerlbl_sid(skb, family, &peer_secid);
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004314
Paul Moore75e22912008-01-29 08:38:04 -05004315out:
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004316 *secid = peer_secid;
Paul Moore75e22912008-01-29 08:38:04 -05004317 if (peer_secid == SECSID_NULL)
4318 return -EINVAL;
4319 return 0;
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004320}
4321
Al Viro7d877f32005-10-21 03:20:43 -04004322static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004323{
Paul Moore84914b72010-04-22 14:46:18 -04004324 struct sk_security_struct *sksec;
4325
4326 sksec = kzalloc(sizeof(*sksec), priority);
4327 if (!sksec)
4328 return -ENOMEM;
4329
4330 sksec->peer_sid = SECINITSID_UNLABELED;
4331 sksec->sid = SECINITSID_UNLABELED;
4332 selinux_netlbl_sk_security_reset(sksec);
4333 sk->sk_security = sksec;
4334
4335 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004336}
4337
4338static void selinux_sk_free_security(struct sock *sk)
4339{
Paul Moore84914b72010-04-22 14:46:18 -04004340 struct sk_security_struct *sksec = sk->sk_security;
4341
4342 sk->sk_security = NULL;
4343 selinux_netlbl_sk_security_free(sksec);
4344 kfree(sksec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004345}
4346
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004347static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk)
4348{
Eric Parisdd3e7832010-04-07 15:08:46 -04004349 struct sk_security_struct *sksec = sk->sk_security;
4350 struct sk_security_struct *newsksec = newsk->sk_security;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004351
Eric Parisdd3e7832010-04-07 15:08:46 -04004352 newsksec->sid = sksec->sid;
4353 newsksec->peer_sid = sksec->peer_sid;
4354 newsksec->sclass = sksec->sclass;
Paul Moore99f59ed2006-08-29 17:53:48 -07004355
Eric Parisdd3e7832010-04-07 15:08:46 -04004356 selinux_netlbl_sk_security_reset(newsksec);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004357}
4358
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004359static void selinux_sk_getsecid(struct sock *sk, u32 *secid)
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004360{
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004361 if (!sk)
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004362 *secid = SECINITSID_ANY_SOCKET;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004363 else {
4364 struct sk_security_struct *sksec = sk->sk_security;
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004365
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004366 *secid = sksec->sid;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004367 }
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004368}
4369
Eric Paris828dfe12008-04-17 13:17:49 -04004370static void selinux_sock_graft(struct sock *sk, struct socket *parent)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004371{
4372 struct inode_security_struct *isec = SOCK_INODE(parent)->i_security;
4373 struct sk_security_struct *sksec = sk->sk_security;
4374
David Woodhouse2148ccc2006-09-29 15:50:25 -07004375 if (sk->sk_family == PF_INET || sk->sk_family == PF_INET6 ||
4376 sk->sk_family == PF_UNIX)
4377 isec->sid = sksec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05004378 sksec->sclass = isec->sclass;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004379}
4380
Adrian Bunk9a673e52006-08-15 00:03:53 -07004381static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
4382 struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004383{
4384 struct sk_security_struct *sksec = sk->sk_security;
4385 int err;
Paul Mooreaa862902008-10-10 10:16:29 -04004386 u16 family = sk->sk_family;
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07004387 u32 newsid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004388 u32 peersid;
4389
Paul Mooreaa862902008-10-10 10:16:29 -04004390 /* handle mapped IPv4 packets arriving via IPv6 sockets */
4391 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
4392 family = PF_INET;
4393
4394 err = selinux_skb_peerlbl_sid(skb, family, &peersid);
Paul Moore220deb92008-01-29 08:38:23 -05004395 if (err)
4396 return err;
Venkat Yekkiralaa51c64f2006-07-27 22:01:34 -07004397 if (peersid == SECSID_NULL) {
4398 req->secid = sksec->sid;
Paul Moore3de4bab2006-11-17 17:38:54 -05004399 req->peer_secid = SECSID_NULL;
Paul Moore389fb8002009-03-27 17:10:34 -04004400 } else {
4401 err = security_sid_mls_copy(sksec->sid, peersid, &newsid);
4402 if (err)
4403 return err;
4404 req->secid = newsid;
4405 req->peer_secid = peersid;
Venkat Yekkiralaa51c64f2006-07-27 22:01:34 -07004406 }
4407
Paul Moore389fb8002009-03-27 17:10:34 -04004408 return selinux_netlbl_inet_conn_request(req, family);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004409}
4410
Adrian Bunk9a673e52006-08-15 00:03:53 -07004411static void selinux_inet_csk_clone(struct sock *newsk,
4412 const struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004413{
4414 struct sk_security_struct *newsksec = newsk->sk_security;
4415
4416 newsksec->sid = req->secid;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004417 newsksec->peer_sid = req->peer_secid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004418 /* NOTE: Ideally, we should also get the isec->sid for the
4419 new socket in sync, but we don't have the isec available yet.
4420 So we will wait until sock_graft to do it, by which
4421 time it will have been created and available. */
Paul Moore99f59ed2006-08-29 17:53:48 -07004422
Paul Moore9f2ad662006-11-17 17:38:53 -05004423 /* We don't need to take any sort of lock here as we are the only
4424 * thread with access to newsksec */
Paul Moore389fb8002009-03-27 17:10:34 -04004425 selinux_netlbl_inet_csk_clone(newsk, req->rsk_ops->family);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004426}
4427
Paul Moore014ab192008-10-10 10:16:33 -04004428static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb)
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004429{
Paul Mooreaa862902008-10-10 10:16:29 -04004430 u16 family = sk->sk_family;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004431 struct sk_security_struct *sksec = sk->sk_security;
4432
Paul Mooreaa862902008-10-10 10:16:29 -04004433 /* handle mapped IPv4 packets arriving via IPv6 sockets */
4434 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
4435 family = PF_INET;
4436
4437 selinux_skb_peerlbl_sid(skb, family, &sksec->peer_sid);
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004438}
4439
Eric Dumazetca10b9e2013-04-08 17:58:11 +00004440static void selinux_skb_owned_by(struct sk_buff *skb, struct sock *sk)
4441{
4442 skb_set_owner_w(skb, sk);
4443}
4444
Eric Paris2606fd12010-10-13 16:24:41 -04004445static int selinux_secmark_relabel_packet(u32 sid)
4446{
4447 const struct task_security_struct *__tsec;
4448 u32 tsid;
4449
4450 __tsec = current_security();
4451 tsid = __tsec->sid;
4452
4453 return avc_has_perm(tsid, sid, SECCLASS_PACKET, PACKET__RELABELTO, NULL);
4454}
4455
4456static void selinux_secmark_refcount_inc(void)
4457{
4458 atomic_inc(&selinux_secmark_refcount);
4459}
4460
4461static void selinux_secmark_refcount_dec(void)
4462{
4463 atomic_dec(&selinux_secmark_refcount);
4464}
4465
Adrian Bunk9a673e52006-08-15 00:03:53 -07004466static void selinux_req_classify_flow(const struct request_sock *req,
4467 struct flowi *fl)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004468{
David S. Miller1d28f422011-03-12 00:29:39 -05004469 fl->flowi_secid = req->secid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004470}
4471
Paul Moore5dbbaf22013-01-14 07:12:19 +00004472static int selinux_tun_dev_alloc_security(void **security)
4473{
4474 struct tun_security_struct *tunsec;
4475
4476 tunsec = kzalloc(sizeof(*tunsec), GFP_KERNEL);
4477 if (!tunsec)
4478 return -ENOMEM;
4479 tunsec->sid = current_sid();
4480
4481 *security = tunsec;
4482 return 0;
4483}
4484
4485static void selinux_tun_dev_free_security(void *security)
4486{
4487 kfree(security);
4488}
4489
Paul Mooreed6d76e2009-08-28 18:12:49 -04004490static int selinux_tun_dev_create(void)
4491{
4492 u32 sid = current_sid();
4493
4494 /* we aren't taking into account the "sockcreate" SID since the socket
4495 * that is being created here is not a socket in the traditional sense,
4496 * instead it is a private sock, accessible only to the kernel, and
4497 * representing a wide range of network traffic spanning multiple
4498 * connections unlike traditional sockets - check the TUN driver to
4499 * get a better understanding of why this socket is special */
4500
4501 return avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET, TUN_SOCKET__CREATE,
4502 NULL);
4503}
4504
Paul Moore5dbbaf22013-01-14 07:12:19 +00004505static int selinux_tun_dev_attach_queue(void *security)
Paul Mooreed6d76e2009-08-28 18:12:49 -04004506{
Paul Moore5dbbaf22013-01-14 07:12:19 +00004507 struct tun_security_struct *tunsec = security;
4508
4509 return avc_has_perm(current_sid(), tunsec->sid, SECCLASS_TUN_SOCKET,
4510 TUN_SOCKET__ATTACH_QUEUE, NULL);
4511}
4512
4513static int selinux_tun_dev_attach(struct sock *sk, void *security)
4514{
4515 struct tun_security_struct *tunsec = security;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004516 struct sk_security_struct *sksec = sk->sk_security;
4517
4518 /* we don't currently perform any NetLabel based labeling here and it
4519 * isn't clear that we would want to do so anyway; while we could apply
4520 * labeling without the support of the TUN user the resulting labeled
4521 * traffic from the other end of the connection would almost certainly
4522 * cause confusion to the TUN user that had no idea network labeling
4523 * protocols were being used */
4524
Paul Moore5dbbaf22013-01-14 07:12:19 +00004525 sksec->sid = tunsec->sid;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004526 sksec->sclass = SECCLASS_TUN_SOCKET;
Paul Moore5dbbaf22013-01-14 07:12:19 +00004527
4528 return 0;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004529}
4530
Paul Moore5dbbaf22013-01-14 07:12:19 +00004531static int selinux_tun_dev_open(void *security)
Paul Mooreed6d76e2009-08-28 18:12:49 -04004532{
Paul Moore5dbbaf22013-01-14 07:12:19 +00004533 struct tun_security_struct *tunsec = security;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004534 u32 sid = current_sid();
4535 int err;
4536
Paul Moore5dbbaf22013-01-14 07:12:19 +00004537 err = avc_has_perm(sid, tunsec->sid, SECCLASS_TUN_SOCKET,
Paul Mooreed6d76e2009-08-28 18:12:49 -04004538 TUN_SOCKET__RELABELFROM, NULL);
4539 if (err)
4540 return err;
4541 err = avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET,
4542 TUN_SOCKET__RELABELTO, NULL);
4543 if (err)
4544 return err;
Paul Moore5dbbaf22013-01-14 07:12:19 +00004545 tunsec->sid = sid;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004546
4547 return 0;
4548}
4549
Linus Torvalds1da177e2005-04-16 15:20:36 -07004550static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
4551{
4552 int err = 0;
4553 u32 perm;
4554 struct nlmsghdr *nlh;
Paul Moore253bfae2010-04-22 14:46:19 -04004555 struct sk_security_struct *sksec = sk->sk_security;
Eric Paris828dfe12008-04-17 13:17:49 -04004556
Hong zhi guo77954982013-03-27 06:49:35 +00004557 if (skb->len < NLMSG_HDRLEN) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004558 err = -EINVAL;
4559 goto out;
4560 }
Arnaldo Carvalho de Melob529ccf2007-04-25 19:08:35 -07004561 nlh = nlmsg_hdr(skb);
Eric Paris828dfe12008-04-17 13:17:49 -04004562
Paul Moore253bfae2010-04-22 14:46:19 -04004563 err = selinux_nlmsg_lookup(sksec->sclass, nlh->nlmsg_type, &perm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004564 if (err) {
4565 if (err == -EINVAL) {
David Woodhouse9ad9ad32005-06-22 15:04:33 +01004566 audit_log(current->audit_context, GFP_KERNEL, AUDIT_SELINUX_ERR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004567 "SELinux: unrecognized netlink message"
4568 " type=%hu for sclass=%hu\n",
Paul Moore253bfae2010-04-22 14:46:19 -04004569 nlh->nlmsg_type, sksec->sclass);
Eric Paris39c9aed2008-11-05 09:34:42 -05004570 if (!selinux_enforcing || security_get_allow_unknown())
Linus Torvalds1da177e2005-04-16 15:20:36 -07004571 err = 0;
4572 }
4573
4574 /* Ignore */
4575 if (err == -ENOENT)
4576 err = 0;
4577 goto out;
4578 }
4579
Paul Moore253bfae2010-04-22 14:46:19 -04004580 err = sock_has_perm(current, sk, perm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004581out:
4582 return err;
4583}
4584
4585#ifdef CONFIG_NETFILTER
4586
Paul Mooreeffad8d2008-01-29 08:49:27 -05004587static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex,
4588 u16 family)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004589{
Paul Mooredfaebe92008-10-10 10:16:31 -04004590 int err;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004591 char *addrp;
4592 u32 peer_sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04004593 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004594 struct lsm_network_audit net = {0,};
Paul Mooreeffad8d2008-01-29 08:49:27 -05004595 u8 secmark_active;
Paul Moore948bf852008-10-10 10:16:32 -04004596 u8 netlbl_active;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004597 u8 peerlbl_active;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004598
Paul Mooreeffad8d2008-01-29 08:49:27 -05004599 if (!selinux_policycap_netpeer)
4600 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004601
Paul Mooreeffad8d2008-01-29 08:49:27 -05004602 secmark_active = selinux_secmark_enabled();
Paul Moore948bf852008-10-10 10:16:32 -04004603 netlbl_active = netlbl_enabled();
4604 peerlbl_active = netlbl_active || selinux_xfrm_enabled();
Paul Mooreeffad8d2008-01-29 08:49:27 -05004605 if (!secmark_active && !peerlbl_active)
4606 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004607
Paul Moored8395c82008-10-10 10:16:30 -04004608 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0)
4609 return NF_DROP;
4610
Eric Paris50c205f2012-04-04 15:01:43 -04004611 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004612 ad.u.net = &net;
4613 ad.u.net->netif = ifindex;
4614 ad.u.net->family = family;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004615 if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0)
4616 return NF_DROP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004617
Paul Mooredfaebe92008-10-10 10:16:31 -04004618 if (peerlbl_active) {
4619 err = selinux_inet_sys_rcv_skb(ifindex, addrp, family,
4620 peer_sid, &ad);
4621 if (err) {
4622 selinux_netlbl_err(skb, err, 1);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004623 return NF_DROP;
Paul Mooredfaebe92008-10-10 10:16:31 -04004624 }
4625 }
Paul Mooreeffad8d2008-01-29 08:49:27 -05004626
4627 if (secmark_active)
4628 if (avc_has_perm(peer_sid, skb->secmark,
4629 SECCLASS_PACKET, PACKET__FORWARD_IN, &ad))
4630 return NF_DROP;
4631
Paul Moore948bf852008-10-10 10:16:32 -04004632 if (netlbl_active)
4633 /* we do this in the FORWARD path and not the POST_ROUTING
4634 * path because we want to make sure we apply the necessary
4635 * labeling before IPsec is applied so we can leverage AH
4636 * protection */
4637 if (selinux_netlbl_skbuff_setsid(skb, family, peer_sid) != 0)
4638 return NF_DROP;
4639
Paul Mooreeffad8d2008-01-29 08:49:27 -05004640 return NF_ACCEPT;
4641}
4642
4643static unsigned int selinux_ipv4_forward(unsigned int hooknum,
4644 struct sk_buff *skb,
4645 const struct net_device *in,
4646 const struct net_device *out,
4647 int (*okfn)(struct sk_buff *))
4648{
4649 return selinux_ip_forward(skb, in->ifindex, PF_INET);
4650}
4651
4652#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
4653static unsigned int selinux_ipv6_forward(unsigned int hooknum,
4654 struct sk_buff *skb,
4655 const struct net_device *in,
4656 const struct net_device *out,
4657 int (*okfn)(struct sk_buff *))
4658{
4659 return selinux_ip_forward(skb, in->ifindex, PF_INET6);
4660}
4661#endif /* IPV6 */
4662
Paul Moore948bf852008-10-10 10:16:32 -04004663static unsigned int selinux_ip_output(struct sk_buff *skb,
4664 u16 family)
4665{
4666 u32 sid;
4667
4668 if (!netlbl_enabled())
4669 return NF_ACCEPT;
4670
4671 /* we do this in the LOCAL_OUT path and not the POST_ROUTING path
4672 * because we want to make sure we apply the necessary labeling
4673 * before IPsec is applied so we can leverage AH protection */
4674 if (skb->sk) {
4675 struct sk_security_struct *sksec = skb->sk->sk_security;
4676 sid = sksec->sid;
4677 } else
4678 sid = SECINITSID_KERNEL;
4679 if (selinux_netlbl_skbuff_setsid(skb, family, sid) != 0)
4680 return NF_DROP;
4681
4682 return NF_ACCEPT;
4683}
4684
4685static unsigned int selinux_ipv4_output(unsigned int hooknum,
4686 struct sk_buff *skb,
4687 const struct net_device *in,
4688 const struct net_device *out,
4689 int (*okfn)(struct sk_buff *))
4690{
4691 return selinux_ip_output(skb, PF_INET);
4692}
4693
Paul Mooreeffad8d2008-01-29 08:49:27 -05004694static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
4695 int ifindex,
Paul Moored8395c82008-10-10 10:16:30 -04004696 u16 family)
James Morris4e5ab4c2006-06-09 00:33:33 -07004697{
Paul Mooreeffad8d2008-01-29 08:49:27 -05004698 struct sock *sk = skb->sk;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004699 struct sk_security_struct *sksec;
Thomas Liu2bf49692009-07-14 12:14:09 -04004700 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004701 struct lsm_network_audit net = {0,};
Paul Moored8395c82008-10-10 10:16:30 -04004702 char *addrp;
4703 u8 proto;
James Morris4e5ab4c2006-06-09 00:33:33 -07004704
Paul Mooreeffad8d2008-01-29 08:49:27 -05004705 if (sk == NULL)
4706 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004707 sksec = sk->sk_security;
James Morris4e5ab4c2006-06-09 00:33:33 -07004708
Eric Paris50c205f2012-04-04 15:01:43 -04004709 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004710 ad.u.net = &net;
4711 ad.u.net->netif = ifindex;
4712 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04004713 if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto))
4714 return NF_DROP;
4715
Paul Moore58bfbb52009-03-27 17:10:41 -04004716 if (selinux_secmark_enabled())
Paul Mooreeffad8d2008-01-29 08:49:27 -05004717 if (avc_has_perm(sksec->sid, skb->secmark,
Paul Moored8395c82008-10-10 10:16:30 -04004718 SECCLASS_PACKET, PACKET__SEND, &ad))
Eric Paris2fe66ec2010-11-23 06:28:08 +00004719 return NF_DROP_ERR(-ECONNREFUSED);
James Morris4e5ab4c2006-06-09 00:33:33 -07004720
Steffen Klassertb9679a72011-02-23 12:55:21 +01004721 if (selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto))
4722 return NF_DROP_ERR(-ECONNREFUSED);
James Morris4e5ab4c2006-06-09 00:33:33 -07004723
Paul Mooreeffad8d2008-01-29 08:49:27 -05004724 return NF_ACCEPT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004725}
4726
Paul Mooreeffad8d2008-01-29 08:49:27 -05004727static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
4728 u16 family)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004729{
Paul Mooreeffad8d2008-01-29 08:49:27 -05004730 u32 secmark_perm;
4731 u32 peer_sid;
4732 struct sock *sk;
Thomas Liu2bf49692009-07-14 12:14:09 -04004733 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004734 struct lsm_network_audit net = {0,};
Paul Mooreeffad8d2008-01-29 08:49:27 -05004735 char *addrp;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004736 u8 secmark_active;
4737 u8 peerlbl_active;
4738
Paul Mooreeffad8d2008-01-29 08:49:27 -05004739 /* If any sort of compatibility mode is enabled then handoff processing
4740 * to the selinux_ip_postroute_compat() function to deal with the
4741 * special handling. We do this in an attempt to keep this function
4742 * as fast and as clean as possible. */
Paul Moore58bfbb52009-03-27 17:10:41 -04004743 if (!selinux_policycap_netpeer)
Paul Moored8395c82008-10-10 10:16:30 -04004744 return selinux_ip_postroute_compat(skb, ifindex, family);
Alexey Dobriyandef8b4f2008-10-28 13:24:06 -07004745#ifdef CONFIG_XFRM
Paul Mooreeffad8d2008-01-29 08:49:27 -05004746 /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec
4747 * packet transformation so allow the packet to pass without any checks
4748 * since we'll have another chance to perform access control checks
4749 * when the packet is on it's final way out.
4750 * NOTE: there appear to be some IPv6 multicast cases where skb->dst
4751 * is NULL, in this case go ahead and apply access control. */
Eric Dumazetadf30902009-06-02 05:19:30 +00004752 if (skb_dst(skb) != NULL && skb_dst(skb)->xfrm != NULL)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004753 return NF_ACCEPT;
Alexey Dobriyandef8b4f2008-10-28 13:24:06 -07004754#endif
Paul Mooreeffad8d2008-01-29 08:49:27 -05004755 secmark_active = selinux_secmark_enabled();
4756 peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled();
4757 if (!secmark_active && !peerlbl_active)
4758 return NF_ACCEPT;
4759
Paul Moored8395c82008-10-10 10:16:30 -04004760 /* if the packet is being forwarded then get the peer label from the
4761 * packet itself; otherwise check to see if it is from a local
4762 * application or the kernel, if from an application get the peer label
4763 * from the sending socket, otherwise use the kernel's sid */
Paul Mooreeffad8d2008-01-29 08:49:27 -05004764 sk = skb->sk;
Paul Moored8395c82008-10-10 10:16:30 -04004765 if (sk == NULL) {
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01004766 if (skb->skb_iif) {
4767 secmark_perm = PACKET__FORWARD_OUT;
Paul Moored8395c82008-10-10 10:16:30 -04004768 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00004769 return NF_DROP;
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01004770 } else {
4771 secmark_perm = PACKET__SEND;
Paul Moored8395c82008-10-10 10:16:30 -04004772 peer_sid = SECINITSID_KERNEL;
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01004773 }
Paul Moored8395c82008-10-10 10:16:30 -04004774 } else {
Paul Mooreeffad8d2008-01-29 08:49:27 -05004775 struct sk_security_struct *sksec = sk->sk_security;
4776 peer_sid = sksec->sid;
4777 secmark_perm = PACKET__SEND;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004778 }
4779
Eric Paris50c205f2012-04-04 15:01:43 -04004780 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004781 ad.u.net = &net;
4782 ad.u.net->netif = ifindex;
4783 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04004784 if (selinux_parse_skb(skb, &ad, &addrp, 0, NULL))
Eric Paris04f6d702010-11-23 06:28:02 +00004785 return NF_DROP;
Paul Moored8395c82008-10-10 10:16:30 -04004786
Paul Mooreeffad8d2008-01-29 08:49:27 -05004787 if (secmark_active)
4788 if (avc_has_perm(peer_sid, skb->secmark,
4789 SECCLASS_PACKET, secmark_perm, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00004790 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004791
4792 if (peerlbl_active) {
4793 u32 if_sid;
4794 u32 node_sid;
4795
4796 if (sel_netif_sid(ifindex, &if_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00004797 return NF_DROP;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004798 if (avc_has_perm(peer_sid, if_sid,
4799 SECCLASS_NETIF, NETIF__EGRESS, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00004800 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004801
4802 if (sel_netnode_sid(addrp, family, &node_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00004803 return NF_DROP;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004804 if (avc_has_perm(peer_sid, node_sid,
4805 SECCLASS_NODE, NODE__SENDTO, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00004806 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004807 }
4808
4809 return NF_ACCEPT;
4810}
4811
4812static unsigned int selinux_ipv4_postroute(unsigned int hooknum,
4813 struct sk_buff *skb,
4814 const struct net_device *in,
4815 const struct net_device *out,
4816 int (*okfn)(struct sk_buff *))
4817{
4818 return selinux_ip_postroute(skb, out->ifindex, PF_INET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004819}
4820
4821#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004822static unsigned int selinux_ipv6_postroute(unsigned int hooknum,
4823 struct sk_buff *skb,
4824 const struct net_device *in,
4825 const struct net_device *out,
4826 int (*okfn)(struct sk_buff *))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004827{
Paul Mooreeffad8d2008-01-29 08:49:27 -05004828 return selinux_ip_postroute(skb, out->ifindex, PF_INET6);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004829}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004830#endif /* IPV6 */
4831
4832#endif /* CONFIG_NETFILTER */
4833
Linus Torvalds1da177e2005-04-16 15:20:36 -07004834static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb)
4835{
Linus Torvalds1da177e2005-04-16 15:20:36 -07004836 int err;
4837
Eric Paris200ac532009-02-12 15:01:04 -05004838 err = cap_netlink_send(sk, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004839 if (err)
4840 return err;
4841
Stephen Smalley941fc5b2009-10-01 14:48:23 -04004842 return selinux_nlmsg_perm(sk, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004843}
4844
Linus Torvalds1da177e2005-04-16 15:20:36 -07004845static int ipc_alloc_security(struct task_struct *task,
4846 struct kern_ipc_perm *perm,
4847 u16 sclass)
4848{
Linus Torvalds1da177e2005-04-16 15:20:36 -07004849 struct ipc_security_struct *isec;
David Howells275bb412008-11-14 10:39:19 +11004850 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004851
James Morris89d155e2005-10-30 14:59:21 -08004852 isec = kzalloc(sizeof(struct ipc_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004853 if (!isec)
4854 return -ENOMEM;
4855
David Howells275bb412008-11-14 10:39:19 +11004856 sid = task_sid(task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004857 isec->sclass = sclass;
David Howells275bb412008-11-14 10:39:19 +11004858 isec->sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004859 perm->security = isec;
4860
4861 return 0;
4862}
4863
4864static void ipc_free_security(struct kern_ipc_perm *perm)
4865{
4866 struct ipc_security_struct *isec = perm->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004867 perm->security = NULL;
4868 kfree(isec);
4869}
4870
4871static int msg_msg_alloc_security(struct msg_msg *msg)
4872{
4873 struct msg_security_struct *msec;
4874
James Morris89d155e2005-10-30 14:59:21 -08004875 msec = kzalloc(sizeof(struct msg_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004876 if (!msec)
4877 return -ENOMEM;
4878
Linus Torvalds1da177e2005-04-16 15:20:36 -07004879 msec->sid = SECINITSID_UNLABELED;
4880 msg->security = msec;
4881
4882 return 0;
4883}
4884
4885static void msg_msg_free_security(struct msg_msg *msg)
4886{
4887 struct msg_security_struct *msec = msg->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004888
4889 msg->security = NULL;
4890 kfree(msec);
4891}
4892
4893static int ipc_has_perm(struct kern_ipc_perm *ipc_perms,
Stephen Smalley6af963f2005-05-01 08:58:39 -07004894 u32 perms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004895{
Linus Torvalds1da177e2005-04-16 15:20:36 -07004896 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04004897 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11004898 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004899
Linus Torvalds1da177e2005-04-16 15:20:36 -07004900 isec = ipc_perms->security;
4901
Eric Paris50c205f2012-04-04 15:01:43 -04004902 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004903 ad.u.ipc_id = ipc_perms->key;
4904
David Howells275bb412008-11-14 10:39:19 +11004905 return avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004906}
4907
4908static int selinux_msg_msg_alloc_security(struct msg_msg *msg)
4909{
4910 return msg_msg_alloc_security(msg);
4911}
4912
4913static void selinux_msg_msg_free_security(struct msg_msg *msg)
4914{
4915 msg_msg_free_security(msg);
4916}
4917
4918/* message queue security operations */
4919static int selinux_msg_queue_alloc_security(struct msg_queue *msq)
4920{
Linus Torvalds1da177e2005-04-16 15:20:36 -07004921 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04004922 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11004923 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004924 int rc;
4925
4926 rc = ipc_alloc_security(current, &msq->q_perm, SECCLASS_MSGQ);
4927 if (rc)
4928 return rc;
4929
Linus Torvalds1da177e2005-04-16 15:20:36 -07004930 isec = msq->q_perm.security;
4931
Eric Paris50c205f2012-04-04 15:01:43 -04004932 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04004933 ad.u.ipc_id = msq->q_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004934
David Howells275bb412008-11-14 10:39:19 +11004935 rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004936 MSGQ__CREATE, &ad);
4937 if (rc) {
4938 ipc_free_security(&msq->q_perm);
4939 return rc;
4940 }
4941 return 0;
4942}
4943
4944static void selinux_msg_queue_free_security(struct msg_queue *msq)
4945{
4946 ipc_free_security(&msq->q_perm);
4947}
4948
4949static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg)
4950{
Linus Torvalds1da177e2005-04-16 15:20:36 -07004951 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04004952 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11004953 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004954
Linus Torvalds1da177e2005-04-16 15:20:36 -07004955 isec = msq->q_perm.security;
4956
Eric Paris50c205f2012-04-04 15:01:43 -04004957 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004958 ad.u.ipc_id = msq->q_perm.key;
4959
David Howells275bb412008-11-14 10:39:19 +11004960 return avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004961 MSGQ__ASSOCIATE, &ad);
4962}
4963
4964static int selinux_msg_queue_msgctl(struct msg_queue *msq, int cmd)
4965{
4966 int err;
4967 int perms;
4968
Eric Paris828dfe12008-04-17 13:17:49 -04004969 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004970 case IPC_INFO:
4971 case MSG_INFO:
4972 /* No specific object, just general system-wide information. */
4973 return task_has_system(current, SYSTEM__IPC_INFO);
4974 case IPC_STAT:
4975 case MSG_STAT:
4976 perms = MSGQ__GETATTR | MSGQ__ASSOCIATE;
4977 break;
4978 case IPC_SET:
4979 perms = MSGQ__SETATTR;
4980 break;
4981 case IPC_RMID:
4982 perms = MSGQ__DESTROY;
4983 break;
4984 default:
4985 return 0;
4986 }
4987
Stephen Smalley6af963f2005-05-01 08:58:39 -07004988 err = ipc_has_perm(&msq->q_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004989 return err;
4990}
4991
4992static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, int msqflg)
4993{
Linus Torvalds1da177e2005-04-16 15:20:36 -07004994 struct ipc_security_struct *isec;
4995 struct msg_security_struct *msec;
Thomas Liu2bf49692009-07-14 12:14:09 -04004996 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11004997 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004998 int rc;
4999
Linus Torvalds1da177e2005-04-16 15:20:36 -07005000 isec = msq->q_perm.security;
5001 msec = msg->security;
5002
5003 /*
5004 * First time through, need to assign label to the message
5005 */
5006 if (msec->sid == SECINITSID_UNLABELED) {
5007 /*
5008 * Compute new sid based on current process and
5009 * message queue this message will be stored in
5010 */
David Howells275bb412008-11-14 10:39:19 +11005011 rc = security_transition_sid(sid, isec->sid, SECCLASS_MSG,
Eric Paris652bb9b2011-02-01 11:05:40 -05005012 NULL, &msec->sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005013 if (rc)
5014 return rc;
5015 }
5016
Eric Paris50c205f2012-04-04 15:01:43 -04005017 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005018 ad.u.ipc_id = msq->q_perm.key;
5019
5020 /* Can this process write to the queue? */
David Howells275bb412008-11-14 10:39:19 +11005021 rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005022 MSGQ__WRITE, &ad);
5023 if (!rc)
5024 /* Can this process send the message */
David Howells275bb412008-11-14 10:39:19 +11005025 rc = avc_has_perm(sid, msec->sid, SECCLASS_MSG,
5026 MSG__SEND, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005027 if (!rc)
5028 /* Can the message be put in the queue? */
David Howells275bb412008-11-14 10:39:19 +11005029 rc = avc_has_perm(msec->sid, isec->sid, SECCLASS_MSGQ,
5030 MSGQ__ENQUEUE, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005031
5032 return rc;
5033}
5034
5035static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
5036 struct task_struct *target,
5037 long type, int mode)
5038{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005039 struct ipc_security_struct *isec;
5040 struct msg_security_struct *msec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005041 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005042 u32 sid = task_sid(target);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005043 int rc;
5044
Linus Torvalds1da177e2005-04-16 15:20:36 -07005045 isec = msq->q_perm.security;
5046 msec = msg->security;
5047
Eric Paris50c205f2012-04-04 15:01:43 -04005048 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04005049 ad.u.ipc_id = msq->q_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005050
David Howells275bb412008-11-14 10:39:19 +11005051 rc = avc_has_perm(sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005052 SECCLASS_MSGQ, MSGQ__READ, &ad);
5053 if (!rc)
David Howells275bb412008-11-14 10:39:19 +11005054 rc = avc_has_perm(sid, msec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005055 SECCLASS_MSG, MSG__RECEIVE, &ad);
5056 return rc;
5057}
5058
5059/* Shared Memory security operations */
5060static int selinux_shm_alloc_security(struct shmid_kernel *shp)
5061{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005062 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005063 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005064 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005065 int rc;
5066
5067 rc = ipc_alloc_security(current, &shp->shm_perm, SECCLASS_SHM);
5068 if (rc)
5069 return rc;
5070
Linus Torvalds1da177e2005-04-16 15:20:36 -07005071 isec = shp->shm_perm.security;
5072
Eric Paris50c205f2012-04-04 15:01:43 -04005073 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04005074 ad.u.ipc_id = shp->shm_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005075
David Howells275bb412008-11-14 10:39:19 +11005076 rc = avc_has_perm(sid, isec->sid, SECCLASS_SHM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005077 SHM__CREATE, &ad);
5078 if (rc) {
5079 ipc_free_security(&shp->shm_perm);
5080 return rc;
5081 }
5082 return 0;
5083}
5084
5085static void selinux_shm_free_security(struct shmid_kernel *shp)
5086{
5087 ipc_free_security(&shp->shm_perm);
5088}
5089
5090static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg)
5091{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005092 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005093 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005094 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005095
Linus Torvalds1da177e2005-04-16 15:20:36 -07005096 isec = shp->shm_perm.security;
5097
Eric Paris50c205f2012-04-04 15:01:43 -04005098 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005099 ad.u.ipc_id = shp->shm_perm.key;
5100
David Howells275bb412008-11-14 10:39:19 +11005101 return avc_has_perm(sid, isec->sid, SECCLASS_SHM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005102 SHM__ASSOCIATE, &ad);
5103}
5104
5105/* Note, at this point, shp is locked down */
5106static int selinux_shm_shmctl(struct shmid_kernel *shp, int cmd)
5107{
5108 int perms;
5109 int err;
5110
Eric Paris828dfe12008-04-17 13:17:49 -04005111 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005112 case IPC_INFO:
5113 case SHM_INFO:
5114 /* No specific object, just general system-wide information. */
5115 return task_has_system(current, SYSTEM__IPC_INFO);
5116 case IPC_STAT:
5117 case SHM_STAT:
5118 perms = SHM__GETATTR | SHM__ASSOCIATE;
5119 break;
5120 case IPC_SET:
5121 perms = SHM__SETATTR;
5122 break;
5123 case SHM_LOCK:
5124 case SHM_UNLOCK:
5125 perms = SHM__LOCK;
5126 break;
5127 case IPC_RMID:
5128 perms = SHM__DESTROY;
5129 break;
5130 default:
5131 return 0;
5132 }
5133
Stephen Smalley6af963f2005-05-01 08:58:39 -07005134 err = ipc_has_perm(&shp->shm_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005135 return err;
5136}
5137
5138static int selinux_shm_shmat(struct shmid_kernel *shp,
5139 char __user *shmaddr, int shmflg)
5140{
5141 u32 perms;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005142
5143 if (shmflg & SHM_RDONLY)
5144 perms = SHM__READ;
5145 else
5146 perms = SHM__READ | SHM__WRITE;
5147
Stephen Smalley6af963f2005-05-01 08:58:39 -07005148 return ipc_has_perm(&shp->shm_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005149}
5150
5151/* Semaphore security operations */
5152static int selinux_sem_alloc_security(struct sem_array *sma)
5153{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005154 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005155 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005156 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005157 int rc;
5158
5159 rc = ipc_alloc_security(current, &sma->sem_perm, SECCLASS_SEM);
5160 if (rc)
5161 return rc;
5162
Linus Torvalds1da177e2005-04-16 15:20:36 -07005163 isec = sma->sem_perm.security;
5164
Eric Paris50c205f2012-04-04 15:01:43 -04005165 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04005166 ad.u.ipc_id = sma->sem_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005167
David Howells275bb412008-11-14 10:39:19 +11005168 rc = avc_has_perm(sid, isec->sid, SECCLASS_SEM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005169 SEM__CREATE, &ad);
5170 if (rc) {
5171 ipc_free_security(&sma->sem_perm);
5172 return rc;
5173 }
5174 return 0;
5175}
5176
5177static void selinux_sem_free_security(struct sem_array *sma)
5178{
5179 ipc_free_security(&sma->sem_perm);
5180}
5181
5182static int selinux_sem_associate(struct sem_array *sma, int semflg)
5183{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005184 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005185 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005186 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005187
Linus Torvalds1da177e2005-04-16 15:20:36 -07005188 isec = sma->sem_perm.security;
5189
Eric Paris50c205f2012-04-04 15:01:43 -04005190 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005191 ad.u.ipc_id = sma->sem_perm.key;
5192
David Howells275bb412008-11-14 10:39:19 +11005193 return avc_has_perm(sid, isec->sid, SECCLASS_SEM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005194 SEM__ASSOCIATE, &ad);
5195}
5196
5197/* Note, at this point, sma is locked down */
5198static int selinux_sem_semctl(struct sem_array *sma, int cmd)
5199{
5200 int err;
5201 u32 perms;
5202
Eric Paris828dfe12008-04-17 13:17:49 -04005203 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005204 case IPC_INFO:
5205 case SEM_INFO:
5206 /* No specific object, just general system-wide information. */
5207 return task_has_system(current, SYSTEM__IPC_INFO);
5208 case GETPID:
5209 case GETNCNT:
5210 case GETZCNT:
5211 perms = SEM__GETATTR;
5212 break;
5213 case GETVAL:
5214 case GETALL:
5215 perms = SEM__READ;
5216 break;
5217 case SETVAL:
5218 case SETALL:
5219 perms = SEM__WRITE;
5220 break;
5221 case IPC_RMID:
5222 perms = SEM__DESTROY;
5223 break;
5224 case IPC_SET:
5225 perms = SEM__SETATTR;
5226 break;
5227 case IPC_STAT:
5228 case SEM_STAT:
5229 perms = SEM__GETATTR | SEM__ASSOCIATE;
5230 break;
5231 default:
5232 return 0;
5233 }
5234
Stephen Smalley6af963f2005-05-01 08:58:39 -07005235 err = ipc_has_perm(&sma->sem_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005236 return err;
5237}
5238
5239static int selinux_sem_semop(struct sem_array *sma,
5240 struct sembuf *sops, unsigned nsops, int alter)
5241{
5242 u32 perms;
5243
5244 if (alter)
5245 perms = SEM__READ | SEM__WRITE;
5246 else
5247 perms = SEM__READ;
5248
Stephen Smalley6af963f2005-05-01 08:58:39 -07005249 return ipc_has_perm(&sma->sem_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005250}
5251
5252static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
5253{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005254 u32 av = 0;
5255
Linus Torvalds1da177e2005-04-16 15:20:36 -07005256 av = 0;
5257 if (flag & S_IRUGO)
5258 av |= IPC__UNIX_READ;
5259 if (flag & S_IWUGO)
5260 av |= IPC__UNIX_WRITE;
5261
5262 if (av == 0)
5263 return 0;
5264
Stephen Smalley6af963f2005-05-01 08:58:39 -07005265 return ipc_has_perm(ipcp, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005266}
5267
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02005268static void selinux_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
5269{
5270 struct ipc_security_struct *isec = ipcp->security;
5271 *secid = isec->sid;
5272}
5273
Eric Paris828dfe12008-04-17 13:17:49 -04005274static void selinux_d_instantiate(struct dentry *dentry, struct inode *inode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005275{
5276 if (inode)
5277 inode_doinit_with_dentry(inode, dentry);
5278}
5279
5280static int selinux_getprocattr(struct task_struct *p,
Al Viro04ff9702007-03-12 16:17:58 +00005281 char *name, char **value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005282{
David Howells275bb412008-11-14 10:39:19 +11005283 const struct task_security_struct *__tsec;
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00005284 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005285 int error;
Al Viro04ff9702007-03-12 16:17:58 +00005286 unsigned len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005287
5288 if (current != p) {
David Howells3b11a1d2008-11-14 10:39:26 +11005289 error = current_has_perm(p, PROCESS__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005290 if (error)
5291 return error;
5292 }
5293
David Howells275bb412008-11-14 10:39:19 +11005294 rcu_read_lock();
5295 __tsec = __task_cred(p)->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005296
5297 if (!strcmp(name, "current"))
David Howells275bb412008-11-14 10:39:19 +11005298 sid = __tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005299 else if (!strcmp(name, "prev"))
David Howells275bb412008-11-14 10:39:19 +11005300 sid = __tsec->osid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005301 else if (!strcmp(name, "exec"))
David Howells275bb412008-11-14 10:39:19 +11005302 sid = __tsec->exec_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005303 else if (!strcmp(name, "fscreate"))
David Howells275bb412008-11-14 10:39:19 +11005304 sid = __tsec->create_sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005305 else if (!strcmp(name, "keycreate"))
David Howells275bb412008-11-14 10:39:19 +11005306 sid = __tsec->keycreate_sid;
Eric Paris42c3e032006-06-26 00:26:03 -07005307 else if (!strcmp(name, "sockcreate"))
David Howells275bb412008-11-14 10:39:19 +11005308 sid = __tsec->sockcreate_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005309 else
David Howells275bb412008-11-14 10:39:19 +11005310 goto invalid;
5311 rcu_read_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005312
5313 if (!sid)
5314 return 0;
5315
Al Viro04ff9702007-03-12 16:17:58 +00005316 error = security_sid_to_context(sid, value, &len);
5317 if (error)
5318 return error;
5319 return len;
David Howells275bb412008-11-14 10:39:19 +11005320
5321invalid:
5322 rcu_read_unlock();
5323 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005324}
5325
5326static int selinux_setprocattr(struct task_struct *p,
5327 char *name, void *value, size_t size)
5328{
5329 struct task_security_struct *tsec;
Roland McGrath03563572008-03-26 15:46:39 -07005330 struct task_struct *tracer;
David Howellsd84f4f92008-11-14 10:39:23 +11005331 struct cred *new;
5332 u32 sid = 0, ptsid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005333 int error;
5334 char *str = value;
5335
5336 if (current != p) {
5337 /* SELinux only allows a process to change its own
5338 security attributes. */
5339 return -EACCES;
5340 }
5341
5342 /*
5343 * Basic control over ability to set these attributes at all.
5344 * current == p, but we'll pass them separately in case the
5345 * above restriction is ever removed.
5346 */
5347 if (!strcmp(name, "exec"))
David Howells3b11a1d2008-11-14 10:39:26 +11005348 error = current_has_perm(p, PROCESS__SETEXEC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005349 else if (!strcmp(name, "fscreate"))
David Howells3b11a1d2008-11-14 10:39:26 +11005350 error = current_has_perm(p, PROCESS__SETFSCREATE);
Michael LeMay4eb582c2006-06-26 00:24:57 -07005351 else if (!strcmp(name, "keycreate"))
David Howells3b11a1d2008-11-14 10:39:26 +11005352 error = current_has_perm(p, PROCESS__SETKEYCREATE);
Eric Paris42c3e032006-06-26 00:26:03 -07005353 else if (!strcmp(name, "sockcreate"))
David Howells3b11a1d2008-11-14 10:39:26 +11005354 error = current_has_perm(p, PROCESS__SETSOCKCREATE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005355 else if (!strcmp(name, "current"))
David Howells3b11a1d2008-11-14 10:39:26 +11005356 error = current_has_perm(p, PROCESS__SETCURRENT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005357 else
5358 error = -EINVAL;
5359 if (error)
5360 return error;
5361
5362 /* Obtain a SID for the context, if one was specified. */
5363 if (size && str[1] && str[1] != '\n') {
5364 if (str[size-1] == '\n') {
5365 str[size-1] = 0;
5366 size--;
5367 }
5368 error = security_context_to_sid(value, size, &sid);
Stephen Smalley12b29f32008-05-07 13:03:20 -04005369 if (error == -EINVAL && !strcmp(name, "fscreate")) {
Eric Parisd6ea83e2012-04-04 13:45:49 -04005370 if (!capable(CAP_MAC_ADMIN)) {
5371 struct audit_buffer *ab;
5372 size_t audit_size;
5373
5374 /* We strip a nul only if it is at the end, otherwise the
5375 * context contains a nul and we should audit that */
5376 if (str[size - 1] == '\0')
5377 audit_size = size - 1;
5378 else
5379 audit_size = size;
5380 ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR);
5381 audit_log_format(ab, "op=fscreate invalid_context=");
5382 audit_log_n_untrustedstring(ab, value, audit_size);
5383 audit_log_end(ab);
5384
Stephen Smalley12b29f32008-05-07 13:03:20 -04005385 return error;
Eric Parisd6ea83e2012-04-04 13:45:49 -04005386 }
Stephen Smalley12b29f32008-05-07 13:03:20 -04005387 error = security_context_to_sid_force(value, size,
5388 &sid);
5389 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005390 if (error)
5391 return error;
5392 }
5393
David Howellsd84f4f92008-11-14 10:39:23 +11005394 new = prepare_creds();
5395 if (!new)
5396 return -ENOMEM;
5397
Linus Torvalds1da177e2005-04-16 15:20:36 -07005398 /* Permission checking based on the specified context is
5399 performed during the actual operation (execve,
5400 open/mkdir/...), when we know the full context of the
David Howellsd84f4f92008-11-14 10:39:23 +11005401 operation. See selinux_bprm_set_creds for the execve
Linus Torvalds1da177e2005-04-16 15:20:36 -07005402 checks and may_create for the file creation checks. The
5403 operation will then fail if the context is not permitted. */
David Howellsd84f4f92008-11-14 10:39:23 +11005404 tsec = new->security;
5405 if (!strcmp(name, "exec")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005406 tsec->exec_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005407 } else if (!strcmp(name, "fscreate")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005408 tsec->create_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005409 } else if (!strcmp(name, "keycreate")) {
Michael LeMay4eb582c2006-06-26 00:24:57 -07005410 error = may_create_key(sid, p);
5411 if (error)
David Howellsd84f4f92008-11-14 10:39:23 +11005412 goto abort_change;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005413 tsec->keycreate_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005414 } else if (!strcmp(name, "sockcreate")) {
Eric Paris42c3e032006-06-26 00:26:03 -07005415 tsec->sockcreate_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005416 } else if (!strcmp(name, "current")) {
5417 error = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005418 if (sid == 0)
David Howellsd84f4f92008-11-14 10:39:23 +11005419 goto abort_change;
KaiGai Koheid9250de2008-08-28 16:35:57 +09005420
David Howellsd84f4f92008-11-14 10:39:23 +11005421 /* Only allow single threaded processes to change context */
5422 error = -EPERM;
Oleg Nesterov5bb459b2009-07-10 03:48:23 +02005423 if (!current_is_single_threaded()) {
David Howellsd84f4f92008-11-14 10:39:23 +11005424 error = security_bounded_transition(tsec->sid, sid);
5425 if (error)
5426 goto abort_change;
Eric Paris828dfe12008-04-17 13:17:49 -04005427 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005428
5429 /* Check permissions for the transition. */
5430 error = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS,
Eric Paris828dfe12008-04-17 13:17:49 -04005431 PROCESS__DYNTRANSITION, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005432 if (error)
David Howellsd84f4f92008-11-14 10:39:23 +11005433 goto abort_change;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005434
5435 /* Check for ptracing, and update the task SID if ok.
5436 Otherwise, leave SID unchanged and fail. */
David Howellsd84f4f92008-11-14 10:39:23 +11005437 ptsid = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005438 task_lock(p);
Tejun Heo06d98472011-06-17 16:50:40 +02005439 tracer = ptrace_parent(p);
David Howellsd84f4f92008-11-14 10:39:23 +11005440 if (tracer)
5441 ptsid = task_sid(tracer);
5442 task_unlock(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005443
David Howellsd84f4f92008-11-14 10:39:23 +11005444 if (tracer) {
5445 error = avc_has_perm(ptsid, sid, SECCLASS_PROCESS,
5446 PROCESS__PTRACE, NULL);
5447 if (error)
5448 goto abort_change;
5449 }
5450
5451 tsec->sid = sid;
5452 } else {
5453 error = -EINVAL;
5454 goto abort_change;
5455 }
5456
5457 commit_creds(new);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005458 return size;
David Howellsd84f4f92008-11-14 10:39:23 +11005459
5460abort_change:
5461 abort_creds(new);
5462 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005463}
5464
David Quigley746df9b2013-05-22 12:50:35 -04005465static int selinux_ismaclabel(const char *name)
5466{
5467 return (strcmp(name, XATTR_SELINUX_SUFFIX) == 0);
5468}
5469
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005470static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
5471{
5472 return security_sid_to_context(secid, secdata, seclen);
5473}
5474
David Howells7bf570d2008-04-29 20:52:51 +01005475static int selinux_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
David Howells63cb3442008-01-15 23:47:35 +00005476{
5477 return security_context_to_sid(secdata, seclen, secid);
5478}
5479
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005480static void selinux_release_secctx(char *secdata, u32 seclen)
5481{
Paul Moore088999e2007-08-01 11:12:58 -04005482 kfree(secdata);
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005483}
5484
David P. Quigley1ee65e32009-09-03 14:25:57 -04005485/*
5486 * called with inode->i_mutex locked
5487 */
5488static int selinux_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen)
5489{
5490 return selinux_inode_setsecurity(inode, XATTR_SELINUX_SUFFIX, ctx, ctxlen, 0);
5491}
5492
5493/*
5494 * called with inode->i_mutex locked
5495 */
5496static int selinux_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen)
5497{
5498 return __vfs_setxattr_noperm(dentry, XATTR_NAME_SELINUX, ctx, ctxlen, 0);
5499}
5500
5501static int selinux_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen)
5502{
5503 int len = 0;
5504 len = selinux_inode_getsecurity(inode, XATTR_SELINUX_SUFFIX,
5505 ctx, true);
5506 if (len < 0)
5507 return len;
5508 *ctxlen = len;
5509 return 0;
5510}
Michael LeMayd7200242006-06-22 14:47:17 -07005511#ifdef CONFIG_KEYS
5512
David Howellsd84f4f92008-11-14 10:39:23 +11005513static int selinux_key_alloc(struct key *k, const struct cred *cred,
David Howells7e047ef2006-06-26 00:24:50 -07005514 unsigned long flags)
Michael LeMayd7200242006-06-22 14:47:17 -07005515{
David Howellsd84f4f92008-11-14 10:39:23 +11005516 const struct task_security_struct *tsec;
Michael LeMayd7200242006-06-22 14:47:17 -07005517 struct key_security_struct *ksec;
5518
5519 ksec = kzalloc(sizeof(struct key_security_struct), GFP_KERNEL);
5520 if (!ksec)
5521 return -ENOMEM;
5522
David Howellsd84f4f92008-11-14 10:39:23 +11005523 tsec = cred->security;
5524 if (tsec->keycreate_sid)
5525 ksec->sid = tsec->keycreate_sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005526 else
David Howellsd84f4f92008-11-14 10:39:23 +11005527 ksec->sid = tsec->sid;
Michael LeMayd7200242006-06-22 14:47:17 -07005528
David Howells275bb412008-11-14 10:39:19 +11005529 k->security = ksec;
Michael LeMayd7200242006-06-22 14:47:17 -07005530 return 0;
5531}
5532
5533static void selinux_key_free(struct key *k)
5534{
5535 struct key_security_struct *ksec = k->security;
5536
5537 k->security = NULL;
5538 kfree(ksec);
5539}
5540
5541static int selinux_key_permission(key_ref_t key_ref,
David Howellsd84f4f92008-11-14 10:39:23 +11005542 const struct cred *cred,
5543 key_perm_t perm)
Michael LeMayd7200242006-06-22 14:47:17 -07005544{
5545 struct key *key;
Michael LeMayd7200242006-06-22 14:47:17 -07005546 struct key_security_struct *ksec;
David Howells275bb412008-11-14 10:39:19 +11005547 u32 sid;
Michael LeMayd7200242006-06-22 14:47:17 -07005548
5549 /* if no specific permissions are requested, we skip the
5550 permission check. No serious, additional covert channels
5551 appear to be created. */
5552 if (perm == 0)
5553 return 0;
5554
David Howellsd84f4f92008-11-14 10:39:23 +11005555 sid = cred_sid(cred);
David Howells275bb412008-11-14 10:39:19 +11005556
5557 key = key_ref_to_ptr(key_ref);
5558 ksec = key->security;
5559
5560 return avc_has_perm(sid, ksec->sid, SECCLASS_KEY, perm, NULL);
Michael LeMayd7200242006-06-22 14:47:17 -07005561}
5562
David Howells70a5bb72008-04-29 01:01:26 -07005563static int selinux_key_getsecurity(struct key *key, char **_buffer)
5564{
5565 struct key_security_struct *ksec = key->security;
5566 char *context = NULL;
5567 unsigned len;
5568 int rc;
5569
5570 rc = security_sid_to_context(ksec->sid, &context, &len);
5571 if (!rc)
5572 rc = len;
5573 *_buffer = context;
5574 return rc;
5575}
5576
Michael LeMayd7200242006-06-22 14:47:17 -07005577#endif
5578
Linus Torvalds1da177e2005-04-16 15:20:36 -07005579static struct security_operations selinux_ops = {
Ahmed S. Darwish076c54c2008-03-06 18:09:10 +02005580 .name = "selinux",
5581
Ingo Molnar9e488582009-05-07 19:26:19 +10005582 .ptrace_access_check = selinux_ptrace_access_check,
David Howells5cd9c582008-08-14 11:37:28 +01005583 .ptrace_traceme = selinux_ptrace_traceme,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005584 .capget = selinux_capget,
David Howellsd84f4f92008-11-14 10:39:23 +11005585 .capset = selinux_capset,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005586 .capable = selinux_capable,
5587 .quotactl = selinux_quotactl,
5588 .quota_on = selinux_quota_on,
5589 .syslog = selinux_syslog,
5590 .vm_enough_memory = selinux_vm_enough_memory,
5591
5592 .netlink_send = selinux_netlink_send,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005593
David Howellsa6f76f22008-11-14 10:39:24 +11005594 .bprm_set_creds = selinux_bprm_set_creds,
David Howellsa6f76f22008-11-14 10:39:24 +11005595 .bprm_committing_creds = selinux_bprm_committing_creds,
5596 .bprm_committed_creds = selinux_bprm_committed_creds,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005597 .bprm_secureexec = selinux_bprm_secureexec,
5598
5599 .sb_alloc_security = selinux_sb_alloc_security,
5600 .sb_free_security = selinux_sb_free_security,
5601 .sb_copy_data = selinux_sb_copy_data,
Eric Paris026eb162011-03-03 16:09:14 -05005602 .sb_remount = selinux_sb_remount,
Eric Paris828dfe12008-04-17 13:17:49 -04005603 .sb_kern_mount = selinux_sb_kern_mount,
Eric Paris2069f452008-07-04 09:47:13 +10005604 .sb_show_options = selinux_sb_show_options,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005605 .sb_statfs = selinux_sb_statfs,
5606 .sb_mount = selinux_mount,
5607 .sb_umount = selinux_umount,
Eric Parisc9180a52007-11-30 13:00:35 -05005608 .sb_set_mnt_opts = selinux_set_mnt_opts,
Eric Paris828dfe12008-04-17 13:17:49 -04005609 .sb_clone_mnt_opts = selinux_sb_clone_mnt_opts,
Eric Parise0007522008-03-05 10:31:54 -05005610 .sb_parse_opts_str = selinux_parse_opts_str,
5611
David Quigleyd47be3d2013-05-22 12:50:34 -04005612 .dentry_init_security = selinux_dentry_init_security,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005613
5614 .inode_alloc_security = selinux_inode_alloc_security,
5615 .inode_free_security = selinux_inode_free_security,
Stephen Smalley5e41ff92005-09-09 13:01:35 -07005616 .inode_init_security = selinux_inode_init_security,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005617 .inode_create = selinux_inode_create,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005618 .inode_link = selinux_inode_link,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005619 .inode_unlink = selinux_inode_unlink,
5620 .inode_symlink = selinux_inode_symlink,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005621 .inode_mkdir = selinux_inode_mkdir,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005622 .inode_rmdir = selinux_inode_rmdir,
5623 .inode_mknod = selinux_inode_mknod,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005624 .inode_rename = selinux_inode_rename,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005625 .inode_readlink = selinux_inode_readlink,
5626 .inode_follow_link = selinux_inode_follow_link,
5627 .inode_permission = selinux_inode_permission,
5628 .inode_setattr = selinux_inode_setattr,
5629 .inode_getattr = selinux_inode_getattr,
5630 .inode_setxattr = selinux_inode_setxattr,
5631 .inode_post_setxattr = selinux_inode_post_setxattr,
5632 .inode_getxattr = selinux_inode_getxattr,
5633 .inode_listxattr = selinux_inode_listxattr,
5634 .inode_removexattr = selinux_inode_removexattr,
Eric Paris828dfe12008-04-17 13:17:49 -04005635 .inode_getsecurity = selinux_inode_getsecurity,
5636 .inode_setsecurity = selinux_inode_setsecurity,
5637 .inode_listsecurity = selinux_inode_listsecurity,
Eric Parisf5269712008-05-14 11:27:45 -04005638 .inode_getsecid = selinux_inode_getsecid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005639
5640 .file_permission = selinux_file_permission,
5641 .file_alloc_security = selinux_file_alloc_security,
5642 .file_free_security = selinux_file_free_security,
5643 .file_ioctl = selinux_file_ioctl,
Al Viroe5467852012-05-30 13:30:51 -04005644 .mmap_file = selinux_mmap_file,
5645 .mmap_addr = selinux_mmap_addr,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005646 .file_mprotect = selinux_file_mprotect,
5647 .file_lock = selinux_file_lock,
5648 .file_fcntl = selinux_file_fcntl,
5649 .file_set_fowner = selinux_file_set_fowner,
5650 .file_send_sigiotask = selinux_file_send_sigiotask,
5651 .file_receive = selinux_file_receive,
5652
Eric Paris83d49852012-04-04 13:45:40 -04005653 .file_open = selinux_file_open,
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09005654
Linus Torvalds1da177e2005-04-16 15:20:36 -07005655 .task_create = selinux_task_create,
David Howellsee18d642009-09-02 09:14:21 +01005656 .cred_alloc_blank = selinux_cred_alloc_blank,
David Howellsf1752ee2008-11-14 10:39:17 +11005657 .cred_free = selinux_cred_free,
David Howellsd84f4f92008-11-14 10:39:23 +11005658 .cred_prepare = selinux_cred_prepare,
David Howellsee18d642009-09-02 09:14:21 +01005659 .cred_transfer = selinux_cred_transfer,
David Howells3a3b7ce2008-11-14 10:39:28 +11005660 .kernel_act_as = selinux_kernel_act_as,
5661 .kernel_create_files_as = selinux_kernel_create_files_as,
Eric Paris25354c42009-08-13 09:45:03 -04005662 .kernel_module_request = selinux_kernel_module_request,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005663 .task_setpgid = selinux_task_setpgid,
5664 .task_getpgid = selinux_task_getpgid,
Eric Paris828dfe12008-04-17 13:17:49 -04005665 .task_getsid = selinux_task_getsid,
David Quigleyf9008e42006-06-30 01:55:46 -07005666 .task_getsecid = selinux_task_getsecid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005667 .task_setnice = selinux_task_setnice,
James Morris03e68062006-06-23 02:03:58 -07005668 .task_setioprio = selinux_task_setioprio,
David Quigleya1836a42006-06-30 01:55:49 -07005669 .task_getioprio = selinux_task_getioprio,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005670 .task_setrlimit = selinux_task_setrlimit,
5671 .task_setscheduler = selinux_task_setscheduler,
5672 .task_getscheduler = selinux_task_getscheduler,
David Quigley35601542006-06-23 02:04:01 -07005673 .task_movememory = selinux_task_movememory,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005674 .task_kill = selinux_task_kill,
5675 .task_wait = selinux_task_wait,
Eric Paris828dfe12008-04-17 13:17:49 -04005676 .task_to_inode = selinux_task_to_inode,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005677
5678 .ipc_permission = selinux_ipc_permission,
Eric Parisf5269712008-05-14 11:27:45 -04005679 .ipc_getsecid = selinux_ipc_getsecid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005680
5681 .msg_msg_alloc_security = selinux_msg_msg_alloc_security,
5682 .msg_msg_free_security = selinux_msg_msg_free_security,
5683
5684 .msg_queue_alloc_security = selinux_msg_queue_alloc_security,
5685 .msg_queue_free_security = selinux_msg_queue_free_security,
5686 .msg_queue_associate = selinux_msg_queue_associate,
5687 .msg_queue_msgctl = selinux_msg_queue_msgctl,
5688 .msg_queue_msgsnd = selinux_msg_queue_msgsnd,
5689 .msg_queue_msgrcv = selinux_msg_queue_msgrcv,
5690
5691 .shm_alloc_security = selinux_shm_alloc_security,
5692 .shm_free_security = selinux_shm_free_security,
5693 .shm_associate = selinux_shm_associate,
5694 .shm_shmctl = selinux_shm_shmctl,
5695 .shm_shmat = selinux_shm_shmat,
5696
Eric Paris828dfe12008-04-17 13:17:49 -04005697 .sem_alloc_security = selinux_sem_alloc_security,
5698 .sem_free_security = selinux_sem_free_security,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005699 .sem_associate = selinux_sem_associate,
5700 .sem_semctl = selinux_sem_semctl,
5701 .sem_semop = selinux_sem_semop,
5702
Eric Paris828dfe12008-04-17 13:17:49 -04005703 .d_instantiate = selinux_d_instantiate,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005704
Eric Paris828dfe12008-04-17 13:17:49 -04005705 .getprocattr = selinux_getprocattr,
5706 .setprocattr = selinux_setprocattr,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005707
David Quigley746df9b2013-05-22 12:50:35 -04005708 .ismaclabel = selinux_ismaclabel,
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005709 .secid_to_secctx = selinux_secid_to_secctx,
David Howells63cb3442008-01-15 23:47:35 +00005710 .secctx_to_secid = selinux_secctx_to_secid,
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005711 .release_secctx = selinux_release_secctx,
David P. Quigley1ee65e32009-09-03 14:25:57 -04005712 .inode_notifysecctx = selinux_inode_notifysecctx,
5713 .inode_setsecctx = selinux_inode_setsecctx,
5714 .inode_getsecctx = selinux_inode_getsecctx,
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005715
Eric Paris828dfe12008-04-17 13:17:49 -04005716 .unix_stream_connect = selinux_socket_unix_stream_connect,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005717 .unix_may_send = selinux_socket_unix_may_send,
5718
5719 .socket_create = selinux_socket_create,
5720 .socket_post_create = selinux_socket_post_create,
5721 .socket_bind = selinux_socket_bind,
5722 .socket_connect = selinux_socket_connect,
5723 .socket_listen = selinux_socket_listen,
5724 .socket_accept = selinux_socket_accept,
5725 .socket_sendmsg = selinux_socket_sendmsg,
5726 .socket_recvmsg = selinux_socket_recvmsg,
5727 .socket_getsockname = selinux_socket_getsockname,
5728 .socket_getpeername = selinux_socket_getpeername,
5729 .socket_getsockopt = selinux_socket_getsockopt,
5730 .socket_setsockopt = selinux_socket_setsockopt,
5731 .socket_shutdown = selinux_socket_shutdown,
5732 .socket_sock_rcv_skb = selinux_socket_sock_rcv_skb,
Catherine Zhang2c7946a2006-03-20 22:41:23 -08005733 .socket_getpeersec_stream = selinux_socket_getpeersec_stream,
5734 .socket_getpeersec_dgram = selinux_socket_getpeersec_dgram,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005735 .sk_alloc_security = selinux_sk_alloc_security,
5736 .sk_free_security = selinux_sk_free_security,
Venkat Yekkirala892c1412006-08-04 23:08:56 -07005737 .sk_clone_security = selinux_sk_clone_security,
Eric Paris828dfe12008-04-17 13:17:49 -04005738 .sk_getsecid = selinux_sk_getsecid,
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005739 .sock_graft = selinux_sock_graft,
5740 .inet_conn_request = selinux_inet_conn_request,
5741 .inet_csk_clone = selinux_inet_csk_clone,
Venkat Yekkirala6b877692006-11-08 17:04:09 -06005742 .inet_conn_established = selinux_inet_conn_established,
Eric Paris2606fd12010-10-13 16:24:41 -04005743 .secmark_relabel_packet = selinux_secmark_relabel_packet,
5744 .secmark_refcount_inc = selinux_secmark_refcount_inc,
5745 .secmark_refcount_dec = selinux_secmark_refcount_dec,
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005746 .req_classify_flow = selinux_req_classify_flow,
Paul Moore5dbbaf22013-01-14 07:12:19 +00005747 .tun_dev_alloc_security = selinux_tun_dev_alloc_security,
5748 .tun_dev_free_security = selinux_tun_dev_free_security,
Paul Mooreed6d76e2009-08-28 18:12:49 -04005749 .tun_dev_create = selinux_tun_dev_create,
Paul Moore5dbbaf22013-01-14 07:12:19 +00005750 .tun_dev_attach_queue = selinux_tun_dev_attach_queue,
Paul Mooreed6d76e2009-08-28 18:12:49 -04005751 .tun_dev_attach = selinux_tun_dev_attach,
Paul Moore5dbbaf22013-01-14 07:12:19 +00005752 .tun_dev_open = selinux_tun_dev_open,
Eric Dumazetca10b9e2013-04-08 17:58:11 +00005753 .skb_owned_by = selinux_skb_owned_by,
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005754
5755#ifdef CONFIG_SECURITY_NETWORK_XFRM
5756 .xfrm_policy_alloc_security = selinux_xfrm_policy_alloc,
5757 .xfrm_policy_clone_security = selinux_xfrm_policy_clone,
5758 .xfrm_policy_free_security = selinux_xfrm_policy_free,
Catherine Zhangc8c05a82006-06-08 23:39:49 -07005759 .xfrm_policy_delete_security = selinux_xfrm_policy_delete,
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005760 .xfrm_state_alloc_security = selinux_xfrm_state_alloc,
5761 .xfrm_state_free_security = selinux_xfrm_state_free,
Catherine Zhangc8c05a82006-06-08 23:39:49 -07005762 .xfrm_state_delete_security = selinux_xfrm_state_delete,
Eric Paris828dfe12008-04-17 13:17:49 -04005763 .xfrm_policy_lookup = selinux_xfrm_policy_lookup,
Venkat Yekkiralae0d1caa2006-07-24 23:29:07 -07005764 .xfrm_state_pol_flow_match = selinux_xfrm_state_pol_flow_match,
Venkat Yekkiralae0d1caa2006-07-24 23:29:07 -07005765 .xfrm_decode_session = selinux_xfrm_decode_session,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005766#endif
Michael LeMayd7200242006-06-22 14:47:17 -07005767
5768#ifdef CONFIG_KEYS
Eric Paris828dfe12008-04-17 13:17:49 -04005769 .key_alloc = selinux_key_alloc,
5770 .key_free = selinux_key_free,
5771 .key_permission = selinux_key_permission,
David Howells70a5bb72008-04-29 01:01:26 -07005772 .key_getsecurity = selinux_key_getsecurity,
Michael LeMayd7200242006-06-22 14:47:17 -07005773#endif
Ahmed S. Darwish9d57a7f2008-03-01 22:03:14 +02005774
5775#ifdef CONFIG_AUDIT
5776 .audit_rule_init = selinux_audit_rule_init,
5777 .audit_rule_known = selinux_audit_rule_known,
5778 .audit_rule_match = selinux_audit_rule_match,
5779 .audit_rule_free = selinux_audit_rule_free,
5780#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07005781};
5782
5783static __init int selinux_init(void)
5784{
Ahmed S. Darwish076c54c2008-03-06 18:09:10 +02005785 if (!security_module_enable(&selinux_ops)) {
5786 selinux_enabled = 0;
5787 return 0;
5788 }
5789
Linus Torvalds1da177e2005-04-16 15:20:36 -07005790 if (!selinux_enabled) {
5791 printk(KERN_INFO "SELinux: Disabled at boot.\n");
5792 return 0;
5793 }
5794
5795 printk(KERN_INFO "SELinux: Initializing.\n");
5796
5797 /* Set the security state for the initial task. */
David Howellsd84f4f92008-11-14 10:39:23 +11005798 cred_init_security();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005799
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04005800 default_noexec = !(VM_DATA_DEFAULT_FLAGS & VM_EXEC);
5801
James Morris7cae7e22006-03-22 00:09:22 -08005802 sel_inode_cache = kmem_cache_create("selinux_inode_security",
5803 sizeof(struct inode_security_struct),
Paul Mundt20c2df82007-07-20 10:11:58 +09005804 0, SLAB_PANIC, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005805 avc_init();
5806
Eric Paris828dfe12008-04-17 13:17:49 -04005807 if (register_security(&selinux_ops))
Linus Torvalds1da177e2005-04-16 15:20:36 -07005808 panic("SELinux: Unable to register with kernel.\n");
5809
Eric Paris828dfe12008-04-17 13:17:49 -04005810 if (selinux_enforcing)
Eric Parisfadcdb42007-02-22 18:11:31 -05005811 printk(KERN_DEBUG "SELinux: Starting in enforcing mode\n");
Eric Paris828dfe12008-04-17 13:17:49 -04005812 else
Eric Parisfadcdb42007-02-22 18:11:31 -05005813 printk(KERN_DEBUG "SELinux: Starting in permissive mode\n");
Michael LeMayd7200242006-06-22 14:47:17 -07005814
Linus Torvalds1da177e2005-04-16 15:20:36 -07005815 return 0;
5816}
5817
Al Viroe8c26252010-03-23 06:36:54 -04005818static void delayed_superblock_init(struct super_block *sb, void *unused)
5819{
5820 superblock_doinit(sb, NULL);
5821}
5822
Linus Torvalds1da177e2005-04-16 15:20:36 -07005823void selinux_complete_init(void)
5824{
Eric Parisfadcdb42007-02-22 18:11:31 -05005825 printk(KERN_DEBUG "SELinux: Completing initialization.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005826
5827 /* Set up any superblocks initialized prior to the policy load. */
Eric Parisfadcdb42007-02-22 18:11:31 -05005828 printk(KERN_DEBUG "SELinux: Setting up existing superblocks.\n");
Al Viroe8c26252010-03-23 06:36:54 -04005829 iterate_supers(delayed_superblock_init, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005830}
5831
5832/* SELinux requires early initialization in order to label
5833 all processes and objects when they are created. */
5834security_initcall(selinux_init);
5835
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08005836#if defined(CONFIG_NETFILTER)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005837
Paul Mooreeffad8d2008-01-29 08:49:27 -05005838static struct nf_hook_ops selinux_ipv4_ops[] = {
5839 {
5840 .hook = selinux_ipv4_postroute,
5841 .owner = THIS_MODULE,
Alban Crequy2597a832012-05-14 03:56:39 +00005842 .pf = NFPROTO_IPV4,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005843 .hooknum = NF_INET_POST_ROUTING,
5844 .priority = NF_IP_PRI_SELINUX_LAST,
5845 },
5846 {
5847 .hook = selinux_ipv4_forward,
5848 .owner = THIS_MODULE,
Alban Crequy2597a832012-05-14 03:56:39 +00005849 .pf = NFPROTO_IPV4,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005850 .hooknum = NF_INET_FORWARD,
5851 .priority = NF_IP_PRI_SELINUX_FIRST,
Paul Moore948bf852008-10-10 10:16:32 -04005852 },
5853 {
5854 .hook = selinux_ipv4_output,
5855 .owner = THIS_MODULE,
Alban Crequy2597a832012-05-14 03:56:39 +00005856 .pf = NFPROTO_IPV4,
Paul Moore948bf852008-10-10 10:16:32 -04005857 .hooknum = NF_INET_LOCAL_OUT,
5858 .priority = NF_IP_PRI_SELINUX_FIRST,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005859 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005860};
5861
5862#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
5863
Paul Mooreeffad8d2008-01-29 08:49:27 -05005864static struct nf_hook_ops selinux_ipv6_ops[] = {
5865 {
5866 .hook = selinux_ipv6_postroute,
5867 .owner = THIS_MODULE,
Alban Crequy2597a832012-05-14 03:56:39 +00005868 .pf = NFPROTO_IPV6,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005869 .hooknum = NF_INET_POST_ROUTING,
5870 .priority = NF_IP6_PRI_SELINUX_LAST,
5871 },
5872 {
5873 .hook = selinux_ipv6_forward,
5874 .owner = THIS_MODULE,
Alban Crequy2597a832012-05-14 03:56:39 +00005875 .pf = NFPROTO_IPV6,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005876 .hooknum = NF_INET_FORWARD,
5877 .priority = NF_IP6_PRI_SELINUX_FIRST,
5878 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005879};
5880
5881#endif /* IPV6 */
5882
5883static int __init selinux_nf_ip_init(void)
5884{
5885 int err = 0;
5886
5887 if (!selinux_enabled)
5888 goto out;
Eric Parisfadcdb42007-02-22 18:11:31 -05005889
5890 printk(KERN_DEBUG "SELinux: Registering netfilter hooks\n");
5891
Alexey Dobriyan6c5a9d22008-07-26 17:48:15 -07005892 err = nf_register_hooks(selinux_ipv4_ops, ARRAY_SIZE(selinux_ipv4_ops));
5893 if (err)
5894 panic("SELinux: nf_register_hooks for IPv4: error %d\n", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005895
5896#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Alexey Dobriyan6c5a9d22008-07-26 17:48:15 -07005897 err = nf_register_hooks(selinux_ipv6_ops, ARRAY_SIZE(selinux_ipv6_ops));
5898 if (err)
5899 panic("SELinux: nf_register_hooks for IPv6: error %d\n", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005900#endif /* IPV6 */
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005901
Linus Torvalds1da177e2005-04-16 15:20:36 -07005902out:
5903 return err;
5904}
5905
5906__initcall(selinux_nf_ip_init);
5907
5908#ifdef CONFIG_SECURITY_SELINUX_DISABLE
5909static void selinux_nf_ip_exit(void)
5910{
Eric Parisfadcdb42007-02-22 18:11:31 -05005911 printk(KERN_DEBUG "SELinux: Unregistering netfilter hooks\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005912
Alexey Dobriyan6c5a9d22008-07-26 17:48:15 -07005913 nf_unregister_hooks(selinux_ipv4_ops, ARRAY_SIZE(selinux_ipv4_ops));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005914#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Alexey Dobriyan6c5a9d22008-07-26 17:48:15 -07005915 nf_unregister_hooks(selinux_ipv6_ops, ARRAY_SIZE(selinux_ipv6_ops));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005916#endif /* IPV6 */
5917}
5918#endif
5919
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08005920#else /* CONFIG_NETFILTER */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005921
5922#ifdef CONFIG_SECURITY_SELINUX_DISABLE
5923#define selinux_nf_ip_exit()
5924#endif
5925
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08005926#endif /* CONFIG_NETFILTER */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005927
5928#ifdef CONFIG_SECURITY_SELINUX_DISABLE
Eric Paris828dfe12008-04-17 13:17:49 -04005929static int selinux_disabled;
5930
Linus Torvalds1da177e2005-04-16 15:20:36 -07005931int selinux_disable(void)
5932{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005933 if (ss_initialized) {
5934 /* Not permitted after initial policy load. */
5935 return -EINVAL;
5936 }
5937
5938 if (selinux_disabled) {
5939 /* Only do this once. */
5940 return -EINVAL;
5941 }
5942
5943 printk(KERN_INFO "SELinux: Disabled at runtime.\n");
5944
5945 selinux_disabled = 1;
Stephen Smalley30d55282006-05-03 10:52:36 -04005946 selinux_enabled = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005947
wzt.wzt@gmail.com189b3b12010-02-23 23:15:28 +08005948 reset_security_ops();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005949
Eric Parisaf8ff042009-09-20 21:23:01 -04005950 /* Try to destroy the avc node cache */
5951 avc_disable();
5952
Linus Torvalds1da177e2005-04-16 15:20:36 -07005953 /* Unregister netfilter hooks. */
5954 selinux_nf_ip_exit();
5955
5956 /* Unregister selinuxfs. */
5957 exit_sel_fs();
5958
5959 return 0;
5960}
5961#endif