blob: 911b780fcf802c44368eb12a77bd5cf011db100c [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
Stephen Smalley5c73fce2013-07-23 17:38:41 -0400409 /*
410 * Special handling for rootfs. Is genfs but supports
411 * setting SELinux context on in-core inodes.
412 */
413 if (strncmp(sb->s_type->name, "rootfs", sizeof("rootfs")) == 0)
414 sbsec->flags |= SE_SBLABELSUPP;
415
Linus Torvalds1da177e2005-04-16 15:20:36 -0700416 /* Initialize the root inode. */
Eric Parisc9180a52007-11-30 13:00:35 -0500417 rc = inode_doinit_with_dentry(root_inode, root);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418
419 /* Initialize any other inodes associated with the superblock, e.g.
420 inodes created prior to initial policy load or inodes created
421 during get_sb by a pseudo filesystem that directly
422 populates itself. */
423 spin_lock(&sbsec->isec_lock);
424next_inode:
425 if (!list_empty(&sbsec->isec_head)) {
426 struct inode_security_struct *isec =
427 list_entry(sbsec->isec_head.next,
Eric Parisc9180a52007-11-30 13:00:35 -0500428 struct inode_security_struct, list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429 struct inode *inode = isec->inode;
430 spin_unlock(&sbsec->isec_lock);
431 inode = igrab(inode);
432 if (inode) {
Eric Parisc9180a52007-11-30 13:00:35 -0500433 if (!IS_PRIVATE(inode))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434 inode_doinit(inode);
435 iput(inode);
436 }
437 spin_lock(&sbsec->isec_lock);
438 list_del_init(&isec->list);
439 goto next_inode;
440 }
441 spin_unlock(&sbsec->isec_lock);
442out:
Eric Parisc9180a52007-11-30 13:00:35 -0500443 return rc;
444}
445
446/*
447 * This function should allow an FS to ask what it's mount security
448 * options were so it can use those later for submounts, displaying
449 * mount options, or whatever.
450 */
451static int selinux_get_mnt_opts(const struct super_block *sb,
Eric Parise0007522008-03-05 10:31:54 -0500452 struct security_mnt_opts *opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500453{
454 int rc = 0, i;
455 struct superblock_security_struct *sbsec = sb->s_security;
456 char *context = NULL;
457 u32 len;
458 char tmp;
459
Eric Parise0007522008-03-05 10:31:54 -0500460 security_init_mnt_opts(opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500461
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500462 if (!(sbsec->flags & SE_SBINITIALIZED))
Eric Parisc9180a52007-11-30 13:00:35 -0500463 return -EINVAL;
464
465 if (!ss_initialized)
466 return -EINVAL;
467
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500468 tmp = sbsec->flags & SE_MNTMASK;
Eric Parisc9180a52007-11-30 13:00:35 -0500469 /* count the number of mount options for this sb */
470 for (i = 0; i < 8; i++) {
471 if (tmp & 0x01)
Eric Parise0007522008-03-05 10:31:54 -0500472 opts->num_mnt_opts++;
Eric Parisc9180a52007-11-30 13:00:35 -0500473 tmp >>= 1;
474 }
David P. Quigley11689d42009-01-16 09:22:03 -0500475 /* Check if the Label support flag is set */
476 if (sbsec->flags & SE_SBLABELSUPP)
477 opts->num_mnt_opts++;
Eric Parisc9180a52007-11-30 13:00:35 -0500478
Eric Parise0007522008-03-05 10:31:54 -0500479 opts->mnt_opts = kcalloc(opts->num_mnt_opts, sizeof(char *), GFP_ATOMIC);
480 if (!opts->mnt_opts) {
Eric Parisc9180a52007-11-30 13:00:35 -0500481 rc = -ENOMEM;
482 goto out_free;
483 }
484
Eric Parise0007522008-03-05 10:31:54 -0500485 opts->mnt_opts_flags = kcalloc(opts->num_mnt_opts, sizeof(int), GFP_ATOMIC);
486 if (!opts->mnt_opts_flags) {
Eric Parisc9180a52007-11-30 13:00:35 -0500487 rc = -ENOMEM;
488 goto out_free;
489 }
490
491 i = 0;
492 if (sbsec->flags & FSCONTEXT_MNT) {
493 rc = security_sid_to_context(sbsec->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++] = FSCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500498 }
499 if (sbsec->flags & CONTEXT_MNT) {
500 rc = security_sid_to_context(sbsec->mntpoint_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++] = CONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500505 }
506 if (sbsec->flags & DEFCONTEXT_MNT) {
507 rc = security_sid_to_context(sbsec->def_sid, &context, &len);
508 if (rc)
509 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500510 opts->mnt_opts[i] = context;
511 opts->mnt_opts_flags[i++] = DEFCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500512 }
513 if (sbsec->flags & ROOTCONTEXT_MNT) {
514 struct inode *root = sbsec->sb->s_root->d_inode;
515 struct inode_security_struct *isec = root->i_security;
516
517 rc = security_sid_to_context(isec->sid, &context, &len);
518 if (rc)
519 goto out_free;
Eric Parise0007522008-03-05 10:31:54 -0500520 opts->mnt_opts[i] = context;
521 opts->mnt_opts_flags[i++] = ROOTCONTEXT_MNT;
Eric Parisc9180a52007-11-30 13:00:35 -0500522 }
David P. Quigley11689d42009-01-16 09:22:03 -0500523 if (sbsec->flags & SE_SBLABELSUPP) {
524 opts->mnt_opts[i] = NULL;
525 opts->mnt_opts_flags[i++] = SE_SBLABELSUPP;
526 }
Eric Parisc9180a52007-11-30 13:00:35 -0500527
Eric Parise0007522008-03-05 10:31:54 -0500528 BUG_ON(i != opts->num_mnt_opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500529
530 return 0;
531
532out_free:
Eric Parise0007522008-03-05 10:31:54 -0500533 security_free_mnt_opts(opts);
Eric Parisc9180a52007-11-30 13:00:35 -0500534 return rc;
535}
536
537static int bad_option(struct superblock_security_struct *sbsec, char flag,
538 u32 old_sid, u32 new_sid)
539{
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500540 char mnt_flags = sbsec->flags & SE_MNTMASK;
541
Eric Parisc9180a52007-11-30 13:00:35 -0500542 /* check if the old mount command had the same options */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500543 if (sbsec->flags & SE_SBINITIALIZED)
Eric Parisc9180a52007-11-30 13:00:35 -0500544 if (!(sbsec->flags & flag) ||
545 (old_sid != new_sid))
546 return 1;
547
548 /* check if we were passed the same options twice,
549 * aka someone passed context=a,context=b
550 */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500551 if (!(sbsec->flags & SE_SBINITIALIZED))
552 if (mnt_flags & flag)
Eric Parisc9180a52007-11-30 13:00:35 -0500553 return 1;
554 return 0;
555}
Eric Parise0007522008-03-05 10:31:54 -0500556
Eric Parisc9180a52007-11-30 13:00:35 -0500557/*
558 * Allow filesystems with binary mount data to explicitly set mount point
559 * labeling information.
560 */
Eric Parise0007522008-03-05 10:31:54 -0500561static int selinux_set_mnt_opts(struct super_block *sb,
562 struct security_mnt_opts *opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500563{
David Howells275bb412008-11-14 10:39:19 +1100564 const struct cred *cred = current_cred();
Eric Parisc9180a52007-11-30 13:00:35 -0500565 int rc = 0, i;
Eric Parisc9180a52007-11-30 13:00:35 -0500566 struct superblock_security_struct *sbsec = sb->s_security;
567 const char *name = sb->s_type->name;
James Morris089be432008-07-15 18:32:49 +1000568 struct inode *inode = sbsec->sb->s_root->d_inode;
569 struct inode_security_struct *root_isec = inode->i_security;
Eric Parisc9180a52007-11-30 13:00:35 -0500570 u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0;
571 u32 defcontext_sid = 0;
Eric Parise0007522008-03-05 10:31:54 -0500572 char **mount_options = opts->mnt_opts;
573 int *flags = opts->mnt_opts_flags;
574 int num_opts = opts->num_mnt_opts;
Eric Parisc9180a52007-11-30 13:00:35 -0500575
576 mutex_lock(&sbsec->lock);
577
578 if (!ss_initialized) {
579 if (!num_opts) {
580 /* Defer initialization until selinux_complete_init,
581 after the initial policy is loaded and the security
582 server is ready to handle calls. */
Eric Parisc9180a52007-11-30 13:00:35 -0500583 goto out;
584 }
585 rc = -EINVAL;
Eric Paris744ba352008-04-17 11:52:44 -0400586 printk(KERN_WARNING "SELinux: Unable to set superblock options "
587 "before the security server is initialized\n");
Eric Parisc9180a52007-11-30 13:00:35 -0500588 goto out;
589 }
590
591 /*
Eric Parise0007522008-03-05 10:31:54 -0500592 * Binary mount data FS will come through this function twice. Once
593 * from an explicit call and once from the generic calls from the vfs.
594 * Since the generic VFS calls will not contain any security mount data
595 * we need to skip the double mount verification.
596 *
597 * This does open a hole in which we will not notice if the first
598 * mount using this sb set explict options and a second mount using
599 * this sb does not set any security options. (The first options
600 * will be used for both mounts)
601 */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500602 if ((sbsec->flags & SE_SBINITIALIZED) && (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)
Eric Parise0007522008-03-05 10:31:54 -0500603 && (num_opts == 0))
Eric Parisf5269712008-05-14 11:27:45 -0400604 goto out;
Eric Parise0007522008-03-05 10:31:54 -0500605
606 /*
Eric Parisc9180a52007-11-30 13:00:35 -0500607 * parse the mount options, check if they are valid sids.
608 * also check if someone is trying to mount the same sb more
609 * than once with different security options.
610 */
611 for (i = 0; i < num_opts; i++) {
612 u32 sid;
David P. Quigley11689d42009-01-16 09:22:03 -0500613
614 if (flags[i] == SE_SBLABELSUPP)
615 continue;
Eric Parisc9180a52007-11-30 13:00:35 -0500616 rc = security_context_to_sid(mount_options[i],
617 strlen(mount_options[i]), &sid);
618 if (rc) {
619 printk(KERN_WARNING "SELinux: security_context_to_sid"
620 "(%s) failed for (dev %s, type %s) errno=%d\n",
621 mount_options[i], sb->s_id, name, rc);
622 goto out;
623 }
624 switch (flags[i]) {
625 case FSCONTEXT_MNT:
626 fscontext_sid = sid;
627
628 if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid,
629 fscontext_sid))
630 goto out_double_mount;
631
632 sbsec->flags |= FSCONTEXT_MNT;
633 break;
634 case CONTEXT_MNT:
635 context_sid = sid;
636
637 if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid,
638 context_sid))
639 goto out_double_mount;
640
641 sbsec->flags |= CONTEXT_MNT;
642 break;
643 case ROOTCONTEXT_MNT:
644 rootcontext_sid = sid;
645
646 if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid,
647 rootcontext_sid))
648 goto out_double_mount;
649
650 sbsec->flags |= ROOTCONTEXT_MNT;
651
652 break;
653 case DEFCONTEXT_MNT:
654 defcontext_sid = sid;
655
656 if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid,
657 defcontext_sid))
658 goto out_double_mount;
659
660 sbsec->flags |= DEFCONTEXT_MNT;
661
662 break;
663 default:
664 rc = -EINVAL;
665 goto out;
666 }
667 }
668
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500669 if (sbsec->flags & SE_SBINITIALIZED) {
Eric Parisc9180a52007-11-30 13:00:35 -0500670 /* previously mounted with options, but not on this attempt? */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500671 if ((sbsec->flags & SE_MNTMASK) && !num_opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500672 goto out_double_mount;
673 rc = 0;
674 goto out;
675 }
676
James Morris089be432008-07-15 18:32:49 +1000677 if (strcmp(sb->s_type->name, "proc") == 0)
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500678 sbsec->flags |= SE_SBPROC;
Eric Parisc9180a52007-11-30 13:00:35 -0500679
680 /* Determine the labeling behavior to use for this filesystem type. */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500681 rc = security_fs_use((sbsec->flags & SE_SBPROC) ? "proc" : sb->s_type->name, &sbsec->behavior, &sbsec->sid);
Eric Parisc9180a52007-11-30 13:00:35 -0500682 if (rc) {
683 printk(KERN_WARNING "%s: security_fs_use(%s) returned %d\n",
James Morris089be432008-07-15 18:32:49 +1000684 __func__, sb->s_type->name, rc);
Eric Parisc9180a52007-11-30 13:00:35 -0500685 goto out;
686 }
687
688 /* sets the context of the superblock for the fs being mounted. */
689 if (fscontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100690 rc = may_context_mount_sb_relabel(fscontext_sid, sbsec, cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500691 if (rc)
692 goto out;
693
694 sbsec->sid = fscontext_sid;
695 }
696
697 /*
698 * Switch to using mount point labeling behavior.
699 * sets the label used on all file below the mountpoint, and will set
700 * the superblock context if not already set.
701 */
702 if (context_sid) {
703 if (!fscontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100704 rc = may_context_mount_sb_relabel(context_sid, sbsec,
705 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500706 if (rc)
707 goto out;
708 sbsec->sid = context_sid;
709 } else {
David Howells275bb412008-11-14 10:39:19 +1100710 rc = may_context_mount_inode_relabel(context_sid, sbsec,
711 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500712 if (rc)
713 goto out;
714 }
715 if (!rootcontext_sid)
716 rootcontext_sid = context_sid;
717
718 sbsec->mntpoint_sid = context_sid;
719 sbsec->behavior = SECURITY_FS_USE_MNTPOINT;
720 }
721
722 if (rootcontext_sid) {
David Howells275bb412008-11-14 10:39:19 +1100723 rc = may_context_mount_inode_relabel(rootcontext_sid, sbsec,
724 cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500725 if (rc)
726 goto out;
727
728 root_isec->sid = rootcontext_sid;
729 root_isec->initialized = 1;
730 }
731
732 if (defcontext_sid) {
733 if (sbsec->behavior != SECURITY_FS_USE_XATTR) {
734 rc = -EINVAL;
735 printk(KERN_WARNING "SELinux: defcontext option is "
736 "invalid for this filesystem type\n");
737 goto out;
738 }
739
740 if (defcontext_sid != sbsec->def_sid) {
741 rc = may_context_mount_inode_relabel(defcontext_sid,
David Howells275bb412008-11-14 10:39:19 +1100742 sbsec, cred);
Eric Parisc9180a52007-11-30 13:00:35 -0500743 if (rc)
744 goto out;
745 }
746
747 sbsec->def_sid = defcontext_sid;
748 }
749
750 rc = sb_finish_set_opts(sb);
751out:
Eric Parisbc7e9822006-09-25 23:32:02 -0700752 mutex_unlock(&sbsec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700753 return rc;
Eric Parisc9180a52007-11-30 13:00:35 -0500754out_double_mount:
755 rc = -EINVAL;
756 printk(KERN_WARNING "SELinux: mount invalid. Same superblock, different "
757 "security settings for (dev %s, type %s)\n", sb->s_id, name);
758 goto out;
759}
760
Jeff Layton094f7b62013-04-01 08:14:24 -0400761static int selinux_cmp_sb_context(const struct super_block *oldsb,
762 const struct super_block *newsb)
763{
764 struct superblock_security_struct *old = oldsb->s_security;
765 struct superblock_security_struct *new = newsb->s_security;
766 char oldflags = old->flags & SE_MNTMASK;
767 char newflags = new->flags & SE_MNTMASK;
768
769 if (oldflags != newflags)
770 goto mismatch;
771 if ((oldflags & FSCONTEXT_MNT) && old->sid != new->sid)
772 goto mismatch;
773 if ((oldflags & CONTEXT_MNT) && old->mntpoint_sid != new->mntpoint_sid)
774 goto mismatch;
775 if ((oldflags & DEFCONTEXT_MNT) && old->def_sid != new->def_sid)
776 goto mismatch;
777 if (oldflags & ROOTCONTEXT_MNT) {
778 struct inode_security_struct *oldroot = oldsb->s_root->d_inode->i_security;
779 struct inode_security_struct *newroot = newsb->s_root->d_inode->i_security;
780 if (oldroot->sid != newroot->sid)
781 goto mismatch;
782 }
783 return 0;
784mismatch:
785 printk(KERN_WARNING "SELinux: mount invalid. Same superblock, "
786 "different security settings for (dev %s, "
787 "type %s)\n", newsb->s_id, newsb->s_type->name);
788 return -EBUSY;
789}
790
791static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
Eric Parisc9180a52007-11-30 13:00:35 -0500792 struct super_block *newsb)
793{
794 const struct superblock_security_struct *oldsbsec = oldsb->s_security;
795 struct superblock_security_struct *newsbsec = newsb->s_security;
796
797 int set_fscontext = (oldsbsec->flags & FSCONTEXT_MNT);
798 int set_context = (oldsbsec->flags & CONTEXT_MNT);
799 int set_rootcontext = (oldsbsec->flags & ROOTCONTEXT_MNT);
800
Eric Paris0f5e6422008-04-21 16:24:11 -0400801 /*
802 * if the parent was able to be mounted it clearly had no special lsm
Al Viroe8c26252010-03-23 06:36:54 -0400803 * mount options. thus we can safely deal with this superblock later
Eric Paris0f5e6422008-04-21 16:24:11 -0400804 */
Al Viroe8c26252010-03-23 06:36:54 -0400805 if (!ss_initialized)
Jeff Layton094f7b62013-04-01 08:14:24 -0400806 return 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500807
Eric Parisc9180a52007-11-30 13:00:35 -0500808 /* how can we clone if the old one wasn't set up?? */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500809 BUG_ON(!(oldsbsec->flags & SE_SBINITIALIZED));
Eric Parisc9180a52007-11-30 13:00:35 -0500810
Jeff Layton094f7b62013-04-01 08:14:24 -0400811 /* if fs is reusing a sb, make sure that the contexts match */
David P. Quigley0d90a7e2009-01-16 09:22:02 -0500812 if (newsbsec->flags & SE_SBINITIALIZED)
Jeff Layton094f7b62013-04-01 08:14:24 -0400813 return selinux_cmp_sb_context(oldsb, newsb);
Eric Paris5a552612008-04-09 14:08:35 -0400814
Eric Parisc9180a52007-11-30 13:00:35 -0500815 mutex_lock(&newsbsec->lock);
816
817 newsbsec->flags = oldsbsec->flags;
818
819 newsbsec->sid = oldsbsec->sid;
820 newsbsec->def_sid = oldsbsec->def_sid;
821 newsbsec->behavior = oldsbsec->behavior;
822
823 if (set_context) {
824 u32 sid = oldsbsec->mntpoint_sid;
825
826 if (!set_fscontext)
827 newsbsec->sid = sid;
828 if (!set_rootcontext) {
829 struct inode *newinode = newsb->s_root->d_inode;
830 struct inode_security_struct *newisec = newinode->i_security;
831 newisec->sid = sid;
832 }
833 newsbsec->mntpoint_sid = sid;
834 }
835 if (set_rootcontext) {
836 const struct inode *oldinode = oldsb->s_root->d_inode;
837 const struct inode_security_struct *oldisec = oldinode->i_security;
838 struct inode *newinode = newsb->s_root->d_inode;
839 struct inode_security_struct *newisec = newinode->i_security;
840
841 newisec->sid = oldisec->sid;
842 }
843
844 sb_finish_set_opts(newsb);
845 mutex_unlock(&newsbsec->lock);
Jeff Layton094f7b62013-04-01 08:14:24 -0400846 return 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500847}
848
Adrian Bunk2e1479d2008-03-17 22:29:23 +0200849static int selinux_parse_opts_str(char *options,
850 struct security_mnt_opts *opts)
Eric Parisc9180a52007-11-30 13:00:35 -0500851{
Eric Parise0007522008-03-05 10:31:54 -0500852 char *p;
Eric Parisc9180a52007-11-30 13:00:35 -0500853 char *context = NULL, *defcontext = NULL;
854 char *fscontext = NULL, *rootcontext = NULL;
Eric Parise0007522008-03-05 10:31:54 -0500855 int rc, num_mnt_opts = 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500856
Eric Parise0007522008-03-05 10:31:54 -0500857 opts->num_mnt_opts = 0;
Eric Parisc9180a52007-11-30 13:00:35 -0500858
859 /* Standard string-based options. */
860 while ((p = strsep(&options, "|")) != NULL) {
861 int token;
862 substring_t args[MAX_OPT_ARGS];
863
864 if (!*p)
865 continue;
866
867 token = match_token(p, tokens, args);
868
869 switch (token) {
870 case Opt_context:
871 if (context || defcontext) {
872 rc = -EINVAL;
873 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
874 goto out_err;
875 }
876 context = match_strdup(&args[0]);
877 if (!context) {
878 rc = -ENOMEM;
879 goto out_err;
880 }
881 break;
882
883 case Opt_fscontext:
884 if (fscontext) {
885 rc = -EINVAL;
886 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
887 goto out_err;
888 }
889 fscontext = match_strdup(&args[0]);
890 if (!fscontext) {
891 rc = -ENOMEM;
892 goto out_err;
893 }
894 break;
895
896 case Opt_rootcontext:
897 if (rootcontext) {
898 rc = -EINVAL;
899 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
900 goto out_err;
901 }
902 rootcontext = match_strdup(&args[0]);
903 if (!rootcontext) {
904 rc = -ENOMEM;
905 goto out_err;
906 }
907 break;
908
909 case Opt_defcontext:
910 if (context || defcontext) {
911 rc = -EINVAL;
912 printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
913 goto out_err;
914 }
915 defcontext = match_strdup(&args[0]);
916 if (!defcontext) {
917 rc = -ENOMEM;
918 goto out_err;
919 }
920 break;
David P. Quigley11689d42009-01-16 09:22:03 -0500921 case Opt_labelsupport:
922 break;
Eric Parisc9180a52007-11-30 13:00:35 -0500923 default:
924 rc = -EINVAL;
925 printk(KERN_WARNING "SELinux: unknown mount option\n");
926 goto out_err;
927
928 }
929 }
930
Eric Parise0007522008-03-05 10:31:54 -0500931 rc = -ENOMEM;
932 opts->mnt_opts = kcalloc(NUM_SEL_MNT_OPTS, sizeof(char *), GFP_ATOMIC);
933 if (!opts->mnt_opts)
934 goto out_err;
935
936 opts->mnt_opts_flags = kcalloc(NUM_SEL_MNT_OPTS, sizeof(int), GFP_ATOMIC);
937 if (!opts->mnt_opts_flags) {
938 kfree(opts->mnt_opts);
939 goto out_err;
Eric Parisc9180a52007-11-30 13:00:35 -0500940 }
941
Eric Parise0007522008-03-05 10:31:54 -0500942 if (fscontext) {
943 opts->mnt_opts[num_mnt_opts] = fscontext;
944 opts->mnt_opts_flags[num_mnt_opts++] = FSCONTEXT_MNT;
945 }
946 if (context) {
947 opts->mnt_opts[num_mnt_opts] = context;
948 opts->mnt_opts_flags[num_mnt_opts++] = CONTEXT_MNT;
949 }
950 if (rootcontext) {
951 opts->mnt_opts[num_mnt_opts] = rootcontext;
952 opts->mnt_opts_flags[num_mnt_opts++] = ROOTCONTEXT_MNT;
953 }
954 if (defcontext) {
955 opts->mnt_opts[num_mnt_opts] = defcontext;
956 opts->mnt_opts_flags[num_mnt_opts++] = DEFCONTEXT_MNT;
957 }
958
959 opts->num_mnt_opts = num_mnt_opts;
960 return 0;
961
Eric Parisc9180a52007-11-30 13:00:35 -0500962out_err:
963 kfree(context);
964 kfree(defcontext);
965 kfree(fscontext);
966 kfree(rootcontext);
967 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700968}
Eric Parise0007522008-03-05 10:31:54 -0500969/*
970 * string mount options parsing and call set the sbsec
971 */
972static int superblock_doinit(struct super_block *sb, void *data)
973{
974 int rc = 0;
975 char *options = data;
976 struct security_mnt_opts opts;
977
978 security_init_mnt_opts(&opts);
979
980 if (!data)
981 goto out;
982
983 BUG_ON(sb->s_type->fs_flags & FS_BINARY_MOUNTDATA);
984
985 rc = selinux_parse_opts_str(options, &opts);
986 if (rc)
987 goto out_err;
988
989out:
990 rc = selinux_set_mnt_opts(sb, &opts);
991
992out_err:
993 security_free_mnt_opts(&opts);
994 return rc;
995}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700996
Adrian Bunk3583a712008-07-22 20:21:23 +0300997static void selinux_write_opts(struct seq_file *m,
998 struct security_mnt_opts *opts)
Eric Paris2069f452008-07-04 09:47:13 +1000999{
1000 int i;
1001 char *prefix;
1002
1003 for (i = 0; i < opts->num_mnt_opts; i++) {
David P. Quigley11689d42009-01-16 09:22:03 -05001004 char *has_comma;
1005
1006 if (opts->mnt_opts[i])
1007 has_comma = strchr(opts->mnt_opts[i], ',');
1008 else
1009 has_comma = NULL;
Eric Paris2069f452008-07-04 09:47:13 +10001010
1011 switch (opts->mnt_opts_flags[i]) {
1012 case CONTEXT_MNT:
1013 prefix = CONTEXT_STR;
1014 break;
1015 case FSCONTEXT_MNT:
1016 prefix = FSCONTEXT_STR;
1017 break;
1018 case ROOTCONTEXT_MNT:
1019 prefix = ROOTCONTEXT_STR;
1020 break;
1021 case DEFCONTEXT_MNT:
1022 prefix = DEFCONTEXT_STR;
1023 break;
David P. Quigley11689d42009-01-16 09:22:03 -05001024 case SE_SBLABELSUPP:
1025 seq_putc(m, ',');
1026 seq_puts(m, LABELSUPP_STR);
1027 continue;
Eric Paris2069f452008-07-04 09:47:13 +10001028 default:
1029 BUG();
Eric Parisa35c6c832011-04-20 10:21:28 -04001030 return;
Eric Paris2069f452008-07-04 09:47:13 +10001031 };
1032 /* we need a comma before each option */
1033 seq_putc(m, ',');
1034 seq_puts(m, prefix);
1035 if (has_comma)
1036 seq_putc(m, '\"');
1037 seq_puts(m, opts->mnt_opts[i]);
1038 if (has_comma)
1039 seq_putc(m, '\"');
1040 }
1041}
1042
1043static int selinux_sb_show_options(struct seq_file *m, struct super_block *sb)
1044{
1045 struct security_mnt_opts opts;
1046 int rc;
1047
1048 rc = selinux_get_mnt_opts(sb, &opts);
Eric Paris383795c2008-07-29 17:07:26 -04001049 if (rc) {
1050 /* before policy load we may get EINVAL, don't show anything */
1051 if (rc == -EINVAL)
1052 rc = 0;
Eric Paris2069f452008-07-04 09:47:13 +10001053 return rc;
Eric Paris383795c2008-07-29 17:07:26 -04001054 }
Eric Paris2069f452008-07-04 09:47:13 +10001055
1056 selinux_write_opts(m, &opts);
1057
1058 security_free_mnt_opts(&opts);
1059
1060 return rc;
1061}
1062
Linus Torvalds1da177e2005-04-16 15:20:36 -07001063static inline u16 inode_mode_to_security_class(umode_t mode)
1064{
1065 switch (mode & S_IFMT) {
1066 case S_IFSOCK:
1067 return SECCLASS_SOCK_FILE;
1068 case S_IFLNK:
1069 return SECCLASS_LNK_FILE;
1070 case S_IFREG:
1071 return SECCLASS_FILE;
1072 case S_IFBLK:
1073 return SECCLASS_BLK_FILE;
1074 case S_IFDIR:
1075 return SECCLASS_DIR;
1076 case S_IFCHR:
1077 return SECCLASS_CHR_FILE;
1078 case S_IFIFO:
1079 return SECCLASS_FIFO_FILE;
1080
1081 }
1082
1083 return SECCLASS_FILE;
1084}
1085
James Morris13402582005-09-30 14:24:34 -04001086static inline int default_protocol_stream(int protocol)
1087{
1088 return (protocol == IPPROTO_IP || protocol == IPPROTO_TCP);
1089}
1090
1091static inline int default_protocol_dgram(int protocol)
1092{
1093 return (protocol == IPPROTO_IP || protocol == IPPROTO_UDP);
1094}
1095
Linus Torvalds1da177e2005-04-16 15:20:36 -07001096static inline u16 socket_type_to_security_class(int family, int type, int protocol)
1097{
1098 switch (family) {
1099 case PF_UNIX:
1100 switch (type) {
1101 case SOCK_STREAM:
1102 case SOCK_SEQPACKET:
1103 return SECCLASS_UNIX_STREAM_SOCKET;
1104 case SOCK_DGRAM:
1105 return SECCLASS_UNIX_DGRAM_SOCKET;
1106 }
1107 break;
1108 case PF_INET:
1109 case PF_INET6:
1110 switch (type) {
1111 case SOCK_STREAM:
James Morris13402582005-09-30 14:24:34 -04001112 if (default_protocol_stream(protocol))
1113 return SECCLASS_TCP_SOCKET;
1114 else
1115 return SECCLASS_RAWIP_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001116 case SOCK_DGRAM:
James Morris13402582005-09-30 14:24:34 -04001117 if (default_protocol_dgram(protocol))
1118 return SECCLASS_UDP_SOCKET;
1119 else
1120 return SECCLASS_RAWIP_SOCKET;
James Morris2ee92d42006-11-13 16:09:01 -08001121 case SOCK_DCCP:
1122 return SECCLASS_DCCP_SOCKET;
James Morris13402582005-09-30 14:24:34 -04001123 default:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001124 return SECCLASS_RAWIP_SOCKET;
1125 }
1126 break;
1127 case PF_NETLINK:
1128 switch (protocol) {
1129 case NETLINK_ROUTE:
1130 return SECCLASS_NETLINK_ROUTE_SOCKET;
1131 case NETLINK_FIREWALL:
1132 return SECCLASS_NETLINK_FIREWALL_SOCKET;
Pavel Emelyanov7f1fb602011-12-06 07:56:43 +00001133 case NETLINK_SOCK_DIAG:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001134 return SECCLASS_NETLINK_TCPDIAG_SOCKET;
1135 case NETLINK_NFLOG:
1136 return SECCLASS_NETLINK_NFLOG_SOCKET;
1137 case NETLINK_XFRM:
1138 return SECCLASS_NETLINK_XFRM_SOCKET;
1139 case NETLINK_SELINUX:
1140 return SECCLASS_NETLINK_SELINUX_SOCKET;
1141 case NETLINK_AUDIT:
1142 return SECCLASS_NETLINK_AUDIT_SOCKET;
1143 case NETLINK_IP6_FW:
1144 return SECCLASS_NETLINK_IP6FW_SOCKET;
1145 case NETLINK_DNRTMSG:
1146 return SECCLASS_NETLINK_DNRT_SOCKET;
James Morris0c9b7942005-04-16 15:24:13 -07001147 case NETLINK_KOBJECT_UEVENT:
1148 return SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001149 default:
1150 return SECCLASS_NETLINK_SOCKET;
1151 }
1152 case PF_PACKET:
1153 return SECCLASS_PACKET_SOCKET;
1154 case PF_KEY:
1155 return SECCLASS_KEY_SOCKET;
Christopher J. PeBenito3e3ff152006-06-09 00:25:03 -07001156 case PF_APPLETALK:
1157 return SECCLASS_APPLETALK_SOCKET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001158 }
1159
1160 return SECCLASS_SOCKET;
1161}
1162
1163#ifdef CONFIG_PROC_FS
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001164static int selinux_proc_get_sid(struct dentry *dentry,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001165 u16 tclass,
1166 u32 *sid)
1167{
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001168 int rc;
1169 char *buffer, *path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001170
Eric Paris828dfe12008-04-17 13:17:49 -04001171 buffer = (char *)__get_free_page(GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001172 if (!buffer)
1173 return -ENOMEM;
1174
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001175 path = dentry_path_raw(dentry, buffer, PAGE_SIZE);
1176 if (IS_ERR(path))
1177 rc = PTR_ERR(path);
1178 else {
1179 /* each process gets a /proc/PID/ entry. Strip off the
1180 * PID part to get a valid selinux labeling.
1181 * e.g. /proc/1/net/rpc/nfs -> /net/rpc/nfs */
1182 while (path[1] >= '0' && path[1] <= '9') {
1183 path[1] = '/';
1184 path++;
1185 }
1186 rc = security_genfs_sid("proc", path, tclass, sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001187 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188 free_page((unsigned long)buffer);
1189 return rc;
1190}
1191#else
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001192static int selinux_proc_get_sid(struct dentry *dentry,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001193 u16 tclass,
1194 u32 *sid)
1195{
1196 return -EINVAL;
1197}
1198#endif
1199
1200/* The inode's security attributes must be initialized before first use. */
1201static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry)
1202{
1203 struct superblock_security_struct *sbsec = NULL;
1204 struct inode_security_struct *isec = inode->i_security;
1205 u32 sid;
1206 struct dentry *dentry;
1207#define INITCONTEXTLEN 255
1208 char *context = NULL;
1209 unsigned len = 0;
1210 int rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001211
1212 if (isec->initialized)
1213 goto out;
1214
Eric Paris23970742006-09-25 23:32:01 -07001215 mutex_lock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001216 if (isec->initialized)
Eric Paris23970742006-09-25 23:32:01 -07001217 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001218
1219 sbsec = inode->i_sb->s_security;
David P. Quigley0d90a7e2009-01-16 09:22:02 -05001220 if (!(sbsec->flags & SE_SBINITIALIZED)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001221 /* Defer initialization until selinux_complete_init,
1222 after the initial policy is loaded and the security
1223 server is ready to handle calls. */
1224 spin_lock(&sbsec->isec_lock);
1225 if (list_empty(&isec->list))
1226 list_add(&isec->list, &sbsec->isec_head);
1227 spin_unlock(&sbsec->isec_lock);
Eric Paris23970742006-09-25 23:32:01 -07001228 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001229 }
1230
1231 switch (sbsec->behavior) {
1232 case SECURITY_FS_USE_XATTR:
1233 if (!inode->i_op->getxattr) {
1234 isec->sid = sbsec->def_sid;
1235 break;
1236 }
1237
1238 /* Need a dentry, since the xattr API requires one.
1239 Life would be simpler if we could just pass the inode. */
1240 if (opt_dentry) {
1241 /* Called from d_instantiate or d_splice_alias. */
1242 dentry = dget(opt_dentry);
1243 } else {
1244 /* Called from selinux_complete_init, try to find a dentry. */
1245 dentry = d_find_alias(inode);
1246 }
1247 if (!dentry) {
Eric Parisdf7f54c2009-03-09 14:35:58 -04001248 /*
1249 * this is can be hit on boot when a file is accessed
1250 * before the policy is loaded. When we load policy we
1251 * may find inodes that have no dentry on the
1252 * sbsec->isec_head list. No reason to complain as these
1253 * will get fixed up the next time we go through
1254 * inode_doinit with a dentry, before these inodes could
1255 * be used again by userspace.
1256 */
Eric Paris23970742006-09-25 23:32:01 -07001257 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001258 }
1259
1260 len = INITCONTEXTLEN;
Eric Paris4cb912f2009-02-12 14:50:05 -05001261 context = kmalloc(len+1, GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001262 if (!context) {
1263 rc = -ENOMEM;
1264 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001265 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001266 }
Eric Paris4cb912f2009-02-12 14:50:05 -05001267 context[len] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001268 rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX,
1269 context, len);
1270 if (rc == -ERANGE) {
James Morris314dabb2009-08-10 22:00:13 +10001271 kfree(context);
1272
Linus Torvalds1da177e2005-04-16 15:20:36 -07001273 /* Need a larger buffer. Query for the right size. */
1274 rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX,
1275 NULL, 0);
1276 if (rc < 0) {
1277 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001278 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001279 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001280 len = rc;
Eric Paris4cb912f2009-02-12 14:50:05 -05001281 context = kmalloc(len+1, GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001282 if (!context) {
1283 rc = -ENOMEM;
1284 dput(dentry);
Eric Paris23970742006-09-25 23:32:01 -07001285 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001286 }
Eric Paris4cb912f2009-02-12 14:50:05 -05001287 context[len] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001288 rc = inode->i_op->getxattr(dentry,
1289 XATTR_NAME_SELINUX,
1290 context, len);
1291 }
1292 dput(dentry);
1293 if (rc < 0) {
1294 if (rc != -ENODATA) {
Eric Paris744ba352008-04-17 11:52:44 -04001295 printk(KERN_WARNING "SELinux: %s: getxattr returned "
Harvey Harrisondd6f9532008-03-06 10:03:59 +11001296 "%d for dev=%s ino=%ld\n", __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001297 -rc, inode->i_sb->s_id, inode->i_ino);
1298 kfree(context);
Eric Paris23970742006-09-25 23:32:01 -07001299 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001300 }
1301 /* Map ENODATA to the default file SID */
1302 sid = sbsec->def_sid;
1303 rc = 0;
1304 } else {
James Morrisf5c1d5b2005-07-28 01:07:37 -07001305 rc = security_context_to_sid_default(context, rc, &sid,
Stephen Smalley869ab512008-04-04 08:46:05 -04001306 sbsec->def_sid,
1307 GFP_NOFS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001308 if (rc) {
Eric Paris4ba0a8a2009-02-12 15:01:10 -05001309 char *dev = inode->i_sb->s_id;
1310 unsigned long ino = inode->i_ino;
1311
1312 if (rc == -EINVAL) {
1313 if (printk_ratelimit())
1314 printk(KERN_NOTICE "SELinux: inode=%lu on dev=%s was found to have an invalid "
1315 "context=%s. This indicates you may need to relabel the inode or the "
1316 "filesystem in question.\n", ino, dev, context);
1317 } else {
1318 printk(KERN_WARNING "SELinux: %s: context_to_sid(%s) "
1319 "returned %d for dev=%s ino=%ld\n",
1320 __func__, context, -rc, dev, ino);
1321 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001322 kfree(context);
1323 /* Leave with the unlabeled SID */
1324 rc = 0;
1325 break;
1326 }
1327 }
1328 kfree(context);
1329 isec->sid = sid;
1330 break;
1331 case SECURITY_FS_USE_TASK:
1332 isec->sid = isec->task_sid;
1333 break;
1334 case SECURITY_FS_USE_TRANS:
1335 /* Default to the fs SID. */
1336 isec->sid = sbsec->sid;
1337
1338 /* Try to obtain a transition SID. */
1339 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Eric Paris652bb9b2011-02-01 11:05:40 -05001340 rc = security_transition_sid(isec->task_sid, sbsec->sid,
1341 isec->sclass, NULL, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001342 if (rc)
Eric Paris23970742006-09-25 23:32:01 -07001343 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001344 isec->sid = sid;
1345 break;
Eric Parisc312feb2006-07-10 04:43:53 -07001346 case SECURITY_FS_USE_MNTPOINT:
1347 isec->sid = sbsec->mntpoint_sid;
1348 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001349 default:
Eric Parisc312feb2006-07-10 04:43:53 -07001350 /* Default to the fs superblock SID. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001351 isec->sid = sbsec->sid;
1352
David P. Quigley0d90a7e2009-01-16 09:22:02 -05001353 if ((sbsec->flags & SE_SBPROC) && !S_ISLNK(inode->i_mode)) {
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001354 if (opt_dentry) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001355 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Lucian Adrian Grijincu8e6c9692011-02-01 18:42:22 +02001356 rc = selinux_proc_get_sid(opt_dentry,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001357 isec->sclass,
1358 &sid);
1359 if (rc)
Eric Paris23970742006-09-25 23:32:01 -07001360 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001361 isec->sid = sid;
1362 }
1363 }
1364 break;
1365 }
1366
1367 isec->initialized = 1;
1368
Eric Paris23970742006-09-25 23:32:01 -07001369out_unlock:
1370 mutex_unlock(&isec->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001371out:
1372 if (isec->sclass == SECCLASS_FILE)
1373 isec->sclass = inode_mode_to_security_class(inode->i_mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001374 return rc;
1375}
1376
1377/* Convert a Linux signal to an access vector. */
1378static inline u32 signal_to_av(int sig)
1379{
1380 u32 perm = 0;
1381
1382 switch (sig) {
1383 case SIGCHLD:
1384 /* Commonly granted from child to parent. */
1385 perm = PROCESS__SIGCHLD;
1386 break;
1387 case SIGKILL:
1388 /* Cannot be caught or ignored */
1389 perm = PROCESS__SIGKILL;
1390 break;
1391 case SIGSTOP:
1392 /* Cannot be caught or ignored */
1393 perm = PROCESS__SIGSTOP;
1394 break;
1395 default:
1396 /* All other signals. */
1397 perm = PROCESS__SIGNAL;
1398 break;
1399 }
1400
1401 return perm;
1402}
1403
David Howells275bb412008-11-14 10:39:19 +11001404/*
David Howellsd84f4f92008-11-14 10:39:23 +11001405 * Check permission between a pair of credentials
1406 * fork check, ptrace check, etc.
1407 */
1408static int cred_has_perm(const struct cred *actor,
1409 const struct cred *target,
1410 u32 perms)
1411{
1412 u32 asid = cred_sid(actor), tsid = cred_sid(target);
1413
1414 return avc_has_perm(asid, tsid, SECCLASS_PROCESS, perms, NULL);
1415}
1416
1417/*
David Howells88e67f32008-11-14 10:39:21 +11001418 * Check permission between a pair of tasks, e.g. signal checks,
David Howells275bb412008-11-14 10:39:19 +11001419 * fork check, ptrace check, etc.
1420 * tsk1 is the actor and tsk2 is the target
David Howells3b11a1d2008-11-14 10:39:26 +11001421 * - this uses the default subjective creds of tsk1
David Howells275bb412008-11-14 10:39:19 +11001422 */
1423static int task_has_perm(const struct task_struct *tsk1,
1424 const struct task_struct *tsk2,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001425 u32 perms)
1426{
David Howells275bb412008-11-14 10:39:19 +11001427 const struct task_security_struct *__tsec1, *__tsec2;
1428 u32 sid1, sid2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001429
David Howells275bb412008-11-14 10:39:19 +11001430 rcu_read_lock();
1431 __tsec1 = __task_cred(tsk1)->security; sid1 = __tsec1->sid;
1432 __tsec2 = __task_cred(tsk2)->security; sid2 = __tsec2->sid;
1433 rcu_read_unlock();
1434 return avc_has_perm(sid1, sid2, SECCLASS_PROCESS, perms, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001435}
1436
David Howells3b11a1d2008-11-14 10:39:26 +11001437/*
1438 * Check permission between current and another task, e.g. signal checks,
1439 * fork check, ptrace check, etc.
1440 * current is the actor and tsk2 is the target
1441 * - this uses current's subjective creds
1442 */
1443static int current_has_perm(const struct task_struct *tsk,
1444 u32 perms)
1445{
1446 u32 sid, tsid;
1447
1448 sid = current_sid();
1449 tsid = task_sid(tsk);
1450 return avc_has_perm(sid, tsid, SECCLASS_PROCESS, perms, NULL);
1451}
1452
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001453#if CAP_LAST_CAP > 63
1454#error Fix SELinux to handle capabilities > 63.
1455#endif
1456
Linus Torvalds1da177e2005-04-16 15:20:36 -07001457/* Check whether a task is allowed to use a capability. */
Eric Paris6a9de492012-01-03 12:25:14 -05001458static int cred_has_capability(const struct cred *cred,
Eric Paris06112162008-11-11 22:02:50 +11001459 int cap, int audit)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001460{
Thomas Liu2bf49692009-07-14 12:14:09 -04001461 struct common_audit_data ad;
Eric Paris06112162008-11-11 22:02:50 +11001462 struct av_decision avd;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001463 u16 sclass;
David Howells3699c532009-01-06 22:27:01 +00001464 u32 sid = cred_sid(cred);
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001465 u32 av = CAP_TO_MASK(cap);
Eric Paris06112162008-11-11 22:02:50 +11001466 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001467
Eric Paris50c205f2012-04-04 15:01:43 -04001468 ad.type = LSM_AUDIT_DATA_CAP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001469 ad.u.cap = cap;
1470
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001471 switch (CAP_TO_INDEX(cap)) {
1472 case 0:
1473 sclass = SECCLASS_CAPABILITY;
1474 break;
1475 case 1:
1476 sclass = SECCLASS_CAPABILITY2;
1477 break;
1478 default:
1479 printk(KERN_ERR
1480 "SELinux: out of range capability %d\n", cap);
1481 BUG();
Eric Parisa35c6c832011-04-20 10:21:28 -04001482 return -EINVAL;
Stephen Smalleyb68e4182008-02-07 11:21:04 -05001483 }
Eric Paris06112162008-11-11 22:02:50 +11001484
David Howells275bb412008-11-14 10:39:19 +11001485 rc = avc_has_perm_noaudit(sid, sid, sclass, av, 0, &avd);
Eric Paris9ade0cf2011-04-25 16:26:29 -04001486 if (audit == SECURITY_CAP_AUDIT) {
1487 int rc2 = avc_audit(sid, sid, sclass, av, &avd, rc, &ad, 0);
1488 if (rc2)
1489 return rc2;
1490 }
Eric Paris06112162008-11-11 22:02:50 +11001491 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001492}
1493
1494/* Check whether a task is allowed to use a system operation. */
1495static int task_has_system(struct task_struct *tsk,
1496 u32 perms)
1497{
David Howells275bb412008-11-14 10:39:19 +11001498 u32 sid = task_sid(tsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001499
David Howells275bb412008-11-14 10:39:19 +11001500 return avc_has_perm(sid, SECINITSID_KERNEL,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001501 SECCLASS_SYSTEM, perms, NULL);
1502}
1503
1504/* Check whether a task has a particular permission to an inode.
1505 The 'adp' parameter is optional and allows other audit
1506 data to be passed (e.g. the dentry). */
David Howells88e67f32008-11-14 10:39:21 +11001507static int inode_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001508 struct inode *inode,
1509 u32 perms,
Eric Paris9ade0cf2011-04-25 16:26:29 -04001510 struct common_audit_data *adp,
1511 unsigned flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001512{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001513 struct inode_security_struct *isec;
David Howells275bb412008-11-14 10:39:19 +11001514 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001515
David Howellse0e81732009-09-02 09:13:40 +01001516 validate_creds(cred);
1517
Eric Paris828dfe12008-04-17 13:17:49 -04001518 if (unlikely(IS_PRIVATE(inode)))
Stephen Smalleybbaca6c2007-02-14 00:34:16 -08001519 return 0;
1520
David Howells88e67f32008-11-14 10:39:21 +11001521 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001522 isec = inode->i_security;
1523
Eric Paris9ade0cf2011-04-25 16:26:29 -04001524 return avc_has_perm_flags(sid, isec->sid, isec->sclass, perms, adp, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001525}
1526
1527/* Same as inode_has_perm, but pass explicit audit data containing
1528 the dentry to help the auditing code to more easily generate the
1529 pathname if needed. */
David Howells88e67f32008-11-14 10:39:21 +11001530static inline int dentry_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001531 struct dentry *dentry,
1532 u32 av)
1533{
1534 struct inode *inode = dentry->d_inode;
Thomas Liu2bf49692009-07-14 12:14:09 -04001535 struct common_audit_data ad;
David Howells88e67f32008-11-14 10:39:21 +11001536
Eric Paris50c205f2012-04-04 15:01:43 -04001537 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Paris2875fa02011-04-28 16:04:24 -04001538 ad.u.dentry = dentry;
1539 return inode_has_perm(cred, inode, av, &ad, 0);
1540}
1541
1542/* Same as inode_has_perm, but pass explicit audit data containing
1543 the path to help the auditing code to more easily generate the
1544 pathname if needed. */
1545static inline int path_has_perm(const struct cred *cred,
1546 struct path *path,
1547 u32 av)
1548{
1549 struct inode *inode = path->dentry->d_inode;
1550 struct common_audit_data ad;
1551
Eric Paris50c205f2012-04-04 15:01:43 -04001552 ad.type = LSM_AUDIT_DATA_PATH;
Eric Paris2875fa02011-04-28 16:04:24 -04001553 ad.u.path = *path;
Eric Paris9ade0cf2011-04-25 16:26:29 -04001554 return inode_has_perm(cred, inode, av, &ad, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001555}
1556
1557/* Check whether a task can use an open file descriptor to
1558 access an inode in a given way. Check access to the
1559 descriptor itself, and then use dentry_has_perm to
1560 check a particular permission to the file.
1561 Access to the descriptor is implicitly granted if it
1562 has the same SID as the process. If av is zero, then
1563 access to the file is not checked, e.g. for cases
1564 where only the descriptor is affected like seek. */
David Howells88e67f32008-11-14 10:39:21 +11001565static int file_has_perm(const struct cred *cred,
1566 struct file *file,
1567 u32 av)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001568{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001569 struct file_security_struct *fsec = file->f_security;
Al Viro496ad9a2013-01-23 17:07:38 -05001570 struct inode *inode = file_inode(file);
Thomas Liu2bf49692009-07-14 12:14:09 -04001571 struct common_audit_data ad;
David Howells88e67f32008-11-14 10:39:21 +11001572 u32 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001573 int rc;
1574
Eric Paris50c205f2012-04-04 15:01:43 -04001575 ad.type = LSM_AUDIT_DATA_PATH;
Eric Parisf48b7392011-04-25 12:54:27 -04001576 ad.u.path = file->f_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001577
David Howells275bb412008-11-14 10:39:19 +11001578 if (sid != fsec->sid) {
1579 rc = avc_has_perm(sid, fsec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001580 SECCLASS_FD,
1581 FD__USE,
1582 &ad);
1583 if (rc)
David Howells88e67f32008-11-14 10:39:21 +11001584 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001585 }
1586
1587 /* av is zero if only checking access to the descriptor. */
David Howells88e67f32008-11-14 10:39:21 +11001588 rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001589 if (av)
Eric Paris9ade0cf2011-04-25 16:26:29 -04001590 rc = inode_has_perm(cred, inode, av, &ad, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001591
David Howells88e67f32008-11-14 10:39:21 +11001592out:
1593 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001594}
1595
1596/* Check whether a task can create a file. */
1597static int may_create(struct inode *dir,
1598 struct dentry *dentry,
1599 u16 tclass)
1600{
Paul Moore5fb49872010-04-22 14:46:19 -04001601 const struct task_security_struct *tsec = current_security();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001602 struct inode_security_struct *dsec;
1603 struct superblock_security_struct *sbsec;
David Howells275bb412008-11-14 10:39:19 +11001604 u32 sid, newsid;
Thomas Liu2bf49692009-07-14 12:14:09 -04001605 struct common_audit_data ad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001606 int rc;
1607
Linus Torvalds1da177e2005-04-16 15:20:36 -07001608 dsec = dir->i_security;
1609 sbsec = dir->i_sb->s_security;
1610
David Howells275bb412008-11-14 10:39:19 +11001611 sid = tsec->sid;
1612 newsid = tsec->create_sid;
1613
Eric Paris50c205f2012-04-04 15:01:43 -04001614 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04001615 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001616
David Howells275bb412008-11-14 10:39:19 +11001617 rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001618 DIR__ADD_NAME | DIR__SEARCH,
1619 &ad);
1620 if (rc)
1621 return rc;
1622
David P. Quigleycd895962009-01-16 09:22:04 -05001623 if (!newsid || !(sbsec->flags & SE_SBLABELSUPP)) {
Eric Pariscb1e9222011-04-28 15:11:21 -04001624 rc = security_transition_sid(sid, dsec->sid, tclass,
1625 &dentry->d_name, &newsid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001626 if (rc)
1627 return rc;
1628 }
1629
David Howells275bb412008-11-14 10:39:19 +11001630 rc = avc_has_perm(sid, newsid, tclass, FILE__CREATE, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001631 if (rc)
1632 return rc;
1633
1634 return avc_has_perm(newsid, sbsec->sid,
1635 SECCLASS_FILESYSTEM,
1636 FILESYSTEM__ASSOCIATE, &ad);
1637}
1638
Michael LeMay4eb582c2006-06-26 00:24:57 -07001639/* Check whether a task can create a key. */
1640static int may_create_key(u32 ksid,
1641 struct task_struct *ctx)
1642{
David Howells275bb412008-11-14 10:39:19 +11001643 u32 sid = task_sid(ctx);
Michael LeMay4eb582c2006-06-26 00:24:57 -07001644
David Howells275bb412008-11-14 10:39:19 +11001645 return avc_has_perm(sid, ksid, SECCLASS_KEY, KEY__CREATE, NULL);
Michael LeMay4eb582c2006-06-26 00:24:57 -07001646}
1647
Eric Paris828dfe12008-04-17 13:17:49 -04001648#define MAY_LINK 0
1649#define MAY_UNLINK 1
1650#define MAY_RMDIR 2
Linus Torvalds1da177e2005-04-16 15:20:36 -07001651
1652/* Check whether a task can link, unlink, or rmdir a file/directory. */
1653static int may_link(struct inode *dir,
1654 struct dentry *dentry,
1655 int kind)
1656
1657{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001658 struct inode_security_struct *dsec, *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04001659 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11001660 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001661 u32 av;
1662 int rc;
1663
Linus Torvalds1da177e2005-04-16 15:20:36 -07001664 dsec = dir->i_security;
1665 isec = dentry->d_inode->i_security;
1666
Eric Paris50c205f2012-04-04 15:01:43 -04001667 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04001668 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001669
1670 av = DIR__SEARCH;
1671 av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME);
David Howells275bb412008-11-14 10:39:19 +11001672 rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001673 if (rc)
1674 return rc;
1675
1676 switch (kind) {
1677 case MAY_LINK:
1678 av = FILE__LINK;
1679 break;
1680 case MAY_UNLINK:
1681 av = FILE__UNLINK;
1682 break;
1683 case MAY_RMDIR:
1684 av = DIR__RMDIR;
1685 break;
1686 default:
Eric Paris744ba352008-04-17 11:52:44 -04001687 printk(KERN_WARNING "SELinux: %s: unrecognized kind %d\n",
1688 __func__, kind);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001689 return 0;
1690 }
1691
David Howells275bb412008-11-14 10:39:19 +11001692 rc = avc_has_perm(sid, isec->sid, isec->sclass, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001693 return rc;
1694}
1695
1696static inline int may_rename(struct inode *old_dir,
1697 struct dentry *old_dentry,
1698 struct inode *new_dir,
1699 struct dentry *new_dentry)
1700{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001701 struct inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04001702 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11001703 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001704 u32 av;
1705 int old_is_dir, new_is_dir;
1706 int rc;
1707
Linus Torvalds1da177e2005-04-16 15:20:36 -07001708 old_dsec = old_dir->i_security;
1709 old_isec = old_dentry->d_inode->i_security;
1710 old_is_dir = S_ISDIR(old_dentry->d_inode->i_mode);
1711 new_dsec = new_dir->i_security;
1712
Eric Paris50c205f2012-04-04 15:01:43 -04001713 ad.type = LSM_AUDIT_DATA_DENTRY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001714
Eric Parisa2694342011-04-25 13:10:27 -04001715 ad.u.dentry = old_dentry;
David Howells275bb412008-11-14 10:39:19 +11001716 rc = avc_has_perm(sid, old_dsec->sid, SECCLASS_DIR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001717 DIR__REMOVE_NAME | DIR__SEARCH, &ad);
1718 if (rc)
1719 return rc;
David Howells275bb412008-11-14 10:39:19 +11001720 rc = avc_has_perm(sid, old_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001721 old_isec->sclass, FILE__RENAME, &ad);
1722 if (rc)
1723 return rc;
1724 if (old_is_dir && new_dir != old_dir) {
David Howells275bb412008-11-14 10:39:19 +11001725 rc = avc_has_perm(sid, old_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001726 old_isec->sclass, DIR__REPARENT, &ad);
1727 if (rc)
1728 return rc;
1729 }
1730
Eric Parisa2694342011-04-25 13:10:27 -04001731 ad.u.dentry = new_dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001732 av = DIR__ADD_NAME | DIR__SEARCH;
1733 if (new_dentry->d_inode)
1734 av |= DIR__REMOVE_NAME;
David Howells275bb412008-11-14 10:39:19 +11001735 rc = avc_has_perm(sid, new_dsec->sid, SECCLASS_DIR, av, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001736 if (rc)
1737 return rc;
1738 if (new_dentry->d_inode) {
1739 new_isec = new_dentry->d_inode->i_security;
1740 new_is_dir = S_ISDIR(new_dentry->d_inode->i_mode);
David Howells275bb412008-11-14 10:39:19 +11001741 rc = avc_has_perm(sid, new_isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001742 new_isec->sclass,
1743 (new_is_dir ? DIR__RMDIR : FILE__UNLINK), &ad);
1744 if (rc)
1745 return rc;
1746 }
1747
1748 return 0;
1749}
1750
1751/* Check whether a task can perform a filesystem operation. */
David Howells88e67f32008-11-14 10:39:21 +11001752static int superblock_has_perm(const struct cred *cred,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001753 struct super_block *sb,
1754 u32 perms,
Thomas Liu2bf49692009-07-14 12:14:09 -04001755 struct common_audit_data *ad)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001756{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001757 struct superblock_security_struct *sbsec;
David Howells88e67f32008-11-14 10:39:21 +11001758 u32 sid = cred_sid(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001759
Linus Torvalds1da177e2005-04-16 15:20:36 -07001760 sbsec = sb->s_security;
David Howells275bb412008-11-14 10:39:19 +11001761 return avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM, perms, ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001762}
1763
1764/* Convert a Linux mode and permission mask to an access vector. */
1765static inline u32 file_mask_to_av(int mode, int mask)
1766{
1767 u32 av = 0;
1768
Al Virodba19c62011-07-25 20:49:29 -04001769 if (!S_ISDIR(mode)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001770 if (mask & MAY_EXEC)
1771 av |= FILE__EXECUTE;
1772 if (mask & MAY_READ)
1773 av |= FILE__READ;
1774
1775 if (mask & MAY_APPEND)
1776 av |= FILE__APPEND;
1777 else if (mask & MAY_WRITE)
1778 av |= FILE__WRITE;
1779
1780 } else {
1781 if (mask & MAY_EXEC)
1782 av |= DIR__SEARCH;
1783 if (mask & MAY_WRITE)
1784 av |= DIR__WRITE;
1785 if (mask & MAY_READ)
1786 av |= DIR__READ;
1787 }
1788
1789 return av;
1790}
1791
1792/* Convert a Linux file to an access vector. */
1793static inline u32 file_to_av(struct file *file)
1794{
1795 u32 av = 0;
1796
1797 if (file->f_mode & FMODE_READ)
1798 av |= FILE__READ;
1799 if (file->f_mode & FMODE_WRITE) {
1800 if (file->f_flags & O_APPEND)
1801 av |= FILE__APPEND;
1802 else
1803 av |= FILE__WRITE;
1804 }
Stephen Smalley0794c662008-03-17 08:55:18 -04001805 if (!av) {
1806 /*
1807 * Special file opened with flags 3 for ioctl-only use.
1808 */
1809 av = FILE__IOCTL;
1810 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001811
1812 return av;
1813}
1814
Eric Paris8b6a5a32008-10-29 17:06:46 -04001815/*
1816 * Convert a file to an access vector and include the correct open
1817 * open permission.
1818 */
1819static inline u32 open_file_to_av(struct file *file)
1820{
1821 u32 av = file_to_av(file);
1822
Eric Paris49b7b8d2010-07-23 11:44:09 -04001823 if (selinux_policycap_openperm)
1824 av |= FILE__OPEN;
1825
Eric Paris8b6a5a32008-10-29 17:06:46 -04001826 return av;
1827}
1828
Linus Torvalds1da177e2005-04-16 15:20:36 -07001829/* Hook functions begin here. */
1830
Ingo Molnar9e488582009-05-07 19:26:19 +10001831static int selinux_ptrace_access_check(struct task_struct *child,
David Howells5cd9c582008-08-14 11:37:28 +01001832 unsigned int mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001833{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001834 int rc;
1835
Ingo Molnar9e488582009-05-07 19:26:19 +10001836 rc = cap_ptrace_access_check(child, mode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001837 if (rc)
1838 return rc;
1839
Eric Paris69f594a2012-01-03 12:25:15 -05001840 if (mode & PTRACE_MODE_READ) {
David Howells275bb412008-11-14 10:39:19 +11001841 u32 sid = current_sid();
1842 u32 csid = task_sid(child);
1843 return avc_has_perm(sid, csid, SECCLASS_FILE, FILE__READ, NULL);
Stephen Smalley006ebb42008-05-19 08:32:49 -04001844 }
1845
David Howells3b11a1d2008-11-14 10:39:26 +11001846 return current_has_perm(child, PROCESS__PTRACE);
David Howells5cd9c582008-08-14 11:37:28 +01001847}
1848
1849static int selinux_ptrace_traceme(struct task_struct *parent)
1850{
1851 int rc;
1852
Eric Paris200ac532009-02-12 15:01:04 -05001853 rc = cap_ptrace_traceme(parent);
David Howells5cd9c582008-08-14 11:37:28 +01001854 if (rc)
1855 return rc;
1856
1857 return task_has_perm(parent, current, PROCESS__PTRACE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001858}
1859
1860static int selinux_capget(struct task_struct *target, kernel_cap_t *effective,
Eric Paris828dfe12008-04-17 13:17:49 -04001861 kernel_cap_t *inheritable, kernel_cap_t *permitted)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001862{
1863 int error;
1864
David Howells3b11a1d2008-11-14 10:39:26 +11001865 error = current_has_perm(target, PROCESS__GETCAP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001866 if (error)
1867 return error;
1868
Eric Paris200ac532009-02-12 15:01:04 -05001869 return cap_capget(target, effective, inheritable, permitted);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001870}
1871
David Howellsd84f4f92008-11-14 10:39:23 +11001872static int selinux_capset(struct cred *new, const struct cred *old,
1873 const kernel_cap_t *effective,
1874 const kernel_cap_t *inheritable,
1875 const kernel_cap_t *permitted)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001876{
1877 int error;
1878
Eric Paris200ac532009-02-12 15:01:04 -05001879 error = cap_capset(new, old,
David Howellsd84f4f92008-11-14 10:39:23 +11001880 effective, inheritable, permitted);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001881 if (error)
1882 return error;
1883
David Howellsd84f4f92008-11-14 10:39:23 +11001884 return cred_has_perm(old, new, PROCESS__SETCAP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001885}
1886
James Morris5626d3e2009-01-30 10:05:06 +11001887/*
1888 * (This comment used to live with the selinux_task_setuid hook,
1889 * which was removed).
1890 *
1891 * Since setuid only affects the current process, and since the SELinux
1892 * controls are not based on the Linux identity attributes, SELinux does not
1893 * need to control this operation. However, SELinux does control the use of
1894 * the CAP_SETUID and CAP_SETGID capabilities using the capable hook.
1895 */
1896
Eric Paris6a9de492012-01-03 12:25:14 -05001897static int selinux_capable(const struct cred *cred, struct user_namespace *ns,
1898 int cap, int audit)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001899{
1900 int rc;
1901
Eric Paris6a9de492012-01-03 12:25:14 -05001902 rc = cap_capable(cred, ns, cap, audit);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001903 if (rc)
1904 return rc;
1905
Eric Paris6a9de492012-01-03 12:25:14 -05001906 return cred_has_capability(cred, cap, audit);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001907}
1908
Linus Torvalds1da177e2005-04-16 15:20:36 -07001909static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb)
1910{
David Howells88e67f32008-11-14 10:39:21 +11001911 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001912 int rc = 0;
1913
1914 if (!sb)
1915 return 0;
1916
1917 switch (cmds) {
Eric Paris828dfe12008-04-17 13:17:49 -04001918 case Q_SYNC:
1919 case Q_QUOTAON:
1920 case Q_QUOTAOFF:
1921 case Q_SETINFO:
1922 case Q_SETQUOTA:
David Howells88e67f32008-11-14 10:39:21 +11001923 rc = superblock_has_perm(cred, sb, FILESYSTEM__QUOTAMOD, NULL);
Eric Paris828dfe12008-04-17 13:17:49 -04001924 break;
1925 case Q_GETFMT:
1926 case Q_GETINFO:
1927 case Q_GETQUOTA:
David Howells88e67f32008-11-14 10:39:21 +11001928 rc = superblock_has_perm(cred, sb, FILESYSTEM__QUOTAGET, NULL);
Eric Paris828dfe12008-04-17 13:17:49 -04001929 break;
1930 default:
1931 rc = 0; /* let the kernel handle invalid cmds */
1932 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001933 }
1934 return rc;
1935}
1936
1937static int selinux_quota_on(struct dentry *dentry)
1938{
David Howells88e67f32008-11-14 10:39:21 +11001939 const struct cred *cred = current_cred();
1940
Eric Paris2875fa02011-04-28 16:04:24 -04001941 return dentry_has_perm(cred, dentry, FILE__QUOTAON);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001942}
1943
Eric Paris12b30522010-11-15 18:36:29 -05001944static int selinux_syslog(int type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001945{
1946 int rc;
1947
Linus Torvalds1da177e2005-04-16 15:20:36 -07001948 switch (type) {
Kees Cookd78ca3c2010-02-03 15:37:13 -08001949 case SYSLOG_ACTION_READ_ALL: /* Read last kernel messages */
1950 case SYSLOG_ACTION_SIZE_BUFFER: /* Return size of the log buffer */
Eric Paris828dfe12008-04-17 13:17:49 -04001951 rc = task_has_system(current, SYSTEM__SYSLOG_READ);
1952 break;
Kees Cookd78ca3c2010-02-03 15:37:13 -08001953 case SYSLOG_ACTION_CONSOLE_OFF: /* Disable logging to console */
1954 case SYSLOG_ACTION_CONSOLE_ON: /* Enable logging to console */
1955 /* Set level of messages printed to console */
1956 case SYSLOG_ACTION_CONSOLE_LEVEL:
Eric Paris828dfe12008-04-17 13:17:49 -04001957 rc = task_has_system(current, SYSTEM__SYSLOG_CONSOLE);
1958 break;
Kees Cookd78ca3c2010-02-03 15:37:13 -08001959 case SYSLOG_ACTION_CLOSE: /* Close log */
1960 case SYSLOG_ACTION_OPEN: /* Open log */
1961 case SYSLOG_ACTION_READ: /* Read from log */
1962 case SYSLOG_ACTION_READ_CLEAR: /* Read/clear last kernel messages */
1963 case SYSLOG_ACTION_CLEAR: /* Clear ring buffer */
Eric Paris828dfe12008-04-17 13:17:49 -04001964 default:
1965 rc = task_has_system(current, SYSTEM__SYSLOG_MOD);
1966 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001967 }
1968 return rc;
1969}
1970
1971/*
1972 * Check that a process has enough memory to allocate a new virtual
1973 * mapping. 0 means there is enough memory for the allocation to
1974 * succeed and -ENOMEM implies there is not.
1975 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07001976 * Do not audit the selinux permission check, as this is applied to all
1977 * processes that allocate mappings.
1978 */
Alan Cox34b4e4a2007-08-22 14:01:28 -07001979static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001980{
1981 int rc, cap_sys_admin = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001982
Eric Paris6a9de492012-01-03 12:25:14 -05001983 rc = selinux_capable(current_cred(), &init_user_ns, CAP_SYS_ADMIN,
David Howells3699c532009-01-06 22:27:01 +00001984 SECURITY_CAP_NOAUDIT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001985 if (rc == 0)
1986 cap_sys_admin = 1;
1987
Alan Cox34b4e4a2007-08-22 14:01:28 -07001988 return __vm_enough_memory(mm, pages, cap_sys_admin);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001989}
1990
1991/* binprm security operations */
1992
David Howellsa6f76f22008-11-14 10:39:24 +11001993static int selinux_bprm_set_creds(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001994{
David Howellsa6f76f22008-11-14 10:39:24 +11001995 const struct task_security_struct *old_tsec;
1996 struct task_security_struct *new_tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001997 struct inode_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04001998 struct common_audit_data ad;
Al Viro496ad9a2013-01-23 17:07:38 -05001999 struct inode *inode = file_inode(bprm->file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002000 int rc;
2001
Eric Paris200ac532009-02-12 15:01:04 -05002002 rc = cap_bprm_set_creds(bprm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002003 if (rc)
2004 return rc;
2005
David Howellsa6f76f22008-11-14 10:39:24 +11002006 /* SELinux context only depends on initial program or script and not
2007 * the script interpreter */
2008 if (bprm->cred_prepared)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002009 return 0;
2010
David Howellsa6f76f22008-11-14 10:39:24 +11002011 old_tsec = current_security();
2012 new_tsec = bprm->cred->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002013 isec = inode->i_security;
2014
2015 /* Default to the current task SID. */
David Howellsa6f76f22008-11-14 10:39:24 +11002016 new_tsec->sid = old_tsec->sid;
2017 new_tsec->osid = old_tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002018
Michael LeMay28eba5b2006-06-27 02:53:42 -07002019 /* Reset fs, key, and sock SIDs on execve. */
David Howellsa6f76f22008-11-14 10:39:24 +11002020 new_tsec->create_sid = 0;
2021 new_tsec->keycreate_sid = 0;
2022 new_tsec->sockcreate_sid = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002023
David Howellsa6f76f22008-11-14 10:39:24 +11002024 if (old_tsec->exec_sid) {
2025 new_tsec->sid = old_tsec->exec_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002026 /* Reset exec SID on execve. */
David Howellsa6f76f22008-11-14 10:39:24 +11002027 new_tsec->exec_sid = 0;
Andy Lutomirski259e5e62012-04-12 16:47:50 -05002028
2029 /*
2030 * Minimize confusion: if no_new_privs and a transition is
2031 * explicitly requested, then fail the exec.
2032 */
2033 if (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS)
2034 return -EPERM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002035 } else {
2036 /* Check for a default transition on this program. */
David Howellsa6f76f22008-11-14 10:39:24 +11002037 rc = security_transition_sid(old_tsec->sid, isec->sid,
Eric Paris652bb9b2011-02-01 11:05:40 -05002038 SECCLASS_PROCESS, NULL,
2039 &new_tsec->sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002040 if (rc)
2041 return rc;
2042 }
2043
Eric Paris50c205f2012-04-04 15:01:43 -04002044 ad.type = LSM_AUDIT_DATA_PATH;
Eric Parisf48b7392011-04-25 12:54:27 -04002045 ad.u.path = bprm->file->f_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002046
Andy Lutomirski259e5e62012-04-12 16:47:50 -05002047 if ((bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) ||
2048 (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS))
David Howellsa6f76f22008-11-14 10:39:24 +11002049 new_tsec->sid = old_tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002050
David Howellsa6f76f22008-11-14 10:39:24 +11002051 if (new_tsec->sid == old_tsec->sid) {
2052 rc = avc_has_perm(old_tsec->sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002053 SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, &ad);
2054 if (rc)
2055 return rc;
2056 } else {
2057 /* Check permissions for the transition. */
David Howellsa6f76f22008-11-14 10:39:24 +11002058 rc = avc_has_perm(old_tsec->sid, new_tsec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002059 SECCLASS_PROCESS, PROCESS__TRANSITION, &ad);
2060 if (rc)
2061 return rc;
2062
David Howellsa6f76f22008-11-14 10:39:24 +11002063 rc = avc_has_perm(new_tsec->sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002064 SECCLASS_FILE, FILE__ENTRYPOINT, &ad);
2065 if (rc)
2066 return rc;
2067
David Howellsa6f76f22008-11-14 10:39:24 +11002068 /* Check for shared state */
2069 if (bprm->unsafe & LSM_UNSAFE_SHARE) {
2070 rc = avc_has_perm(old_tsec->sid, new_tsec->sid,
2071 SECCLASS_PROCESS, PROCESS__SHARE,
2072 NULL);
2073 if (rc)
2074 return -EPERM;
2075 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002076
David Howellsa6f76f22008-11-14 10:39:24 +11002077 /* Make sure that anyone attempting to ptrace over a task that
2078 * changes its SID has the appropriate permit */
2079 if (bprm->unsafe &
2080 (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) {
2081 struct task_struct *tracer;
2082 struct task_security_struct *sec;
2083 u32 ptsid = 0;
2084
2085 rcu_read_lock();
Tejun Heo06d98472011-06-17 16:50:40 +02002086 tracer = ptrace_parent(current);
David Howellsa6f76f22008-11-14 10:39:24 +11002087 if (likely(tracer != NULL)) {
2088 sec = __task_cred(tracer)->security;
2089 ptsid = sec->sid;
2090 }
2091 rcu_read_unlock();
2092
2093 if (ptsid != 0) {
2094 rc = avc_has_perm(ptsid, new_tsec->sid,
2095 SECCLASS_PROCESS,
2096 PROCESS__PTRACE, NULL);
2097 if (rc)
2098 return -EPERM;
2099 }
2100 }
2101
2102 /* Clear any possibly unsafe personality bits on exec: */
2103 bprm->per_clear |= PER_CLEAR_ON_SETID;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002104 }
2105
Linus Torvalds1da177e2005-04-16 15:20:36 -07002106 return 0;
2107}
2108
Eric Paris828dfe12008-04-17 13:17:49 -04002109static int selinux_bprm_secureexec(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002110{
Paul Moore5fb49872010-04-22 14:46:19 -04002111 const struct task_security_struct *tsec = current_security();
David Howells275bb412008-11-14 10:39:19 +11002112 u32 sid, osid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002113 int atsecure = 0;
2114
David Howells275bb412008-11-14 10:39:19 +11002115 sid = tsec->sid;
2116 osid = tsec->osid;
2117
2118 if (osid != sid) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002119 /* Enable secure mode for SIDs transitions unless
2120 the noatsecure permission is granted between
2121 the two SIDs, i.e. ahp returns 0. */
David Howells275bb412008-11-14 10:39:19 +11002122 atsecure = avc_has_perm(osid, sid,
David Howellsa6f76f22008-11-14 10:39:24 +11002123 SECCLASS_PROCESS,
2124 PROCESS__NOATSECURE, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002125 }
2126
Eric Paris200ac532009-02-12 15:01:04 -05002127 return (atsecure || cap_bprm_secureexec(bprm));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002128}
2129
Al Viroc3c073f2012-08-21 22:32:06 -04002130static int match_file(const void *p, struct file *file, unsigned fd)
2131{
2132 return file_has_perm(p, file, file_to_av(file)) ? fd + 1 : 0;
2133}
2134
Linus Torvalds1da177e2005-04-16 15:20:36 -07002135/* Derived from fs/exec.c:flush_old_files. */
David Howells745ca242008-11-14 10:39:22 +11002136static inline void flush_unauthorized_files(const struct cred *cred,
2137 struct files_struct *files)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002138{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002139 struct file *file, *devnull = NULL;
Stephen Smalleyb20c8122006-09-25 23:32:03 -07002140 struct tty_struct *tty;
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002141 int drop_tty = 0;
Al Viroc3c073f2012-08-21 22:32:06 -04002142 unsigned n;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002143
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002144 tty = get_current_tty();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002145 if (tty) {
Nick Pigginee2ffa02010-08-18 04:37:35 +10002146 spin_lock(&tty_files_lock);
Eric Paris37dd0bd2008-10-31 17:40:00 -04002147 if (!list_empty(&tty->tty_files)) {
Nick Piggind996b622010-08-18 04:37:36 +10002148 struct tty_file_private *file_priv;
Eric Paris37dd0bd2008-10-31 17:40:00 -04002149
Linus Torvalds1da177e2005-04-16 15:20:36 -07002150 /* Revalidate access to controlling tty.
Eric Paris602a8dd2012-04-04 15:01:42 -04002151 Use path_has_perm on the tty path directly rather
Linus Torvalds1da177e2005-04-16 15:20:36 -07002152 than using file_has_perm, as this particular open
2153 file may belong to another process and we are only
2154 interested in the inode-based check here. */
Nick Piggind996b622010-08-18 04:37:36 +10002155 file_priv = list_first_entry(&tty->tty_files,
2156 struct tty_file_private, list);
2157 file = file_priv->file;
Eric Paris602a8dd2012-04-04 15:01:42 -04002158 if (path_has_perm(cred, &file->f_path, FILE__READ | FILE__WRITE))
Peter Zijlstra24ec8392006-12-08 02:36:04 -08002159 drop_tty = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002160 }
Nick Pigginee2ffa02010-08-18 04:37:35 +10002161 spin_unlock(&tty_files_lock);
Alan Cox452a00d2008-10-13 10:39:13 +01002162 tty_kref_put(tty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002163 }
Eric W. Biederman98a27ba2007-05-08 00:26:56 -07002164 /* Reset controlling tty. */
2165 if (drop_tty)
2166 no_tty();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002167
2168 /* Revalidate access to inherited open files. */
Al Viroc3c073f2012-08-21 22:32:06 -04002169 n = iterate_fd(files, 0, match_file, cred);
2170 if (!n) /* none found? */
2171 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002172
Al Viroc3c073f2012-08-21 22:32:06 -04002173 devnull = dentry_open(&selinux_null, O_RDWR, cred);
Al Viro45525b22012-10-16 13:30:07 -04002174 if (IS_ERR(devnull))
2175 devnull = NULL;
2176 /* replace all the matching ones with this */
2177 do {
2178 replace_fd(n - 1, devnull, 0);
2179 } while ((n = iterate_fd(files, n, match_file, cred)) != 0);
2180 if (devnull)
Al Viroc3c073f2012-08-21 22:32:06 -04002181 fput(devnull);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002182}
2183
Linus Torvalds1da177e2005-04-16 15:20:36 -07002184/*
David Howellsa6f76f22008-11-14 10:39:24 +11002185 * Prepare a process for imminent new credential changes due to exec
Linus Torvalds1da177e2005-04-16 15:20:36 -07002186 */
David Howellsa6f76f22008-11-14 10:39:24 +11002187static void selinux_bprm_committing_creds(struct linux_binprm *bprm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002188{
David Howellsa6f76f22008-11-14 10:39:24 +11002189 struct task_security_struct *new_tsec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002190 struct rlimit *rlim, *initrlim;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002191 int rc, i;
2192
David Howellsa6f76f22008-11-14 10:39:24 +11002193 new_tsec = bprm->cred->security;
2194 if (new_tsec->sid == new_tsec->osid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002195 return;
2196
2197 /* Close files for which the new task SID is not authorized. */
David Howellsa6f76f22008-11-14 10:39:24 +11002198 flush_unauthorized_files(bprm->cred, current->files);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002199
David Howellsa6f76f22008-11-14 10:39:24 +11002200 /* Always clear parent death signal on SID transitions. */
2201 current->pdeath_signal = 0;
2202
2203 /* Check whether the new SID can inherit resource limits from the old
2204 * SID. If not, reset all soft limits to the lower of the current
2205 * task's hard limit and the init task's soft limit.
2206 *
2207 * Note that the setting of hard limits (even to lower them) can be
2208 * controlled by the setrlimit check. The inclusion of the init task's
2209 * soft limit into the computation is to avoid resetting soft limits
2210 * higher than the default soft limit for cases where the default is
2211 * lower than the hard limit, e.g. RLIMIT_CORE or RLIMIT_STACK.
2212 */
2213 rc = avc_has_perm(new_tsec->osid, new_tsec->sid, SECCLASS_PROCESS,
2214 PROCESS__RLIMITINH, NULL);
2215 if (rc) {
Oleg Nesteroveb2d55a2010-06-23 22:43:32 +02002216 /* protect against do_prlimit() */
2217 task_lock(current);
David Howellsa6f76f22008-11-14 10:39:24 +11002218 for (i = 0; i < RLIM_NLIMITS; i++) {
2219 rlim = current->signal->rlim + i;
2220 initrlim = init_task.signal->rlim + i;
2221 rlim->rlim_cur = min(rlim->rlim_max, initrlim->rlim_cur);
2222 }
Oleg Nesteroveb2d55a2010-06-23 22:43:32 +02002223 task_unlock(current);
2224 update_rlimit_cpu(current, rlimit(RLIMIT_CPU));
David Howellsa6f76f22008-11-14 10:39:24 +11002225 }
2226}
2227
2228/*
2229 * Clean up the process immediately after the installation of new credentials
2230 * due to exec
2231 */
2232static void selinux_bprm_committed_creds(struct linux_binprm *bprm)
2233{
2234 const struct task_security_struct *tsec = current_security();
2235 struct itimerval itimer;
David Howellsa6f76f22008-11-14 10:39:24 +11002236 u32 osid, sid;
2237 int rc, i;
David Howellsa6f76f22008-11-14 10:39:24 +11002238
David Howellsa6f76f22008-11-14 10:39:24 +11002239 osid = tsec->osid;
2240 sid = tsec->sid;
2241
2242 if (sid == osid)
2243 return;
2244
2245 /* Check whether the new SID can inherit signal state from the old SID.
2246 * If not, clear itimers to avoid subsequent signal generation and
2247 * flush and unblock signals.
2248 *
2249 * This must occur _after_ the task SID has been updated so that any
2250 * kill done after the flush will be checked against the new SID.
2251 */
2252 rc = avc_has_perm(osid, sid, SECCLASS_PROCESS, PROCESS__SIGINH, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002253 if (rc) {
2254 memset(&itimer, 0, sizeof itimer);
2255 for (i = 0; i < 3; i++)
2256 do_setitimer(i, &itimer, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002257 spin_lock_irq(&current->sighand->siglock);
David Howells3bcac022009-04-29 13:45:05 +01002258 if (!(current->signal->flags & SIGNAL_GROUP_EXIT)) {
2259 __flush_signals(current);
2260 flush_signal_handlers(current, 1);
2261 sigemptyset(&current->blocked);
2262 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002263 spin_unlock_irq(&current->sighand->siglock);
2264 }
2265
David Howellsa6f76f22008-11-14 10:39:24 +11002266 /* Wake up the parent if it is waiting so that it can recheck
2267 * wait permission to the new task SID. */
Oleg Nesterovecd6de32009-04-29 16:02:24 +02002268 read_lock(&tasklist_lock);
Oleg Nesterov0b7570e2009-09-23 15:56:46 -07002269 __wake_up_parent(current, current->real_parent);
Oleg Nesterovecd6de32009-04-29 16:02:24 +02002270 read_unlock(&tasklist_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002271}
2272
2273/* superblock security operations */
2274
2275static int selinux_sb_alloc_security(struct super_block *sb)
2276{
2277 return superblock_alloc_security(sb);
2278}
2279
2280static void selinux_sb_free_security(struct super_block *sb)
2281{
2282 superblock_free_security(sb);
2283}
2284
2285static inline int match_prefix(char *prefix, int plen, char *option, int olen)
2286{
2287 if (plen > olen)
2288 return 0;
2289
2290 return !memcmp(prefix, option, plen);
2291}
2292
2293static inline int selinux_option(char *option, int len)
2294{
Eric Paris832cbd92008-04-01 13:24:09 -04002295 return (match_prefix(CONTEXT_STR, sizeof(CONTEXT_STR)-1, option, len) ||
2296 match_prefix(FSCONTEXT_STR, sizeof(FSCONTEXT_STR)-1, option, len) ||
2297 match_prefix(DEFCONTEXT_STR, sizeof(DEFCONTEXT_STR)-1, option, len) ||
David P. Quigley11689d42009-01-16 09:22:03 -05002298 match_prefix(ROOTCONTEXT_STR, sizeof(ROOTCONTEXT_STR)-1, option, len) ||
2299 match_prefix(LABELSUPP_STR, sizeof(LABELSUPP_STR)-1, option, len));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002300}
2301
2302static inline void take_option(char **to, char *from, int *first, int len)
2303{
2304 if (!*first) {
2305 **to = ',';
2306 *to += 1;
Cory Olmo3528a952006-09-29 01:58:44 -07002307 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002308 *first = 0;
2309 memcpy(*to, from, len);
2310 *to += len;
2311}
2312
Eric Paris828dfe12008-04-17 13:17:49 -04002313static inline void take_selinux_option(char **to, char *from, int *first,
2314 int len)
Cory Olmo3528a952006-09-29 01:58:44 -07002315{
2316 int current_size = 0;
2317
2318 if (!*first) {
2319 **to = '|';
2320 *to += 1;
Eric Paris828dfe12008-04-17 13:17:49 -04002321 } else
Cory Olmo3528a952006-09-29 01:58:44 -07002322 *first = 0;
2323
2324 while (current_size < len) {
2325 if (*from != '"') {
2326 **to = *from;
2327 *to += 1;
2328 }
2329 from += 1;
2330 current_size += 1;
2331 }
2332}
2333
Eric Parise0007522008-03-05 10:31:54 -05002334static int selinux_sb_copy_data(char *orig, char *copy)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002335{
2336 int fnosec, fsec, rc = 0;
2337 char *in_save, *in_curr, *in_end;
2338 char *sec_curr, *nosec_save, *nosec;
Cory Olmo3528a952006-09-29 01:58:44 -07002339 int open_quote = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002340
2341 in_curr = orig;
2342 sec_curr = copy;
2343
Linus Torvalds1da177e2005-04-16 15:20:36 -07002344 nosec = (char *)get_zeroed_page(GFP_KERNEL);
2345 if (!nosec) {
2346 rc = -ENOMEM;
2347 goto out;
2348 }
2349
2350 nosec_save = nosec;
2351 fnosec = fsec = 1;
2352 in_save = in_end = orig;
2353
2354 do {
Cory Olmo3528a952006-09-29 01:58:44 -07002355 if (*in_end == '"')
2356 open_quote = !open_quote;
2357 if ((*in_end == ',' && open_quote == 0) ||
2358 *in_end == '\0') {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002359 int len = in_end - in_curr;
2360
2361 if (selinux_option(in_curr, len))
Cory Olmo3528a952006-09-29 01:58:44 -07002362 take_selinux_option(&sec_curr, in_curr, &fsec, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002363 else
2364 take_option(&nosec, in_curr, &fnosec, len);
2365
2366 in_curr = in_end + 1;
2367 }
2368 } while (*in_end++);
2369
Eric Paris6931dfc2005-06-30 02:58:51 -07002370 strcpy(in_save, nosec_save);
Gerald Schaeferda3caa22005-06-21 17:15:18 -07002371 free_page((unsigned long)nosec_save);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002372out:
2373 return rc;
2374}
2375
Eric Paris026eb162011-03-03 16:09:14 -05002376static int selinux_sb_remount(struct super_block *sb, void *data)
2377{
2378 int rc, i, *flags;
2379 struct security_mnt_opts opts;
2380 char *secdata, **mount_options;
2381 struct superblock_security_struct *sbsec = sb->s_security;
2382
2383 if (!(sbsec->flags & SE_SBINITIALIZED))
2384 return 0;
2385
2386 if (!data)
2387 return 0;
2388
2389 if (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)
2390 return 0;
2391
2392 security_init_mnt_opts(&opts);
2393 secdata = alloc_secdata();
2394 if (!secdata)
2395 return -ENOMEM;
2396 rc = selinux_sb_copy_data(data, secdata);
2397 if (rc)
2398 goto out_free_secdata;
2399
2400 rc = selinux_parse_opts_str(secdata, &opts);
2401 if (rc)
2402 goto out_free_secdata;
2403
2404 mount_options = opts.mnt_opts;
2405 flags = opts.mnt_opts_flags;
2406
2407 for (i = 0; i < opts.num_mnt_opts; i++) {
2408 u32 sid;
2409 size_t len;
2410
2411 if (flags[i] == SE_SBLABELSUPP)
2412 continue;
2413 len = strlen(mount_options[i]);
2414 rc = security_context_to_sid(mount_options[i], len, &sid);
2415 if (rc) {
2416 printk(KERN_WARNING "SELinux: security_context_to_sid"
2417 "(%s) failed for (dev %s, type %s) errno=%d\n",
2418 mount_options[i], sb->s_id, sb->s_type->name, rc);
2419 goto out_free_opts;
2420 }
2421 rc = -EINVAL;
2422 switch (flags[i]) {
2423 case FSCONTEXT_MNT:
2424 if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid, sid))
2425 goto out_bad_option;
2426 break;
2427 case CONTEXT_MNT:
2428 if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid, sid))
2429 goto out_bad_option;
2430 break;
2431 case ROOTCONTEXT_MNT: {
2432 struct inode_security_struct *root_isec;
2433 root_isec = sb->s_root->d_inode->i_security;
2434
2435 if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid, sid))
2436 goto out_bad_option;
2437 break;
2438 }
2439 case DEFCONTEXT_MNT:
2440 if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid, sid))
2441 goto out_bad_option;
2442 break;
2443 default:
2444 goto out_free_opts;
2445 }
2446 }
2447
2448 rc = 0;
2449out_free_opts:
2450 security_free_mnt_opts(&opts);
2451out_free_secdata:
2452 free_secdata(secdata);
2453 return rc;
2454out_bad_option:
2455 printk(KERN_WARNING "SELinux: unable to change security options "
2456 "during remount (dev %s, type=%s)\n", sb->s_id,
2457 sb->s_type->name);
2458 goto out_free_opts;
2459}
2460
James Morris12204e22008-12-19 10:44:42 +11002461static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002462{
David Howells88e67f32008-11-14 10:39:21 +11002463 const struct cred *cred = current_cred();
Thomas Liu2bf49692009-07-14 12:14:09 -04002464 struct common_audit_data ad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002465 int rc;
2466
2467 rc = superblock_doinit(sb, data);
2468 if (rc)
2469 return rc;
2470
James Morris74192242008-12-19 11:41:10 +11002471 /* Allow all mounts performed by the kernel */
2472 if (flags & MS_KERNMOUNT)
2473 return 0;
2474
Eric Paris50c205f2012-04-04 15:01:43 -04002475 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04002476 ad.u.dentry = sb->s_root;
David Howells88e67f32008-11-14 10:39:21 +11002477 return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002478}
2479
David Howells726c3342006-06-23 02:02:58 -07002480static int selinux_sb_statfs(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002481{
David Howells88e67f32008-11-14 10:39:21 +11002482 const struct cred *cred = current_cred();
Thomas Liu2bf49692009-07-14 12:14:09 -04002483 struct common_audit_data ad;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002484
Eric Paris50c205f2012-04-04 15:01:43 -04002485 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04002486 ad.u.dentry = dentry->d_sb->s_root;
David Howells88e67f32008-11-14 10:39:21 +11002487 return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002488}
2489
Al Viro808d4e32012-10-11 11:42:01 -04002490static int selinux_mount(const char *dev_name,
Al Virob5266eb2008-03-22 17:48:24 -04002491 struct path *path,
Al Viro808d4e32012-10-11 11:42:01 -04002492 const char *type,
Eric Paris828dfe12008-04-17 13:17:49 -04002493 unsigned long flags,
2494 void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002495{
David Howells88e67f32008-11-14 10:39:21 +11002496 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002497
2498 if (flags & MS_REMOUNT)
Al Virod8c95842011-12-07 18:16:57 -05002499 return superblock_has_perm(cred, path->dentry->d_sb,
Eric Paris828dfe12008-04-17 13:17:49 -04002500 FILESYSTEM__REMOUNT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002501 else
Eric Paris2875fa02011-04-28 16:04:24 -04002502 return path_has_perm(cred, path, FILE__MOUNTON);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002503}
2504
2505static int selinux_umount(struct vfsmount *mnt, int flags)
2506{
David Howells88e67f32008-11-14 10:39:21 +11002507 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002508
David Howells88e67f32008-11-14 10:39:21 +11002509 return superblock_has_perm(cred, mnt->mnt_sb,
Eric Paris828dfe12008-04-17 13:17:49 -04002510 FILESYSTEM__UNMOUNT, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002511}
2512
2513/* inode security operations */
2514
2515static int selinux_inode_alloc_security(struct inode *inode)
2516{
2517 return inode_alloc_security(inode);
2518}
2519
2520static void selinux_inode_free_security(struct inode *inode)
2521{
2522 inode_free_security(inode);
2523}
2524
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002525static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
Eric Paris2a7dba32011-02-01 11:05:39 -05002526 const struct qstr *qstr, char **name,
2527 void **value, size_t *len)
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002528{
Paul Moore5fb49872010-04-22 14:46:19 -04002529 const struct task_security_struct *tsec = current_security();
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002530 struct inode_security_struct *dsec;
2531 struct superblock_security_struct *sbsec;
David Howells275bb412008-11-14 10:39:19 +11002532 u32 sid, newsid, clen;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002533 int rc;
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002534 char *namep = NULL, *context;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002535
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002536 dsec = dir->i_security;
2537 sbsec = dir->i_sb->s_security;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002538
David Howells275bb412008-11-14 10:39:19 +11002539 sid = tsec->sid;
2540 newsid = tsec->create_sid;
2541
Eric Paris415103f2010-12-02 16:13:40 -05002542 if ((sbsec->flags & SE_SBINITIALIZED) &&
2543 (sbsec->behavior == SECURITY_FS_USE_MNTPOINT))
2544 newsid = sbsec->mntpoint_sid;
2545 else if (!newsid || !(sbsec->flags & SE_SBLABELSUPP)) {
David Howells275bb412008-11-14 10:39:19 +11002546 rc = security_transition_sid(sid, dsec->sid,
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002547 inode_mode_to_security_class(inode->i_mode),
Eric Paris652bb9b2011-02-01 11:05:40 -05002548 qstr, &newsid);
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002549 if (rc) {
2550 printk(KERN_WARNING "%s: "
2551 "security_transition_sid failed, rc=%d (dev=%s "
2552 "ino=%ld)\n",
Harvey Harrisondd6f9532008-03-06 10:03:59 +11002553 __func__,
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002554 -rc, inode->i_sb->s_id, inode->i_ino);
2555 return rc;
2556 }
2557 }
2558
Eric Paris296fddf2006-09-25 23:32:00 -07002559 /* Possibly defer initialization to selinux_complete_init. */
David P. Quigley0d90a7e2009-01-16 09:22:02 -05002560 if (sbsec->flags & SE_SBINITIALIZED) {
Eric Paris296fddf2006-09-25 23:32:00 -07002561 struct inode_security_struct *isec = inode->i_security;
2562 isec->sclass = inode_mode_to_security_class(inode->i_mode);
2563 isec->sid = newsid;
2564 isec->initialized = 1;
2565 }
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002566
David P. Quigleycd895962009-01-16 09:22:04 -05002567 if (!ss_initialized || !(sbsec->flags & SE_SBLABELSUPP))
Stephen Smalley25a74f32005-11-08 21:34:33 -08002568 return -EOPNOTSUPP;
2569
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002570 if (name) {
Josef Bacika02fe132008-04-04 09:35:05 +11002571 namep = kstrdup(XATTR_SELINUX_SUFFIX, GFP_NOFS);
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002572 if (!namep)
2573 return -ENOMEM;
2574 *name = namep;
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002575 }
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002576
2577 if (value && len) {
Stephen Smalley12b29f32008-05-07 13:03:20 -04002578 rc = security_sid_to_context_force(newsid, &context, &clen);
Stephen Smalley570bc1c2005-09-09 13:01:43 -07002579 if (rc) {
2580 kfree(namep);
2581 return rc;
2582 }
2583 *value = context;
2584 *len = clen;
2585 }
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002586
Stephen Smalley5e41ff92005-09-09 13:01:35 -07002587 return 0;
2588}
2589
Al Viro4acdaf22011-07-26 01:42:34 -04002590static int selinux_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002591{
2592 return may_create(dir, dentry, SECCLASS_FILE);
2593}
2594
Linus Torvalds1da177e2005-04-16 15:20:36 -07002595static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
2596{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002597 return may_link(dir, old_dentry, MAY_LINK);
2598}
2599
Linus Torvalds1da177e2005-04-16 15:20:36 -07002600static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry)
2601{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002602 return may_link(dir, dentry, MAY_UNLINK);
2603}
2604
2605static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry, const char *name)
2606{
2607 return may_create(dir, dentry, SECCLASS_LNK_FILE);
2608}
2609
Al Viro18bb1db2011-07-26 01:41:39 -04002610static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry, umode_t mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002611{
2612 return may_create(dir, dentry, SECCLASS_DIR);
2613}
2614
Linus Torvalds1da177e2005-04-16 15:20:36 -07002615static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry)
2616{
2617 return may_link(dir, dentry, MAY_RMDIR);
2618}
2619
Al Viro1a67aaf2011-07-26 01:52:52 -04002620static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002621{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002622 return may_create(dir, dentry, inode_mode_to_security_class(mode));
2623}
2624
Linus Torvalds1da177e2005-04-16 15:20:36 -07002625static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
Eric Paris828dfe12008-04-17 13:17:49 -04002626 struct inode *new_inode, struct dentry *new_dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002627{
2628 return may_rename(old_inode, old_dentry, new_inode, new_dentry);
2629}
2630
Linus Torvalds1da177e2005-04-16 15:20:36 -07002631static int selinux_inode_readlink(struct dentry *dentry)
2632{
David Howells88e67f32008-11-14 10:39:21 +11002633 const struct cred *cred = current_cred();
2634
Eric Paris2875fa02011-04-28 16:04:24 -04002635 return dentry_has_perm(cred, dentry, FILE__READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002636}
2637
2638static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *nameidata)
2639{
David Howells88e67f32008-11-14 10:39:21 +11002640 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002641
Eric Paris2875fa02011-04-28 16:04:24 -04002642 return dentry_has_perm(cred, dentry, FILE__READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002643}
2644
Eric Parisd4cf970d2012-04-04 15:01:42 -04002645static noinline int audit_inode_permission(struct inode *inode,
2646 u32 perms, u32 audited, u32 denied,
2647 unsigned flags)
2648{
2649 struct common_audit_data ad;
Eric Parisd4cf970d2012-04-04 15:01:42 -04002650 struct inode_security_struct *isec = inode->i_security;
2651 int rc;
2652
Eric Paris50c205f2012-04-04 15:01:43 -04002653 ad.type = LSM_AUDIT_DATA_INODE;
Eric Parisd4cf970d2012-04-04 15:01:42 -04002654 ad.u.inode = inode;
2655
2656 rc = slow_avc_audit(current_sid(), isec->sid, isec->sclass, perms,
2657 audited, denied, &ad, flags);
2658 if (rc)
2659 return rc;
2660 return 0;
2661}
2662
Al Viroe74f71e2011-06-20 19:38:15 -04002663static int selinux_inode_permission(struct inode *inode, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002664{
David Howells88e67f32008-11-14 10:39:21 +11002665 const struct cred *cred = current_cred();
Eric Parisb782e0a2010-07-23 11:44:03 -04002666 u32 perms;
2667 bool from_access;
Al Virocf1dd1d2011-06-20 19:44:08 -04002668 unsigned flags = mask & MAY_NOT_BLOCK;
Eric Paris2e334052012-04-04 15:01:42 -04002669 struct inode_security_struct *isec;
2670 u32 sid;
2671 struct av_decision avd;
2672 int rc, rc2;
2673 u32 audited, denied;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002674
Eric Parisb782e0a2010-07-23 11:44:03 -04002675 from_access = mask & MAY_ACCESS;
Eric Parisd09ca732010-07-23 11:43:57 -04002676 mask &= (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND);
2677
Eric Parisb782e0a2010-07-23 11:44:03 -04002678 /* No permission to check. Existence test. */
2679 if (!mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002680 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002681
Eric Paris2e334052012-04-04 15:01:42 -04002682 validate_creds(cred);
Eric Parisb782e0a2010-07-23 11:44:03 -04002683
Eric Paris2e334052012-04-04 15:01:42 -04002684 if (unlikely(IS_PRIVATE(inode)))
2685 return 0;
Eric Parisb782e0a2010-07-23 11:44:03 -04002686
2687 perms = file_mask_to_av(inode->i_mode, mask);
2688
Eric Paris2e334052012-04-04 15:01:42 -04002689 sid = cred_sid(cred);
2690 isec = inode->i_security;
2691
2692 rc = avc_has_perm_noaudit(sid, isec->sid, isec->sclass, perms, 0, &avd);
2693 audited = avc_audit_required(perms, &avd, rc,
2694 from_access ? FILE__AUDIT_ACCESS : 0,
2695 &denied);
2696 if (likely(!audited))
2697 return rc;
2698
Eric Parisd4cf970d2012-04-04 15:01:42 -04002699 rc2 = audit_inode_permission(inode, perms, audited, denied, flags);
Eric Paris2e334052012-04-04 15:01:42 -04002700 if (rc2)
2701 return rc2;
2702 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002703}
2704
2705static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
2706{
David Howells88e67f32008-11-14 10:39:21 +11002707 const struct cred *cred = current_cred();
Amerigo Wangbc6a6002009-08-20 19:29:02 -07002708 unsigned int ia_valid = iattr->ia_valid;
Eric Paris95dbf732012-04-04 13:45:34 -04002709 __u32 av = FILE__WRITE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002710
Amerigo Wangbc6a6002009-08-20 19:29:02 -07002711 /* ATTR_FORCE is just used for ATTR_KILL_S[UG]ID. */
2712 if (ia_valid & ATTR_FORCE) {
2713 ia_valid &= ~(ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_MODE |
2714 ATTR_FORCE);
2715 if (!ia_valid)
2716 return 0;
2717 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002718
Amerigo Wangbc6a6002009-08-20 19:29:02 -07002719 if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID |
2720 ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_TIMES_SET))
Eric Paris2875fa02011-04-28 16:04:24 -04002721 return dentry_has_perm(cred, dentry, FILE__SETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002722
Eric Paris3d2195c2012-07-06 14:13:30 -04002723 if (selinux_policycap_openperm && (ia_valid & ATTR_SIZE))
Eric Paris95dbf732012-04-04 13:45:34 -04002724 av |= FILE__OPEN;
2725
2726 return dentry_has_perm(cred, dentry, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002727}
2728
2729static int selinux_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
2730{
David Howells88e67f32008-11-14 10:39:21 +11002731 const struct cred *cred = current_cred();
Eric Paris2875fa02011-04-28 16:04:24 -04002732 struct path path;
David Howells88e67f32008-11-14 10:39:21 +11002733
Eric Paris2875fa02011-04-28 16:04:24 -04002734 path.dentry = dentry;
2735 path.mnt = mnt;
2736
2737 return path_has_perm(cred, &path, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002738}
2739
David Howells8f0cfa52008-04-29 00:59:41 -07002740static int selinux_inode_setotherxattr(struct dentry *dentry, const char *name)
Serge E. Hallynb5376772007-10-16 23:31:36 -07002741{
David Howells88e67f32008-11-14 10:39:21 +11002742 const struct cred *cred = current_cred();
2743
Serge E. Hallynb5376772007-10-16 23:31:36 -07002744 if (!strncmp(name, XATTR_SECURITY_PREFIX,
2745 sizeof XATTR_SECURITY_PREFIX - 1)) {
2746 if (!strcmp(name, XATTR_NAME_CAPS)) {
2747 if (!capable(CAP_SETFCAP))
2748 return -EPERM;
2749 } else if (!capable(CAP_SYS_ADMIN)) {
2750 /* A different attribute in the security namespace.
2751 Restrict to administrator. */
2752 return -EPERM;
2753 }
2754 }
2755
2756 /* Not an attribute we recognize, so just check the
2757 ordinary setattr permission. */
Eric Paris2875fa02011-04-28 16:04:24 -04002758 return dentry_has_perm(cred, dentry, FILE__SETATTR);
Serge E. Hallynb5376772007-10-16 23:31:36 -07002759}
2760
David Howells8f0cfa52008-04-29 00:59:41 -07002761static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
2762 const void *value, size_t size, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002763{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002764 struct inode *inode = dentry->d_inode;
2765 struct inode_security_struct *isec = inode->i_security;
2766 struct superblock_security_struct *sbsec;
Thomas Liu2bf49692009-07-14 12:14:09 -04002767 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11002768 u32 newsid, sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002769 int rc = 0;
2770
Serge E. Hallynb5376772007-10-16 23:31:36 -07002771 if (strcmp(name, XATTR_NAME_SELINUX))
2772 return selinux_inode_setotherxattr(dentry, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002773
2774 sbsec = inode->i_sb->s_security;
David P. Quigleycd895962009-01-16 09:22:04 -05002775 if (!(sbsec->flags & SE_SBLABELSUPP))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002776 return -EOPNOTSUPP;
2777
Serge E. Hallyn2e149672011-03-23 16:43:26 -07002778 if (!inode_owner_or_capable(inode))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002779 return -EPERM;
2780
Eric Paris50c205f2012-04-04 15:01:43 -04002781 ad.type = LSM_AUDIT_DATA_DENTRY;
Eric Parisa2694342011-04-25 13:10:27 -04002782 ad.u.dentry = dentry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002783
David Howells275bb412008-11-14 10:39:19 +11002784 rc = avc_has_perm(sid, isec->sid, isec->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002785 FILE__RELABELFROM, &ad);
2786 if (rc)
2787 return rc;
2788
2789 rc = security_context_to_sid(value, size, &newsid);
Stephen Smalley12b29f32008-05-07 13:03:20 -04002790 if (rc == -EINVAL) {
Eric Parisd6ea83e2012-04-04 13:45:49 -04002791 if (!capable(CAP_MAC_ADMIN)) {
2792 struct audit_buffer *ab;
2793 size_t audit_size;
2794 const char *str;
2795
2796 /* We strip a nul only if it is at the end, otherwise the
2797 * context contains a nul and we should audit that */
Al Viroe3fea3f2012-06-09 08:15:16 +01002798 if (value) {
2799 str = value;
2800 if (str[size - 1] == '\0')
2801 audit_size = size - 1;
2802 else
2803 audit_size = size;
2804 } else {
2805 str = "";
2806 audit_size = 0;
2807 }
Eric Parisd6ea83e2012-04-04 13:45:49 -04002808 ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR);
2809 audit_log_format(ab, "op=setxattr invalid_context=");
2810 audit_log_n_untrustedstring(ab, value, audit_size);
2811 audit_log_end(ab);
2812
Stephen Smalley12b29f32008-05-07 13:03:20 -04002813 return rc;
Eric Parisd6ea83e2012-04-04 13:45:49 -04002814 }
Stephen Smalley12b29f32008-05-07 13:03:20 -04002815 rc = security_context_to_sid_force(value, size, &newsid);
2816 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002817 if (rc)
2818 return rc;
2819
David Howells275bb412008-11-14 10:39:19 +11002820 rc = avc_has_perm(sid, newsid, isec->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002821 FILE__RELABELTO, &ad);
2822 if (rc)
2823 return rc;
2824
David Howells275bb412008-11-14 10:39:19 +11002825 rc = security_validate_transition(isec->sid, newsid, sid,
Eric Paris828dfe12008-04-17 13:17:49 -04002826 isec->sclass);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002827 if (rc)
2828 return rc;
2829
2830 return avc_has_perm(newsid,
2831 sbsec->sid,
2832 SECCLASS_FILESYSTEM,
2833 FILESYSTEM__ASSOCIATE,
2834 &ad);
2835}
2836
David Howells8f0cfa52008-04-29 00:59:41 -07002837static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
Eric Parisf5269712008-05-14 11:27:45 -04002838 const void *value, size_t size,
David Howells8f0cfa52008-04-29 00:59:41 -07002839 int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002840{
2841 struct inode *inode = dentry->d_inode;
2842 struct inode_security_struct *isec = inode->i_security;
2843 u32 newsid;
2844 int rc;
2845
2846 if (strcmp(name, XATTR_NAME_SELINUX)) {
2847 /* Not an attribute we recognize, so nothing to do. */
2848 return;
2849 }
2850
Stephen Smalley12b29f32008-05-07 13:03:20 -04002851 rc = security_context_to_sid_force(value, size, &newsid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002852 if (rc) {
Stephen Smalley12b29f32008-05-07 13:03:20 -04002853 printk(KERN_ERR "SELinux: unable to map context to SID"
2854 "for (%s, %lu), rc=%d\n",
2855 inode->i_sb->s_id, inode->i_ino, -rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002856 return;
2857 }
2858
2859 isec->sid = newsid;
2860 return;
2861}
2862
David Howells8f0cfa52008-04-29 00:59:41 -07002863static int selinux_inode_getxattr(struct dentry *dentry, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002864{
David Howells88e67f32008-11-14 10:39:21 +11002865 const struct cred *cred = current_cred();
2866
Eric Paris2875fa02011-04-28 16:04:24 -04002867 return dentry_has_perm(cred, dentry, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002868}
2869
Eric Paris828dfe12008-04-17 13:17:49 -04002870static int selinux_inode_listxattr(struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002871{
David Howells88e67f32008-11-14 10:39:21 +11002872 const struct cred *cred = current_cred();
2873
Eric Paris2875fa02011-04-28 16:04:24 -04002874 return dentry_has_perm(cred, dentry, FILE__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002875}
2876
David Howells8f0cfa52008-04-29 00:59:41 -07002877static int selinux_inode_removexattr(struct dentry *dentry, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002878{
Serge E. Hallynb5376772007-10-16 23:31:36 -07002879 if (strcmp(name, XATTR_NAME_SELINUX))
2880 return selinux_inode_setotherxattr(dentry, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002881
2882 /* No one is allowed to remove a SELinux security label.
2883 You can change the label, but all data must be labeled. */
2884 return -EACCES;
2885}
2886
James Morrisd381d8a2005-10-30 14:59:22 -08002887/*
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04002888 * Copy the inode security context value to the user.
James Morrisd381d8a2005-10-30 14:59:22 -08002889 *
2890 * Permission check is handled by selinux_inode_getxattr hook.
2891 */
David P. Quigley42492592008-02-04 22:29:39 -08002892static int selinux_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002893{
David P. Quigley42492592008-02-04 22:29:39 -08002894 u32 size;
2895 int error;
2896 char *context = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002897 struct inode_security_struct *isec = inode->i_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002898
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00002899 if (strcmp(name, XATTR_SELINUX_SUFFIX))
2900 return -EOPNOTSUPP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002901
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04002902 /*
2903 * If the caller has CAP_MAC_ADMIN, then get the raw context
2904 * value even if it is not defined by current policy; otherwise,
2905 * use the in-core value under current policy.
2906 * Use the non-auditing forms of the permission checks since
2907 * getxattr may be called by unprivileged processes commonly
2908 * and lack of permission just means that we fall back to the
2909 * in-core context value, not a denial.
2910 */
Eric Paris6a9de492012-01-03 12:25:14 -05002911 error = selinux_capable(current_cred(), &init_user_ns, CAP_MAC_ADMIN,
David Howells3699c532009-01-06 22:27:01 +00002912 SECURITY_CAP_NOAUDIT);
Stephen Smalleyabc69bb2008-05-21 14:16:12 -04002913 if (!error)
2914 error = security_sid_to_context_force(isec->sid, &context,
2915 &size);
2916 else
2917 error = security_sid_to_context(isec->sid, &context, &size);
David P. Quigley42492592008-02-04 22:29:39 -08002918 if (error)
2919 return error;
2920 error = size;
2921 if (alloc) {
2922 *buffer = context;
2923 goto out_nofree;
2924 }
2925 kfree(context);
2926out_nofree:
2927 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002928}
2929
2930static int selinux_inode_setsecurity(struct inode *inode, const char *name,
Eric Paris828dfe12008-04-17 13:17:49 -04002931 const void *value, size_t size, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002932{
2933 struct inode_security_struct *isec = inode->i_security;
2934 u32 newsid;
2935 int rc;
2936
2937 if (strcmp(name, XATTR_SELINUX_SUFFIX))
2938 return -EOPNOTSUPP;
2939
2940 if (!value || !size)
2941 return -EACCES;
2942
Eric Paris828dfe12008-04-17 13:17:49 -04002943 rc = security_context_to_sid((void *)value, size, &newsid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002944 if (rc)
2945 return rc;
2946
2947 isec->sid = newsid;
David P. Quigleyddd29ec2009-09-09 14:25:37 -04002948 isec->initialized = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002949 return 0;
2950}
2951
2952static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size)
2953{
2954 const int len = sizeof(XATTR_NAME_SELINUX);
2955 if (buffer && len <= buffer_size)
2956 memcpy(buffer, XATTR_NAME_SELINUX, len);
2957 return len;
2958}
2959
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02002960static void selinux_inode_getsecid(const struct inode *inode, u32 *secid)
2961{
2962 struct inode_security_struct *isec = inode->i_security;
2963 *secid = isec->sid;
2964}
2965
Linus Torvalds1da177e2005-04-16 15:20:36 -07002966/* file security operations */
2967
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09002968static int selinux_revalidate_file_permission(struct file *file, int mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002969{
David Howells88e67f32008-11-14 10:39:21 +11002970 const struct cred *cred = current_cred();
Al Viro496ad9a2013-01-23 17:07:38 -05002971 struct inode *inode = file_inode(file);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002972
Linus Torvalds1da177e2005-04-16 15:20:36 -07002973 /* file_mask_to_av won't add FILE__WRITE if MAY_APPEND is set */
2974 if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE))
2975 mask |= MAY_APPEND;
2976
Paul Moore389fb8002009-03-27 17:10:34 -04002977 return file_has_perm(cred, file,
2978 file_mask_to_av(inode->i_mode, mask));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002979}
2980
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09002981static int selinux_file_permission(struct file *file, int mask)
2982{
Al Viro496ad9a2013-01-23 17:07:38 -05002983 struct inode *inode = file_inode(file);
Stephen Smalley20dda182009-06-22 14:54:53 -04002984 struct file_security_struct *fsec = file->f_security;
2985 struct inode_security_struct *isec = inode->i_security;
2986 u32 sid = current_sid();
2987
Paul Moore389fb8002009-03-27 17:10:34 -04002988 if (!mask)
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09002989 /* No permission to check. Existence test. */
2990 return 0;
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09002991
Stephen Smalley20dda182009-06-22 14:54:53 -04002992 if (sid == fsec->sid && fsec->isid == isec->sid &&
2993 fsec->pseqno == avc_policy_seqno())
Eric Paris83d49852012-04-04 13:45:40 -04002994 /* No change since file_open check. */
Stephen Smalley20dda182009-06-22 14:54:53 -04002995 return 0;
2996
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09002997 return selinux_revalidate_file_permission(file, mask);
2998}
2999
Linus Torvalds1da177e2005-04-16 15:20:36 -07003000static int selinux_file_alloc_security(struct file *file)
3001{
3002 return file_alloc_security(file);
3003}
3004
3005static void selinux_file_free_security(struct file *file)
3006{
3007 file_free_security(file);
3008}
3009
3010static int selinux_file_ioctl(struct file *file, unsigned int cmd,
3011 unsigned long arg)
3012{
David Howells88e67f32008-11-14 10:39:21 +11003013 const struct cred *cred = current_cred();
Eric Paris0b24dcb2011-02-25 15:39:20 -05003014 int error = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003015
Eric Paris0b24dcb2011-02-25 15:39:20 -05003016 switch (cmd) {
3017 case FIONREAD:
3018 /* fall through */
3019 case FIBMAP:
3020 /* fall through */
3021 case FIGETBSZ:
3022 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003023 case FS_IOC_GETFLAGS:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003024 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003025 case FS_IOC_GETVERSION:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003026 error = file_has_perm(cred, file, FILE__GETATTR);
3027 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003028
Al Viro2f99c362012-03-23 16:04:05 -04003029 case FS_IOC_SETFLAGS:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003030 /* fall through */
Al Viro2f99c362012-03-23 16:04:05 -04003031 case FS_IOC_SETVERSION:
Eric Paris0b24dcb2011-02-25 15:39:20 -05003032 error = file_has_perm(cred, file, FILE__SETATTR);
3033 break;
3034
3035 /* sys_ioctl() checks */
3036 case FIONBIO:
3037 /* fall through */
3038 case FIOASYNC:
3039 error = file_has_perm(cred, file, 0);
3040 break;
3041
3042 case KDSKBENT:
3043 case KDSKBSENT:
Eric Paris6a9de492012-01-03 12:25:14 -05003044 error = cred_has_capability(cred, CAP_SYS_TTY_CONFIG,
3045 SECURITY_CAP_AUDIT);
Eric Paris0b24dcb2011-02-25 15:39:20 -05003046 break;
3047
3048 /* default case assumes that the command will go
3049 * to the file's ioctl() function.
3050 */
3051 default:
3052 error = file_has_perm(cred, file, FILE__IOCTL);
3053 }
3054 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003055}
3056
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003057static int default_noexec;
3058
Linus Torvalds1da177e2005-04-16 15:20:36 -07003059static int file_map_prot_check(struct file *file, unsigned long prot, int shared)
3060{
David Howells88e67f32008-11-14 10:39:21 +11003061 const struct cred *cred = current_cred();
David Howellsd84f4f92008-11-14 10:39:23 +11003062 int rc = 0;
David Howells88e67f32008-11-14 10:39:21 +11003063
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003064 if (default_noexec &&
3065 (prot & PROT_EXEC) && (!file || (!shared && (prot & PROT_WRITE)))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003066 /*
3067 * We are making executable an anonymous mapping or a
3068 * private file mapping that will also be writable.
3069 * This has an additional check.
3070 */
David Howellsd84f4f92008-11-14 10:39:23 +11003071 rc = cred_has_perm(cred, cred, PROCESS__EXECMEM);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003072 if (rc)
David Howellsd84f4f92008-11-14 10:39:23 +11003073 goto error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003074 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003075
3076 if (file) {
3077 /* read access is always possible with a mapping */
3078 u32 av = FILE__READ;
3079
3080 /* write access only matters if the mapping is shared */
3081 if (shared && (prot & PROT_WRITE))
3082 av |= FILE__WRITE;
3083
3084 if (prot & PROT_EXEC)
3085 av |= FILE__EXECUTE;
3086
David Howells88e67f32008-11-14 10:39:21 +11003087 return file_has_perm(cred, file, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003088 }
David Howellsd84f4f92008-11-14 10:39:23 +11003089
3090error:
3091 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003092}
3093
Al Viroe5467852012-05-30 13:30:51 -04003094static int selinux_mmap_addr(unsigned long addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003095{
Eric Parised032182007-06-28 15:55:21 -04003096 int rc = 0;
David Howells275bb412008-11-14 10:39:19 +11003097 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003098
Eric Paris84336d1a2009-07-31 12:54:05 -04003099 /*
3100 * notice that we are intentionally putting the SELinux check before
3101 * the secondary cap_file_mmap check. This is such a likely attempt
3102 * at bad behaviour/exploit that we always want to get the AVC, even
3103 * if DAC would have also denied the operation.
3104 */
Eric Parisa2551df72009-07-31 12:54:11 -04003105 if (addr < CONFIG_LSM_MMAP_MIN_ADDR) {
Eric Parised032182007-06-28 15:55:21 -04003106 rc = avc_has_perm(sid, sid, SECCLASS_MEMPROTECT,
3107 MEMPROTECT__MMAP_ZERO, NULL);
Eric Paris84336d1a2009-07-31 12:54:05 -04003108 if (rc)
3109 return rc;
3110 }
3111
3112 /* do DAC check on address space usage */
Al Viroe5467852012-05-30 13:30:51 -04003113 return cap_mmap_addr(addr);
3114}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003115
Al Viroe5467852012-05-30 13:30:51 -04003116static int selinux_mmap_file(struct file *file, unsigned long reqprot,
3117 unsigned long prot, unsigned long flags)
3118{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003119 if (selinux_checkreqprot)
3120 prot = reqprot;
3121
3122 return file_map_prot_check(file, prot,
3123 (flags & MAP_TYPE) == MAP_SHARED);
3124}
3125
3126static int selinux_file_mprotect(struct vm_area_struct *vma,
3127 unsigned long reqprot,
3128 unsigned long prot)
3129{
David Howells88e67f32008-11-14 10:39:21 +11003130 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003131
3132 if (selinux_checkreqprot)
3133 prot = reqprot;
3134
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04003135 if (default_noexec &&
3136 (prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) {
James Morrisd541bbe2009-01-29 12:19:51 +11003137 int rc = 0;
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003138 if (vma->vm_start >= vma->vm_mm->start_brk &&
3139 vma->vm_end <= vma->vm_mm->brk) {
David Howellsd84f4f92008-11-14 10:39:23 +11003140 rc = cred_has_perm(cred, cred, PROCESS__EXECHEAP);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003141 } else if (!vma->vm_file &&
3142 vma->vm_start <= vma->vm_mm->start_stack &&
3143 vma->vm_end >= vma->vm_mm->start_stack) {
David Howells3b11a1d2008-11-14 10:39:26 +11003144 rc = current_has_perm(current, PROCESS__EXECSTACK);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003145 } else if (vma->vm_file && vma->anon_vma) {
3146 /*
3147 * We are making executable a file mapping that has
3148 * had some COW done. Since pages might have been
3149 * written, check ability to execute the possibly
3150 * modified content. This typically should only
3151 * occur for text relocations.
3152 */
David Howellsd84f4f92008-11-14 10:39:23 +11003153 rc = file_has_perm(cred, vma->vm_file, FILE__EXECMOD);
Stephen Smalleydb4c9642006-02-01 03:05:54 -08003154 }
Lorenzo Hernandez García-Hierro6b992192005-06-25 14:54:34 -07003155 if (rc)
3156 return rc;
3157 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003158
3159 return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED);
3160}
3161
3162static int selinux_file_lock(struct file *file, unsigned int cmd)
3163{
David Howells88e67f32008-11-14 10:39:21 +11003164 const struct cred *cred = current_cred();
3165
3166 return file_has_perm(cred, file, FILE__LOCK);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003167}
3168
3169static int selinux_file_fcntl(struct file *file, unsigned int cmd,
3170 unsigned long arg)
3171{
David Howells88e67f32008-11-14 10:39:21 +11003172 const struct cred *cred = current_cred();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003173 int err = 0;
3174
3175 switch (cmd) {
Eric Paris828dfe12008-04-17 13:17:49 -04003176 case F_SETFL:
Eric Paris828dfe12008-04-17 13:17:49 -04003177 if ((file->f_flags & O_APPEND) && !(arg & O_APPEND)) {
David Howells88e67f32008-11-14 10:39:21 +11003178 err = file_has_perm(cred, file, FILE__WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003179 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003180 }
3181 /* fall through */
3182 case F_SETOWN:
3183 case F_SETSIG:
3184 case F_GETFL:
3185 case F_GETOWN:
3186 case F_GETSIG:
Cyrill Gorcunov1d151c32012-07-30 14:43:00 -07003187 case F_GETOWNER_UIDS:
Eric Paris828dfe12008-04-17 13:17:49 -04003188 /* Just check FD__USE permission */
David Howells88e67f32008-11-14 10:39:21 +11003189 err = file_has_perm(cred, file, 0);
Eric Paris828dfe12008-04-17 13:17:49 -04003190 break;
3191 case F_GETLK:
3192 case F_SETLK:
3193 case F_SETLKW:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003194#if BITS_PER_LONG == 32
Eric Paris828dfe12008-04-17 13:17:49 -04003195 case F_GETLK64:
3196 case F_SETLK64:
3197 case F_SETLKW64:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003198#endif
David Howells88e67f32008-11-14 10:39:21 +11003199 err = file_has_perm(cred, file, FILE__LOCK);
Eric Paris828dfe12008-04-17 13:17:49 -04003200 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003201 }
3202
3203 return err;
3204}
3205
3206static int selinux_file_set_fowner(struct file *file)
3207{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003208 struct file_security_struct *fsec;
3209
Linus Torvalds1da177e2005-04-16 15:20:36 -07003210 fsec = file->f_security;
David Howells275bb412008-11-14 10:39:19 +11003211 fsec->fown_sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003212
3213 return 0;
3214}
3215
3216static int selinux_file_send_sigiotask(struct task_struct *tsk,
3217 struct fown_struct *fown, int signum)
3218{
Eric Paris828dfe12008-04-17 13:17:49 -04003219 struct file *file;
Stephen Smalley65c90bc2009-05-04 15:43:18 -04003220 u32 sid = task_sid(tsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003221 u32 perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003222 struct file_security_struct *fsec;
3223
3224 /* struct fown_struct is never outside the context of a struct file */
Eric Paris828dfe12008-04-17 13:17:49 -04003225 file = container_of(fown, struct file, f_owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003226
Linus Torvalds1da177e2005-04-16 15:20:36 -07003227 fsec = file->f_security;
3228
3229 if (!signum)
3230 perm = signal_to_av(SIGIO); /* as per send_sigio_to_task */
3231 else
3232 perm = signal_to_av(signum);
3233
David Howells275bb412008-11-14 10:39:19 +11003234 return avc_has_perm(fsec->fown_sid, sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003235 SECCLASS_PROCESS, perm, NULL);
3236}
3237
3238static int selinux_file_receive(struct file *file)
3239{
David Howells88e67f32008-11-14 10:39:21 +11003240 const struct cred *cred = current_cred();
3241
3242 return file_has_perm(cred, file, file_to_av(file));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003243}
3244
Eric Paris83d49852012-04-04 13:45:40 -04003245static int selinux_file_open(struct file *file, const struct cred *cred)
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003246{
3247 struct file_security_struct *fsec;
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003248 struct inode_security_struct *isec;
David Howellsd84f4f92008-11-14 10:39:23 +11003249
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003250 fsec = file->f_security;
Al Viro496ad9a2013-01-23 17:07:38 -05003251 isec = file_inode(file)->i_security;
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003252 /*
3253 * Save inode label and policy sequence number
3254 * at open-time so that selinux_file_permission
3255 * can determine whether revalidation is necessary.
3256 * Task label is already saved in the file security
3257 * struct as its SID.
3258 */
3259 fsec->isid = isec->sid;
3260 fsec->pseqno = avc_policy_seqno();
3261 /*
3262 * Since the inode label or policy seqno may have changed
3263 * between the selinux_inode_permission check and the saving
3264 * of state above, recheck that access is still permitted.
3265 * Otherwise, access might never be revalidated against the
3266 * new inode label or new policy.
3267 * This check is not redundant - do not remove.
3268 */
Eric Paris602a8dd2012-04-04 15:01:42 -04003269 return path_has_perm(cred, &file->f_path, open_file_to_av(file));
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09003270}
3271
Linus Torvalds1da177e2005-04-16 15:20:36 -07003272/* task security operations */
3273
3274static int selinux_task_create(unsigned long clone_flags)
3275{
David Howells3b11a1d2008-11-14 10:39:26 +11003276 return current_has_perm(current, PROCESS__FORK);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003277}
3278
David Howellsf1752ee2008-11-14 10:39:17 +11003279/*
David Howellsee18d642009-09-02 09:14:21 +01003280 * allocate the SELinux part of blank credentials
3281 */
3282static int selinux_cred_alloc_blank(struct cred *cred, gfp_t gfp)
3283{
3284 struct task_security_struct *tsec;
3285
3286 tsec = kzalloc(sizeof(struct task_security_struct), gfp);
3287 if (!tsec)
3288 return -ENOMEM;
3289
3290 cred->security = tsec;
3291 return 0;
3292}
3293
3294/*
David Howellsf1752ee2008-11-14 10:39:17 +11003295 * detach and free the LSM part of a set of credentials
3296 */
3297static void selinux_cred_free(struct cred *cred)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003298{
David Howellsf1752ee2008-11-14 10:39:17 +11003299 struct task_security_struct *tsec = cred->security;
David Howellse0e81732009-09-02 09:13:40 +01003300
Tetsuo Handa2edeaa32011-02-07 13:36:10 +00003301 /*
3302 * cred->security == NULL if security_cred_alloc_blank() or
3303 * security_prepare_creds() returned an error.
3304 */
3305 BUG_ON(cred->security && (unsigned long) cred->security < PAGE_SIZE);
David Howellse0e81732009-09-02 09:13:40 +01003306 cred->security = (void *) 0x7UL;
David Howellsf1752ee2008-11-14 10:39:17 +11003307 kfree(tsec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003308}
3309
David Howellsd84f4f92008-11-14 10:39:23 +11003310/*
3311 * prepare a new set of credentials for modification
3312 */
3313static int selinux_cred_prepare(struct cred *new, const struct cred *old,
3314 gfp_t gfp)
3315{
3316 const struct task_security_struct *old_tsec;
3317 struct task_security_struct *tsec;
3318
3319 old_tsec = old->security;
3320
3321 tsec = kmemdup(old_tsec, sizeof(struct task_security_struct), gfp);
3322 if (!tsec)
3323 return -ENOMEM;
3324
3325 new->security = tsec;
3326 return 0;
3327}
3328
3329/*
David Howellsee18d642009-09-02 09:14:21 +01003330 * transfer the SELinux data to a blank set of creds
3331 */
3332static void selinux_cred_transfer(struct cred *new, const struct cred *old)
3333{
3334 const struct task_security_struct *old_tsec = old->security;
3335 struct task_security_struct *tsec = new->security;
3336
3337 *tsec = *old_tsec;
3338}
3339
3340/*
David Howells3a3b7ce2008-11-14 10:39:28 +11003341 * set the security data for a kernel service
3342 * - all the creation contexts are set to unlabelled
3343 */
3344static int selinux_kernel_act_as(struct cred *new, u32 secid)
3345{
3346 struct task_security_struct *tsec = new->security;
3347 u32 sid = current_sid();
3348 int ret;
3349
3350 ret = avc_has_perm(sid, secid,
3351 SECCLASS_KERNEL_SERVICE,
3352 KERNEL_SERVICE__USE_AS_OVERRIDE,
3353 NULL);
3354 if (ret == 0) {
3355 tsec->sid = secid;
3356 tsec->create_sid = 0;
3357 tsec->keycreate_sid = 0;
3358 tsec->sockcreate_sid = 0;
3359 }
3360 return ret;
3361}
3362
3363/*
3364 * set the file creation context in a security record to the same as the
3365 * objective context of the specified inode
3366 */
3367static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode)
3368{
3369 struct inode_security_struct *isec = inode->i_security;
3370 struct task_security_struct *tsec = new->security;
3371 u32 sid = current_sid();
3372 int ret;
3373
3374 ret = avc_has_perm(sid, isec->sid,
3375 SECCLASS_KERNEL_SERVICE,
3376 KERNEL_SERVICE__CREATE_FILES_AS,
3377 NULL);
3378
3379 if (ret == 0)
3380 tsec->create_sid = isec->sid;
David Howellsef574712010-02-26 01:56:16 +00003381 return ret;
David Howells3a3b7ce2008-11-14 10:39:28 +11003382}
3383
Eric Parisdd8dbf22009-11-03 16:35:32 +11003384static int selinux_kernel_module_request(char *kmod_name)
Eric Paris25354c42009-08-13 09:45:03 -04003385{
Eric Parisdd8dbf22009-11-03 16:35:32 +11003386 u32 sid;
3387 struct common_audit_data ad;
3388
3389 sid = task_sid(current);
3390
Eric Paris50c205f2012-04-04 15:01:43 -04003391 ad.type = LSM_AUDIT_DATA_KMOD;
Eric Parisdd8dbf22009-11-03 16:35:32 +11003392 ad.u.kmod_name = kmod_name;
3393
3394 return avc_has_perm(sid, SECINITSID_KERNEL, SECCLASS_SYSTEM,
3395 SYSTEM__MODULE_REQUEST, &ad);
Eric Paris25354c42009-08-13 09:45:03 -04003396}
3397
Linus Torvalds1da177e2005-04-16 15:20:36 -07003398static int selinux_task_setpgid(struct task_struct *p, pid_t pgid)
3399{
David Howells3b11a1d2008-11-14 10:39:26 +11003400 return current_has_perm(p, PROCESS__SETPGID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003401}
3402
3403static int selinux_task_getpgid(struct task_struct *p)
3404{
David Howells3b11a1d2008-11-14 10:39:26 +11003405 return current_has_perm(p, PROCESS__GETPGID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003406}
3407
3408static int selinux_task_getsid(struct task_struct *p)
3409{
David Howells3b11a1d2008-11-14 10:39:26 +11003410 return current_has_perm(p, PROCESS__GETSESSION);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003411}
3412
David Quigleyf9008e42006-06-30 01:55:46 -07003413static void selinux_task_getsecid(struct task_struct *p, u32 *secid)
3414{
David Howells275bb412008-11-14 10:39:19 +11003415 *secid = task_sid(p);
David Quigleyf9008e42006-06-30 01:55:46 -07003416}
3417
Linus Torvalds1da177e2005-04-16 15:20:36 -07003418static int selinux_task_setnice(struct task_struct *p, int nice)
3419{
3420 int rc;
3421
Eric Paris200ac532009-02-12 15:01:04 -05003422 rc = cap_task_setnice(p, nice);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003423 if (rc)
3424 return rc;
3425
David Howells3b11a1d2008-11-14 10:39:26 +11003426 return current_has_perm(p, PROCESS__SETSCHED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003427}
3428
James Morris03e68062006-06-23 02:03:58 -07003429static int selinux_task_setioprio(struct task_struct *p, int ioprio)
3430{
Serge E. Hallynb5376772007-10-16 23:31:36 -07003431 int rc;
3432
Eric Paris200ac532009-02-12 15:01:04 -05003433 rc = cap_task_setioprio(p, ioprio);
Serge E. Hallynb5376772007-10-16 23:31:36 -07003434 if (rc)
3435 return rc;
3436
David Howells3b11a1d2008-11-14 10:39:26 +11003437 return current_has_perm(p, PROCESS__SETSCHED);
James Morris03e68062006-06-23 02:03:58 -07003438}
3439
David Quigleya1836a42006-06-30 01:55:49 -07003440static int selinux_task_getioprio(struct task_struct *p)
3441{
David Howells3b11a1d2008-11-14 10:39:26 +11003442 return current_has_perm(p, PROCESS__GETSCHED);
David Quigleya1836a42006-06-30 01:55:49 -07003443}
3444
Jiri Slaby8fd00b42009-08-26 18:41:16 +02003445static int selinux_task_setrlimit(struct task_struct *p, unsigned int resource,
3446 struct rlimit *new_rlim)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003447{
Jiri Slaby8fd00b42009-08-26 18:41:16 +02003448 struct rlimit *old_rlim = p->signal->rlim + resource;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003449
3450 /* Control the ability to change the hard limit (whether
3451 lowering or raising it), so that the hard limit can
3452 later be used as a safe reset point for the soft limit
David Howellsd84f4f92008-11-14 10:39:23 +11003453 upon context transitions. See selinux_bprm_committing_creds. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003454 if (old_rlim->rlim_max != new_rlim->rlim_max)
Jiri Slaby8fd00b42009-08-26 18:41:16 +02003455 return current_has_perm(p, PROCESS__SETRLIMIT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003456
3457 return 0;
3458}
3459
KOSAKI Motohirob0ae1982010-10-15 04:21:18 +09003460static int selinux_task_setscheduler(struct task_struct *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003461{
Serge E. Hallynb5376772007-10-16 23:31:36 -07003462 int rc;
3463
KOSAKI Motohirob0ae1982010-10-15 04:21:18 +09003464 rc = cap_task_setscheduler(p);
Serge E. Hallynb5376772007-10-16 23:31:36 -07003465 if (rc)
3466 return rc;
3467
David Howells3b11a1d2008-11-14 10:39:26 +11003468 return current_has_perm(p, PROCESS__SETSCHED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003469}
3470
3471static int selinux_task_getscheduler(struct task_struct *p)
3472{
David Howells3b11a1d2008-11-14 10:39:26 +11003473 return current_has_perm(p, PROCESS__GETSCHED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003474}
3475
David Quigley35601542006-06-23 02:04:01 -07003476static int selinux_task_movememory(struct task_struct *p)
3477{
David Howells3b11a1d2008-11-14 10:39:26 +11003478 return current_has_perm(p, PROCESS__SETSCHED);
David Quigley35601542006-06-23 02:04:01 -07003479}
3480
David Quigleyf9008e42006-06-30 01:55:46 -07003481static int selinux_task_kill(struct task_struct *p, struct siginfo *info,
3482 int sig, u32 secid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003483{
3484 u32 perm;
3485 int rc;
3486
Linus Torvalds1da177e2005-04-16 15:20:36 -07003487 if (!sig)
3488 perm = PROCESS__SIGNULL; /* null signal; existence test */
3489 else
3490 perm = signal_to_av(sig);
David Quigleyf9008e42006-06-30 01:55:46 -07003491 if (secid)
David Howells275bb412008-11-14 10:39:19 +11003492 rc = avc_has_perm(secid, task_sid(p),
3493 SECCLASS_PROCESS, perm, NULL);
David Quigleyf9008e42006-06-30 01:55:46 -07003494 else
David Howells3b11a1d2008-11-14 10:39:26 +11003495 rc = current_has_perm(p, perm);
David Quigleyf9008e42006-06-30 01:55:46 -07003496 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003497}
3498
Linus Torvalds1da177e2005-04-16 15:20:36 -07003499static int selinux_task_wait(struct task_struct *p)
3500{
Eric Paris8a535142007-10-22 16:10:31 -04003501 return task_has_perm(p, current, PROCESS__SIGCHLD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003502}
3503
Linus Torvalds1da177e2005-04-16 15:20:36 -07003504static void selinux_task_to_inode(struct task_struct *p,
3505 struct inode *inode)
3506{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003507 struct inode_security_struct *isec = inode->i_security;
David Howells275bb412008-11-14 10:39:19 +11003508 u32 sid = task_sid(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003509
David Howells275bb412008-11-14 10:39:19 +11003510 isec->sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003511 isec->initialized = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003512}
3513
Linus Torvalds1da177e2005-04-16 15:20:36 -07003514/* Returns error only if unable to parse addresses */
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003515static int selinux_parse_skb_ipv4(struct sk_buff *skb,
Thomas Liu2bf49692009-07-14 12:14:09 -04003516 struct common_audit_data *ad, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003517{
3518 int offset, ihlen, ret = -EINVAL;
3519 struct iphdr _iph, *ih;
3520
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03003521 offset = skb_network_offset(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003522 ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph);
3523 if (ih == NULL)
3524 goto out;
3525
3526 ihlen = ih->ihl * 4;
3527 if (ihlen < sizeof(_iph))
3528 goto out;
3529
Eric Paris48c62af2012-04-02 13:15:44 -04003530 ad->u.net->v4info.saddr = ih->saddr;
3531 ad->u.net->v4info.daddr = ih->daddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003532 ret = 0;
3533
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003534 if (proto)
3535 *proto = ih->protocol;
3536
Linus Torvalds1da177e2005-04-16 15:20:36 -07003537 switch (ih->protocol) {
Eric Paris828dfe12008-04-17 13:17:49 -04003538 case IPPROTO_TCP: {
3539 struct tcphdr _tcph, *th;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003540
Eric Paris828dfe12008-04-17 13:17:49 -04003541 if (ntohs(ih->frag_off) & IP_OFFSET)
3542 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003543
3544 offset += ihlen;
3545 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
3546 if (th == NULL)
3547 break;
3548
Eric Paris48c62af2012-04-02 13:15:44 -04003549 ad->u.net->sport = th->source;
3550 ad->u.net->dport = th->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003551 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003552 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003553
Eric Paris828dfe12008-04-17 13:17:49 -04003554 case IPPROTO_UDP: {
3555 struct udphdr _udph, *uh;
3556
3557 if (ntohs(ih->frag_off) & IP_OFFSET)
3558 break;
3559
3560 offset += ihlen;
3561 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
3562 if (uh == NULL)
3563 break;
3564
Eric Paris48c62af2012-04-02 13:15:44 -04003565 ad->u.net->sport = uh->source;
3566 ad->u.net->dport = uh->dest;
Eric Paris828dfe12008-04-17 13:17:49 -04003567 break;
3568 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003569
James Morris2ee92d42006-11-13 16:09:01 -08003570 case IPPROTO_DCCP: {
3571 struct dccp_hdr _dccph, *dh;
3572
3573 if (ntohs(ih->frag_off) & IP_OFFSET)
3574 break;
3575
3576 offset += ihlen;
3577 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
3578 if (dh == NULL)
3579 break;
3580
Eric Paris48c62af2012-04-02 13:15:44 -04003581 ad->u.net->sport = dh->dccph_sport;
3582 ad->u.net->dport = dh->dccph_dport;
James Morris2ee92d42006-11-13 16:09:01 -08003583 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003584 }
James Morris2ee92d42006-11-13 16:09:01 -08003585
Eric Paris828dfe12008-04-17 13:17:49 -04003586 default:
3587 break;
3588 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003589out:
3590 return ret;
3591}
3592
3593#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
3594
3595/* Returns error only if unable to parse addresses */
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003596static int selinux_parse_skb_ipv6(struct sk_buff *skb,
Thomas Liu2bf49692009-07-14 12:14:09 -04003597 struct common_audit_data *ad, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003598{
3599 u8 nexthdr;
3600 int ret = -EINVAL, offset;
3601 struct ipv6hdr _ipv6h, *ip6;
Jesse Gross75f28112011-11-30 17:05:51 -08003602 __be16 frag_off;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003603
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03003604 offset = skb_network_offset(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003605 ip6 = skb_header_pointer(skb, offset, sizeof(_ipv6h), &_ipv6h);
3606 if (ip6 == NULL)
3607 goto out;
3608
Eric Paris48c62af2012-04-02 13:15:44 -04003609 ad->u.net->v6info.saddr = ip6->saddr;
3610 ad->u.net->v6info.daddr = ip6->daddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003611 ret = 0;
3612
3613 nexthdr = ip6->nexthdr;
3614 offset += sizeof(_ipv6h);
Jesse Gross75f28112011-11-30 17:05:51 -08003615 offset = ipv6_skip_exthdr(skb, offset, &nexthdr, &frag_off);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003616 if (offset < 0)
3617 goto out;
3618
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003619 if (proto)
3620 *proto = nexthdr;
3621
Linus Torvalds1da177e2005-04-16 15:20:36 -07003622 switch (nexthdr) {
3623 case IPPROTO_TCP: {
Eric Paris828dfe12008-04-17 13:17:49 -04003624 struct tcphdr _tcph, *th;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003625
3626 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
3627 if (th == NULL)
3628 break;
3629
Eric Paris48c62af2012-04-02 13:15:44 -04003630 ad->u.net->sport = th->source;
3631 ad->u.net->dport = th->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003632 break;
3633 }
3634
3635 case IPPROTO_UDP: {
3636 struct udphdr _udph, *uh;
3637
3638 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
3639 if (uh == NULL)
3640 break;
3641
Eric Paris48c62af2012-04-02 13:15:44 -04003642 ad->u.net->sport = uh->source;
3643 ad->u.net->dport = uh->dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003644 break;
3645 }
3646
James Morris2ee92d42006-11-13 16:09:01 -08003647 case IPPROTO_DCCP: {
3648 struct dccp_hdr _dccph, *dh;
3649
3650 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
3651 if (dh == NULL)
3652 break;
3653
Eric Paris48c62af2012-04-02 13:15:44 -04003654 ad->u.net->sport = dh->dccph_sport;
3655 ad->u.net->dport = dh->dccph_dport;
James Morris2ee92d42006-11-13 16:09:01 -08003656 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003657 }
James Morris2ee92d42006-11-13 16:09:01 -08003658
Linus Torvalds1da177e2005-04-16 15:20:36 -07003659 /* includes fragments */
3660 default:
3661 break;
3662 }
3663out:
3664 return ret;
3665}
3666
3667#endif /* IPV6 */
3668
Thomas Liu2bf49692009-07-14 12:14:09 -04003669static int selinux_parse_skb(struct sk_buff *skb, struct common_audit_data *ad,
David Howellscf9481e2008-07-27 21:31:07 +10003670 char **_addrp, int src, u8 *proto)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003671{
David Howellscf9481e2008-07-27 21:31:07 +10003672 char *addrp;
3673 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003674
Eric Paris48c62af2012-04-02 13:15:44 -04003675 switch (ad->u.net->family) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003676 case PF_INET:
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003677 ret = selinux_parse_skb_ipv4(skb, ad, proto);
David Howellscf9481e2008-07-27 21:31:07 +10003678 if (ret)
3679 goto parse_error;
Eric Paris48c62af2012-04-02 13:15:44 -04003680 addrp = (char *)(src ? &ad->u.net->v4info.saddr :
3681 &ad->u.net->v4info.daddr);
David Howellscf9481e2008-07-27 21:31:07 +10003682 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003683
3684#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
3685 case PF_INET6:
Venkat Yekkirala67f83cb2006-11-08 17:04:26 -06003686 ret = selinux_parse_skb_ipv6(skb, ad, proto);
David Howellscf9481e2008-07-27 21:31:07 +10003687 if (ret)
3688 goto parse_error;
Eric Paris48c62af2012-04-02 13:15:44 -04003689 addrp = (char *)(src ? &ad->u.net->v6info.saddr :
3690 &ad->u.net->v6info.daddr);
David Howellscf9481e2008-07-27 21:31:07 +10003691 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003692#endif /* IPV6 */
3693 default:
David Howellscf9481e2008-07-27 21:31:07 +10003694 addrp = NULL;
3695 goto okay;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003696 }
3697
David Howellscf9481e2008-07-27 21:31:07 +10003698parse_error:
3699 printk(KERN_WARNING
3700 "SELinux: failure in selinux_parse_skb(),"
3701 " unable to parse packet\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003702 return ret;
David Howellscf9481e2008-07-27 21:31:07 +10003703
3704okay:
3705 if (_addrp)
3706 *_addrp = addrp;
3707 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003708}
3709
Paul Moore4f6a9932007-03-01 14:35:22 -05003710/**
Paul Moore220deb92008-01-29 08:38:23 -05003711 * selinux_skb_peerlbl_sid - Determine the peer label of a packet
Paul Moore4f6a9932007-03-01 14:35:22 -05003712 * @skb: the packet
Paul Moore75e22912008-01-29 08:38:04 -05003713 * @family: protocol family
Paul Moore220deb92008-01-29 08:38:23 -05003714 * @sid: the packet's peer label SID
Paul Moore4f6a9932007-03-01 14:35:22 -05003715 *
3716 * Description:
Paul Moore220deb92008-01-29 08:38:23 -05003717 * Check the various different forms of network peer labeling and determine
3718 * the peer label/SID for the packet; most of the magic actually occurs in
3719 * the security server function security_net_peersid_cmp(). The function
3720 * returns zero if the value in @sid is valid (although it may be SECSID_NULL)
3721 * or -EACCES if @sid is invalid due to inconsistencies with the different
3722 * peer labels.
Paul Moore4f6a9932007-03-01 14:35:22 -05003723 *
3724 */
Paul Moore220deb92008-01-29 08:38:23 -05003725static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)
Paul Moore4f6a9932007-03-01 14:35:22 -05003726{
Paul Moore71f1cb02008-01-29 08:51:16 -05003727 int err;
Paul Moore4f6a9932007-03-01 14:35:22 -05003728 u32 xfrm_sid;
3729 u32 nlbl_sid;
Paul Moore220deb92008-01-29 08:38:23 -05003730 u32 nlbl_type;
Paul Moore4f6a9932007-03-01 14:35:22 -05003731
Paul Moorebed4d7e2013-07-23 17:38:40 -04003732 err = selinux_skb_xfrm_sid(skb, &xfrm_sid);
3733 if (unlikely(err))
3734 return -EACCES;
3735 err = selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid);
3736 if (unlikely(err))
3737 return -EACCES;
Paul Moore220deb92008-01-29 08:38:23 -05003738
Paul Moore71f1cb02008-01-29 08:51:16 -05003739 err = security_net_peersid_resolve(nlbl_sid, nlbl_type, xfrm_sid, sid);
3740 if (unlikely(err)) {
3741 printk(KERN_WARNING
3742 "SELinux: failure in selinux_skb_peerlbl_sid(),"
3743 " unable to determine packet's peer label\n");
Paul Moore220deb92008-01-29 08:38:23 -05003744 return -EACCES;
Paul Moore71f1cb02008-01-29 08:51:16 -05003745 }
Paul Moore220deb92008-01-29 08:38:23 -05003746
3747 return 0;
Paul Moore4f6a9932007-03-01 14:35:22 -05003748}
3749
Linus Torvalds1da177e2005-04-16 15:20:36 -07003750/* socket security operations */
Paul Moored4f2d972010-04-22 14:46:18 -04003751
Harry Ciao2ad18bd2011-03-02 13:32:34 +08003752static int socket_sockcreate_sid(const struct task_security_struct *tsec,
3753 u16 secclass, u32 *socksid)
Paul Moored4f2d972010-04-22 14:46:18 -04003754{
Harry Ciao2ad18bd2011-03-02 13:32:34 +08003755 if (tsec->sockcreate_sid > SECSID_NULL) {
3756 *socksid = tsec->sockcreate_sid;
3757 return 0;
3758 }
3759
3760 return security_transition_sid(tsec->sid, tsec->sid, secclass, NULL,
3761 socksid);
Paul Moored4f2d972010-04-22 14:46:18 -04003762}
3763
Paul Moore253bfae2010-04-22 14:46:19 -04003764static int sock_has_perm(struct task_struct *task, struct sock *sk, u32 perms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003765{
Paul Moore253bfae2010-04-22 14:46:19 -04003766 struct sk_security_struct *sksec = sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04003767 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04003768 struct lsm_network_audit net = {0,};
Paul Moore253bfae2010-04-22 14:46:19 -04003769 u32 tsid = task_sid(task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003770
Paul Moore253bfae2010-04-22 14:46:19 -04003771 if (sksec->sid == SECINITSID_KERNEL)
3772 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003773
Eric Paris50c205f2012-04-04 15:01:43 -04003774 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04003775 ad.u.net = &net;
3776 ad.u.net->sk = sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003777
Paul Moore253bfae2010-04-22 14:46:19 -04003778 return avc_has_perm(tsid, sksec->sid, sksec->sclass, perms, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003779}
3780
3781static int selinux_socket_create(int family, int type,
3782 int protocol, int kern)
3783{
Paul Moore5fb49872010-04-22 14:46:19 -04003784 const struct task_security_struct *tsec = current_security();
Paul Moored4f2d972010-04-22 14:46:18 -04003785 u32 newsid;
David Howells275bb412008-11-14 10:39:19 +11003786 u16 secclass;
Harry Ciao2ad18bd2011-03-02 13:32:34 +08003787 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003788
3789 if (kern)
Paul Moored4f2d972010-04-22 14:46:18 -04003790 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003791
David Howells275bb412008-11-14 10:39:19 +11003792 secclass = socket_type_to_security_class(family, type, protocol);
Harry Ciao2ad18bd2011-03-02 13:32:34 +08003793 rc = socket_sockcreate_sid(tsec, secclass, &newsid);
3794 if (rc)
3795 return rc;
3796
Paul Moored4f2d972010-04-22 14:46:18 -04003797 return avc_has_perm(tsec->sid, newsid, secclass, SOCKET__CREATE, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003798}
3799
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07003800static int selinux_socket_post_create(struct socket *sock, int family,
3801 int type, int protocol, int kern)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003802{
Paul Moore5fb49872010-04-22 14:46:19 -04003803 const struct task_security_struct *tsec = current_security();
Paul Moored4f2d972010-04-22 14:46:18 -04003804 struct inode_security_struct *isec = SOCK_INODE(sock)->i_security;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07003805 struct sk_security_struct *sksec;
David Howells275bb412008-11-14 10:39:19 +11003806 int err = 0;
3807
Harry Ciao2ad18bd2011-03-02 13:32:34 +08003808 isec->sclass = socket_type_to_security_class(family, type, protocol);
3809
David Howells275bb412008-11-14 10:39:19 +11003810 if (kern)
3811 isec->sid = SECINITSID_KERNEL;
Harry Ciao2ad18bd2011-03-02 13:32:34 +08003812 else {
3813 err = socket_sockcreate_sid(tsec, isec->sclass, &(isec->sid));
3814 if (err)
3815 return err;
3816 }
David Howells275bb412008-11-14 10:39:19 +11003817
Linus Torvalds1da177e2005-04-16 15:20:36 -07003818 isec->initialized = 1;
3819
Venkat Yekkirala892c1412006-08-04 23:08:56 -07003820 if (sock->sk) {
3821 sksec = sock->sk->sk_security;
3822 sksec->sid = isec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05003823 sksec->sclass = isec->sclass;
Paul Moore389fb8002009-03-27 17:10:34 -04003824 err = selinux_netlbl_socket_post_create(sock->sk, family);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07003825 }
3826
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07003827 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003828}
3829
3830/* Range of port numbers used to automatically bind.
3831 Need to determine whether we should perform a name_bind
3832 permission check between the socket and the port number. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003833
3834static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen)
3835{
Paul Moore253bfae2010-04-22 14:46:19 -04003836 struct sock *sk = sock->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003837 u16 family;
3838 int err;
3839
Paul Moore253bfae2010-04-22 14:46:19 -04003840 err = sock_has_perm(current, sk, SOCKET__BIND);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003841 if (err)
3842 goto out;
3843
3844 /*
3845 * If PF_INET or PF_INET6, check name_bind permission for the port.
James Morris13402582005-09-30 14:24:34 -04003846 * Multiple address binding for SCTP is not supported yet: we just
3847 * check the first address now.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003848 */
Paul Moore253bfae2010-04-22 14:46:19 -04003849 family = sk->sk_family;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003850 if (family == PF_INET || family == PF_INET6) {
3851 char *addrp;
Paul Moore253bfae2010-04-22 14:46:19 -04003852 struct sk_security_struct *sksec = sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04003853 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04003854 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07003855 struct sockaddr_in *addr4 = NULL;
3856 struct sockaddr_in6 *addr6 = NULL;
3857 unsigned short snum;
James Morrise399f982008-06-12 01:39:58 +10003858 u32 sid, node_perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003859
Linus Torvalds1da177e2005-04-16 15:20:36 -07003860 if (family == PF_INET) {
3861 addr4 = (struct sockaddr_in *)address;
3862 snum = ntohs(addr4->sin_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003863 addrp = (char *)&addr4->sin_addr.s_addr;
3864 } else {
3865 addr6 = (struct sockaddr_in6 *)address;
3866 snum = ntohs(addr6->sin6_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003867 addrp = (char *)&addr6->sin6_addr.s6_addr;
3868 }
3869
Stephen Hemminger227b60f2007-10-10 17:30:46 -07003870 if (snum) {
3871 int low, high;
3872
3873 inet_get_local_port_range(&low, &high);
3874
3875 if (snum < max(PROT_SOCK, low) || snum > high) {
Paul Moore3e112172008-04-10 10:48:14 -04003876 err = sel_netport_sid(sk->sk_protocol,
3877 snum, &sid);
Stephen Hemminger227b60f2007-10-10 17:30:46 -07003878 if (err)
3879 goto out;
Eric Paris50c205f2012-04-04 15:01:43 -04003880 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04003881 ad.u.net = &net;
3882 ad.u.net->sport = htons(snum);
3883 ad.u.net->family = family;
Paul Moore253bfae2010-04-22 14:46:19 -04003884 err = avc_has_perm(sksec->sid, sid,
3885 sksec->sclass,
Stephen Hemminger227b60f2007-10-10 17:30:46 -07003886 SOCKET__NAME_BIND, &ad);
3887 if (err)
3888 goto out;
3889 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003890 }
Eric Paris828dfe12008-04-17 13:17:49 -04003891
Paul Moore253bfae2010-04-22 14:46:19 -04003892 switch (sksec->sclass) {
James Morris13402582005-09-30 14:24:34 -04003893 case SECCLASS_TCP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003894 node_perm = TCP_SOCKET__NODE_BIND;
3895 break;
Eric Paris828dfe12008-04-17 13:17:49 -04003896
James Morris13402582005-09-30 14:24:34 -04003897 case SECCLASS_UDP_SOCKET:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003898 node_perm = UDP_SOCKET__NODE_BIND;
3899 break;
James Morris2ee92d42006-11-13 16:09:01 -08003900
3901 case SECCLASS_DCCP_SOCKET:
3902 node_perm = DCCP_SOCKET__NODE_BIND;
3903 break;
3904
Linus Torvalds1da177e2005-04-16 15:20:36 -07003905 default:
3906 node_perm = RAWIP_SOCKET__NODE_BIND;
3907 break;
3908 }
Eric Paris828dfe12008-04-17 13:17:49 -04003909
Paul Moore224dfbd2008-01-29 08:38:13 -05003910 err = sel_netnode_sid(addrp, family, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003911 if (err)
3912 goto out;
Eric Paris828dfe12008-04-17 13:17:49 -04003913
Eric Paris50c205f2012-04-04 15:01:43 -04003914 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04003915 ad.u.net = &net;
3916 ad.u.net->sport = htons(snum);
3917 ad.u.net->family = family;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003918
3919 if (family == PF_INET)
Eric Paris48c62af2012-04-02 13:15:44 -04003920 ad.u.net->v4info.saddr = addr4->sin_addr.s_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003921 else
Eric Paris48c62af2012-04-02 13:15:44 -04003922 ad.u.net->v6info.saddr = addr6->sin6_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003923
Paul Moore253bfae2010-04-22 14:46:19 -04003924 err = avc_has_perm(sksec->sid, sid,
3925 sksec->sclass, node_perm, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003926 if (err)
3927 goto out;
3928 }
3929out:
3930 return err;
3931}
3932
3933static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen)
3934{
Paul Moore014ab192008-10-10 10:16:33 -04003935 struct sock *sk = sock->sk;
Paul Moore253bfae2010-04-22 14:46:19 -04003936 struct sk_security_struct *sksec = sk->sk_security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003937 int err;
3938
Paul Moore253bfae2010-04-22 14:46:19 -04003939 err = sock_has_perm(current, sk, SOCKET__CONNECT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003940 if (err)
3941 return err;
3942
3943 /*
James Morris2ee92d42006-11-13 16:09:01 -08003944 * If a TCP or DCCP socket, check name_connect permission for the port.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003945 */
Paul Moore253bfae2010-04-22 14:46:19 -04003946 if (sksec->sclass == SECCLASS_TCP_SOCKET ||
3947 sksec->sclass == SECCLASS_DCCP_SOCKET) {
Thomas Liu2bf49692009-07-14 12:14:09 -04003948 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04003949 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07003950 struct sockaddr_in *addr4 = NULL;
3951 struct sockaddr_in6 *addr6 = NULL;
3952 unsigned short snum;
James Morris2ee92d42006-11-13 16:09:01 -08003953 u32 sid, perm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003954
3955 if (sk->sk_family == PF_INET) {
3956 addr4 = (struct sockaddr_in *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07003957 if (addrlen < sizeof(struct sockaddr_in))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003958 return -EINVAL;
3959 snum = ntohs(addr4->sin_port);
3960 } else {
3961 addr6 = (struct sockaddr_in6 *)address;
Stephen Smalley911656f2005-07-28 21:16:21 -07003962 if (addrlen < SIN6_LEN_RFC2133)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003963 return -EINVAL;
3964 snum = ntohs(addr6->sin6_port);
3965 }
3966
Paul Moore3e112172008-04-10 10:48:14 -04003967 err = sel_netport_sid(sk->sk_protocol, snum, &sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003968 if (err)
3969 goto out;
3970
Paul Moore253bfae2010-04-22 14:46:19 -04003971 perm = (sksec->sclass == SECCLASS_TCP_SOCKET) ?
James Morris2ee92d42006-11-13 16:09:01 -08003972 TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT;
3973
Eric Paris50c205f2012-04-04 15:01:43 -04003974 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04003975 ad.u.net = &net;
3976 ad.u.net->dport = htons(snum);
3977 ad.u.net->family = sk->sk_family;
Paul Moore253bfae2010-04-22 14:46:19 -04003978 err = avc_has_perm(sksec->sid, sid, sksec->sclass, perm, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003979 if (err)
3980 goto out;
3981 }
3982
Paul Moore014ab192008-10-10 10:16:33 -04003983 err = selinux_netlbl_socket_connect(sk, address);
3984
Linus Torvalds1da177e2005-04-16 15:20:36 -07003985out:
3986 return err;
3987}
3988
3989static int selinux_socket_listen(struct socket *sock, int backlog)
3990{
Paul Moore253bfae2010-04-22 14:46:19 -04003991 return sock_has_perm(current, sock->sk, SOCKET__LISTEN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003992}
3993
3994static int selinux_socket_accept(struct socket *sock, struct socket *newsock)
3995{
3996 int err;
3997 struct inode_security_struct *isec;
3998 struct inode_security_struct *newisec;
3999
Paul Moore253bfae2010-04-22 14:46:19 -04004000 err = sock_has_perm(current, sock->sk, SOCKET__ACCEPT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004001 if (err)
4002 return err;
4003
4004 newisec = SOCK_INODE(newsock)->i_security;
4005
4006 isec = SOCK_INODE(sock)->i_security;
4007 newisec->sclass = isec->sclass;
4008 newisec->sid = isec->sid;
4009 newisec->initialized = 1;
4010
4011 return 0;
4012}
4013
4014static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg,
Eric Paris828dfe12008-04-17 13:17:49 -04004015 int size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004016{
Paul Moore253bfae2010-04-22 14:46:19 -04004017 return sock_has_perm(current, sock->sk, SOCKET__WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004018}
4019
4020static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg,
4021 int size, int flags)
4022{
Paul Moore253bfae2010-04-22 14:46:19 -04004023 return sock_has_perm(current, sock->sk, SOCKET__READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004024}
4025
4026static int selinux_socket_getsockname(struct socket *sock)
4027{
Paul Moore253bfae2010-04-22 14:46:19 -04004028 return sock_has_perm(current, sock->sk, SOCKET__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004029}
4030
4031static int selinux_socket_getpeername(struct socket *sock)
4032{
Paul Moore253bfae2010-04-22 14:46:19 -04004033 return sock_has_perm(current, sock->sk, SOCKET__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004034}
4035
Eric Paris828dfe12008-04-17 13:17:49 -04004036static int selinux_socket_setsockopt(struct socket *sock, int level, int optname)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004037{
Paul Mooref8687af2006-10-30 15:22:15 -08004038 int err;
4039
Paul Moore253bfae2010-04-22 14:46:19 -04004040 err = sock_has_perm(current, sock->sk, SOCKET__SETOPT);
Paul Mooref8687af2006-10-30 15:22:15 -08004041 if (err)
4042 return err;
4043
4044 return selinux_netlbl_socket_setsockopt(sock, level, optname);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004045}
4046
4047static int selinux_socket_getsockopt(struct socket *sock, int level,
4048 int optname)
4049{
Paul Moore253bfae2010-04-22 14:46:19 -04004050 return sock_has_perm(current, sock->sk, SOCKET__GETOPT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004051}
4052
4053static int selinux_socket_shutdown(struct socket *sock, int how)
4054{
Paul Moore253bfae2010-04-22 14:46:19 -04004055 return sock_has_perm(current, sock->sk, SOCKET__SHUTDOWN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004056}
4057
David S. Miller3610cda2011-01-05 15:38:53 -08004058static int selinux_socket_unix_stream_connect(struct sock *sock,
4059 struct sock *other,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004060 struct sock *newsk)
4061{
David S. Miller3610cda2011-01-05 15:38:53 -08004062 struct sk_security_struct *sksec_sock = sock->sk_security;
4063 struct sk_security_struct *sksec_other = other->sk_security;
Paul Moore4d1e2452010-04-22 14:46:18 -04004064 struct sk_security_struct *sksec_new = newsk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004065 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004066 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004067 int err;
4068
Eric Paris50c205f2012-04-04 15:01:43 -04004069 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004070 ad.u.net = &net;
4071 ad.u.net->sk = other;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004072
Paul Moore4d1e2452010-04-22 14:46:18 -04004073 err = avc_has_perm(sksec_sock->sid, sksec_other->sid,
4074 sksec_other->sclass,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004075 UNIX_STREAM_SOCKET__CONNECTTO, &ad);
4076 if (err)
4077 return err;
4078
Linus Torvalds1da177e2005-04-16 15:20:36 -07004079 /* server child socket */
Paul Moore4d1e2452010-04-22 14:46:18 -04004080 sksec_new->peer_sid = sksec_sock->sid;
4081 err = security_sid_mls_copy(sksec_other->sid, sksec_sock->sid,
4082 &sksec_new->sid);
4083 if (err)
4084 return err;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004085
Paul Moore4d1e2452010-04-22 14:46:18 -04004086 /* connecting socket */
4087 sksec_sock->peer_sid = sksec_new->sid;
4088
4089 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004090}
4091
4092static int selinux_socket_unix_may_send(struct socket *sock,
4093 struct socket *other)
4094{
Paul Moore253bfae2010-04-22 14:46:19 -04004095 struct sk_security_struct *ssec = sock->sk->sk_security;
4096 struct sk_security_struct *osec = other->sk->sk_security;
Thomas Liu2bf49692009-07-14 12:14:09 -04004097 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004098 struct lsm_network_audit net = {0,};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004099
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->sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004103
Paul Moore253bfae2010-04-22 14:46:19 -04004104 return avc_has_perm(ssec->sid, osec->sid, osec->sclass, SOCKET__SENDTO,
4105 &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004106}
4107
Paul Mooreeffad8d2008-01-29 08:49:27 -05004108static int selinux_inet_sys_rcv_skb(int ifindex, char *addrp, u16 family,
4109 u32 peer_sid,
Thomas Liu2bf49692009-07-14 12:14:09 -04004110 struct common_audit_data *ad)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004111{
4112 int err;
4113 u32 if_sid;
4114 u32 node_sid;
4115
4116 err = sel_netif_sid(ifindex, &if_sid);
4117 if (err)
4118 return err;
4119 err = avc_has_perm(peer_sid, if_sid,
4120 SECCLASS_NETIF, NETIF__INGRESS, ad);
4121 if (err)
4122 return err;
4123
4124 err = sel_netnode_sid(addrp, family, &node_sid);
4125 if (err)
4126 return err;
4127 return avc_has_perm(peer_sid, node_sid,
4128 SECCLASS_NODE, NODE__RECVFROM, ad);
4129}
4130
Paul Moore220deb92008-01-29 08:38:23 -05004131static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
Paul Moored8395c82008-10-10 10:16:30 -04004132 u16 family)
Paul Moore220deb92008-01-29 08:38:23 -05004133{
Paul Moore277d3422008-12-31 12:54:11 -05004134 int err = 0;
Paul Moore220deb92008-01-29 08:38:23 -05004135 struct sk_security_struct *sksec = sk->sk_security;
Paul Moore220deb92008-01-29 08:38:23 -05004136 u32 sk_sid = sksec->sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04004137 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004138 struct lsm_network_audit net = {0,};
Paul Moored8395c82008-10-10 10:16:30 -04004139 char *addrp;
4140
Eric Paris50c205f2012-04-04 15:01:43 -04004141 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004142 ad.u.net = &net;
4143 ad.u.net->netif = skb->skb_iif;
4144 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04004145 err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
4146 if (err)
4147 return err;
Paul Moore220deb92008-01-29 08:38:23 -05004148
Paul Moore58bfbb52009-03-27 17:10:41 -04004149 if (selinux_secmark_enabled()) {
Paul Moore220deb92008-01-29 08:38:23 -05004150 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
Paul Moored8395c82008-10-10 10:16:30 -04004151 PACKET__RECV, &ad);
Paul Moore58bfbb52009-03-27 17:10:41 -04004152 if (err)
4153 return err;
4154 }
Paul Moore220deb92008-01-29 08:38:23 -05004155
Steffen Klassertb9679a72011-02-23 12:55:21 +01004156 err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, &ad);
4157 if (err)
4158 return err;
4159 err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, &ad);
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004160
James Morris4e5ab4c2006-06-09 00:33:33 -07004161 return err;
4162}
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004163
James Morris4e5ab4c2006-06-09 00:33:33 -07004164static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
4165{
Paul Moore220deb92008-01-29 08:38:23 -05004166 int err;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004167 struct sk_security_struct *sksec = sk->sk_security;
Paul Moore220deb92008-01-29 08:38:23 -05004168 u16 family = sk->sk_family;
4169 u32 sk_sid = sksec->sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04004170 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004171 struct lsm_network_audit net = {0,};
Paul Moore220deb92008-01-29 08:38:23 -05004172 char *addrp;
Paul Moored8395c82008-10-10 10:16:30 -04004173 u8 secmark_active;
4174 u8 peerlbl_active;
James Morris4e5ab4c2006-06-09 00:33:33 -07004175
James Morris4e5ab4c2006-06-09 00:33:33 -07004176 if (family != PF_INET && family != PF_INET6)
Paul Moore220deb92008-01-29 08:38:23 -05004177 return 0;
James Morris4e5ab4c2006-06-09 00:33:33 -07004178
4179 /* Handle mapped IPv4 packets arriving via IPv6 sockets */
Al Viro87fcd702006-12-04 22:00:55 +00004180 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
James Morris4e5ab4c2006-06-09 00:33:33 -07004181 family = PF_INET;
4182
Paul Moored8395c82008-10-10 10:16:30 -04004183 /* If any sort of compatibility mode is enabled then handoff processing
4184 * to the selinux_sock_rcv_skb_compat() function to deal with the
4185 * special handling. We do this in an attempt to keep this function
4186 * as fast and as clean as possible. */
Paul Moore58bfbb52009-03-27 17:10:41 -04004187 if (!selinux_policycap_netpeer)
Paul Moored8395c82008-10-10 10:16:30 -04004188 return selinux_sock_rcv_skb_compat(sk, skb, family);
4189
4190 secmark_active = selinux_secmark_enabled();
4191 peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled();
4192 if (!secmark_active && !peerlbl_active)
4193 return 0;
4194
Eric Paris50c205f2012-04-04 15:01:43 -04004195 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004196 ad.u.net = &net;
4197 ad.u.net->netif = skb->skb_iif;
4198 ad.u.net->family = family;
Paul Moore224dfbd2008-01-29 08:38:13 -05004199 err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
James Morris4e5ab4c2006-06-09 00:33:33 -07004200 if (err)
Paul Moore220deb92008-01-29 08:38:23 -05004201 return err;
James Morris4e5ab4c2006-06-09 00:33:33 -07004202
Paul Moored8395c82008-10-10 10:16:30 -04004203 if (peerlbl_active) {
Paul Moored621d352008-01-29 08:43:36 -05004204 u32 peer_sid;
4205
4206 err = selinux_skb_peerlbl_sid(skb, family, &peer_sid);
4207 if (err)
4208 return err;
Eric Dumazet8964be42009-11-20 15:35:04 -08004209 err = selinux_inet_sys_rcv_skb(skb->skb_iif, addrp, family,
Paul Mooreeffad8d2008-01-29 08:49:27 -05004210 peer_sid, &ad);
Paul Mooredfaebe92008-10-10 10:16:31 -04004211 if (err) {
4212 selinux_netlbl_err(skb, err, 0);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004213 return err;
Paul Mooredfaebe92008-10-10 10:16:31 -04004214 }
Paul Moored621d352008-01-29 08:43:36 -05004215 err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER,
4216 PEER__RECV, &ad);
Paul Mooredfaebe92008-10-10 10:16:31 -04004217 if (err)
4218 selinux_netlbl_err(skb, err, 0);
Paul Moored621d352008-01-29 08:43:36 -05004219 }
4220
Paul Moored8395c82008-10-10 10:16:30 -04004221 if (secmark_active) {
Paul Mooreeffad8d2008-01-29 08:49:27 -05004222 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
4223 PACKET__RECV, &ad);
4224 if (err)
4225 return err;
4226 }
4227
Paul Moored621d352008-01-29 08:43:36 -05004228 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004229}
4230
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004231static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *optval,
4232 int __user *optlen, unsigned len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004233{
4234 int err = 0;
4235 char *scontext;
4236 u32 scontext_len;
Paul Moore253bfae2010-04-22 14:46:19 -04004237 struct sk_security_struct *sksec = sock->sk->sk_security;
Paul Moore3de4bab2006-11-17 17:38:54 -05004238 u32 peer_sid = SECSID_NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004239
Paul Moore253bfae2010-04-22 14:46:19 -04004240 if (sksec->sclass == SECCLASS_UNIX_STREAM_SOCKET ||
4241 sksec->sclass == SECCLASS_TCP_SOCKET)
Eric Parisdd3e7832010-04-07 15:08:46 -04004242 peer_sid = sksec->peer_sid;
Paul Moore253bfae2010-04-22 14:46:19 -04004243 if (peer_sid == SECSID_NULL)
4244 return -ENOPROTOOPT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004245
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004246 err = security_sid_to_context(peer_sid, &scontext, &scontext_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004247 if (err)
Paul Moore253bfae2010-04-22 14:46:19 -04004248 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004249
4250 if (scontext_len > len) {
4251 err = -ERANGE;
4252 goto out_len;
4253 }
4254
4255 if (copy_to_user(optval, scontext, scontext_len))
4256 err = -EFAULT;
4257
4258out_len:
4259 if (put_user(scontext_len, optlen))
4260 err = -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004261 kfree(scontext);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004262 return err;
4263}
4264
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004265static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid)
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004266{
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004267 u32 peer_secid = SECSID_NULL;
Paul Moore75e22912008-01-29 08:38:04 -05004268 u16 family;
Catherine Zhang877ce7c2006-06-29 12:27:47 -07004269
Paul Mooreaa862902008-10-10 10:16:29 -04004270 if (skb && skb->protocol == htons(ETH_P_IP))
4271 family = PF_INET;
4272 else if (skb && skb->protocol == htons(ETH_P_IPV6))
4273 family = PF_INET6;
4274 else if (sock)
Paul Moore75e22912008-01-29 08:38:04 -05004275 family = sock->sk->sk_family;
Paul Moore75e22912008-01-29 08:38:04 -05004276 else
4277 goto out;
4278
4279 if (sock && family == PF_UNIX)
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02004280 selinux_inode_getsecid(SOCK_INODE(sock), &peer_secid);
Paul Moore3de4bab2006-11-17 17:38:54 -05004281 else if (skb)
Paul Moore220deb92008-01-29 08:38:23 -05004282 selinux_skb_peerlbl_sid(skb, family, &peer_secid);
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004283
Paul Moore75e22912008-01-29 08:38:04 -05004284out:
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07004285 *secid = peer_secid;
Paul Moore75e22912008-01-29 08:38:04 -05004286 if (peer_secid == SECSID_NULL)
4287 return -EINVAL;
4288 return 0;
Catherine Zhang2c7946a2006-03-20 22:41:23 -08004289}
4290
Al Viro7d877f32005-10-21 03:20:43 -04004291static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004292{
Paul Moore84914b72010-04-22 14:46:18 -04004293 struct sk_security_struct *sksec;
4294
4295 sksec = kzalloc(sizeof(*sksec), priority);
4296 if (!sksec)
4297 return -ENOMEM;
4298
4299 sksec->peer_sid = SECINITSID_UNLABELED;
4300 sksec->sid = SECINITSID_UNLABELED;
4301 selinux_netlbl_sk_security_reset(sksec);
4302 sk->sk_security = sksec;
4303
4304 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004305}
4306
4307static void selinux_sk_free_security(struct sock *sk)
4308{
Paul Moore84914b72010-04-22 14:46:18 -04004309 struct sk_security_struct *sksec = sk->sk_security;
4310
4311 sk->sk_security = NULL;
4312 selinux_netlbl_sk_security_free(sksec);
4313 kfree(sksec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004314}
4315
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004316static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk)
4317{
Eric Parisdd3e7832010-04-07 15:08:46 -04004318 struct sk_security_struct *sksec = sk->sk_security;
4319 struct sk_security_struct *newsksec = newsk->sk_security;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004320
Eric Parisdd3e7832010-04-07 15:08:46 -04004321 newsksec->sid = sksec->sid;
4322 newsksec->peer_sid = sksec->peer_sid;
4323 newsksec->sclass = sksec->sclass;
Paul Moore99f59ed2006-08-29 17:53:48 -07004324
Eric Parisdd3e7832010-04-07 15:08:46 -04004325 selinux_netlbl_sk_security_reset(newsksec);
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004326}
4327
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004328static void selinux_sk_getsecid(struct sock *sk, u32 *secid)
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004329{
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004330 if (!sk)
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004331 *secid = SECINITSID_ANY_SOCKET;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004332 else {
4333 struct sk_security_struct *sksec = sk->sk_security;
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004334
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -07004335 *secid = sksec->sid;
Venkat Yekkirala892c1412006-08-04 23:08:56 -07004336 }
Trent Jaegerd28d1e02005-12-13 23:12:40 -08004337}
4338
Eric Paris828dfe12008-04-17 13:17:49 -04004339static void selinux_sock_graft(struct sock *sk, struct socket *parent)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004340{
4341 struct inode_security_struct *isec = SOCK_INODE(parent)->i_security;
4342 struct sk_security_struct *sksec = sk->sk_security;
4343
David Woodhouse2148ccc2006-09-29 15:50:25 -07004344 if (sk->sk_family == PF_INET || sk->sk_family == PF_INET6 ||
4345 sk->sk_family == PF_UNIX)
4346 isec->sid = sksec->sid;
Paul Moore220deb92008-01-29 08:38:23 -05004347 sksec->sclass = isec->sclass;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004348}
4349
Adrian Bunk9a673e52006-08-15 00:03:53 -07004350static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
4351 struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004352{
4353 struct sk_security_struct *sksec = sk->sk_security;
4354 int err;
Paul Mooreaa862902008-10-10 10:16:29 -04004355 u16 family = sk->sk_family;
Venkat Yekkirala7420ed22006-08-04 23:17:57 -07004356 u32 newsid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004357 u32 peersid;
4358
Paul Mooreaa862902008-10-10 10:16:29 -04004359 /* handle mapped IPv4 packets arriving via IPv6 sockets */
4360 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
4361 family = PF_INET;
4362
4363 err = selinux_skb_peerlbl_sid(skb, family, &peersid);
Paul Moore220deb92008-01-29 08:38:23 -05004364 if (err)
4365 return err;
Venkat Yekkiralaa51c64f2006-07-27 22:01:34 -07004366 if (peersid == SECSID_NULL) {
4367 req->secid = sksec->sid;
Paul Moore3de4bab2006-11-17 17:38:54 -05004368 req->peer_secid = SECSID_NULL;
Paul Moore389fb8002009-03-27 17:10:34 -04004369 } else {
4370 err = security_sid_mls_copy(sksec->sid, peersid, &newsid);
4371 if (err)
4372 return err;
4373 req->secid = newsid;
4374 req->peer_secid = peersid;
Venkat Yekkiralaa51c64f2006-07-27 22:01:34 -07004375 }
4376
Paul Moore389fb8002009-03-27 17:10:34 -04004377 return selinux_netlbl_inet_conn_request(req, family);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004378}
4379
Adrian Bunk9a673e52006-08-15 00:03:53 -07004380static void selinux_inet_csk_clone(struct sock *newsk,
4381 const struct request_sock *req)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004382{
4383 struct sk_security_struct *newsksec = newsk->sk_security;
4384
4385 newsksec->sid = req->secid;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004386 newsksec->peer_sid = req->peer_secid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004387 /* NOTE: Ideally, we should also get the isec->sid for the
4388 new socket in sync, but we don't have the isec available yet.
4389 So we will wait until sock_graft to do it, by which
4390 time it will have been created and available. */
Paul Moore99f59ed2006-08-29 17:53:48 -07004391
Paul Moore9f2ad662006-11-17 17:38:53 -05004392 /* We don't need to take any sort of lock here as we are the only
4393 * thread with access to newsksec */
Paul Moore389fb8002009-03-27 17:10:34 -04004394 selinux_netlbl_inet_csk_clone(newsk, req->rsk_ops->family);
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004395}
4396
Paul Moore014ab192008-10-10 10:16:33 -04004397static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb)
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004398{
Paul Mooreaa862902008-10-10 10:16:29 -04004399 u16 family = sk->sk_family;
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004400 struct sk_security_struct *sksec = sk->sk_security;
4401
Paul Mooreaa862902008-10-10 10:16:29 -04004402 /* handle mapped IPv4 packets arriving via IPv6 sockets */
4403 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
4404 family = PF_INET;
4405
4406 selinux_skb_peerlbl_sid(skb, family, &sksec->peer_sid);
Venkat Yekkirala6b877692006-11-08 17:04:09 -06004407}
4408
Eric Dumazetca10b9e2013-04-08 17:58:11 +00004409static void selinux_skb_owned_by(struct sk_buff *skb, struct sock *sk)
4410{
4411 skb_set_owner_w(skb, sk);
4412}
4413
Eric Paris2606fd12010-10-13 16:24:41 -04004414static int selinux_secmark_relabel_packet(u32 sid)
4415{
4416 const struct task_security_struct *__tsec;
4417 u32 tsid;
4418
4419 __tsec = current_security();
4420 tsid = __tsec->sid;
4421
4422 return avc_has_perm(tsid, sid, SECCLASS_PACKET, PACKET__RELABELTO, NULL);
4423}
4424
4425static void selinux_secmark_refcount_inc(void)
4426{
4427 atomic_inc(&selinux_secmark_refcount);
4428}
4429
4430static void selinux_secmark_refcount_dec(void)
4431{
4432 atomic_dec(&selinux_secmark_refcount);
4433}
4434
Adrian Bunk9a673e52006-08-15 00:03:53 -07004435static void selinux_req_classify_flow(const struct request_sock *req,
4436 struct flowi *fl)
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004437{
David S. Miller1d28f422011-03-12 00:29:39 -05004438 fl->flowi_secid = req->secid;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004439}
4440
Paul Moore5dbbaf22013-01-14 07:12:19 +00004441static int selinux_tun_dev_alloc_security(void **security)
4442{
4443 struct tun_security_struct *tunsec;
4444
4445 tunsec = kzalloc(sizeof(*tunsec), GFP_KERNEL);
4446 if (!tunsec)
4447 return -ENOMEM;
4448 tunsec->sid = current_sid();
4449
4450 *security = tunsec;
4451 return 0;
4452}
4453
4454static void selinux_tun_dev_free_security(void *security)
4455{
4456 kfree(security);
4457}
4458
Paul Mooreed6d76e2009-08-28 18:12:49 -04004459static int selinux_tun_dev_create(void)
4460{
4461 u32 sid = current_sid();
4462
4463 /* we aren't taking into account the "sockcreate" SID since the socket
4464 * that is being created here is not a socket in the traditional sense,
4465 * instead it is a private sock, accessible only to the kernel, and
4466 * representing a wide range of network traffic spanning multiple
4467 * connections unlike traditional sockets - check the TUN driver to
4468 * get a better understanding of why this socket is special */
4469
4470 return avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET, TUN_SOCKET__CREATE,
4471 NULL);
4472}
4473
Paul Moore5dbbaf22013-01-14 07:12:19 +00004474static int selinux_tun_dev_attach_queue(void *security)
Paul Mooreed6d76e2009-08-28 18:12:49 -04004475{
Paul Moore5dbbaf22013-01-14 07:12:19 +00004476 struct tun_security_struct *tunsec = security;
4477
4478 return avc_has_perm(current_sid(), tunsec->sid, SECCLASS_TUN_SOCKET,
4479 TUN_SOCKET__ATTACH_QUEUE, NULL);
4480}
4481
4482static int selinux_tun_dev_attach(struct sock *sk, void *security)
4483{
4484 struct tun_security_struct *tunsec = security;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004485 struct sk_security_struct *sksec = sk->sk_security;
4486
4487 /* we don't currently perform any NetLabel based labeling here and it
4488 * isn't clear that we would want to do so anyway; while we could apply
4489 * labeling without the support of the TUN user the resulting labeled
4490 * traffic from the other end of the connection would almost certainly
4491 * cause confusion to the TUN user that had no idea network labeling
4492 * protocols were being used */
4493
Paul Moore5dbbaf22013-01-14 07:12:19 +00004494 sksec->sid = tunsec->sid;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004495 sksec->sclass = SECCLASS_TUN_SOCKET;
Paul Moore5dbbaf22013-01-14 07:12:19 +00004496
4497 return 0;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004498}
4499
Paul Moore5dbbaf22013-01-14 07:12:19 +00004500static int selinux_tun_dev_open(void *security)
Paul Mooreed6d76e2009-08-28 18:12:49 -04004501{
Paul Moore5dbbaf22013-01-14 07:12:19 +00004502 struct tun_security_struct *tunsec = security;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004503 u32 sid = current_sid();
4504 int err;
4505
Paul Moore5dbbaf22013-01-14 07:12:19 +00004506 err = avc_has_perm(sid, tunsec->sid, SECCLASS_TUN_SOCKET,
Paul Mooreed6d76e2009-08-28 18:12:49 -04004507 TUN_SOCKET__RELABELFROM, NULL);
4508 if (err)
4509 return err;
4510 err = avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET,
4511 TUN_SOCKET__RELABELTO, NULL);
4512 if (err)
4513 return err;
Paul Moore5dbbaf22013-01-14 07:12:19 +00004514 tunsec->sid = sid;
Paul Mooreed6d76e2009-08-28 18:12:49 -04004515
4516 return 0;
4517}
4518
Linus Torvalds1da177e2005-04-16 15:20:36 -07004519static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
4520{
4521 int err = 0;
4522 u32 perm;
4523 struct nlmsghdr *nlh;
Paul Moore253bfae2010-04-22 14:46:19 -04004524 struct sk_security_struct *sksec = sk->sk_security;
Eric Paris828dfe12008-04-17 13:17:49 -04004525
Hong zhi guo77954982013-03-27 06:49:35 +00004526 if (skb->len < NLMSG_HDRLEN) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004527 err = -EINVAL;
4528 goto out;
4529 }
Arnaldo Carvalho de Melob529ccf2007-04-25 19:08:35 -07004530 nlh = nlmsg_hdr(skb);
Eric Paris828dfe12008-04-17 13:17:49 -04004531
Paul Moore253bfae2010-04-22 14:46:19 -04004532 err = selinux_nlmsg_lookup(sksec->sclass, nlh->nlmsg_type, &perm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004533 if (err) {
4534 if (err == -EINVAL) {
David Woodhouse9ad9ad32005-06-22 15:04:33 +01004535 audit_log(current->audit_context, GFP_KERNEL, AUDIT_SELINUX_ERR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004536 "SELinux: unrecognized netlink message"
4537 " type=%hu for sclass=%hu\n",
Paul Moore253bfae2010-04-22 14:46:19 -04004538 nlh->nlmsg_type, sksec->sclass);
Eric Paris39c9aed2008-11-05 09:34:42 -05004539 if (!selinux_enforcing || security_get_allow_unknown())
Linus Torvalds1da177e2005-04-16 15:20:36 -07004540 err = 0;
4541 }
4542
4543 /* Ignore */
4544 if (err == -ENOENT)
4545 err = 0;
4546 goto out;
4547 }
4548
Paul Moore253bfae2010-04-22 14:46:19 -04004549 err = sock_has_perm(current, sk, perm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004550out:
4551 return err;
4552}
4553
4554#ifdef CONFIG_NETFILTER
4555
Paul Mooreeffad8d2008-01-29 08:49:27 -05004556static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex,
4557 u16 family)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004558{
Paul Mooredfaebe92008-10-10 10:16:31 -04004559 int err;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004560 char *addrp;
4561 u32 peer_sid;
Thomas Liu2bf49692009-07-14 12:14:09 -04004562 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004563 struct lsm_network_audit net = {0,};
Paul Mooreeffad8d2008-01-29 08:49:27 -05004564 u8 secmark_active;
Paul Moore948bf852008-10-10 10:16:32 -04004565 u8 netlbl_active;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004566 u8 peerlbl_active;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004567
Paul Mooreeffad8d2008-01-29 08:49:27 -05004568 if (!selinux_policycap_netpeer)
4569 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004570
Paul Mooreeffad8d2008-01-29 08:49:27 -05004571 secmark_active = selinux_secmark_enabled();
Paul Moore948bf852008-10-10 10:16:32 -04004572 netlbl_active = netlbl_enabled();
4573 peerlbl_active = netlbl_active || selinux_xfrm_enabled();
Paul Mooreeffad8d2008-01-29 08:49:27 -05004574 if (!secmark_active && !peerlbl_active)
4575 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004576
Paul Moored8395c82008-10-10 10:16:30 -04004577 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0)
4578 return NF_DROP;
4579
Eric Paris50c205f2012-04-04 15:01:43 -04004580 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004581 ad.u.net = &net;
4582 ad.u.net->netif = ifindex;
4583 ad.u.net->family = family;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004584 if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0)
4585 return NF_DROP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004586
Paul Mooredfaebe92008-10-10 10:16:31 -04004587 if (peerlbl_active) {
4588 err = selinux_inet_sys_rcv_skb(ifindex, addrp, family,
4589 peer_sid, &ad);
4590 if (err) {
4591 selinux_netlbl_err(skb, err, 1);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004592 return NF_DROP;
Paul Mooredfaebe92008-10-10 10:16:31 -04004593 }
4594 }
Paul Mooreeffad8d2008-01-29 08:49:27 -05004595
4596 if (secmark_active)
4597 if (avc_has_perm(peer_sid, skb->secmark,
4598 SECCLASS_PACKET, PACKET__FORWARD_IN, &ad))
4599 return NF_DROP;
4600
Paul Moore948bf852008-10-10 10:16:32 -04004601 if (netlbl_active)
4602 /* we do this in the FORWARD path and not the POST_ROUTING
4603 * path because we want to make sure we apply the necessary
4604 * labeling before IPsec is applied so we can leverage AH
4605 * protection */
4606 if (selinux_netlbl_skbuff_setsid(skb, family, peer_sid) != 0)
4607 return NF_DROP;
4608
Paul Mooreeffad8d2008-01-29 08:49:27 -05004609 return NF_ACCEPT;
4610}
4611
4612static unsigned int selinux_ipv4_forward(unsigned int hooknum,
4613 struct sk_buff *skb,
4614 const struct net_device *in,
4615 const struct net_device *out,
4616 int (*okfn)(struct sk_buff *))
4617{
4618 return selinux_ip_forward(skb, in->ifindex, PF_INET);
4619}
4620
4621#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
4622static unsigned int selinux_ipv6_forward(unsigned int hooknum,
4623 struct sk_buff *skb,
4624 const struct net_device *in,
4625 const struct net_device *out,
4626 int (*okfn)(struct sk_buff *))
4627{
4628 return selinux_ip_forward(skb, in->ifindex, PF_INET6);
4629}
4630#endif /* IPV6 */
4631
Paul Moore948bf852008-10-10 10:16:32 -04004632static unsigned int selinux_ip_output(struct sk_buff *skb,
4633 u16 family)
4634{
4635 u32 sid;
4636
4637 if (!netlbl_enabled())
4638 return NF_ACCEPT;
4639
4640 /* we do this in the LOCAL_OUT path and not the POST_ROUTING path
4641 * because we want to make sure we apply the necessary labeling
4642 * before IPsec is applied so we can leverage AH protection */
4643 if (skb->sk) {
4644 struct sk_security_struct *sksec = skb->sk->sk_security;
4645 sid = sksec->sid;
4646 } else
4647 sid = SECINITSID_KERNEL;
4648 if (selinux_netlbl_skbuff_setsid(skb, family, sid) != 0)
4649 return NF_DROP;
4650
4651 return NF_ACCEPT;
4652}
4653
4654static unsigned int selinux_ipv4_output(unsigned int hooknum,
4655 struct sk_buff *skb,
4656 const struct net_device *in,
4657 const struct net_device *out,
4658 int (*okfn)(struct sk_buff *))
4659{
4660 return selinux_ip_output(skb, PF_INET);
4661}
4662
Paul Mooreeffad8d2008-01-29 08:49:27 -05004663static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
4664 int ifindex,
Paul Moored8395c82008-10-10 10:16:30 -04004665 u16 family)
James Morris4e5ab4c2006-06-09 00:33:33 -07004666{
Paul Mooreeffad8d2008-01-29 08:49:27 -05004667 struct sock *sk = skb->sk;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004668 struct sk_security_struct *sksec;
Thomas Liu2bf49692009-07-14 12:14:09 -04004669 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004670 struct lsm_network_audit net = {0,};
Paul Moored8395c82008-10-10 10:16:30 -04004671 char *addrp;
4672 u8 proto;
James Morris4e5ab4c2006-06-09 00:33:33 -07004673
Paul Mooreeffad8d2008-01-29 08:49:27 -05004674 if (sk == NULL)
4675 return NF_ACCEPT;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07004676 sksec = sk->sk_security;
James Morris4e5ab4c2006-06-09 00:33:33 -07004677
Eric Paris50c205f2012-04-04 15:01:43 -04004678 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004679 ad.u.net = &net;
4680 ad.u.net->netif = ifindex;
4681 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04004682 if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto))
4683 return NF_DROP;
4684
Paul Moore58bfbb52009-03-27 17:10:41 -04004685 if (selinux_secmark_enabled())
Paul Mooreeffad8d2008-01-29 08:49:27 -05004686 if (avc_has_perm(sksec->sid, skb->secmark,
Paul Moored8395c82008-10-10 10:16:30 -04004687 SECCLASS_PACKET, PACKET__SEND, &ad))
Eric Paris2fe66ec2010-11-23 06:28:08 +00004688 return NF_DROP_ERR(-ECONNREFUSED);
James Morris4e5ab4c2006-06-09 00:33:33 -07004689
Steffen Klassertb9679a72011-02-23 12:55:21 +01004690 if (selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto))
4691 return NF_DROP_ERR(-ECONNREFUSED);
James Morris4e5ab4c2006-06-09 00:33:33 -07004692
Paul Mooreeffad8d2008-01-29 08:49:27 -05004693 return NF_ACCEPT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004694}
4695
Paul Mooreeffad8d2008-01-29 08:49:27 -05004696static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
4697 u16 family)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004698{
Paul Mooreeffad8d2008-01-29 08:49:27 -05004699 u32 secmark_perm;
4700 u32 peer_sid;
4701 struct sock *sk;
Thomas Liu2bf49692009-07-14 12:14:09 -04004702 struct common_audit_data ad;
Eric Paris48c62af2012-04-02 13:15:44 -04004703 struct lsm_network_audit net = {0,};
Paul Mooreeffad8d2008-01-29 08:49:27 -05004704 char *addrp;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004705 u8 secmark_active;
4706 u8 peerlbl_active;
4707
Paul Mooreeffad8d2008-01-29 08:49:27 -05004708 /* If any sort of compatibility mode is enabled then handoff processing
4709 * to the selinux_ip_postroute_compat() function to deal with the
4710 * special handling. We do this in an attempt to keep this function
4711 * as fast and as clean as possible. */
Paul Moore58bfbb52009-03-27 17:10:41 -04004712 if (!selinux_policycap_netpeer)
Paul Moored8395c82008-10-10 10:16:30 -04004713 return selinux_ip_postroute_compat(skb, ifindex, family);
Alexey Dobriyandef8b4f2008-10-28 13:24:06 -07004714#ifdef CONFIG_XFRM
Paul Mooreeffad8d2008-01-29 08:49:27 -05004715 /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec
4716 * packet transformation so allow the packet to pass without any checks
4717 * since we'll have another chance to perform access control checks
4718 * when the packet is on it's final way out.
4719 * NOTE: there appear to be some IPv6 multicast cases where skb->dst
4720 * is NULL, in this case go ahead and apply access control. */
Eric Dumazetadf30902009-06-02 05:19:30 +00004721 if (skb_dst(skb) != NULL && skb_dst(skb)->xfrm != NULL)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004722 return NF_ACCEPT;
Alexey Dobriyandef8b4f2008-10-28 13:24:06 -07004723#endif
Paul Mooreeffad8d2008-01-29 08:49:27 -05004724 secmark_active = selinux_secmark_enabled();
4725 peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled();
4726 if (!secmark_active && !peerlbl_active)
4727 return NF_ACCEPT;
4728
Paul Moored8395c82008-10-10 10:16:30 -04004729 /* if the packet is being forwarded then get the peer label from the
4730 * packet itself; otherwise check to see if it is from a local
4731 * application or the kernel, if from an application get the peer label
4732 * from the sending socket, otherwise use the kernel's sid */
Paul Mooreeffad8d2008-01-29 08:49:27 -05004733 sk = skb->sk;
Paul Moored8395c82008-10-10 10:16:30 -04004734 if (sk == NULL) {
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01004735 if (skb->skb_iif) {
4736 secmark_perm = PACKET__FORWARD_OUT;
Paul Moored8395c82008-10-10 10:16:30 -04004737 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00004738 return NF_DROP;
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01004739 } else {
4740 secmark_perm = PACKET__SEND;
Paul Moored8395c82008-10-10 10:16:30 -04004741 peer_sid = SECINITSID_KERNEL;
Steffen Klassert4a7ab3d2011-02-23 12:56:23 +01004742 }
Paul Moored8395c82008-10-10 10:16:30 -04004743 } else {
Paul Mooreeffad8d2008-01-29 08:49:27 -05004744 struct sk_security_struct *sksec = sk->sk_security;
4745 peer_sid = sksec->sid;
4746 secmark_perm = PACKET__SEND;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004747 }
4748
Eric Paris50c205f2012-04-04 15:01:43 -04004749 ad.type = LSM_AUDIT_DATA_NET;
Eric Paris48c62af2012-04-02 13:15:44 -04004750 ad.u.net = &net;
4751 ad.u.net->netif = ifindex;
4752 ad.u.net->family = family;
Paul Moored8395c82008-10-10 10:16:30 -04004753 if (selinux_parse_skb(skb, &ad, &addrp, 0, NULL))
Eric Paris04f6d702010-11-23 06:28:02 +00004754 return NF_DROP;
Paul Moored8395c82008-10-10 10:16:30 -04004755
Paul Mooreeffad8d2008-01-29 08:49:27 -05004756 if (secmark_active)
4757 if (avc_has_perm(peer_sid, skb->secmark,
4758 SECCLASS_PACKET, secmark_perm, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00004759 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004760
4761 if (peerlbl_active) {
4762 u32 if_sid;
4763 u32 node_sid;
4764
4765 if (sel_netif_sid(ifindex, &if_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00004766 return NF_DROP;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004767 if (avc_has_perm(peer_sid, if_sid,
4768 SECCLASS_NETIF, NETIF__EGRESS, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00004769 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004770
4771 if (sel_netnode_sid(addrp, family, &node_sid))
Eric Paris04f6d702010-11-23 06:28:02 +00004772 return NF_DROP;
Paul Mooreeffad8d2008-01-29 08:49:27 -05004773 if (avc_has_perm(peer_sid, node_sid,
4774 SECCLASS_NODE, NODE__SENDTO, &ad))
Eric Paris1f1aaf82010-11-16 11:52:57 +00004775 return NF_DROP_ERR(-ECONNREFUSED);
Paul Mooreeffad8d2008-01-29 08:49:27 -05004776 }
4777
4778 return NF_ACCEPT;
4779}
4780
4781static unsigned int selinux_ipv4_postroute(unsigned int hooknum,
4782 struct sk_buff *skb,
4783 const struct net_device *in,
4784 const struct net_device *out,
4785 int (*okfn)(struct sk_buff *))
4786{
4787 return selinux_ip_postroute(skb, out->ifindex, PF_INET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004788}
4789
4790#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Paul Mooreeffad8d2008-01-29 08:49:27 -05004791static unsigned int selinux_ipv6_postroute(unsigned int hooknum,
4792 struct sk_buff *skb,
4793 const struct net_device *in,
4794 const struct net_device *out,
4795 int (*okfn)(struct sk_buff *))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004796{
Paul Mooreeffad8d2008-01-29 08:49:27 -05004797 return selinux_ip_postroute(skb, out->ifindex, PF_INET6);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004798}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004799#endif /* IPV6 */
4800
4801#endif /* CONFIG_NETFILTER */
4802
Linus Torvalds1da177e2005-04-16 15:20:36 -07004803static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb)
4804{
Linus Torvalds1da177e2005-04-16 15:20:36 -07004805 int err;
4806
Eric Paris200ac532009-02-12 15:01:04 -05004807 err = cap_netlink_send(sk, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004808 if (err)
4809 return err;
4810
Stephen Smalley941fc5b2009-10-01 14:48:23 -04004811 return selinux_nlmsg_perm(sk, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004812}
4813
Linus Torvalds1da177e2005-04-16 15:20:36 -07004814static int ipc_alloc_security(struct task_struct *task,
4815 struct kern_ipc_perm *perm,
4816 u16 sclass)
4817{
Linus Torvalds1da177e2005-04-16 15:20:36 -07004818 struct ipc_security_struct *isec;
David Howells275bb412008-11-14 10:39:19 +11004819 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004820
James Morris89d155e2005-10-30 14:59:21 -08004821 isec = kzalloc(sizeof(struct ipc_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004822 if (!isec)
4823 return -ENOMEM;
4824
David Howells275bb412008-11-14 10:39:19 +11004825 sid = task_sid(task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004826 isec->sclass = sclass;
David Howells275bb412008-11-14 10:39:19 +11004827 isec->sid = sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004828 perm->security = isec;
4829
4830 return 0;
4831}
4832
4833static void ipc_free_security(struct kern_ipc_perm *perm)
4834{
4835 struct ipc_security_struct *isec = perm->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004836 perm->security = NULL;
4837 kfree(isec);
4838}
4839
4840static int msg_msg_alloc_security(struct msg_msg *msg)
4841{
4842 struct msg_security_struct *msec;
4843
James Morris89d155e2005-10-30 14:59:21 -08004844 msec = kzalloc(sizeof(struct msg_security_struct), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004845 if (!msec)
4846 return -ENOMEM;
4847
Linus Torvalds1da177e2005-04-16 15:20:36 -07004848 msec->sid = SECINITSID_UNLABELED;
4849 msg->security = msec;
4850
4851 return 0;
4852}
4853
4854static void msg_msg_free_security(struct msg_msg *msg)
4855{
4856 struct msg_security_struct *msec = msg->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004857
4858 msg->security = NULL;
4859 kfree(msec);
4860}
4861
4862static int ipc_has_perm(struct kern_ipc_perm *ipc_perms,
Stephen Smalley6af963f2005-05-01 08:58:39 -07004863 u32 perms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004864{
Linus Torvalds1da177e2005-04-16 15:20:36 -07004865 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04004866 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11004867 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004868
Linus Torvalds1da177e2005-04-16 15:20:36 -07004869 isec = ipc_perms->security;
4870
Eric Paris50c205f2012-04-04 15:01:43 -04004871 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004872 ad.u.ipc_id = ipc_perms->key;
4873
David Howells275bb412008-11-14 10:39:19 +11004874 return avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004875}
4876
4877static int selinux_msg_msg_alloc_security(struct msg_msg *msg)
4878{
4879 return msg_msg_alloc_security(msg);
4880}
4881
4882static void selinux_msg_msg_free_security(struct msg_msg *msg)
4883{
4884 msg_msg_free_security(msg);
4885}
4886
4887/* message queue security operations */
4888static int selinux_msg_queue_alloc_security(struct msg_queue *msq)
4889{
Linus Torvalds1da177e2005-04-16 15:20:36 -07004890 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04004891 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11004892 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004893 int rc;
4894
4895 rc = ipc_alloc_security(current, &msq->q_perm, SECCLASS_MSGQ);
4896 if (rc)
4897 return rc;
4898
Linus Torvalds1da177e2005-04-16 15:20:36 -07004899 isec = msq->q_perm.security;
4900
Eric Paris50c205f2012-04-04 15:01:43 -04004901 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04004902 ad.u.ipc_id = msq->q_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004903
David Howells275bb412008-11-14 10:39:19 +11004904 rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004905 MSGQ__CREATE, &ad);
4906 if (rc) {
4907 ipc_free_security(&msq->q_perm);
4908 return rc;
4909 }
4910 return 0;
4911}
4912
4913static void selinux_msg_queue_free_security(struct msg_queue *msq)
4914{
4915 ipc_free_security(&msq->q_perm);
4916}
4917
4918static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg)
4919{
Linus Torvalds1da177e2005-04-16 15:20:36 -07004920 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04004921 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11004922 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004923
Linus Torvalds1da177e2005-04-16 15:20:36 -07004924 isec = msq->q_perm.security;
4925
Eric Paris50c205f2012-04-04 15:01:43 -04004926 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004927 ad.u.ipc_id = msq->q_perm.key;
4928
David Howells275bb412008-11-14 10:39:19 +11004929 return avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004930 MSGQ__ASSOCIATE, &ad);
4931}
4932
4933static int selinux_msg_queue_msgctl(struct msg_queue *msq, int cmd)
4934{
4935 int err;
4936 int perms;
4937
Eric Paris828dfe12008-04-17 13:17:49 -04004938 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004939 case IPC_INFO:
4940 case MSG_INFO:
4941 /* No specific object, just general system-wide information. */
4942 return task_has_system(current, SYSTEM__IPC_INFO);
4943 case IPC_STAT:
4944 case MSG_STAT:
4945 perms = MSGQ__GETATTR | MSGQ__ASSOCIATE;
4946 break;
4947 case IPC_SET:
4948 perms = MSGQ__SETATTR;
4949 break;
4950 case IPC_RMID:
4951 perms = MSGQ__DESTROY;
4952 break;
4953 default:
4954 return 0;
4955 }
4956
Stephen Smalley6af963f2005-05-01 08:58:39 -07004957 err = ipc_has_perm(&msq->q_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004958 return err;
4959}
4960
4961static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, int msqflg)
4962{
Linus Torvalds1da177e2005-04-16 15:20:36 -07004963 struct ipc_security_struct *isec;
4964 struct msg_security_struct *msec;
Thomas Liu2bf49692009-07-14 12:14:09 -04004965 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11004966 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004967 int rc;
4968
Linus Torvalds1da177e2005-04-16 15:20:36 -07004969 isec = msq->q_perm.security;
4970 msec = msg->security;
4971
4972 /*
4973 * First time through, need to assign label to the message
4974 */
4975 if (msec->sid == SECINITSID_UNLABELED) {
4976 /*
4977 * Compute new sid based on current process and
4978 * message queue this message will be stored in
4979 */
David Howells275bb412008-11-14 10:39:19 +11004980 rc = security_transition_sid(sid, isec->sid, SECCLASS_MSG,
Eric Paris652bb9b2011-02-01 11:05:40 -05004981 NULL, &msec->sid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004982 if (rc)
4983 return rc;
4984 }
4985
Eric Paris50c205f2012-04-04 15:01:43 -04004986 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004987 ad.u.ipc_id = msq->q_perm.key;
4988
4989 /* Can this process write to the queue? */
David Howells275bb412008-11-14 10:39:19 +11004990 rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004991 MSGQ__WRITE, &ad);
4992 if (!rc)
4993 /* Can this process send the message */
David Howells275bb412008-11-14 10:39:19 +11004994 rc = avc_has_perm(sid, msec->sid, SECCLASS_MSG,
4995 MSG__SEND, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004996 if (!rc)
4997 /* Can the message be put in the queue? */
David Howells275bb412008-11-14 10:39:19 +11004998 rc = avc_has_perm(msec->sid, isec->sid, SECCLASS_MSGQ,
4999 MSGQ__ENQUEUE, &ad);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005000
5001 return rc;
5002}
5003
5004static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
5005 struct task_struct *target,
5006 long type, int mode)
5007{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005008 struct ipc_security_struct *isec;
5009 struct msg_security_struct *msec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005010 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005011 u32 sid = task_sid(target);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005012 int rc;
5013
Linus Torvalds1da177e2005-04-16 15:20:36 -07005014 isec = msq->q_perm.security;
5015 msec = msg->security;
5016
Eric Paris50c205f2012-04-04 15:01:43 -04005017 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04005018 ad.u.ipc_id = msq->q_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005019
David Howells275bb412008-11-14 10:39:19 +11005020 rc = avc_has_perm(sid, isec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005021 SECCLASS_MSGQ, MSGQ__READ, &ad);
5022 if (!rc)
David Howells275bb412008-11-14 10:39:19 +11005023 rc = avc_has_perm(sid, msec->sid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005024 SECCLASS_MSG, MSG__RECEIVE, &ad);
5025 return rc;
5026}
5027
5028/* Shared Memory security operations */
5029static int selinux_shm_alloc_security(struct shmid_kernel *shp)
5030{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005031 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005032 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005033 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005034 int rc;
5035
5036 rc = ipc_alloc_security(current, &shp->shm_perm, SECCLASS_SHM);
5037 if (rc)
5038 return rc;
5039
Linus Torvalds1da177e2005-04-16 15:20:36 -07005040 isec = shp->shm_perm.security;
5041
Eric Paris50c205f2012-04-04 15:01:43 -04005042 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04005043 ad.u.ipc_id = shp->shm_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005044
David Howells275bb412008-11-14 10:39:19 +11005045 rc = avc_has_perm(sid, isec->sid, SECCLASS_SHM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005046 SHM__CREATE, &ad);
5047 if (rc) {
5048 ipc_free_security(&shp->shm_perm);
5049 return rc;
5050 }
5051 return 0;
5052}
5053
5054static void selinux_shm_free_security(struct shmid_kernel *shp)
5055{
5056 ipc_free_security(&shp->shm_perm);
5057}
5058
5059static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg)
5060{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005061 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005062 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005063 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005064
Linus Torvalds1da177e2005-04-16 15:20:36 -07005065 isec = shp->shm_perm.security;
5066
Eric Paris50c205f2012-04-04 15:01:43 -04005067 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005068 ad.u.ipc_id = shp->shm_perm.key;
5069
David Howells275bb412008-11-14 10:39:19 +11005070 return avc_has_perm(sid, isec->sid, SECCLASS_SHM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005071 SHM__ASSOCIATE, &ad);
5072}
5073
5074/* Note, at this point, shp is locked down */
5075static int selinux_shm_shmctl(struct shmid_kernel *shp, int cmd)
5076{
5077 int perms;
5078 int err;
5079
Eric Paris828dfe12008-04-17 13:17:49 -04005080 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005081 case IPC_INFO:
5082 case SHM_INFO:
5083 /* No specific object, just general system-wide information. */
5084 return task_has_system(current, SYSTEM__IPC_INFO);
5085 case IPC_STAT:
5086 case SHM_STAT:
5087 perms = SHM__GETATTR | SHM__ASSOCIATE;
5088 break;
5089 case IPC_SET:
5090 perms = SHM__SETATTR;
5091 break;
5092 case SHM_LOCK:
5093 case SHM_UNLOCK:
5094 perms = SHM__LOCK;
5095 break;
5096 case IPC_RMID:
5097 perms = SHM__DESTROY;
5098 break;
5099 default:
5100 return 0;
5101 }
5102
Stephen Smalley6af963f2005-05-01 08:58:39 -07005103 err = ipc_has_perm(&shp->shm_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005104 return err;
5105}
5106
5107static int selinux_shm_shmat(struct shmid_kernel *shp,
5108 char __user *shmaddr, int shmflg)
5109{
5110 u32 perms;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005111
5112 if (shmflg & SHM_RDONLY)
5113 perms = SHM__READ;
5114 else
5115 perms = SHM__READ | SHM__WRITE;
5116
Stephen Smalley6af963f2005-05-01 08:58:39 -07005117 return ipc_has_perm(&shp->shm_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005118}
5119
5120/* Semaphore security operations */
5121static int selinux_sem_alloc_security(struct sem_array *sma)
5122{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005123 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005124 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005125 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005126 int rc;
5127
5128 rc = ipc_alloc_security(current, &sma->sem_perm, SECCLASS_SEM);
5129 if (rc)
5130 return rc;
5131
Linus Torvalds1da177e2005-04-16 15:20:36 -07005132 isec = sma->sem_perm.security;
5133
Eric Paris50c205f2012-04-04 15:01:43 -04005134 ad.type = LSM_AUDIT_DATA_IPC;
Eric Paris828dfe12008-04-17 13:17:49 -04005135 ad.u.ipc_id = sma->sem_perm.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005136
David Howells275bb412008-11-14 10:39:19 +11005137 rc = avc_has_perm(sid, isec->sid, SECCLASS_SEM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005138 SEM__CREATE, &ad);
5139 if (rc) {
5140 ipc_free_security(&sma->sem_perm);
5141 return rc;
5142 }
5143 return 0;
5144}
5145
5146static void selinux_sem_free_security(struct sem_array *sma)
5147{
5148 ipc_free_security(&sma->sem_perm);
5149}
5150
5151static int selinux_sem_associate(struct sem_array *sma, int semflg)
5152{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005153 struct ipc_security_struct *isec;
Thomas Liu2bf49692009-07-14 12:14:09 -04005154 struct common_audit_data ad;
David Howells275bb412008-11-14 10:39:19 +11005155 u32 sid = current_sid();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005156
Linus Torvalds1da177e2005-04-16 15:20:36 -07005157 isec = sma->sem_perm.security;
5158
Eric Paris50c205f2012-04-04 15:01:43 -04005159 ad.type = LSM_AUDIT_DATA_IPC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005160 ad.u.ipc_id = sma->sem_perm.key;
5161
David Howells275bb412008-11-14 10:39:19 +11005162 return avc_has_perm(sid, isec->sid, SECCLASS_SEM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005163 SEM__ASSOCIATE, &ad);
5164}
5165
5166/* Note, at this point, sma is locked down */
5167static int selinux_sem_semctl(struct sem_array *sma, int cmd)
5168{
5169 int err;
5170 u32 perms;
5171
Eric Paris828dfe12008-04-17 13:17:49 -04005172 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005173 case IPC_INFO:
5174 case SEM_INFO:
5175 /* No specific object, just general system-wide information. */
5176 return task_has_system(current, SYSTEM__IPC_INFO);
5177 case GETPID:
5178 case GETNCNT:
5179 case GETZCNT:
5180 perms = SEM__GETATTR;
5181 break;
5182 case GETVAL:
5183 case GETALL:
5184 perms = SEM__READ;
5185 break;
5186 case SETVAL:
5187 case SETALL:
5188 perms = SEM__WRITE;
5189 break;
5190 case IPC_RMID:
5191 perms = SEM__DESTROY;
5192 break;
5193 case IPC_SET:
5194 perms = SEM__SETATTR;
5195 break;
5196 case IPC_STAT:
5197 case SEM_STAT:
5198 perms = SEM__GETATTR | SEM__ASSOCIATE;
5199 break;
5200 default:
5201 return 0;
5202 }
5203
Stephen Smalley6af963f2005-05-01 08:58:39 -07005204 err = ipc_has_perm(&sma->sem_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005205 return err;
5206}
5207
5208static int selinux_sem_semop(struct sem_array *sma,
5209 struct sembuf *sops, unsigned nsops, int alter)
5210{
5211 u32 perms;
5212
5213 if (alter)
5214 perms = SEM__READ | SEM__WRITE;
5215 else
5216 perms = SEM__READ;
5217
Stephen Smalley6af963f2005-05-01 08:58:39 -07005218 return ipc_has_perm(&sma->sem_perm, perms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005219}
5220
5221static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
5222{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005223 u32 av = 0;
5224
Linus Torvalds1da177e2005-04-16 15:20:36 -07005225 av = 0;
5226 if (flag & S_IRUGO)
5227 av |= IPC__UNIX_READ;
5228 if (flag & S_IWUGO)
5229 av |= IPC__UNIX_WRITE;
5230
5231 if (av == 0)
5232 return 0;
5233
Stephen Smalley6af963f2005-05-01 08:58:39 -07005234 return ipc_has_perm(ipcp, av);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005235}
5236
Ahmed S. Darwish713a04ae2008-03-01 21:52:30 +02005237static void selinux_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
5238{
5239 struct ipc_security_struct *isec = ipcp->security;
5240 *secid = isec->sid;
5241}
5242
Eric Paris828dfe12008-04-17 13:17:49 -04005243static void selinux_d_instantiate(struct dentry *dentry, struct inode *inode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005244{
5245 if (inode)
5246 inode_doinit_with_dentry(inode, dentry);
5247}
5248
5249static int selinux_getprocattr(struct task_struct *p,
Al Viro04ff9702007-03-12 16:17:58 +00005250 char *name, char **value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005251{
David Howells275bb412008-11-14 10:39:19 +11005252 const struct task_security_struct *__tsec;
Dustin Kirkland8c8570f2005-11-03 17:15:16 +00005253 u32 sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005254 int error;
Al Viro04ff9702007-03-12 16:17:58 +00005255 unsigned len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005256
5257 if (current != p) {
David Howells3b11a1d2008-11-14 10:39:26 +11005258 error = current_has_perm(p, PROCESS__GETATTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005259 if (error)
5260 return error;
5261 }
5262
David Howells275bb412008-11-14 10:39:19 +11005263 rcu_read_lock();
5264 __tsec = __task_cred(p)->security;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005265
5266 if (!strcmp(name, "current"))
David Howells275bb412008-11-14 10:39:19 +11005267 sid = __tsec->sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005268 else if (!strcmp(name, "prev"))
David Howells275bb412008-11-14 10:39:19 +11005269 sid = __tsec->osid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005270 else if (!strcmp(name, "exec"))
David Howells275bb412008-11-14 10:39:19 +11005271 sid = __tsec->exec_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005272 else if (!strcmp(name, "fscreate"))
David Howells275bb412008-11-14 10:39:19 +11005273 sid = __tsec->create_sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005274 else if (!strcmp(name, "keycreate"))
David Howells275bb412008-11-14 10:39:19 +11005275 sid = __tsec->keycreate_sid;
Eric Paris42c3e032006-06-26 00:26:03 -07005276 else if (!strcmp(name, "sockcreate"))
David Howells275bb412008-11-14 10:39:19 +11005277 sid = __tsec->sockcreate_sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005278 else
David Howells275bb412008-11-14 10:39:19 +11005279 goto invalid;
5280 rcu_read_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005281
5282 if (!sid)
5283 return 0;
5284
Al Viro04ff9702007-03-12 16:17:58 +00005285 error = security_sid_to_context(sid, value, &len);
5286 if (error)
5287 return error;
5288 return len;
David Howells275bb412008-11-14 10:39:19 +11005289
5290invalid:
5291 rcu_read_unlock();
5292 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005293}
5294
5295static int selinux_setprocattr(struct task_struct *p,
5296 char *name, void *value, size_t size)
5297{
5298 struct task_security_struct *tsec;
Roland McGrath03563572008-03-26 15:46:39 -07005299 struct task_struct *tracer;
David Howellsd84f4f92008-11-14 10:39:23 +11005300 struct cred *new;
5301 u32 sid = 0, ptsid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005302 int error;
5303 char *str = value;
5304
5305 if (current != p) {
5306 /* SELinux only allows a process to change its own
5307 security attributes. */
5308 return -EACCES;
5309 }
5310
5311 /*
5312 * Basic control over ability to set these attributes at all.
5313 * current == p, but we'll pass them separately in case the
5314 * above restriction is ever removed.
5315 */
5316 if (!strcmp(name, "exec"))
David Howells3b11a1d2008-11-14 10:39:26 +11005317 error = current_has_perm(p, PROCESS__SETEXEC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005318 else if (!strcmp(name, "fscreate"))
David Howells3b11a1d2008-11-14 10:39:26 +11005319 error = current_has_perm(p, PROCESS__SETFSCREATE);
Michael LeMay4eb582c2006-06-26 00:24:57 -07005320 else if (!strcmp(name, "keycreate"))
David Howells3b11a1d2008-11-14 10:39:26 +11005321 error = current_has_perm(p, PROCESS__SETKEYCREATE);
Eric Paris42c3e032006-06-26 00:26:03 -07005322 else if (!strcmp(name, "sockcreate"))
David Howells3b11a1d2008-11-14 10:39:26 +11005323 error = current_has_perm(p, PROCESS__SETSOCKCREATE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005324 else if (!strcmp(name, "current"))
David Howells3b11a1d2008-11-14 10:39:26 +11005325 error = current_has_perm(p, PROCESS__SETCURRENT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005326 else
5327 error = -EINVAL;
5328 if (error)
5329 return error;
5330
5331 /* Obtain a SID for the context, if one was specified. */
5332 if (size && str[1] && str[1] != '\n') {
5333 if (str[size-1] == '\n') {
5334 str[size-1] = 0;
5335 size--;
5336 }
5337 error = security_context_to_sid(value, size, &sid);
Stephen Smalley12b29f32008-05-07 13:03:20 -04005338 if (error == -EINVAL && !strcmp(name, "fscreate")) {
Eric Parisd6ea83e2012-04-04 13:45:49 -04005339 if (!capable(CAP_MAC_ADMIN)) {
5340 struct audit_buffer *ab;
5341 size_t audit_size;
5342
5343 /* We strip a nul only if it is at the end, otherwise the
5344 * context contains a nul and we should audit that */
5345 if (str[size - 1] == '\0')
5346 audit_size = size - 1;
5347 else
5348 audit_size = size;
5349 ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR);
5350 audit_log_format(ab, "op=fscreate invalid_context=");
5351 audit_log_n_untrustedstring(ab, value, audit_size);
5352 audit_log_end(ab);
5353
Stephen Smalley12b29f32008-05-07 13:03:20 -04005354 return error;
Eric Parisd6ea83e2012-04-04 13:45:49 -04005355 }
Stephen Smalley12b29f32008-05-07 13:03:20 -04005356 error = security_context_to_sid_force(value, size,
5357 &sid);
5358 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005359 if (error)
5360 return error;
5361 }
5362
David Howellsd84f4f92008-11-14 10:39:23 +11005363 new = prepare_creds();
5364 if (!new)
5365 return -ENOMEM;
5366
Linus Torvalds1da177e2005-04-16 15:20:36 -07005367 /* Permission checking based on the specified context is
5368 performed during the actual operation (execve,
5369 open/mkdir/...), when we know the full context of the
David Howellsd84f4f92008-11-14 10:39:23 +11005370 operation. See selinux_bprm_set_creds for the execve
Linus Torvalds1da177e2005-04-16 15:20:36 -07005371 checks and may_create for the file creation checks. The
5372 operation will then fail if the context is not permitted. */
David Howellsd84f4f92008-11-14 10:39:23 +11005373 tsec = new->security;
5374 if (!strcmp(name, "exec")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005375 tsec->exec_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005376 } else if (!strcmp(name, "fscreate")) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005377 tsec->create_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005378 } else if (!strcmp(name, "keycreate")) {
Michael LeMay4eb582c2006-06-26 00:24:57 -07005379 error = may_create_key(sid, p);
5380 if (error)
David Howellsd84f4f92008-11-14 10:39:23 +11005381 goto abort_change;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005382 tsec->keycreate_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005383 } else if (!strcmp(name, "sockcreate")) {
Eric Paris42c3e032006-06-26 00:26:03 -07005384 tsec->sockcreate_sid = sid;
David Howellsd84f4f92008-11-14 10:39:23 +11005385 } else if (!strcmp(name, "current")) {
5386 error = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005387 if (sid == 0)
David Howellsd84f4f92008-11-14 10:39:23 +11005388 goto abort_change;
KaiGai Koheid9250de2008-08-28 16:35:57 +09005389
David Howellsd84f4f92008-11-14 10:39:23 +11005390 /* Only allow single threaded processes to change context */
5391 error = -EPERM;
Oleg Nesterov5bb459b2009-07-10 03:48:23 +02005392 if (!current_is_single_threaded()) {
David Howellsd84f4f92008-11-14 10:39:23 +11005393 error = security_bounded_transition(tsec->sid, sid);
5394 if (error)
5395 goto abort_change;
Eric Paris828dfe12008-04-17 13:17:49 -04005396 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005397
5398 /* Check permissions for the transition. */
5399 error = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS,
Eric Paris828dfe12008-04-17 13:17:49 -04005400 PROCESS__DYNTRANSITION, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005401 if (error)
David Howellsd84f4f92008-11-14 10:39:23 +11005402 goto abort_change;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005403
5404 /* Check for ptracing, and update the task SID if ok.
5405 Otherwise, leave SID unchanged and fail. */
David Howellsd84f4f92008-11-14 10:39:23 +11005406 ptsid = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005407 task_lock(p);
Tejun Heo06d98472011-06-17 16:50:40 +02005408 tracer = ptrace_parent(p);
David Howellsd84f4f92008-11-14 10:39:23 +11005409 if (tracer)
5410 ptsid = task_sid(tracer);
5411 task_unlock(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005412
David Howellsd84f4f92008-11-14 10:39:23 +11005413 if (tracer) {
5414 error = avc_has_perm(ptsid, sid, SECCLASS_PROCESS,
5415 PROCESS__PTRACE, NULL);
5416 if (error)
5417 goto abort_change;
5418 }
5419
5420 tsec->sid = sid;
5421 } else {
5422 error = -EINVAL;
5423 goto abort_change;
5424 }
5425
5426 commit_creds(new);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005427 return size;
David Howellsd84f4f92008-11-14 10:39:23 +11005428
5429abort_change:
5430 abort_creds(new);
5431 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005432}
5433
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005434static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
5435{
5436 return security_sid_to_context(secid, secdata, seclen);
5437}
5438
David Howells7bf570d2008-04-29 20:52:51 +01005439static int selinux_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
David Howells63cb3442008-01-15 23:47:35 +00005440{
5441 return security_context_to_sid(secdata, seclen, secid);
5442}
5443
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005444static void selinux_release_secctx(char *secdata, u32 seclen)
5445{
Paul Moore088999e2007-08-01 11:12:58 -04005446 kfree(secdata);
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005447}
5448
David P. Quigley1ee65e32009-09-03 14:25:57 -04005449/*
5450 * called with inode->i_mutex locked
5451 */
5452static int selinux_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen)
5453{
5454 return selinux_inode_setsecurity(inode, XATTR_SELINUX_SUFFIX, ctx, ctxlen, 0);
5455}
5456
5457/*
5458 * called with inode->i_mutex locked
5459 */
5460static int selinux_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen)
5461{
5462 return __vfs_setxattr_noperm(dentry, XATTR_NAME_SELINUX, ctx, ctxlen, 0);
5463}
5464
5465static int selinux_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen)
5466{
5467 int len = 0;
5468 len = selinux_inode_getsecurity(inode, XATTR_SELINUX_SUFFIX,
5469 ctx, true);
5470 if (len < 0)
5471 return len;
5472 *ctxlen = len;
5473 return 0;
5474}
Michael LeMayd7200242006-06-22 14:47:17 -07005475#ifdef CONFIG_KEYS
5476
David Howellsd84f4f92008-11-14 10:39:23 +11005477static int selinux_key_alloc(struct key *k, const struct cred *cred,
David Howells7e047ef2006-06-26 00:24:50 -07005478 unsigned long flags)
Michael LeMayd7200242006-06-22 14:47:17 -07005479{
David Howellsd84f4f92008-11-14 10:39:23 +11005480 const struct task_security_struct *tsec;
Michael LeMayd7200242006-06-22 14:47:17 -07005481 struct key_security_struct *ksec;
5482
5483 ksec = kzalloc(sizeof(struct key_security_struct), GFP_KERNEL);
5484 if (!ksec)
5485 return -ENOMEM;
5486
David Howellsd84f4f92008-11-14 10:39:23 +11005487 tsec = cred->security;
5488 if (tsec->keycreate_sid)
5489 ksec->sid = tsec->keycreate_sid;
Michael LeMay4eb582c2006-06-26 00:24:57 -07005490 else
David Howellsd84f4f92008-11-14 10:39:23 +11005491 ksec->sid = tsec->sid;
Michael LeMayd7200242006-06-22 14:47:17 -07005492
David Howells275bb412008-11-14 10:39:19 +11005493 k->security = ksec;
Michael LeMayd7200242006-06-22 14:47:17 -07005494 return 0;
5495}
5496
5497static void selinux_key_free(struct key *k)
5498{
5499 struct key_security_struct *ksec = k->security;
5500
5501 k->security = NULL;
5502 kfree(ksec);
5503}
5504
5505static int selinux_key_permission(key_ref_t key_ref,
David Howellsd84f4f92008-11-14 10:39:23 +11005506 const struct cred *cred,
5507 key_perm_t perm)
Michael LeMayd7200242006-06-22 14:47:17 -07005508{
5509 struct key *key;
Michael LeMayd7200242006-06-22 14:47:17 -07005510 struct key_security_struct *ksec;
David Howells275bb412008-11-14 10:39:19 +11005511 u32 sid;
Michael LeMayd7200242006-06-22 14:47:17 -07005512
5513 /* if no specific permissions are requested, we skip the
5514 permission check. No serious, additional covert channels
5515 appear to be created. */
5516 if (perm == 0)
5517 return 0;
5518
David Howellsd84f4f92008-11-14 10:39:23 +11005519 sid = cred_sid(cred);
David Howells275bb412008-11-14 10:39:19 +11005520
5521 key = key_ref_to_ptr(key_ref);
5522 ksec = key->security;
5523
5524 return avc_has_perm(sid, ksec->sid, SECCLASS_KEY, perm, NULL);
Michael LeMayd7200242006-06-22 14:47:17 -07005525}
5526
David Howells70a5bb72008-04-29 01:01:26 -07005527static int selinux_key_getsecurity(struct key *key, char **_buffer)
5528{
5529 struct key_security_struct *ksec = key->security;
5530 char *context = NULL;
5531 unsigned len;
5532 int rc;
5533
5534 rc = security_sid_to_context(ksec->sid, &context, &len);
5535 if (!rc)
5536 rc = len;
5537 *_buffer = context;
5538 return rc;
5539}
5540
Michael LeMayd7200242006-06-22 14:47:17 -07005541#endif
5542
Linus Torvalds1da177e2005-04-16 15:20:36 -07005543static struct security_operations selinux_ops = {
Ahmed S. Darwish076c54c2008-03-06 18:09:10 +02005544 .name = "selinux",
5545
Ingo Molnar9e488582009-05-07 19:26:19 +10005546 .ptrace_access_check = selinux_ptrace_access_check,
David Howells5cd9c582008-08-14 11:37:28 +01005547 .ptrace_traceme = selinux_ptrace_traceme,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005548 .capget = selinux_capget,
David Howellsd84f4f92008-11-14 10:39:23 +11005549 .capset = selinux_capset,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005550 .capable = selinux_capable,
5551 .quotactl = selinux_quotactl,
5552 .quota_on = selinux_quota_on,
5553 .syslog = selinux_syslog,
5554 .vm_enough_memory = selinux_vm_enough_memory,
5555
5556 .netlink_send = selinux_netlink_send,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005557
David Howellsa6f76f22008-11-14 10:39:24 +11005558 .bprm_set_creds = selinux_bprm_set_creds,
David Howellsa6f76f22008-11-14 10:39:24 +11005559 .bprm_committing_creds = selinux_bprm_committing_creds,
5560 .bprm_committed_creds = selinux_bprm_committed_creds,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005561 .bprm_secureexec = selinux_bprm_secureexec,
5562
5563 .sb_alloc_security = selinux_sb_alloc_security,
5564 .sb_free_security = selinux_sb_free_security,
5565 .sb_copy_data = selinux_sb_copy_data,
Eric Paris026eb162011-03-03 16:09:14 -05005566 .sb_remount = selinux_sb_remount,
Eric Paris828dfe12008-04-17 13:17:49 -04005567 .sb_kern_mount = selinux_sb_kern_mount,
Eric Paris2069f452008-07-04 09:47:13 +10005568 .sb_show_options = selinux_sb_show_options,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005569 .sb_statfs = selinux_sb_statfs,
5570 .sb_mount = selinux_mount,
5571 .sb_umount = selinux_umount,
Eric Parisc9180a52007-11-30 13:00:35 -05005572 .sb_set_mnt_opts = selinux_set_mnt_opts,
Eric Paris828dfe12008-04-17 13:17:49 -04005573 .sb_clone_mnt_opts = selinux_sb_clone_mnt_opts,
Eric Parise0007522008-03-05 10:31:54 -05005574 .sb_parse_opts_str = selinux_parse_opts_str,
5575
Linus Torvalds1da177e2005-04-16 15:20:36 -07005576
5577 .inode_alloc_security = selinux_inode_alloc_security,
5578 .inode_free_security = selinux_inode_free_security,
Stephen Smalley5e41ff92005-09-09 13:01:35 -07005579 .inode_init_security = selinux_inode_init_security,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005580 .inode_create = selinux_inode_create,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005581 .inode_link = selinux_inode_link,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005582 .inode_unlink = selinux_inode_unlink,
5583 .inode_symlink = selinux_inode_symlink,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005584 .inode_mkdir = selinux_inode_mkdir,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005585 .inode_rmdir = selinux_inode_rmdir,
5586 .inode_mknod = selinux_inode_mknod,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005587 .inode_rename = selinux_inode_rename,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005588 .inode_readlink = selinux_inode_readlink,
5589 .inode_follow_link = selinux_inode_follow_link,
5590 .inode_permission = selinux_inode_permission,
5591 .inode_setattr = selinux_inode_setattr,
5592 .inode_getattr = selinux_inode_getattr,
5593 .inode_setxattr = selinux_inode_setxattr,
5594 .inode_post_setxattr = selinux_inode_post_setxattr,
5595 .inode_getxattr = selinux_inode_getxattr,
5596 .inode_listxattr = selinux_inode_listxattr,
5597 .inode_removexattr = selinux_inode_removexattr,
Eric Paris828dfe12008-04-17 13:17:49 -04005598 .inode_getsecurity = selinux_inode_getsecurity,
5599 .inode_setsecurity = selinux_inode_setsecurity,
5600 .inode_listsecurity = selinux_inode_listsecurity,
Eric Parisf5269712008-05-14 11:27:45 -04005601 .inode_getsecid = selinux_inode_getsecid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005602
5603 .file_permission = selinux_file_permission,
5604 .file_alloc_security = selinux_file_alloc_security,
5605 .file_free_security = selinux_file_free_security,
5606 .file_ioctl = selinux_file_ioctl,
Al Viroe5467852012-05-30 13:30:51 -04005607 .mmap_file = selinux_mmap_file,
5608 .mmap_addr = selinux_mmap_addr,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005609 .file_mprotect = selinux_file_mprotect,
5610 .file_lock = selinux_file_lock,
5611 .file_fcntl = selinux_file_fcntl,
5612 .file_set_fowner = selinux_file_set_fowner,
5613 .file_send_sigiotask = selinux_file_send_sigiotask,
5614 .file_receive = selinux_file_receive,
5615
Eric Paris83d49852012-04-04 13:45:40 -04005616 .file_open = selinux_file_open,
Yuichi Nakamura788e7dd2007-09-14 09:27:07 +09005617
Linus Torvalds1da177e2005-04-16 15:20:36 -07005618 .task_create = selinux_task_create,
David Howellsee18d642009-09-02 09:14:21 +01005619 .cred_alloc_blank = selinux_cred_alloc_blank,
David Howellsf1752ee2008-11-14 10:39:17 +11005620 .cred_free = selinux_cred_free,
David Howellsd84f4f92008-11-14 10:39:23 +11005621 .cred_prepare = selinux_cred_prepare,
David Howellsee18d642009-09-02 09:14:21 +01005622 .cred_transfer = selinux_cred_transfer,
David Howells3a3b7ce2008-11-14 10:39:28 +11005623 .kernel_act_as = selinux_kernel_act_as,
5624 .kernel_create_files_as = selinux_kernel_create_files_as,
Eric Paris25354c42009-08-13 09:45:03 -04005625 .kernel_module_request = selinux_kernel_module_request,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005626 .task_setpgid = selinux_task_setpgid,
5627 .task_getpgid = selinux_task_getpgid,
Eric Paris828dfe12008-04-17 13:17:49 -04005628 .task_getsid = selinux_task_getsid,
David Quigleyf9008e42006-06-30 01:55:46 -07005629 .task_getsecid = selinux_task_getsecid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005630 .task_setnice = selinux_task_setnice,
James Morris03e68062006-06-23 02:03:58 -07005631 .task_setioprio = selinux_task_setioprio,
David Quigleya1836a42006-06-30 01:55:49 -07005632 .task_getioprio = selinux_task_getioprio,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005633 .task_setrlimit = selinux_task_setrlimit,
5634 .task_setscheduler = selinux_task_setscheduler,
5635 .task_getscheduler = selinux_task_getscheduler,
David Quigley35601542006-06-23 02:04:01 -07005636 .task_movememory = selinux_task_movememory,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005637 .task_kill = selinux_task_kill,
5638 .task_wait = selinux_task_wait,
Eric Paris828dfe12008-04-17 13:17:49 -04005639 .task_to_inode = selinux_task_to_inode,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005640
5641 .ipc_permission = selinux_ipc_permission,
Eric Parisf5269712008-05-14 11:27:45 -04005642 .ipc_getsecid = selinux_ipc_getsecid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005643
5644 .msg_msg_alloc_security = selinux_msg_msg_alloc_security,
5645 .msg_msg_free_security = selinux_msg_msg_free_security,
5646
5647 .msg_queue_alloc_security = selinux_msg_queue_alloc_security,
5648 .msg_queue_free_security = selinux_msg_queue_free_security,
5649 .msg_queue_associate = selinux_msg_queue_associate,
5650 .msg_queue_msgctl = selinux_msg_queue_msgctl,
5651 .msg_queue_msgsnd = selinux_msg_queue_msgsnd,
5652 .msg_queue_msgrcv = selinux_msg_queue_msgrcv,
5653
5654 .shm_alloc_security = selinux_shm_alloc_security,
5655 .shm_free_security = selinux_shm_free_security,
5656 .shm_associate = selinux_shm_associate,
5657 .shm_shmctl = selinux_shm_shmctl,
5658 .shm_shmat = selinux_shm_shmat,
5659
Eric Paris828dfe12008-04-17 13:17:49 -04005660 .sem_alloc_security = selinux_sem_alloc_security,
5661 .sem_free_security = selinux_sem_free_security,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005662 .sem_associate = selinux_sem_associate,
5663 .sem_semctl = selinux_sem_semctl,
5664 .sem_semop = selinux_sem_semop,
5665
Eric Paris828dfe12008-04-17 13:17:49 -04005666 .d_instantiate = selinux_d_instantiate,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005667
Eric Paris828dfe12008-04-17 13:17:49 -04005668 .getprocattr = selinux_getprocattr,
5669 .setprocattr = selinux_setprocattr,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005670
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005671 .secid_to_secctx = selinux_secid_to_secctx,
David Howells63cb3442008-01-15 23:47:35 +00005672 .secctx_to_secid = selinux_secctx_to_secid,
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005673 .release_secctx = selinux_release_secctx,
David P. Quigley1ee65e32009-09-03 14:25:57 -04005674 .inode_notifysecctx = selinux_inode_notifysecctx,
5675 .inode_setsecctx = selinux_inode_setsecctx,
5676 .inode_getsecctx = selinux_inode_getsecctx,
Catherine Zhangdc49c1f2006-08-02 14:12:06 -07005677
Eric Paris828dfe12008-04-17 13:17:49 -04005678 .unix_stream_connect = selinux_socket_unix_stream_connect,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005679 .unix_may_send = selinux_socket_unix_may_send,
5680
5681 .socket_create = selinux_socket_create,
5682 .socket_post_create = selinux_socket_post_create,
5683 .socket_bind = selinux_socket_bind,
5684 .socket_connect = selinux_socket_connect,
5685 .socket_listen = selinux_socket_listen,
5686 .socket_accept = selinux_socket_accept,
5687 .socket_sendmsg = selinux_socket_sendmsg,
5688 .socket_recvmsg = selinux_socket_recvmsg,
5689 .socket_getsockname = selinux_socket_getsockname,
5690 .socket_getpeername = selinux_socket_getpeername,
5691 .socket_getsockopt = selinux_socket_getsockopt,
5692 .socket_setsockopt = selinux_socket_setsockopt,
5693 .socket_shutdown = selinux_socket_shutdown,
5694 .socket_sock_rcv_skb = selinux_socket_sock_rcv_skb,
Catherine Zhang2c7946a2006-03-20 22:41:23 -08005695 .socket_getpeersec_stream = selinux_socket_getpeersec_stream,
5696 .socket_getpeersec_dgram = selinux_socket_getpeersec_dgram,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005697 .sk_alloc_security = selinux_sk_alloc_security,
5698 .sk_free_security = selinux_sk_free_security,
Venkat Yekkirala892c1412006-08-04 23:08:56 -07005699 .sk_clone_security = selinux_sk_clone_security,
Eric Paris828dfe12008-04-17 13:17:49 -04005700 .sk_getsecid = selinux_sk_getsecid,
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005701 .sock_graft = selinux_sock_graft,
5702 .inet_conn_request = selinux_inet_conn_request,
5703 .inet_csk_clone = selinux_inet_csk_clone,
Venkat Yekkirala6b877692006-11-08 17:04:09 -06005704 .inet_conn_established = selinux_inet_conn_established,
Eric Paris2606fd12010-10-13 16:24:41 -04005705 .secmark_relabel_packet = selinux_secmark_relabel_packet,
5706 .secmark_refcount_inc = selinux_secmark_refcount_inc,
5707 .secmark_refcount_dec = selinux_secmark_refcount_dec,
Venkat Yekkirala4237c752006-07-24 23:32:50 -07005708 .req_classify_flow = selinux_req_classify_flow,
Paul Moore5dbbaf22013-01-14 07:12:19 +00005709 .tun_dev_alloc_security = selinux_tun_dev_alloc_security,
5710 .tun_dev_free_security = selinux_tun_dev_free_security,
Paul Mooreed6d76e2009-08-28 18:12:49 -04005711 .tun_dev_create = selinux_tun_dev_create,
Paul Moore5dbbaf22013-01-14 07:12:19 +00005712 .tun_dev_attach_queue = selinux_tun_dev_attach_queue,
Paul Mooreed6d76e2009-08-28 18:12:49 -04005713 .tun_dev_attach = selinux_tun_dev_attach,
Paul Moore5dbbaf22013-01-14 07:12:19 +00005714 .tun_dev_open = selinux_tun_dev_open,
Eric Dumazetca10b9e2013-04-08 17:58:11 +00005715 .skb_owned_by = selinux_skb_owned_by,
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005716
5717#ifdef CONFIG_SECURITY_NETWORK_XFRM
5718 .xfrm_policy_alloc_security = selinux_xfrm_policy_alloc,
5719 .xfrm_policy_clone_security = selinux_xfrm_policy_clone,
5720 .xfrm_policy_free_security = selinux_xfrm_policy_free,
Catherine Zhangc8c05a82006-06-08 23:39:49 -07005721 .xfrm_policy_delete_security = selinux_xfrm_policy_delete,
Paul Moore2e5aa862013-07-23 17:38:38 -04005722 .xfrm_state_alloc = selinux_xfrm_state_alloc,
5723 .xfrm_state_alloc_acquire = selinux_xfrm_state_alloc_acquire,
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005724 .xfrm_state_free_security = selinux_xfrm_state_free,
Catherine Zhangc8c05a82006-06-08 23:39:49 -07005725 .xfrm_state_delete_security = selinux_xfrm_state_delete,
Eric Paris828dfe12008-04-17 13:17:49 -04005726 .xfrm_policy_lookup = selinux_xfrm_policy_lookup,
Venkat Yekkiralae0d1caa2006-07-24 23:29:07 -07005727 .xfrm_state_pol_flow_match = selinux_xfrm_state_pol_flow_match,
Venkat Yekkiralae0d1caa2006-07-24 23:29:07 -07005728 .xfrm_decode_session = selinux_xfrm_decode_session,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005729#endif
Michael LeMayd7200242006-06-22 14:47:17 -07005730
5731#ifdef CONFIG_KEYS
Eric Paris828dfe12008-04-17 13:17:49 -04005732 .key_alloc = selinux_key_alloc,
5733 .key_free = selinux_key_free,
5734 .key_permission = selinux_key_permission,
David Howells70a5bb72008-04-29 01:01:26 -07005735 .key_getsecurity = selinux_key_getsecurity,
Michael LeMayd7200242006-06-22 14:47:17 -07005736#endif
Ahmed S. Darwish9d57a7f2008-03-01 22:03:14 +02005737
5738#ifdef CONFIG_AUDIT
5739 .audit_rule_init = selinux_audit_rule_init,
5740 .audit_rule_known = selinux_audit_rule_known,
5741 .audit_rule_match = selinux_audit_rule_match,
5742 .audit_rule_free = selinux_audit_rule_free,
5743#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07005744};
5745
5746static __init int selinux_init(void)
5747{
Ahmed S. Darwish076c54c2008-03-06 18:09:10 +02005748 if (!security_module_enable(&selinux_ops)) {
5749 selinux_enabled = 0;
5750 return 0;
5751 }
5752
Linus Torvalds1da177e2005-04-16 15:20:36 -07005753 if (!selinux_enabled) {
5754 printk(KERN_INFO "SELinux: Disabled at boot.\n");
5755 return 0;
5756 }
5757
5758 printk(KERN_INFO "SELinux: Initializing.\n");
5759
5760 /* Set the security state for the initial task. */
David Howellsd84f4f92008-11-14 10:39:23 +11005761 cred_init_security();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005762
Stephen Smalleyfcaaade2010-04-28 15:57:57 -04005763 default_noexec = !(VM_DATA_DEFAULT_FLAGS & VM_EXEC);
5764
James Morris7cae7e22006-03-22 00:09:22 -08005765 sel_inode_cache = kmem_cache_create("selinux_inode_security",
5766 sizeof(struct inode_security_struct),
Paul Mundt20c2df82007-07-20 10:11:58 +09005767 0, SLAB_PANIC, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005768 avc_init();
5769
Eric Paris828dfe12008-04-17 13:17:49 -04005770 if (register_security(&selinux_ops))
Linus Torvalds1da177e2005-04-16 15:20:36 -07005771 panic("SELinux: Unable to register with kernel.\n");
5772
Eric Paris828dfe12008-04-17 13:17:49 -04005773 if (selinux_enforcing)
Eric Parisfadcdb42007-02-22 18:11:31 -05005774 printk(KERN_DEBUG "SELinux: Starting in enforcing mode\n");
Eric Paris828dfe12008-04-17 13:17:49 -04005775 else
Eric Parisfadcdb42007-02-22 18:11:31 -05005776 printk(KERN_DEBUG "SELinux: Starting in permissive mode\n");
Michael LeMayd7200242006-06-22 14:47:17 -07005777
Linus Torvalds1da177e2005-04-16 15:20:36 -07005778 return 0;
5779}
5780
Al Viroe8c26252010-03-23 06:36:54 -04005781static void delayed_superblock_init(struct super_block *sb, void *unused)
5782{
5783 superblock_doinit(sb, NULL);
5784}
5785
Linus Torvalds1da177e2005-04-16 15:20:36 -07005786void selinux_complete_init(void)
5787{
Eric Parisfadcdb42007-02-22 18:11:31 -05005788 printk(KERN_DEBUG "SELinux: Completing initialization.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005789
5790 /* Set up any superblocks initialized prior to the policy load. */
Eric Parisfadcdb42007-02-22 18:11:31 -05005791 printk(KERN_DEBUG "SELinux: Setting up existing superblocks.\n");
Al Viroe8c26252010-03-23 06:36:54 -04005792 iterate_supers(delayed_superblock_init, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005793}
5794
5795/* SELinux requires early initialization in order to label
5796 all processes and objects when they are created. */
5797security_initcall(selinux_init);
5798
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08005799#if defined(CONFIG_NETFILTER)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005800
Paul Mooreeffad8d2008-01-29 08:49:27 -05005801static struct nf_hook_ops selinux_ipv4_ops[] = {
5802 {
5803 .hook = selinux_ipv4_postroute,
5804 .owner = THIS_MODULE,
Alban Crequy2597a832012-05-14 03:56:39 +00005805 .pf = NFPROTO_IPV4,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005806 .hooknum = NF_INET_POST_ROUTING,
5807 .priority = NF_IP_PRI_SELINUX_LAST,
5808 },
5809 {
5810 .hook = selinux_ipv4_forward,
5811 .owner = THIS_MODULE,
Alban Crequy2597a832012-05-14 03:56:39 +00005812 .pf = NFPROTO_IPV4,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005813 .hooknum = NF_INET_FORWARD,
5814 .priority = NF_IP_PRI_SELINUX_FIRST,
Paul Moore948bf852008-10-10 10:16:32 -04005815 },
5816 {
5817 .hook = selinux_ipv4_output,
5818 .owner = THIS_MODULE,
Alban Crequy2597a832012-05-14 03:56:39 +00005819 .pf = NFPROTO_IPV4,
Paul Moore948bf852008-10-10 10:16:32 -04005820 .hooknum = NF_INET_LOCAL_OUT,
5821 .priority = NF_IP_PRI_SELINUX_FIRST,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005822 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005823};
5824
5825#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
5826
Paul Mooreeffad8d2008-01-29 08:49:27 -05005827static struct nf_hook_ops selinux_ipv6_ops[] = {
5828 {
5829 .hook = selinux_ipv6_postroute,
5830 .owner = THIS_MODULE,
Alban Crequy2597a832012-05-14 03:56:39 +00005831 .pf = NFPROTO_IPV6,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005832 .hooknum = NF_INET_POST_ROUTING,
5833 .priority = NF_IP6_PRI_SELINUX_LAST,
5834 },
5835 {
5836 .hook = selinux_ipv6_forward,
5837 .owner = THIS_MODULE,
Alban Crequy2597a832012-05-14 03:56:39 +00005838 .pf = NFPROTO_IPV6,
Paul Mooreeffad8d2008-01-29 08:49:27 -05005839 .hooknum = NF_INET_FORWARD,
5840 .priority = NF_IP6_PRI_SELINUX_FIRST,
5841 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005842};
5843
5844#endif /* IPV6 */
5845
5846static int __init selinux_nf_ip_init(void)
5847{
5848 int err = 0;
5849
5850 if (!selinux_enabled)
5851 goto out;
Eric Parisfadcdb42007-02-22 18:11:31 -05005852
5853 printk(KERN_DEBUG "SELinux: Registering netfilter hooks\n");
5854
Alexey Dobriyan6c5a9d22008-07-26 17:48:15 -07005855 err = nf_register_hooks(selinux_ipv4_ops, ARRAY_SIZE(selinux_ipv4_ops));
5856 if (err)
5857 panic("SELinux: nf_register_hooks for IPv4: error %d\n", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005858
5859#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Alexey Dobriyan6c5a9d22008-07-26 17:48:15 -07005860 err = nf_register_hooks(selinux_ipv6_ops, ARRAY_SIZE(selinux_ipv6_ops));
5861 if (err)
5862 panic("SELinux: nf_register_hooks for IPv6: error %d\n", err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005863#endif /* IPV6 */
Trent Jaegerd28d1e02005-12-13 23:12:40 -08005864
Linus Torvalds1da177e2005-04-16 15:20:36 -07005865out:
5866 return err;
5867}
5868
5869__initcall(selinux_nf_ip_init);
5870
5871#ifdef CONFIG_SECURITY_SELINUX_DISABLE
5872static void selinux_nf_ip_exit(void)
5873{
Eric Parisfadcdb42007-02-22 18:11:31 -05005874 printk(KERN_DEBUG "SELinux: Unregistering netfilter hooks\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005875
Alexey Dobriyan6c5a9d22008-07-26 17:48:15 -07005876 nf_unregister_hooks(selinux_ipv4_ops, ARRAY_SIZE(selinux_ipv4_ops));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005877#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Alexey Dobriyan6c5a9d22008-07-26 17:48:15 -07005878 nf_unregister_hooks(selinux_ipv6_ops, ARRAY_SIZE(selinux_ipv6_ops));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005879#endif /* IPV6 */
5880}
5881#endif
5882
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08005883#else /* CONFIG_NETFILTER */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005884
5885#ifdef CONFIG_SECURITY_SELINUX_DISABLE
5886#define selinux_nf_ip_exit()
5887#endif
5888
Stephen Smalleyc2b507f2006-02-04 23:27:50 -08005889#endif /* CONFIG_NETFILTER */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005890
5891#ifdef CONFIG_SECURITY_SELINUX_DISABLE
Eric Paris828dfe12008-04-17 13:17:49 -04005892static int selinux_disabled;
5893
Linus Torvalds1da177e2005-04-16 15:20:36 -07005894int selinux_disable(void)
5895{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005896 if (ss_initialized) {
5897 /* Not permitted after initial policy load. */
5898 return -EINVAL;
5899 }
5900
5901 if (selinux_disabled) {
5902 /* Only do this once. */
5903 return -EINVAL;
5904 }
5905
5906 printk(KERN_INFO "SELinux: Disabled at runtime.\n");
5907
5908 selinux_disabled = 1;
Stephen Smalley30d55282006-05-03 10:52:36 -04005909 selinux_enabled = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005910
wzt.wzt@gmail.com189b3b12010-02-23 23:15:28 +08005911 reset_security_ops();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005912
Eric Parisaf8ff042009-09-20 21:23:01 -04005913 /* Try to destroy the avc node cache */
5914 avc_disable();
5915
Linus Torvalds1da177e2005-04-16 15:20:36 -07005916 /* Unregister netfilter hooks. */
5917 selinux_nf_ip_exit();
5918
5919 /* Unregister selinuxfs. */
5920 exit_sel_fs();
5921
5922 return 0;
5923}
5924#endif