aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2009-04-05 19:41:22 -0400
committerIngo Molnar <mingo@elte.hu>2009-04-05 19:41:22 -0400
commit9efe21cb82b5dbe3b0b2ae4de4eccc64ecb94e95 (patch)
tree7ff8833745d2f268f897f6fa4a27263b4a572245 /security
parentde18836e447c2dc30120c0919b8db8ddc0401cc4 (diff)
parent0221c81b1b8eb0cbb6b30a0ced52ead32d2b4e4c (diff)
Merge branch 'linus' into irq/threaded
Conflicts: include/linux/irq.h kernel/irq/handle.c
Diffstat (limited to 'security')
-rw-r--r--security/Kconfig6
-rw-r--r--security/Makefile6
-rw-r--r--security/capability.c5
-rw-r--r--security/device_cgroup.c21
-rw-r--r--security/inode.c7
-rw-r--r--security/integrity/ima/Kconfig55
-rw-r--r--security/integrity/ima/Makefile9
-rw-r--r--security/integrity/ima/ima.h166
-rw-r--r--security/integrity/ima/ima_api.c190
-rw-r--r--security/integrity/ima/ima_audit.c81
-rw-r--r--security/integrity/ima/ima_crypto.c140
-rw-r--r--security/integrity/ima/ima_fs.c376
-rw-r--r--security/integrity/ima/ima_iint.c204
-rw-r--r--security/integrity/ima/ima_init.c96
-rw-r--r--security/integrity/ima/ima_main.c327
-rw-r--r--security/integrity/ima/ima_policy.c414
-rw-r--r--security/integrity/ima/ima_queue.c140
-rw-r--r--security/keys/internal.h4
-rw-r--r--security/keys/key.c11
-rw-r--r--security/keys/keyctl.c2
-rw-r--r--security/keys/keyring.c3
-rw-r--r--security/keys/permission.c5
-rw-r--r--security/keys/proc.c55
-rw-r--r--security/keys/process_keys.c2
-rw-r--r--security/keys/request_key.c2
-rw-r--r--security/security.c7
-rw-r--r--security/selinux/avc.c169
-rw-r--r--security/selinux/hooks.c515
-rw-r--r--security/selinux/include/av_perm_to_string.h2
-rw-r--r--security/selinux/include/av_permissions.h2
-rw-r--r--security/selinux/include/netlabel.h27
-rw-r--r--security/selinux/include/objsec.h2
-rw-r--r--security/selinux/include/security.h9
-rw-r--r--security/selinux/netlabel.c186
-rw-r--r--security/selinux/nlmsgtab.c2
-rw-r--r--security/selinux/selinuxfs.c70
-rw-r--r--security/selinux/ss/services.c2
-rw-r--r--security/smack/smack.h32
-rw-r--r--security/smack/smack_access.c70
-rw-r--r--security/smack/smack_lsm.c334
-rw-r--r--security/smack/smackfs.c233
-rw-r--r--security/tomoyo/Kconfig11
-rw-r--r--security/tomoyo/Makefile1
-rw-r--r--security/tomoyo/common.c2206
-rw-r--r--security/tomoyo/common.h359
-rw-r--r--security/tomoyo/domain.c878
-rw-r--r--security/tomoyo/file.c1241
-rw-r--r--security/tomoyo/realpath.c483
-rw-r--r--security/tomoyo/realpath.h66
-rw-r--r--security/tomoyo/tomoyo.c294
-rw-r--r--security/tomoyo/tomoyo.h106
51 files changed, 8635 insertions, 999 deletions
diff --git a/security/Kconfig b/security/Kconfig
index 9438535d7fd0..bb244774e9d7 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -55,7 +55,8 @@ config SECURITYFS
55 bool "Enable the securityfs filesystem" 55 bool "Enable the securityfs filesystem"
56 help 56 help
57 This will build the securityfs filesystem. It is currently used by 57 This will build the securityfs filesystem. It is currently used by
58 the TPM bios character driver. It is not used by SELinux or SMACK. 58 the TPM bios character driver and IMA, an integrity provider. It is
59 not used by SELinux or SMACK.
59 60
60 If you are unsure how to answer this question, answer N. 61 If you are unsure how to answer this question, answer N.
61 62
@@ -134,6 +135,9 @@ config SECURITY_DEFAULT_MMAP_MIN_ADDR
134 135
135source security/selinux/Kconfig 136source security/selinux/Kconfig
136source security/smack/Kconfig 137source security/smack/Kconfig
138source security/tomoyo/Kconfig
139
140source security/integrity/ima/Kconfig
137 141
138endmenu 142endmenu
139 143
diff --git a/security/Makefile b/security/Makefile
index c05c127fff9a..fa77021d9778 100644
--- a/security/Makefile
+++ b/security/Makefile
@@ -5,6 +5,7 @@
5obj-$(CONFIG_KEYS) += keys/ 5obj-$(CONFIG_KEYS) += keys/
6subdir-$(CONFIG_SECURITY_SELINUX) += selinux 6subdir-$(CONFIG_SECURITY_SELINUX) += selinux
7subdir-$(CONFIG_SECURITY_SMACK) += smack 7subdir-$(CONFIG_SECURITY_SMACK) += smack
8subdir-$(CONFIG_SECURITY_TOMOYO) += tomoyo
8 9
9# always enable default capabilities 10# always enable default capabilities
10obj-y += commoncap.o 11obj-y += commoncap.o
@@ -15,5 +16,10 @@ obj-$(CONFIG_SECURITYFS) += inode.o
15# Must precede capability.o in order to stack properly. 16# Must precede capability.o in order to stack properly.
16obj-$(CONFIG_SECURITY_SELINUX) += selinux/built-in.o 17obj-$(CONFIG_SECURITY_SELINUX) += selinux/built-in.o
17obj-$(CONFIG_SECURITY_SMACK) += smack/built-in.o 18obj-$(CONFIG_SECURITY_SMACK) += smack/built-in.o
19obj-$(CONFIG_SECURITY_TOMOYO) += tomoyo/built-in.o
18obj-$(CONFIG_SECURITY_ROOTPLUG) += root_plug.o 20obj-$(CONFIG_SECURITY_ROOTPLUG) += root_plug.o
19obj-$(CONFIG_CGROUP_DEVICE) += device_cgroup.o 21obj-$(CONFIG_CGROUP_DEVICE) += device_cgroup.o
22
23# Object integrity file lists
24subdir-$(CONFIG_IMA) += integrity/ima
25obj-$(CONFIG_IMA) += integrity/ima/built-in.o
diff --git a/security/capability.c b/security/capability.c
index c545bd1300b5..21b6cead6a8e 100644
--- a/security/capability.c
+++ b/security/capability.c
@@ -620,10 +620,6 @@ static int cap_socket_accept(struct socket *sock, struct socket *newsock)
620 return 0; 620 return 0;
621} 621}
622 622
623static void cap_socket_post_accept(struct socket *sock, struct socket *newsock)
624{
625}
626
627static int cap_socket_sendmsg(struct socket *sock, struct msghdr *msg, int size) 623static int cap_socket_sendmsg(struct socket *sock, struct msghdr *msg, int size)
628{ 624{
629 return 0; 625 return 0;
@@ -1014,7 +1010,6 @@ void security_fixup_ops(struct security_operations *ops)
1014 set_to_cap_if_null(ops, socket_connect); 1010 set_to_cap_if_null(ops, socket_connect);
1015 set_to_cap_if_null(ops, socket_listen); 1011 set_to_cap_if_null(ops, socket_listen);
1016 set_to_cap_if_null(ops, socket_accept); 1012 set_to_cap_if_null(ops, socket_accept);
1017 set_to_cap_if_null(ops, socket_post_accept);
1018 set_to_cap_if_null(ops, socket_sendmsg); 1013 set_to_cap_if_null(ops, socket_sendmsg);
1019 set_to_cap_if_null(ops, socket_recvmsg); 1014 set_to_cap_if_null(ops, socket_recvmsg);
1020 set_to_cap_if_null(ops, socket_getsockname); 1015 set_to_cap_if_null(ops, socket_getsockname);
diff --git a/security/device_cgroup.c b/security/device_cgroup.c
index 3aacd0fe7179..5fda7df19723 100644
--- a/security/device_cgroup.c
+++ b/security/device_cgroup.c
@@ -11,6 +11,7 @@
11#include <linux/uaccess.h> 11#include <linux/uaccess.h>
12#include <linux/seq_file.h> 12#include <linux/seq_file.h>
13#include <linux/rcupdate.h> 13#include <linux/rcupdate.h>
14#include <linux/mutex.h>
14 15
15#define ACC_MKNOD 1 16#define ACC_MKNOD 1
16#define ACC_READ 2 17#define ACC_READ 2
@@ -21,9 +22,11 @@
21#define DEV_CHAR 2 22#define DEV_CHAR 2
22#define DEV_ALL 4 /* this represents all devices */ 23#define DEV_ALL 4 /* this represents all devices */
23 24
25static DEFINE_MUTEX(devcgroup_mutex);
26
24/* 27/*
25 * whitelist locking rules: 28 * whitelist locking rules:
26 * hold cgroup_lock() for update/read. 29 * hold devcgroup_mutex for update/read.
27 * hold rcu_read_lock() for read. 30 * hold rcu_read_lock() for read.
28 */ 31 */
29 32
@@ -67,7 +70,7 @@ static int devcgroup_can_attach(struct cgroup_subsys *ss,
67} 70}
68 71
69/* 72/*
70 * called under cgroup_lock() 73 * called under devcgroup_mutex
71 */ 74 */
72static int dev_whitelist_copy(struct list_head *dest, struct list_head *orig) 75static int dev_whitelist_copy(struct list_head *dest, struct list_head *orig)
73{ 76{
@@ -92,7 +95,7 @@ free_and_exit:
92 95
93/* Stupid prototype - don't bother combining existing entries */ 96/* Stupid prototype - don't bother combining existing entries */
94/* 97/*
95 * called under cgroup_lock() 98 * called under devcgroup_mutex
96 */ 99 */
97static int dev_whitelist_add(struct dev_cgroup *dev_cgroup, 100static int dev_whitelist_add(struct dev_cgroup *dev_cgroup,
98 struct dev_whitelist_item *wh) 101 struct dev_whitelist_item *wh)
@@ -130,7 +133,7 @@ static void whitelist_item_free(struct rcu_head *rcu)
130} 133}
131 134
132/* 135/*
133 * called under cgroup_lock() 136 * called under devcgroup_mutex
134 */ 137 */
135static void dev_whitelist_rm(struct dev_cgroup *dev_cgroup, 138static void dev_whitelist_rm(struct dev_cgroup *dev_cgroup,
136 struct dev_whitelist_item *wh) 139 struct dev_whitelist_item *wh)
@@ -185,8 +188,10 @@ static struct cgroup_subsys_state *devcgroup_create(struct cgroup_subsys *ss,
185 list_add(&wh->list, &dev_cgroup->whitelist); 188 list_add(&wh->list, &dev_cgroup->whitelist);
186 } else { 189 } else {
187 parent_dev_cgroup = cgroup_to_devcgroup(parent_cgroup); 190 parent_dev_cgroup = cgroup_to_devcgroup(parent_cgroup);
191 mutex_lock(&devcgroup_mutex);
188 ret = dev_whitelist_copy(&dev_cgroup->whitelist, 192 ret = dev_whitelist_copy(&dev_cgroup->whitelist,
189 &parent_dev_cgroup->whitelist); 193 &parent_dev_cgroup->whitelist);
194 mutex_unlock(&devcgroup_mutex);
190 if (ret) { 195 if (ret) {
191 kfree(dev_cgroup); 196 kfree(dev_cgroup);
192 return ERR_PTR(ret); 197 return ERR_PTR(ret);
@@ -273,7 +278,7 @@ static int devcgroup_seq_read(struct cgroup *cgroup, struct cftype *cft,
273 * does the access granted to dev_cgroup c contain the access 278 * does the access granted to dev_cgroup c contain the access
274 * requested in whitelist item refwh. 279 * requested in whitelist item refwh.
275 * return 1 if yes, 0 if no. 280 * return 1 if yes, 0 if no.
276 * call with c->lock held 281 * call with devcgroup_mutex held
277 */ 282 */
278static int may_access_whitelist(struct dev_cgroup *c, 283static int may_access_whitelist(struct dev_cgroup *c,
279 struct dev_whitelist_item *refwh) 284 struct dev_whitelist_item *refwh)
@@ -426,11 +431,11 @@ static int devcgroup_access_write(struct cgroup *cgrp, struct cftype *cft,
426 const char *buffer) 431 const char *buffer)
427{ 432{
428 int retval; 433 int retval;
429 if (!cgroup_lock_live_group(cgrp)) 434
430 return -ENODEV; 435 mutex_lock(&devcgroup_mutex);
431 retval = devcgroup_update_access(cgroup_to_devcgroup(cgrp), 436 retval = devcgroup_update_access(cgroup_to_devcgroup(cgrp),
432 cft->private, buffer); 437 cft->private, buffer);
433 cgroup_unlock(); 438 mutex_unlock(&devcgroup_mutex);
434 return retval; 439 return retval;
435} 440}
436 441
diff --git a/security/inode.c b/security/inode.c
index 007ef252dde7..f3b91bfbe4cb 100644
--- a/security/inode.c
+++ b/security/inode.c
@@ -202,12 +202,11 @@ static int create_by_name(const char *name, mode_t mode,
202 * This function returns a pointer to a dentry if it succeeds. This 202 * This function returns a pointer to a dentry if it succeeds. This
203 * pointer must be passed to the securityfs_remove() function when the file is 203 * pointer must be passed to the securityfs_remove() function when the file is
204 * to be removed (no automatic cleanup happens if your module is unloaded, 204 * to be removed (no automatic cleanup happens if your module is unloaded,
205 * you are responsible here). If an error occurs, %NULL is returned. 205 * you are responsible here). If an error occurs, the function will return
206 * the erorr value (via ERR_PTR).
206 * 207 *
207 * If securityfs is not enabled in the kernel, the value %-ENODEV is 208 * If securityfs is not enabled in the kernel, the value %-ENODEV is
208 * returned. It is not wise to check for this value, but rather, check for 209 * returned.
209 * %NULL or !%NULL instead as to eliminate the need for #ifdef in the calling
210 * code.
211 */ 210 */
212struct dentry *securityfs_create_file(const char *name, mode_t mode, 211struct dentry *securityfs_create_file(const char *name, mode_t mode,
213 struct dentry *parent, void *data, 212 struct dentry *parent, void *data,
diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig
new file mode 100644
index 000000000000..53d9764e8f09
--- /dev/null
+++ b/security/integrity/ima/Kconfig
@@ -0,0 +1,55 @@
1# IBM Integrity Measurement Architecture
2#
3config IMA
4 bool "Integrity Measurement Architecture(IMA)"
5 depends on ACPI
6 select SECURITYFS
7 select CRYPTO
8 select CRYPTO_HMAC
9 select CRYPTO_MD5
10 select CRYPTO_SHA1
11 select TCG_TPM
12 select TCG_TIS
13 help
14 The Trusted Computing Group(TCG) runtime Integrity
15 Measurement Architecture(IMA) maintains a list of hash
16 values of executables and other sensitive system files,
17 as they are read or executed. If an attacker manages
18 to change the contents of an important system file
19 being measured, we can tell.
20
21 If your system has a TPM chip, then IMA also maintains
22 an aggregate integrity value over this list inside the
23 TPM hardware, so that the TPM can prove to a third party
24 whether or not critical system files have been modified.
25 Read <http://www.usenix.org/events/sec04/tech/sailer.html>
26 to learn more about IMA.
27 If unsure, say N.
28
29config IMA_MEASURE_PCR_IDX
30 int
31 depends on IMA
32 range 8 14
33 default 10
34 help
35 IMA_MEASURE_PCR_IDX determines the TPM PCR register index
36 that IMA uses to maintain the integrity aggregate of the
37 measurement list. If unsure, use the default 10.
38
39config IMA_AUDIT
40 bool
41 depends on IMA
42 default y
43 help
44 This option adds a kernel parameter 'ima_audit', which
45 allows informational auditing messages to be enabled
46 at boot. If this option is selected, informational integrity
47 auditing messages can be enabled with 'ima_audit=1' on
48 the kernel command line.
49
50config IMA_LSM_RULES
51 bool
52 depends on IMA && AUDIT && (SECURITY_SELINUX || SECURITY_SMACK)
53 default y
54 help
55 Disabling this option will disregard LSM based policy rules.
diff --git a/security/integrity/ima/Makefile b/security/integrity/ima/Makefile
new file mode 100644
index 000000000000..787c4cb916cd
--- /dev/null
+++ b/security/integrity/ima/Makefile
@@ -0,0 +1,9 @@
1#
2# Makefile for building Trusted Computing Group's(TCG) runtime Integrity
3# Measurement Architecture(IMA).
4#
5
6obj-$(CONFIG_IMA) += ima.o
7
8ima-y := ima_fs.o ima_queue.o ima_init.o ima_main.o ima_crypto.o ima_api.o \
9 ima_policy.o ima_iint.o ima_audit.o
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
new file mode 100644
index 000000000000..165eb5397ea5
--- /dev/null
+++ b/security/integrity/ima/ima.h
@@ -0,0 +1,166 @@
1/*
2 * Copyright (C) 2005,2006,2007,2008 IBM Corporation
3 *
4 * Authors:
5 * Reiner Sailer <sailer@watson.ibm.com>
6 * Mimi Zohar <zohar@us.ibm.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation, version 2 of the
11 * License.
12 *
13 * File: ima.h
14 * internal Integrity Measurement Architecture (IMA) definitions
15 */
16
17#ifndef __LINUX_IMA_H
18#define __LINUX_IMA_H
19
20#include <linux/types.h>
21#include <linux/crypto.h>
22#include <linux/security.h>
23#include <linux/hash.h>
24#include <linux/tpm.h>
25#include <linux/audit.h>
26
27enum ima_show_type { IMA_SHOW_BINARY, IMA_SHOW_ASCII };
28enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8 };
29
30/* digest size for IMA, fits SHA1 or MD5 */
31#define IMA_DIGEST_SIZE 20
32#define IMA_EVENT_NAME_LEN_MAX 255
33
34#define IMA_HASH_BITS 9
35#define IMA_MEASURE_HTABLE_SIZE (1 << IMA_HASH_BITS)
36
37/* set during initialization */
38extern int ima_initialized;
39extern int ima_used_chip;
40extern char *ima_hash;
41
42/* IMA inode template definition */
43struct ima_template_data {
44 u8 digest[IMA_DIGEST_SIZE]; /* sha1/md5 measurement hash */
45 char file_name[IMA_EVENT_NAME_LEN_MAX + 1]; /* name + \0 */
46};
47
48struct ima_template_entry {
49 u8 digest[IMA_DIGEST_SIZE]; /* sha1 or md5 measurement hash */
50 const char *template_name;
51 int template_len;
52 struct ima_template_data template;
53};
54
55struct ima_queue_entry {
56 struct hlist_node hnext; /* place in hash collision list */
57 struct list_head later; /* place in ima_measurements list */
58 struct ima_template_entry *entry;
59};
60extern struct list_head ima_measurements; /* list of all measurements */
61
62/* declarations */
63void integrity_audit_msg(int audit_msgno, struct inode *inode,
64 const unsigned char *fname, const char *op,
65 const char *cause, int result, int info);
66
67/* Internal IMA function definitions */
68void ima_iintcache_init(void);
69int ima_init(void);
70void ima_cleanup(void);
71int ima_fs_init(void);
72void ima_fs_cleanup(void);
73int ima_add_template_entry(struct ima_template_entry *entry, int violation,
74 const char *op, struct inode *inode);
75int ima_calc_hash(struct file *file, char *digest);
76int ima_calc_template_hash(int template_len, void *template, char *digest);
77int ima_calc_boot_aggregate(char *digest);
78void ima_add_violation(struct inode *inode, const unsigned char *filename,
79 const char *op, const char *cause);
80
81/*
82 * used to protect h_table and sha_table
83 */
84extern spinlock_t ima_queue_lock;
85
86struct ima_h_table {
87 atomic_long_t len; /* number of stored measurements in the list */
88 atomic_long_t violations;
89 struct hlist_head queue[IMA_MEASURE_HTABLE_SIZE];
90};
91extern struct ima_h_table ima_htable;
92
93static inline unsigned long ima_hash_key(u8 *digest)
94{
95 return hash_long(*digest, IMA_HASH_BITS);
96}
97
98/* iint cache flags */
99#define IMA_MEASURED 1
100#define IMA_IINT_DUMP_STACK 512
101
102/* integrity data associated with an inode */
103struct ima_iint_cache {
104 u64 version; /* track inode changes */
105 unsigned long flags;
106 u8 digest[IMA_DIGEST_SIZE];
107 struct mutex mutex; /* protects: version, flags, digest */
108 long readcount; /* measured files readcount */
109 long writecount; /* measured files writecount */
110 long opencount; /* opens reference count */
111 struct kref refcount; /* ima_iint_cache reference count */
112 struct rcu_head rcu;
113};
114
115/* LIM API function definitions */
116int ima_must_measure(struct ima_iint_cache *iint, struct inode *inode,
117 int mask, int function);
118int ima_collect_measurement(struct ima_iint_cache *iint, struct file *file);
119void ima_store_measurement(struct ima_iint_cache *iint, struct file *file,
120 const unsigned char *filename);
121int ima_store_template(struct ima_template_entry *entry, int violation,
122 struct inode *inode);
123void ima_template_show(struct seq_file *m, void *e,
124 enum ima_show_type show);
125
126/* radix tree calls to lookup, insert, delete
127 * integrity data associated with an inode.
128 */
129struct ima_iint_cache *ima_iint_insert(struct inode *inode);
130struct ima_iint_cache *ima_iint_find_get(struct inode *inode);
131struct ima_iint_cache *ima_iint_find_insert_get(struct inode *inode);
132void ima_iint_delete(struct inode *inode);
133void iint_free(struct kref *kref);
134void iint_rcu_free(struct rcu_head *rcu);
135
136/* IMA policy related functions */
137enum ima_hooks { PATH_CHECK = 1, FILE_MMAP, BPRM_CHECK };
138
139int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask);
140void ima_init_policy(void);
141void ima_update_policy(void);
142int ima_parse_add_rule(char *);
143void ima_delete_rules(void);
144
145/* LSM based policy rules require audit */
146#ifdef CONFIG_IMA_LSM_RULES
147
148#define security_filter_rule_init security_audit_rule_init
149#define security_filter_rule_match security_audit_rule_match
150
151#else
152
153static inline int security_filter_rule_init(u32 field, u32 op, char *rulestr,
154 void **lsmrule)
155{
156 return -EINVAL;
157}
158
159static inline int security_filter_rule_match(u32 secid, u32 field, u32 op,
160 void *lsmrule,
161 struct audit_context *actx)
162{
163 return -EINVAL;
164}
165#endif /* CONFIG_IMA_LSM_RULES */
166#endif
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
new file mode 100644
index 000000000000..3cd58b60afd2
--- /dev/null
+++ b/security/integrity/ima/ima_api.c
@@ -0,0 +1,190 @@
1/*
2 * Copyright (C) 2008 IBM Corporation
3 *
4 * Author: Mimi Zohar <zohar@us.ibm.com>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation, version 2 of the
9 * License.
10 *
11 * File: ima_api.c
12 * Implements must_measure, collect_measurement, store_measurement,
13 * and store_template.
14 */
15#include <linux/module.h>
16
17#include "ima.h"
18static const char *IMA_TEMPLATE_NAME = "ima";
19
20/*
21 * ima_store_template - store ima template measurements
22 *
23 * Calculate the hash of a template entry, add the template entry
24 * to an ordered list of measurement entries maintained inside the kernel,
25 * and also update the aggregate integrity value (maintained inside the
26 * configured TPM PCR) over the hashes of the current list of measurement
27 * entries.
28 *
29 * Applications retrieve the current kernel-held measurement list through
30 * the securityfs entries in /sys/kernel/security/ima. The signed aggregate
31 * TPM PCR (called quote) can be retrieved using a TPM user space library
32 * and is used to validate the measurement list.
33 *
34 * Returns 0 on success, error code otherwise
35 */
36int ima_store_template(struct ima_template_entry *entry,
37 int violation, struct inode *inode)
38{
39 const char *op = "add_template_measure";
40 const char *audit_cause = "hashing_error";
41 int result;
42
43 memset(entry->digest, 0, sizeof(entry->digest));
44 entry->template_name = IMA_TEMPLATE_NAME;
45 entry->template_len = sizeof(entry->template);
46
47 if (!violation) {
48 result = ima_calc_template_hash(entry->template_len,
49 &entry->template,
50 entry->digest);
51 if (result < 0) {
52 integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode,
53 entry->template_name, op,
54 audit_cause, result, 0);
55 return result;
56 }
57 }
58 result = ima_add_template_entry(entry, violation, op, inode);
59 return result;
60}
61
62/*
63 * ima_add_violation - add violation to measurement list.
64 *
65 * Violations are flagged in the measurement list with zero hash values.
66 * By extending the PCR with 0xFF's instead of with zeroes, the PCR
67 * value is invalidated.
68 */
69void ima_add_violation(struct inode *inode, const unsigned char *filename,
70 const char *op, const char *cause)
71{
72 struct ima_template_entry *entry;
73 int violation = 1;
74 int result;
75
76 /* can overflow, only indicator */
77 atomic_long_inc(&ima_htable.violations);
78
79 entry = kmalloc(sizeof(*entry), GFP_KERNEL);
80 if (!entry) {
81 result = -ENOMEM;
82 goto err_out;
83 }
84 memset(&entry->template, 0, sizeof(entry->template));
85 strncpy(entry->template.file_name, filename, IMA_EVENT_NAME_LEN_MAX);
86 result = ima_store_template(entry, violation, inode);
87 if (result < 0)
88 kfree(entry);
89err_out:
90 integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, filename,
91 op, cause, result, 0);
92}
93
94/**
95 * ima_must_measure - measure decision based on policy.
96 * @inode: pointer to inode to measure
97 * @mask: contains the permission mask (MAY_READ, MAY_WRITE, MAY_EXECUTE)
98 * @function: calling function (PATH_CHECK, BPRM_CHECK, FILE_MMAP)
99 *
100 * The policy is defined in terms of keypairs:
101 * subj=, obj=, type=, func=, mask=, fsmagic=
102 * subj,obj, and type: are LSM specific.
103 * func: PATH_CHECK | BPRM_CHECK | FILE_MMAP
104 * mask: contains the permission mask
105 * fsmagic: hex value
106 *
107 * Must be called with iint->mutex held.
108 *
109 * Return 0 to measure. Return 1 if already measured.
110 * For matching a DONT_MEASURE policy, no policy, or other
111 * error, return an error code.
112*/
113int ima_must_measure(struct ima_iint_cache *iint, struct inode *inode,
114 int mask, int function)
115{
116 int must_measure;
117
118 if (iint->flags & IMA_MEASURED)
119 return 1;
120
121 must_measure = ima_match_policy(inode, function, mask);
122 return must_measure ? 0 : -EACCES;
123}
124
125/*
126 * ima_collect_measurement - collect file measurement
127 *
128 * Calculate the file hash, if it doesn't already exist,
129 * storing the measurement and i_version in the iint.
130 *
131 * Must be called with iint->mutex held.
132 *
133 * Return 0 on success, error code otherwise
134 */
135int ima_collect_measurement(struct ima_iint_cache *iint, struct file *file)
136{
137 int result = -EEXIST;
138
139 if (!(iint->flags & IMA_MEASURED)) {
140 u64 i_version = file->f_dentry->d_inode->i_version;
141
142 memset(iint->digest, 0, IMA_DIGEST_SIZE);
143 result = ima_calc_hash(file, iint->digest);
144 if (!result)
145 iint->version = i_version;
146 }
147 return result;
148}
149
150/*
151 * ima_store_measurement - store file measurement
152 *
153 * Create an "ima" template and then store the template by calling
154 * ima_store_template.
155 *
156 * We only get here if the inode has not already been measured,
157 * but the measurement could already exist:
158 * - multiple copies of the same file on either the same or
159 * different filesystems.
160 * - the inode was previously flushed as well as the iint info,
161 * containing the hashing info.
162 *
163 * Must be called with iint->mutex held.
164 */
165void ima_store_measurement(struct ima_iint_cache *iint, struct file *file,
166 const unsigned char *filename)
167{
168 const char *op = "add_template_measure";
169 const char *audit_cause = "ENOMEM";
170 int result = -ENOMEM;
171 struct inode *inode = file->f_dentry->d_inode;
172 struct ima_template_entry *entry;
173 int violation = 0;
174
175 entry = kmalloc(sizeof(*entry), GFP_KERNEL);
176 if (!entry) {
177 integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, filename,
178 op, audit_cause, result, 0);
179 return;
180 }
181 memset(&entry->template, 0, sizeof(entry->template));
182 memcpy(entry->template.digest, iint->digest, IMA_DIGEST_SIZE);
183 strncpy(entry->template.file_name, filename, IMA_EVENT_NAME_LEN_MAX);
184
185 result = ima_store_template(entry, violation, inode);
186 if (!result)
187 iint->flags |= IMA_MEASURED;
188 else
189 kfree(entry);
190}
diff --git a/security/integrity/ima/ima_audit.c b/security/integrity/ima/ima_audit.c
new file mode 100644
index 000000000000..1e082bb987be
--- /dev/null
+++ b/security/integrity/ima/ima_audit.c
@@ -0,0 +1,81 @@
1/*
2 * Copyright (C) 2008 IBM Corporation
3 * Author: Mimi Zohar <zohar@us.ibm.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, version 2 of the License.
8 *
9 * File: integrity_audit.c
10 * Audit calls for the integrity subsystem
11 */
12
13#include <linux/fs.h>
14#include <linux/audit.h>
15#include "ima.h"
16
17static int ima_audit;
18
19#ifdef CONFIG_IMA_AUDIT
20
21/* ima_audit_setup - enable informational auditing messages */
22static int __init ima_audit_setup(char *str)
23{
24 unsigned long audit;
25 int rc, result = 0;
26 char *op = "ima_audit";
27 char *cause;
28
29 rc = strict_strtoul(str, 0, &audit);
30 if (rc || audit > 1)
31 result = 1;
32 else
33 ima_audit = audit;
34 cause = ima_audit ? "enabled" : "not_enabled";
35 integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, NULL,
36 op, cause, result, 0);
37 return 1;
38}
39__setup("ima_audit=", ima_audit_setup);
40#endif
41
42void integrity_audit_msg(int audit_msgno, struct inode *inode,
43 const unsigned char *fname, const char *op,
44 const char *cause, int result, int audit_info)
45{
46 struct audit_buffer *ab;
47
48 if (!ima_audit && audit_info == 1) /* Skip informational messages */
49 return;
50
51 ab = audit_log_start(current->audit_context, GFP_KERNEL, audit_msgno);
52 audit_log_format(ab, "integrity: pid=%d uid=%u auid=%u ses=%u",
53 current->pid, current->cred->uid,
54 audit_get_loginuid(current),
55 audit_get_sessionid(current));
56 audit_log_task_context(ab);
57 switch (audit_msgno) {
58 case AUDIT_INTEGRITY_DATA:
59 case AUDIT_INTEGRITY_METADATA:
60 case AUDIT_INTEGRITY_PCR:
61 case AUDIT_INTEGRITY_STATUS:
62 audit_log_format(ab, " op=%s cause=%s", op, cause);
63 break;
64 case AUDIT_INTEGRITY_HASH:
65 audit_log_format(ab, " op=%s hash=%s", op, cause);
66 break;
67 default:
68 audit_log_format(ab, " op=%s", op);
69 }
70 audit_log_format(ab, " comm=");
71 audit_log_untrustedstring(ab, current->comm);
72 if (fname) {
73 audit_log_format(ab, " name=");
74 audit_log_untrustedstring(ab, fname);
75 }
76 if (inode)
77 audit_log_format(ab, " dev=%s ino=%lu",
78 inode->i_sb->s_id, inode->i_ino);
79 audit_log_format(ab, " res=%d", !result ? 0 : 1);
80 audit_log_end(ab);
81}
diff --git a/security/integrity/ima/ima_crypto.c b/security/integrity/ima/ima_crypto.c
new file mode 100644
index 000000000000..50d572b74caf
--- /dev/null
+++ b/security/integrity/ima/ima_crypto.c
@@ -0,0 +1,140 @@
1/*
2 * Copyright (C) 2005,2006,2007,2008 IBM Corporation
3 *
4 * Authors:
5 * Mimi Zohar <zohar@us.ibm.com>
6 * Kylene Hall <kjhall@us.ibm.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, version 2 of the License.
11 *
12 * File: ima_crypto.c
13 * Calculates md5/sha1 file hash, template hash, boot-aggreate hash
14 */
15
16#include <linux/kernel.h>
17#include <linux/file.h>
18#include <linux/crypto.h>
19#include <linux/scatterlist.h>
20#include <linux/err.h>
21#include "ima.h"
22
23static int init_desc(struct hash_desc *desc)
24{
25 int rc;
26
27 desc->tfm = crypto_alloc_hash(ima_hash, 0, CRYPTO_ALG_ASYNC);
28 if (IS_ERR(desc->tfm)) {
29 pr_info("failed to load %s transform: %ld\n",
30 ima_hash, PTR_ERR(desc->tfm));
31 rc = PTR_ERR(desc->tfm);
32 return rc;
33 }
34 desc->flags = 0;
35 rc = crypto_hash_init(desc);
36 if (rc)
37 crypto_free_hash(desc->tfm);
38 return rc;
39}
40
41/*
42 * Calculate the MD5/SHA1 file digest
43 */
44int ima_calc_hash(struct file *file, char *digest)
45{
46 struct hash_desc desc;
47 struct scatterlist sg[1];
48 loff_t i_size;
49 char *rbuf;
50 int rc, offset = 0;
51
52 rc = init_desc(&desc);
53 if (rc != 0)
54 return rc;
55
56 rbuf = kzalloc(PAGE_SIZE, GFP_KERNEL);
57 if (!rbuf) {
58 rc = -ENOMEM;
59 goto out;
60 }
61 i_size = i_size_read(file->f_dentry->d_inode);
62 while (offset < i_size) {
63 int rbuf_len;
64
65 rbuf_len = kernel_read(file, offset, rbuf, PAGE_SIZE);
66 if (rbuf_len < 0) {
67 rc = rbuf_len;
68 break;
69 }
70 offset += rbuf_len;
71 sg_init_one(sg, rbuf, rbuf_len);
72
73 rc = crypto_hash_update(&desc, sg, rbuf_len);
74 if (rc)
75 break;
76 }
77 kfree(rbuf);
78 if (!rc)
79 rc = crypto_hash_final(&desc, digest);
80out:
81 crypto_free_hash(desc.tfm);
82 return rc;
83}
84
85/*
86 * Calculate the hash of a given template
87 */
88int ima_calc_template_hash(int template_len, void *template, char *digest)
89{
90 struct hash_desc desc;
91 struct scatterlist sg[1];
92 int rc;
93
94 rc = init_desc(&desc);
95 if (rc != 0)
96 return rc;
97
98 sg_init_one(sg, template, template_len);
99 rc = crypto_hash_update(&desc, sg, template_len);
100 if (!rc)
101 rc = crypto_hash_final(&desc, digest);
102 crypto_free_hash(desc.tfm);
103 return rc;
104}
105
106static void ima_pcrread(int idx, u8 *pcr)
107{
108 if (!ima_used_chip)
109 return;
110
111 if (tpm_pcr_read(TPM_ANY_NUM, idx, pcr) != 0)
112 pr_err("Error Communicating to TPM chip\n");
113}
114
115/*
116 * Calculate the boot aggregate hash
117 */
118int ima_calc_boot_aggregate(char *digest)
119{
120 struct hash_desc desc;
121 struct scatterlist sg;
122 u8 pcr_i[IMA_DIGEST_SIZE];
123 int rc, i;
124
125 rc = init_desc(&desc);
126 if (rc != 0)
127 return rc;
128
129 /* cumulative sha1 over tpm registers 0-7 */
130 for (i = TPM_PCR0; i < TPM_PCR8; i++) {
131 ima_pcrread(i, pcr_i);
132 /* now accumulate with current aggregate */
133 sg_init_one(&sg, pcr_i, IMA_DIGEST_SIZE);
134 rc = crypto_hash_update(&desc, &sg, IMA_DIGEST_SIZE);
135 }
136 if (!rc)
137 crypto_hash_final(&desc, digest);
138 crypto_free_hash(desc.tfm);
139 return rc;
140}
diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c
new file mode 100644
index 000000000000..ffbe259700b1
--- /dev/null
+++ b/security/integrity/ima/ima_fs.c
@@ -0,0 +1,376 @@
1/*
2 * Copyright (C) 2005,2006,2007,2008 IBM Corporation
3 *
4 * Authors:
5 * Kylene Hall <kjhall@us.ibm.com>
6 * Reiner Sailer <sailer@us.ibm.com>
7 * Mimi Zohar <zohar@us.ibm.com>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation, version 2 of the
12 * License.
13 *
14 * File: ima_fs.c
15 * implemenents security file system for reporting
16 * current measurement list and IMA statistics
17 */
18#include <linux/module.h>
19#include <linux/seq_file.h>
20#include <linux/rculist.h>
21#include <linux/rcupdate.h>
22#include <linux/parser.h>
23
24#include "ima.h"
25
26static int valid_policy = 1;
27#define TMPBUFLEN 12
28static ssize_t ima_show_htable_value(char __user *buf, size_t count,
29 loff_t *ppos, atomic_long_t *val)
30{
31 char tmpbuf[TMPBUFLEN];
32 ssize_t len;
33
34 len = scnprintf(tmpbuf, TMPBUFLEN, "%li\n", atomic_long_read(val));
35 return simple_read_from_buffer(buf, count, ppos, tmpbuf, len);
36}
37
38static ssize_t ima_show_htable_violations(struct file *filp,
39 char __user *buf,
40 size_t count, loff_t *ppos)
41{
42 return ima_show_htable_value(buf, count, ppos, &ima_htable.violations);
43}
44
45static struct file_operations ima_htable_violations_ops = {
46 .read = ima_show_htable_violations
47};
48
49static ssize_t ima_show_measurements_count(struct file *filp,
50 char __user *buf,
51 size_t count, loff_t *ppos)
52{
53 return ima_show_htable_value(buf, count, ppos, &ima_htable.len);
54
55}
56
57static struct file_operations ima_measurements_count_ops = {
58 .read = ima_show_measurements_count
59};
60
61/* returns pointer to hlist_node */
62static void *ima_measurements_start(struct seq_file *m, loff_t *pos)
63{
64 loff_t l = *pos;
65 struct ima_queue_entry *qe;
66
67 /* we need a lock since pos could point beyond last element */
68 rcu_read_lock();
69 list_for_each_entry_rcu(qe, &ima_measurements, later) {
70 if (!l--) {
71 rcu_read_unlock();
72 return qe;
73 }
74 }
75 rcu_read_unlock();
76 return NULL;
77}
78
79static void *ima_measurements_next(struct seq_file *m, void *v, loff_t *pos)
80{
81 struct ima_queue_entry *qe = v;
82
83 /* lock protects when reading beyond last element
84 * against concurrent list-extension
85 */
86 rcu_read_lock();
87 qe = list_entry(rcu_dereference(qe->later.next),
88 struct ima_queue_entry, later);
89 rcu_read_unlock();
90 (*pos)++;
91
92 return (&qe->later == &ima_measurements) ? NULL : qe;
93}
94
95static void ima_measurements_stop(struct seq_file *m, void *v)
96{
97}
98
99static void ima_putc(struct seq_file *m, void *data, int datalen)
100{
101 while (datalen--)
102 seq_putc(m, *(char *)data++);
103}
104
105/* print format:
106 * 32bit-le=pcr#
107 * char[20]=template digest
108 * 32bit-le=template name size
109 * char[n]=template name
110 * eventdata[n]=template specific data
111 */
112static int ima_measurements_show(struct seq_file *m, void *v)
113{
114 /* the list never shrinks, so we don't need a lock here */
115 struct ima_queue_entry *qe = v;
116 struct ima_template_entry *e;
117 int namelen;
118 u32 pcr = CONFIG_IMA_MEASURE_PCR_IDX;
119
120 /* get entry */
121 e = qe->entry;
122 if (e == NULL)
123 return -1;
124
125 /*
126 * 1st: PCRIndex
127 * PCR used is always the same (config option) in
128 * little-endian format
129 */
130 ima_putc(m, &pcr, sizeof pcr);
131
132 /* 2nd: template digest */
133 ima_putc(m, e->digest, IMA_DIGEST_SIZE);
134
135 /* 3rd: template name size */
136 namelen = strlen(e->template_name);
137 ima_putc(m, &namelen, sizeof namelen);
138
139 /* 4th: template name */
140 ima_putc(m, (void *)e->template_name, namelen);
141
142 /* 5th: template specific data */
143 ima_template_show(m, (struct ima_template_data *)&e->template,
144 IMA_SHOW_BINARY);
145 return 0;
146}
147
148static struct seq_operations ima_measurments_seqops = {
149 .start = ima_measurements_start,
150 .next = ima_measurements_next,
151 .stop = ima_measurements_stop,
152 .show = ima_measurements_show
153};
154
155static int ima_measurements_open(struct inode *inode, struct file *file)
156{
157 return seq_open(file, &ima_measurments_seqops);
158}
159
160static struct file_operations ima_measurements_ops = {
161 .open = ima_measurements_open,
162 .read = seq_read,
163 .llseek = seq_lseek,
164 .release = seq_release,
165};
166
167static void ima_print_digest(struct seq_file *m, u8 *digest)
168{
169 int i;
170
171 for (i = 0; i < IMA_DIGEST_SIZE; i++)
172 seq_printf(m, "%02x", *(digest + i));
173}
174
175void ima_template_show(struct seq_file *m, void *e, enum ima_show_type show)
176{
177 struct ima_template_data *entry = e;
178 int namelen;
179
180 switch (show) {
181 case IMA_SHOW_ASCII:
182 ima_print_digest(m, entry->digest);
183 seq_printf(m, " %s\n", entry->file_name);
184 break;
185 case IMA_SHOW_BINARY:
186 ima_putc(m, entry->digest, IMA_DIGEST_SIZE);
187
188 namelen = strlen(entry->file_name);
189 ima_putc(m, &namelen, sizeof namelen);
190 ima_putc(m, entry->file_name, namelen);
191 default:
192 break;
193 }
194}
195
196/* print in ascii */
197static int ima_ascii_measurements_show(struct seq_file *m, void *v)
198{
199 /* the list never shrinks, so we don't need a lock here */
200 struct ima_queue_entry *qe = v;
201 struct ima_template_entry *e;
202
203 /* get entry */
204 e = qe->entry;
205 if (e == NULL)
206 return -1;
207
208 /* 1st: PCR used (config option) */
209 seq_printf(m, "%2d ", CONFIG_IMA_MEASURE_PCR_IDX);
210
211 /* 2nd: SHA1 template hash */
212 ima_print_digest(m, e->digest);
213
214 /* 3th: template name */
215 seq_printf(m, " %s ", e->template_name);
216
217 /* 4th: template specific data */
218 ima_template_show(m, (struct ima_template_data *)&e->template,
219 IMA_SHOW_ASCII);
220 return 0;
221}
222
223static struct seq_operations ima_ascii_measurements_seqops = {
224 .start = ima_measurements_start,
225 .next = ima_measurements_next,
226 .stop = ima_measurements_stop,
227 .show = ima_ascii_measurements_show
228};
229
230static int ima_ascii_measurements_open(struct inode *inode, struct file *file)
231{
232 return seq_open(file, &ima_ascii_measurements_seqops);
233}
234
235static struct file_operations ima_ascii_measurements_ops = {
236 .open = ima_ascii_measurements_open,
237 .read = seq_read,
238 .llseek = seq_lseek,
239 .release = seq_release,
240};
241
242static ssize_t ima_write_policy(struct file *file, const char __user *buf,
243 size_t datalen, loff_t *ppos)
244{
245 char *data;
246 int rc;
247
248 if (datalen >= PAGE_SIZE)
249 return -ENOMEM;
250 if (*ppos != 0) {
251 /* No partial writes. */
252 return -EINVAL;
253 }
254 data = kmalloc(datalen + 1, GFP_KERNEL);
255 if (!data)
256 return -ENOMEM;
257
258 if (copy_from_user(data, buf, datalen)) {
259 kfree(data);
260 return -EFAULT;
261 }
262 *(data + datalen) = '\0';
263 rc = ima_parse_add_rule(data);
264 if (rc < 0) {
265 datalen = -EINVAL;
266 valid_policy = 0;
267 }
268
269 kfree(data);
270 return datalen;
271}
272
273static struct dentry *ima_dir;
274static struct dentry *binary_runtime_measurements;
275static struct dentry *ascii_runtime_measurements;
276static struct dentry *runtime_measurements_count;
277static struct dentry *violations;
278static struct dentry *ima_policy;
279
280static atomic_t policy_opencount = ATOMIC_INIT(1);
281/*
282 * ima_open_policy: sequentialize access to the policy file
283 */
284int ima_open_policy(struct inode * inode, struct file * filp)
285{
286 if (atomic_dec_and_test(&policy_opencount))
287 return 0;
288 return -EBUSY;
289}
290
291/*
292 * ima_release_policy - start using the new measure policy rules.
293 *
294 * Initially, ima_measure points to the default policy rules, now
295 * point to the new policy rules, and remove the securityfs policy file,
296 * assuming a valid policy.
297 */
298static int ima_release_policy(struct inode *inode, struct file *file)
299{
300 if (!valid_policy) {
301 ima_delete_rules();
302 valid_policy = 1;
303 atomic_set(&policy_opencount, 1);
304 return 0;
305 }
306 ima_update_policy();
307 securityfs_remove(ima_policy);
308 ima_policy = NULL;
309 return 0;
310}
311
312static struct file_operations ima_measure_policy_ops = {
313 .open = ima_open_policy,
314 .write = ima_write_policy,
315 .release = ima_release_policy
316};
317
318int ima_fs_init(void)
319{
320 ima_dir = securityfs_create_dir("ima", NULL);
321 if (IS_ERR(ima_dir))
322 return -1;
323
324 binary_runtime_measurements =
325 securityfs_create_file("binary_runtime_measurements",
326 S_IRUSR | S_IRGRP, ima_dir, NULL,
327 &ima_measurements_ops);
328 if (IS_ERR(binary_runtime_measurements))
329 goto out;
330
331 ascii_runtime_measurements =
332 securityfs_create_file("ascii_runtime_measurements",
333 S_IRUSR | S_IRGRP, ima_dir, NULL,
334 &ima_ascii_measurements_ops);
335 if (IS_ERR(ascii_runtime_measurements))
336 goto out;
337
338 runtime_measurements_count =
339 securityfs_create_file("runtime_measurements_count",
340 S_IRUSR | S_IRGRP, ima_dir, NULL,
341 &ima_measurements_count_ops);
342 if (IS_ERR(runtime_measurements_count))
343 goto out;
344
345 violations =
346 securityfs_create_file("violations", S_IRUSR | S_IRGRP,
347 ima_dir, NULL, &ima_htable_violations_ops);
348 if (IS_ERR(violations))
349 goto out;
350
351 ima_policy = securityfs_create_file("policy",
352 S_IRUSR | S_IRGRP | S_IWUSR,
353 ima_dir, NULL,
354 &ima_measure_policy_ops);
355 if (IS_ERR(ima_policy))
356 goto out;
357
358 return 0;
359out:
360 securityfs_remove(runtime_measurements_count);
361 securityfs_remove(ascii_runtime_measurements);
362 securityfs_remove(binary_runtime_measurements);
363 securityfs_remove(ima_dir);
364 securityfs_remove(ima_policy);
365 return -1;
366}
367
368void __exit ima_fs_cleanup(void)
369{
370 securityfs_remove(violations);
371 securityfs_remove(runtime_measurements_count);
372 securityfs_remove(ascii_runtime_measurements);
373 securityfs_remove(binary_runtime_measurements);
374 securityfs_remove(ima_dir);
375 securityfs_remove(ima_policy);
376}
diff --git a/security/integrity/ima/ima_iint.c b/security/integrity/ima/ima_iint.c
new file mode 100644
index 000000000000..ec79f1ee992c
--- /dev/null
+++ b/security/integrity/ima/ima_iint.c
@@ -0,0 +1,204 @@
1/*
2 * Copyright (C) 2008 IBM Corporation
3 *
4 * Authors:
5 * Mimi Zohar <zohar@us.ibm.com>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation, version 2 of the
10 * License.
11 *
12 * File: ima_iint.c
13 * - implements the IMA hooks: ima_inode_alloc, ima_inode_free
14 * - cache integrity information associated with an inode
15 * using a radix tree.
16 */
17#include <linux/module.h>
18#include <linux/spinlock.h>
19#include <linux/radix-tree.h>
20#include "ima.h"
21
22#define ima_iint_delete ima_inode_free
23
24RADIX_TREE(ima_iint_store, GFP_ATOMIC);
25DEFINE_SPINLOCK(ima_iint_lock);
26
27static struct kmem_cache *iint_cache __read_mostly;
28
29/* ima_iint_find_get - return the iint associated with an inode
30 *
31 * ima_iint_find_get gets a reference to the iint. Caller must
32 * remember to put the iint reference.
33 */
34struct ima_iint_cache *ima_iint_find_get(struct inode *inode)
35{
36 struct ima_iint_cache *iint;
37
38 rcu_read_lock();
39 iint = radix_tree_lookup(&ima_iint_store, (unsigned long)inode);
40 if (!iint)
41 goto out;
42 kref_get(&iint->refcount);
43out:
44 rcu_read_unlock();
45 return iint;
46}
47
48/* Allocate memory for the iint associated with the inode
49 * from the iint_cache slab, initialize the iint, and
50 * insert it into the radix tree.
51 *
52 * On success return a pointer to the iint; on failure return NULL.
53 */
54struct ima_iint_cache *ima_iint_insert(struct inode *inode)
55{
56 struct ima_iint_cache *iint = NULL;
57 int rc = 0;
58
59 if (!ima_initialized)
60 return iint;
61 iint = kmem_cache_alloc(iint_cache, GFP_KERNEL);
62 if (!iint)
63 return iint;
64
65 rc = radix_tree_preload(GFP_KERNEL);
66 if (rc < 0)
67 goto out;
68
69 spin_lock(&ima_iint_lock);
70 rc = radix_tree_insert(&ima_iint_store, (unsigned long)inode, iint);
71 spin_unlock(&ima_iint_lock);
72out:
73 if (rc < 0) {
74 kmem_cache_free(iint_cache, iint);
75 if (rc == -EEXIST) {
76 spin_lock(&ima_iint_lock);
77 iint = radix_tree_lookup(&ima_iint_store,
78 (unsigned long)inode);
79 spin_unlock(&ima_iint_lock);
80 } else
81 iint = NULL;
82 }
83 radix_tree_preload_end();
84 return iint;
85}
86
87/**
88 * ima_inode_alloc - allocate an iint associated with an inode
89 * @inode: pointer to the inode
90 *
91 * Return 0 on success, 1 on failure.
92 */
93int ima_inode_alloc(struct inode *inode)
94{
95 struct ima_iint_cache *iint;
96
97 if (!ima_initialized)
98 return 0;
99
100 iint = ima_iint_insert(inode);
101 if (!iint)
102 return 1;
103 return 0;
104}
105
106/* ima_iint_find_insert_get - get the iint associated with an inode
107 *
108 * Most insertions are done at inode_alloc, except those allocated
109 * before late_initcall. When the iint does not exist, allocate it,
110 * initialize and insert it, and increment the iint refcount.
111 *
112 * (Can't initialize at security_initcall before any inodes are
113 * allocated, got to wait at least until proc_init.)
114 *
115 * Return the iint.
116 */
117struct ima_iint_cache *ima_iint_find_insert_get(struct inode *inode)
118{
119 struct ima_iint_cache *iint = NULL;
120
121 iint = ima_iint_find_get(inode);
122 if (iint)
123 return iint;
124
125 iint = ima_iint_insert(inode);
126 if (iint)
127 kref_get(&iint->refcount);
128
129 return iint;
130}
131EXPORT_SYMBOL_GPL(ima_iint_find_insert_get);
132
133/* iint_free - called when the iint refcount goes to zero */
134void iint_free(struct kref *kref)
135{
136 struct ima_iint_cache *iint = container_of(kref, struct ima_iint_cache,
137 refcount);
138 iint->version = 0;
139 iint->flags = 0UL;
140 if (iint->readcount != 0) {
141 printk(KERN_INFO "%s: readcount: %ld\n", __FUNCTION__,
142 iint->readcount);
143 iint->readcount = 0;
144 }
145 if (iint->writecount != 0) {
146 printk(KERN_INFO "%s: writecount: %ld\n", __FUNCTION__,
147 iint->writecount);
148 iint->writecount = 0;
149 }
150 if (iint->opencount != 0) {
151 printk(KERN_INFO "%s: opencount: %ld\n", __FUNCTION__,
152 iint->opencount);
153 iint->opencount = 0;
154 }
155 kref_set(&iint->refcount, 1);
156 kmem_cache_free(iint_cache, iint);
157}
158
159void iint_rcu_free(struct rcu_head *rcu_head)
160{
161 struct ima_iint_cache *iint = container_of(rcu_head,
162 struct ima_iint_cache, rcu);
163 kref_put(&iint->refcount, iint_free);
164}
165
166/**
167 * ima_iint_delete - called on integrity_inode_free
168 * @inode: pointer to the inode
169 *
170 * Free the integrity information(iint) associated with an inode.
171 */
172void ima_iint_delete(struct inode *inode)
173{
174 struct ima_iint_cache *iint;
175
176 if (!ima_initialized)
177 return;
178 spin_lock(&ima_iint_lock);
179 iint = radix_tree_delete(&ima_iint_store, (unsigned long)inode);
180 spin_unlock(&ima_iint_lock);
181 if (iint)
182 call_rcu(&iint->rcu, iint_rcu_free);
183}
184
185static void init_once(void *foo)
186{
187 struct ima_iint_cache *iint = foo;
188
189 memset(iint, 0, sizeof *iint);
190 iint->version = 0;
191 iint->flags = 0UL;
192 mutex_init(&iint->mutex);
193 iint->readcount = 0;
194 iint->writecount = 0;
195 iint->opencount = 0;
196 kref_set(&iint->refcount, 1);
197}
198
199void ima_iintcache_init(void)
200{
201 iint_cache =
202 kmem_cache_create("iint_cache", sizeof(struct ima_iint_cache), 0,
203 SLAB_PANIC, init_once);
204}
diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c
new file mode 100644
index 000000000000..0b0bb8c978cc
--- /dev/null
+++ b/security/integrity/ima/ima_init.c
@@ -0,0 +1,96 @@
1/*
2 * Copyright (C) 2005,2006,2007,2008 IBM Corporation
3 *
4 * Authors:
5 * Reiner Sailer <sailer@watson.ibm.com>
6 * Leendert van Doorn <leendert@watson.ibm.com>
7 * Mimi Zohar <zohar@us.ibm.com>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation, version 2 of the
12 * License.
13 *
14 * File: ima_init.c
15 * initialization and cleanup functions
16 */
17#include <linux/module.h>
18#include <linux/scatterlist.h>
19#include <linux/err.h>
20#include "ima.h"
21
22/* name for boot aggregate entry */
23static const char *boot_aggregate_name = "boot_aggregate";
24int ima_used_chip;
25
26/* Add the boot aggregate to the IMA measurement list and extend
27 * the PCR register.
28 *
29 * Calculate the boot aggregate, a SHA1 over tpm registers 0-7,
30 * assuming a TPM chip exists, and zeroes if the TPM chip does not
31 * exist. Add the boot aggregate measurement to the measurement
32 * list and extend the PCR register.
33 *
34 * If a tpm chip does not exist, indicate the core root of trust is
35 * not hardware based by invalidating the aggregate PCR value.
36 * (The aggregate PCR value is invalidated by adding one value to
37 * the measurement list and extending the aggregate PCR value with
38 * a different value.) Violations add a zero entry to the measurement
39 * list and extend the aggregate PCR value with ff...ff's.
40 */
41static void ima_add_boot_aggregate(void)
42{
43 struct ima_template_entry *entry;
44 const char *op = "add_boot_aggregate";
45 const char *audit_cause = "ENOMEM";
46 int result = -ENOMEM;
47 int violation = 1;
48
49 entry = kmalloc(sizeof(*entry), GFP_KERNEL);
50 if (!entry)
51 goto err_out;
52
53 memset(&entry->template, 0, sizeof(entry->template));
54 strncpy(entry->template.file_name, boot_aggregate_name,
55 IMA_EVENT_NAME_LEN_MAX);
56 if (ima_used_chip) {
57 violation = 0;
58 result = ima_calc_boot_aggregate(entry->template.digest);
59 if (result < 0) {
60 audit_cause = "hashing_error";
61 kfree(entry);
62 goto err_out;
63 }
64 }
65 result = ima_store_template(entry, violation, NULL);
66 if (result < 0)
67 kfree(entry);
68 return;
69err_out:
70 integrity_audit_msg(AUDIT_INTEGRITY_PCR, NULL, boot_aggregate_name, op,
71 audit_cause, result, 0);
72}
73
74int ima_init(void)
75{
76 u8 pcr_i[IMA_DIGEST_SIZE];
77 int rc;
78
79 ima_used_chip = 0;
80 rc = tpm_pcr_read(TPM_ANY_NUM, 0, pcr_i);
81 if (rc == 0)
82 ima_used_chip = 1;
83
84 if (!ima_used_chip)
85 pr_info("No TPM chip found, activating TPM-bypass!\n");
86
87 ima_add_boot_aggregate(); /* boot aggregate must be first entry */
88 ima_init_policy();
89
90 return ima_fs_init();
91}
92
93void __exit ima_cleanup(void)
94{
95 ima_fs_cleanup();
96}
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
new file mode 100644
index 000000000000..f4e7266f5aee
--- /dev/null
+++ b/security/integrity/ima/ima_main.c
@@ -0,0 +1,327 @@
1/*
2 * Copyright (C) 2005,2006,2007,2008 IBM Corporation
3 *
4 * Authors:
5 * Reiner Sailer <sailer@watson.ibm.com>
6 * Serge Hallyn <serue@us.ibm.com>
7 * Kylene Hall <kylene@us.ibm.com>
8 * Mimi Zohar <zohar@us.ibm.com>
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License as
12 * published by the Free Software Foundation, version 2 of the
13 * License.
14 *
15 * File: ima_main.c
16 * implements the IMA hooks: ima_bprm_check, ima_file_mmap,
17 * and ima_path_check.
18 */
19#include <linux/module.h>
20#include <linux/file.h>
21#include <linux/binfmts.h>
22#include <linux/mount.h>
23#include <linux/mman.h>
24
25#include "ima.h"
26
27int ima_initialized;
28
29char *ima_hash = "sha1";
30static int __init hash_setup(char *str)
31{
32 const char *op = "hash_setup";
33 const char *hash = "sha1";
34 int result = 0;
35 int audit_info = 0;
36
37 if (strncmp(str, "md5", 3) == 0) {
38 hash = "md5";
39 ima_hash = str;
40 } else if (strncmp(str, "sha1", 4) != 0) {
41 hash = "invalid_hash_type";
42 result = 1;
43 }
44 integrity_audit_msg(AUDIT_INTEGRITY_HASH, NULL, NULL, op, hash,
45 result, audit_info);
46 return 1;
47}
48__setup("ima_hash=", hash_setup);
49
50/**
51 * ima_file_free - called on __fput()
52 * @file: pointer to file structure being freed
53 *
54 * Flag files that changed, based on i_version;
55 * and decrement the iint readcount/writecount.
56 */
57void ima_file_free(struct file *file)
58{
59 struct inode *inode = file->f_dentry->d_inode;
60 struct ima_iint_cache *iint;
61
62 if (!ima_initialized || !S_ISREG(inode->i_mode))
63 return;
64 iint = ima_iint_find_get(inode);
65 if (!iint)
66 return;
67
68 mutex_lock(&iint->mutex);
69 if (iint->opencount <= 0) {
70 printk(KERN_INFO
71 "%s: %s open/free imbalance (r:%ld w:%ld o:%ld f:%ld)\n",
72 __FUNCTION__, file->f_dentry->d_name.name,
73 iint->readcount, iint->writecount,
74 iint->opencount, atomic_long_read(&file->f_count));
75 if (!(iint->flags & IMA_IINT_DUMP_STACK)) {
76 dump_stack();
77 iint->flags |= IMA_IINT_DUMP_STACK;
78 }
79 }
80 iint->opencount--;
81
82 if ((file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
83 iint->readcount--;
84
85 if (file->f_mode & FMODE_WRITE) {
86 iint->writecount--;
87 if (iint->writecount == 0) {
88 if (iint->version != inode->i_version)
89 iint->flags &= ~IMA_MEASURED;
90 }
91 }
92 mutex_unlock(&iint->mutex);
93 kref_put(&iint->refcount, iint_free);
94}
95
96/* ima_read_write_check - reflect possible reading/writing errors in the PCR.
97 *
98 * When opening a file for read, if the file is already open for write,
99 * the file could change, resulting in a file measurement error.
100 *
101 * Opening a file for write, if the file is already open for read, results
102 * in a time of measure, time of use (ToMToU) error.
103 *
104 * In either case invalidate the PCR.
105 */
106enum iint_pcr_error { TOMTOU, OPEN_WRITERS };
107static void ima_read_write_check(enum iint_pcr_error error,
108 struct ima_iint_cache *iint,
109 struct inode *inode,
110 const unsigned char *filename)
111{
112 switch (error) {
113 case TOMTOU:
114 if (iint->readcount > 0)
115 ima_add_violation(inode, filename, "invalid_pcr",
116 "ToMToU");
117 break;
118 case OPEN_WRITERS:
119 if (iint->writecount > 0)
120 ima_add_violation(inode, filename, "invalid_pcr",
121 "open_writers");
122 break;
123 }
124}
125
126static int get_path_measurement(struct ima_iint_cache *iint, struct file *file,
127 const unsigned char *filename)
128{
129 int rc = 0;
130
131 if (IS_ERR(file)) {
132 pr_info("%s dentry_open failed\n", filename);
133 return rc;
134 }
135 iint->opencount++;
136 iint->readcount++;
137
138 rc = ima_collect_measurement(iint, file);
139 if (!rc)
140 ima_store_measurement(iint, file, filename);
141 return rc;
142}
143
144/**
145 * ima_path_check - based on policy, collect/store measurement.
146 * @path: contains a pointer to the path to be measured
147 * @mask: contains MAY_READ, MAY_WRITE or MAY_EXECUTE
148 *
149 * Measure the file being open for readonly, based on the
150 * ima_must_measure() policy decision.
151 *
152 * Keep read/write counters for all files, but only
153 * invalidate the PCR for measured files:
154 * - Opening a file for write when already open for read,
155 * results in a time of measure, time of use (ToMToU) error.
156 * - Opening a file for read when already open for write,
157 * could result in a file measurement error.
158 *
159 * Return 0 on success, an error code on failure.
160 * (Based on the results of appraise_measurement().)
161 */
162int ima_path_check(struct path *path, int mask)
163{
164 struct inode *inode = path->dentry->d_inode;
165 struct ima_iint_cache *iint;
166 struct file *file = NULL;
167 int rc;
168
169 if (!ima_initialized || !S_ISREG(inode->i_mode))
170 return 0;
171 iint = ima_iint_find_insert_get(inode);
172 if (!iint)
173 return 0;
174
175 mutex_lock(&iint->mutex);
176 iint->opencount++;
177 if ((mask & MAY_WRITE) || (mask == 0))
178 iint->writecount++;
179 else if (mask & (MAY_READ | MAY_EXEC))
180 iint->readcount++;
181
182 rc = ima_must_measure(iint, inode, MAY_READ, PATH_CHECK);
183 if (rc < 0)
184 goto out;
185
186 if ((mask & MAY_WRITE) || (mask == 0))
187 ima_read_write_check(TOMTOU, iint, inode,
188 path->dentry->d_name.name);
189
190 if ((mask & (MAY_WRITE | MAY_READ | MAY_EXEC)) != MAY_READ)
191 goto out;
192
193 ima_read_write_check(OPEN_WRITERS, iint, inode,
194 path->dentry->d_name.name);
195 if (!(iint->flags & IMA_MEASURED)) {
196 struct dentry *dentry = dget(path->dentry);
197 struct vfsmount *mnt = mntget(path->mnt);
198
199 file = dentry_open(dentry, mnt, O_RDONLY, current->cred);
200 rc = get_path_measurement(iint, file, dentry->d_name.name);
201 }
202out:
203 mutex_unlock(&iint->mutex);
204 if (file)
205 fput(file);
206 kref_put(&iint->refcount, iint_free);
207 return 0;
208}
209
210static int process_measurement(struct file *file, const unsigned char *filename,
211 int mask, int function)
212{
213 struct inode *inode = file->f_dentry->d_inode;
214 struct ima_iint_cache *iint;
215 int rc;
216
217 if (!ima_initialized || !S_ISREG(inode->i_mode))
218 return 0;
219 iint = ima_iint_find_insert_get(inode);
220 if (!iint)
221 return -ENOMEM;
222
223 mutex_lock(&iint->mutex);
224 rc = ima_must_measure(iint, inode, mask, function);
225 if (rc != 0)
226 goto out;
227
228 rc = ima_collect_measurement(iint, file);
229 if (!rc)
230 ima_store_measurement(iint, file, filename);
231out:
232 mutex_unlock(&iint->mutex);
233 kref_put(&iint->refcount, iint_free);
234 return rc;
235}
236
237static void opencount_get(struct file *file)
238{
239 struct inode *inode = file->f_dentry->d_inode;
240 struct ima_iint_cache *iint;
241
242 if (!ima_initialized || !S_ISREG(inode->i_mode))
243 return;
244 iint = ima_iint_find_insert_get(inode);
245 if (!iint)
246 return;
247 mutex_lock(&iint->mutex);
248 iint->opencount++;
249 mutex_unlock(&iint->mutex);
250}
251
252/**
253 * ima_file_mmap - based on policy, collect/store measurement.
254 * @file: pointer to the file to be measured (May be NULL)
255 * @prot: contains the protection that will be applied by the kernel.
256 *
257 * Measure files being mmapped executable based on the ima_must_measure()
258 * policy decision.
259 *
260 * Return 0 on success, an error code on failure.
261 * (Based on the results of appraise_measurement().)
262 */
263int ima_file_mmap(struct file *file, unsigned long prot)
264{
265 int rc;
266
267 if (!file)
268 return 0;
269 if (prot & PROT_EXEC)
270 rc = process_measurement(file, file->f_dentry->d_name.name,
271 MAY_EXEC, FILE_MMAP);
272 return 0;
273}
274
275/*
276 * ima_shm_check - IPC shm and shmat create/fput a file
277 *
278 * Maintain the opencount for these files to prevent unnecessary
279 * imbalance messages.
280 */
281void ima_shm_check(struct file *file)
282{
283 opencount_get(file);
284 return;
285}
286
287/**
288 * ima_bprm_check - based on policy, collect/store measurement.
289 * @bprm: contains the linux_binprm structure
290 *
291 * The OS protects against an executable file, already open for write,
292 * from being executed in deny_write_access() and an executable file,
293 * already open for execute, from being modified in get_write_access().
294 * So we can be certain that what we verify and measure here is actually
295 * what is being executed.
296 *
297 * Return 0 on success, an error code on failure.
298 * (Based on the results of appraise_measurement().)
299 */
300int ima_bprm_check(struct linux_binprm *bprm)
301{
302 int rc;
303
304 rc = process_measurement(bprm->file, bprm->filename,
305 MAY_EXEC, BPRM_CHECK);
306 return 0;
307}
308
309static int __init init_ima(void)
310{
311 int error;
312
313 ima_iintcache_init();
314 error = ima_init();
315 ima_initialized = 1;
316 return error;
317}
318
319static void __exit cleanup_ima(void)
320{
321 ima_cleanup();
322}
323
324late_initcall(init_ima); /* Start IMA after the TPM is available */
325
326MODULE_DESCRIPTION("Integrity Measurement Architecture");
327MODULE_LICENSE("GPL");
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
new file mode 100644
index 000000000000..b5291ad5ef56
--- /dev/null
+++ b/security/integrity/ima/ima_policy.c
@@ -0,0 +1,414 @@
1/*
2 * Copyright (C) 2008 IBM Corporation
3 * Author: Mimi Zohar <zohar@us.ibm.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, version 2 of the License.
8 *
9 * ima_policy.c
10 * - initialize default measure policy rules
11 *
12 */
13#include <linux/module.h>
14#include <linux/list.h>
15#include <linux/security.h>
16#include <linux/magic.h>
17#include <linux/parser.h>
18
19#include "ima.h"
20
21/* flags definitions */
22#define IMA_FUNC 0x0001
23#define IMA_MASK 0x0002
24#define IMA_FSMAGIC 0x0004
25#define IMA_UID 0x0008
26
27enum ima_action { UNKNOWN = -1, DONT_MEASURE = 0, MEASURE };
28
29#define MAX_LSM_RULES 6
30enum lsm_rule_types { LSM_OBJ_USER, LSM_OBJ_ROLE, LSM_OBJ_TYPE,
31 LSM_SUBJ_USER, LSM_SUBJ_ROLE, LSM_SUBJ_TYPE
32};
33
34struct ima_measure_rule_entry {
35 struct list_head list;
36 enum ima_action action;
37 unsigned int flags;
38 enum ima_hooks func;
39 int mask;
40 unsigned long fsmagic;
41 uid_t uid;
42 struct {
43 void *rule; /* LSM file metadata specific */
44 int type; /* audit type */
45 } lsm[MAX_LSM_RULES];
46};
47
48/* Without LSM specific knowledge, the default policy can only be
49 * written in terms of .action, .func, .mask, .fsmagic, and .uid
50 */
51static struct ima_measure_rule_entry default_rules[] = {
52 {.action = DONT_MEASURE,.fsmagic = PROC_SUPER_MAGIC,
53 .flags = IMA_FSMAGIC},
54 {.action = DONT_MEASURE,.fsmagic = SYSFS_MAGIC,.flags = IMA_FSMAGIC},
55 {.action = DONT_MEASURE,.fsmagic = DEBUGFS_MAGIC,.flags = IMA_FSMAGIC},
56 {.action = DONT_MEASURE,.fsmagic = TMPFS_MAGIC,.flags = IMA_FSMAGIC},
57 {.action = DONT_MEASURE,.fsmagic = SECURITYFS_MAGIC,
58 .flags = IMA_FSMAGIC},
59 {.action = DONT_MEASURE,.fsmagic = 0xF97CFF8C,.flags = IMA_FSMAGIC},
60 {.action = MEASURE,.func = FILE_MMAP,.mask = MAY_EXEC,
61 .flags = IMA_FUNC | IMA_MASK},
62 {.action = MEASURE,.func = BPRM_CHECK,.mask = MAY_EXEC,
63 .flags = IMA_FUNC | IMA_MASK},
64 {.action = MEASURE,.func = PATH_CHECK,.mask = MAY_READ,.uid = 0,
65 .flags = IMA_FUNC | IMA_MASK | IMA_UID}
66};
67
68static LIST_HEAD(measure_default_rules);
69static LIST_HEAD(measure_policy_rules);
70static struct list_head *ima_measure;
71
72static DEFINE_MUTEX(ima_measure_mutex);
73
74/**
75 * ima_match_rules - determine whether an inode matches the measure rule.
76 * @rule: a pointer to a rule
77 * @inode: a pointer to an inode
78 * @func: LIM hook identifier
79 * @mask: requested action (MAY_READ | MAY_WRITE | MAY_APPEND | MAY_EXEC)
80 *
81 * Returns true on rule match, false on failure.
82 */
83static bool ima_match_rules(struct ima_measure_rule_entry *rule,
84 struct inode *inode, enum ima_hooks func, int mask)
85{
86 struct task_struct *tsk = current;
87 int i;
88
89 if ((rule->flags & IMA_FUNC) && rule->func != func)
90 return false;
91 if ((rule->flags & IMA_MASK) && rule->mask != mask)
92 return false;
93 if ((rule->flags & IMA_FSMAGIC)
94 && rule->fsmagic != inode->i_sb->s_magic)
95 return false;
96 if ((rule->flags & IMA_UID) && rule->uid != tsk->cred->uid)
97 return false;
98 for (i = 0; i < MAX_LSM_RULES; i++) {
99 int rc;
100 u32 osid, sid;
101
102 if (!rule->lsm[i].rule)
103 continue;
104
105 switch (i) {
106 case LSM_OBJ_USER:
107 case LSM_OBJ_ROLE:
108 case LSM_OBJ_TYPE:
109 security_inode_getsecid(inode, &osid);
110 rc = security_filter_rule_match(osid,
111 rule->lsm[i].type,
112 AUDIT_EQUAL,
113 rule->lsm[i].rule,
114 NULL);
115 break;
116 case LSM_SUBJ_USER:
117 case LSM_SUBJ_ROLE:
118 case LSM_SUBJ_TYPE:
119 security_task_getsecid(tsk, &sid);
120 rc = security_filter_rule_match(sid,
121 rule->lsm[i].type,
122 AUDIT_EQUAL,
123 rule->lsm[i].rule,
124 NULL);
125 default:
126 break;
127 }
128 if (!rc)
129 return false;
130 }
131 return true;
132}
133
134/**
135 * ima_match_policy - decision based on LSM and other conditions
136 * @inode: pointer to an inode for which the policy decision is being made
137 * @func: IMA hook identifier
138 * @mask: requested action (MAY_READ | MAY_WRITE | MAY_APPEND | MAY_EXEC)
139 *
140 * Measure decision based on func/mask/fsmagic and LSM(subj/obj/type)
141 * conditions.
142 *
143 * (There is no need for locking when walking the policy list,
144 * as elements in the list are never deleted, nor does the list
145 * change.)
146 */
147int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask)
148{
149 struct ima_measure_rule_entry *entry;
150
151 list_for_each_entry(entry, ima_measure, list) {
152 bool rc;
153
154 rc = ima_match_rules(entry, inode, func, mask);
155 if (rc)
156 return entry->action;
157 }
158 return 0;
159}
160
161/**
162 * ima_init_policy - initialize the default measure rules.
163 *
164 * ima_measure points to either the measure_default_rules or the
165 * the new measure_policy_rules.
166 */
167void ima_init_policy(void)
168{
169 int i;
170
171 for (i = 0; i < ARRAY_SIZE(default_rules); i++)
172 list_add_tail(&default_rules[i].list, &measure_default_rules);
173 ima_measure = &measure_default_rules;
174}
175
176/**
177 * ima_update_policy - update default_rules with new measure rules
178 *
179 * Called on file .release to update the default rules with a complete new
180 * policy. Once updated, the policy is locked, no additional rules can be
181 * added to the policy.
182 */
183void ima_update_policy(void)
184{
185 const char *op = "policy_update";
186 const char *cause = "already exists";
187 int result = 1;
188 int audit_info = 0;
189
190 if (ima_measure == &measure_default_rules) {
191 ima_measure = &measure_policy_rules;
192 cause = "complete";
193 result = 0;
194 }
195 integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL,
196 NULL, op, cause, result, audit_info);
197}
198
199enum {
200 Opt_err = -1,
201 Opt_measure = 1, Opt_dont_measure,
202 Opt_obj_user, Opt_obj_role, Opt_obj_type,
203 Opt_subj_user, Opt_subj_role, Opt_subj_type,
204 Opt_func, Opt_mask, Opt_fsmagic, Opt_uid
205};
206
207static match_table_t policy_tokens = {
208 {Opt_measure, "measure"},
209 {Opt_dont_measure, "dont_measure"},
210 {Opt_obj_user, "obj_user=%s"},
211 {Opt_obj_role, "obj_role=%s"},
212 {Opt_obj_type, "obj_type=%s"},
213 {Opt_subj_user, "subj_user=%s"},
214 {Opt_subj_role, "subj_role=%s"},
215 {Opt_subj_type, "subj_type=%s"},
216 {Opt_func, "func=%s"},
217 {Opt_mask, "mask=%s"},
218 {Opt_fsmagic, "fsmagic=%s"},
219 {Opt_uid, "uid=%s"},
220 {Opt_err, NULL}
221};
222
223static int ima_lsm_rule_init(struct ima_measure_rule_entry *entry,
224 char *args, int lsm_rule, int audit_type)
225{
226 int result;
227
228 entry->lsm[lsm_rule].type = audit_type;
229 result = security_filter_rule_init(entry->lsm[lsm_rule].type,
230 AUDIT_EQUAL, args,
231 &entry->lsm[lsm_rule].rule);
232 return result;
233}
234
235static int ima_parse_rule(char *rule, struct ima_measure_rule_entry *entry)
236{
237 struct audit_buffer *ab;
238 char *p;
239 int result = 0;
240
241 ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_INTEGRITY_RULE);
242
243 entry->action = -1;
244 while ((p = strsep(&rule, " \n")) != NULL) {
245 substring_t args[MAX_OPT_ARGS];
246 int token;
247 unsigned long lnum;
248
249 if (result < 0)
250 break;
251 if (!*p)
252 continue;
253 token = match_token(p, policy_tokens, args);
254 switch (token) {
255 case Opt_measure:
256 audit_log_format(ab, "%s ", "measure");
257 entry->action = MEASURE;
258 break;
259 case Opt_dont_measure:
260 audit_log_format(ab, "%s ", "dont_measure");
261 entry->action = DONT_MEASURE;
262 break;
263 case Opt_func:
264 audit_log_format(ab, "func=%s ", args[0].from);
265 if (strcmp(args[0].from, "PATH_CHECK") == 0)
266 entry->func = PATH_CHECK;
267 else if (strcmp(args[0].from, "FILE_MMAP") == 0)
268 entry->func = FILE_MMAP;
269 else if (strcmp(args[0].from, "BPRM_CHECK") == 0)
270 entry->func = BPRM_CHECK;
271 else
272 result = -EINVAL;
273 if (!result)
274 entry->flags |= IMA_FUNC;
275 break;
276 case Opt_mask:
277 audit_log_format(ab, "mask=%s ", args[0].from);
278 if ((strcmp(args[0].from, "MAY_EXEC")) == 0)
279 entry->mask = MAY_EXEC;
280 else if (strcmp(args[0].from, "MAY_WRITE") == 0)
281 entry->mask = MAY_WRITE;
282 else if (strcmp(args[0].from, "MAY_READ") == 0)
283 entry->mask = MAY_READ;
284 else if (strcmp(args[0].from, "MAY_APPEND") == 0)
285 entry->mask = MAY_APPEND;
286 else
287 result = -EINVAL;
288 if (!result)
289 entry->flags |= IMA_MASK;
290 break;
291 case Opt_fsmagic:
292 audit_log_format(ab, "fsmagic=%s ", args[0].from);
293 result = strict_strtoul(args[0].from, 16,
294 &entry->fsmagic);
295 if (!result)
296 entry->flags |= IMA_FSMAGIC;
297 break;
298 case Opt_uid:
299 audit_log_format(ab, "uid=%s ", args[0].from);
300 result = strict_strtoul(args[0].from, 10, &lnum);
301 if (!result) {
302 entry->uid = (uid_t) lnum;
303 if (entry->uid != lnum)
304 result = -EINVAL;
305 else
306 entry->flags |= IMA_UID;
307 }
308 break;
309 case Opt_obj_user:
310 audit_log_format(ab, "obj_user=%s ", args[0].from);
311 result = ima_lsm_rule_init(entry, args[0].from,
312 LSM_OBJ_USER,
313 AUDIT_OBJ_USER);
314 break;
315 case Opt_obj_role:
316 audit_log_format(ab, "obj_role=%s ", args[0].from);
317 result = ima_lsm_rule_init(entry, args[0].from,
318 LSM_OBJ_ROLE,
319 AUDIT_OBJ_ROLE);
320 break;
321 case Opt_obj_type:
322 audit_log_format(ab, "obj_type=%s ", args[0].from);
323 result = ima_lsm_rule_init(entry, args[0].from,
324 LSM_OBJ_TYPE,
325 AUDIT_OBJ_TYPE);
326 break;
327 case Opt_subj_user:
328 audit_log_format(ab, "subj_user=%s ", args[0].from);
329 result = ima_lsm_rule_init(entry, args[0].from,
330 LSM_SUBJ_USER,
331 AUDIT_SUBJ_USER);
332 break;
333 case Opt_subj_role:
334 audit_log_format(ab, "subj_role=%s ", args[0].from);
335 result = ima_lsm_rule_init(entry, args[0].from,
336 LSM_SUBJ_ROLE,
337 AUDIT_SUBJ_ROLE);
338 break;
339 case Opt_subj_type:
340 audit_log_format(ab, "subj_type=%s ", args[0].from);
341 result = ima_lsm_rule_init(entry, args[0].from,
342 LSM_SUBJ_TYPE,
343 AUDIT_SUBJ_TYPE);
344 break;
345 case Opt_err:
346 audit_log_format(ab, "UNKNOWN=%s ", p);
347 break;
348 }
349 }
350 if (entry->action == UNKNOWN)
351 result = -EINVAL;
352
353 audit_log_format(ab, "res=%d", !result ? 0 : 1);
354 audit_log_end(ab);
355 return result;
356}
357
358/**
359 * ima_parse_add_rule - add a rule to measure_policy_rules
360 * @rule - ima measurement policy rule
361 *
362 * Uses a mutex to protect the policy list from multiple concurrent writers.
363 * Returns 0 on success, an error code on failure.
364 */
365int ima_parse_add_rule(char *rule)
366{
367 const char *op = "update_policy";
368 struct ima_measure_rule_entry *entry;
369 int result = 0;
370 int audit_info = 0;
371
372 /* Prevent installed policy from changing */
373 if (ima_measure != &measure_default_rules) {
374 integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL,
375 NULL, op, "already exists",
376 -EACCES, audit_info);
377 return -EACCES;
378 }
379
380 entry = kzalloc(sizeof(*entry), GFP_KERNEL);
381 if (!entry) {
382 integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL,
383 NULL, op, "-ENOMEM", -ENOMEM, audit_info);
384 return -ENOMEM;
385 }
386
387 INIT_LIST_HEAD(&entry->list);
388
389 result = ima_parse_rule(rule, entry);
390 if (!result) {
391 mutex_lock(&ima_measure_mutex);
392 list_add_tail(&entry->list, &measure_policy_rules);
393 mutex_unlock(&ima_measure_mutex);
394 } else {
395 kfree(entry);
396 integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL,
397 NULL, op, "invalid policy", result,
398 audit_info);
399 }
400 return result;
401}
402
403/* ima_delete_rules called to cleanup invalid policy */
404void ima_delete_rules(void)
405{
406 struct ima_measure_rule_entry *entry, *tmp;
407
408 mutex_lock(&ima_measure_mutex);
409 list_for_each_entry_safe(entry, tmp, &measure_policy_rules, list) {
410 list_del(&entry->list);
411 kfree(entry);
412 }
413 mutex_unlock(&ima_measure_mutex);
414}
diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/ima_queue.c
new file mode 100644
index 000000000000..7ec94314ac0c
--- /dev/null
+++ b/security/integrity/ima/ima_queue.c
@@ -0,0 +1,140 @@
1/*
2 * Copyright (C) 2005,2006,2007,2008 IBM Corporation
3 *
4 * Authors:
5 * Serge Hallyn <serue@us.ibm.com>
6 * Reiner Sailer <sailer@watson.ibm.com>
7 * Mimi Zohar <zohar@us.ibm.com>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation, version 2 of the
12 * License.
13 *
14 * File: ima_queue.c
15 * Implements queues that store template measurements and
16 * maintains aggregate over the stored measurements
17 * in the pre-configured TPM PCR (if available).
18 * The measurement list is append-only. No entry is
19 * ever removed or changed during the boot-cycle.
20 */
21#include <linux/module.h>
22#include <linux/rculist.h>
23#include "ima.h"
24
25LIST_HEAD(ima_measurements); /* list of all measurements */
26
27/* key: inode (before secure-hashing a file) */
28struct ima_h_table ima_htable = {
29 .len = ATOMIC_LONG_INIT(0),
30 .violations = ATOMIC_LONG_INIT(0),
31 .queue[0 ... IMA_MEASURE_HTABLE_SIZE - 1] = HLIST_HEAD_INIT
32};
33
34/* mutex protects atomicity of extending measurement list
35 * and extending the TPM PCR aggregate. Since tpm_extend can take
36 * long (and the tpm driver uses a mutex), we can't use the spinlock.
37 */
38static DEFINE_MUTEX(ima_extend_list_mutex);
39
40/* lookup up the digest value in the hash table, and return the entry */
41static struct ima_queue_entry *ima_lookup_digest_entry(u8 *digest_value)
42{
43 struct ima_queue_entry *qe, *ret = NULL;
44 unsigned int key;
45 struct hlist_node *pos;
46 int rc;
47
48 key = ima_hash_key(digest_value);
49 rcu_read_lock();
50 hlist_for_each_entry_rcu(qe, pos, &ima_htable.queue[key], hnext) {
51 rc = memcmp(qe->entry->digest, digest_value, IMA_DIGEST_SIZE);
52 if (rc == 0) {
53 ret = qe;
54 break;
55 }
56 }
57 rcu_read_unlock();
58 return ret;
59}
60
61/* ima_add_template_entry helper function:
62 * - Add template entry to measurement list and hash table.
63 *
64 * (Called with ima_extend_list_mutex held.)
65 */
66static int ima_add_digest_entry(struct ima_template_entry *entry)
67{
68 struct ima_queue_entry *qe;
69 unsigned int key;
70
71 qe = kmalloc(sizeof(*qe), GFP_KERNEL);
72 if (qe == NULL) {
73 pr_err("OUT OF MEMORY ERROR creating queue entry.\n");
74 return -ENOMEM;
75 }
76 qe->entry = entry;
77
78 INIT_LIST_HEAD(&qe->later);
79 list_add_tail_rcu(&qe->later, &ima_measurements);
80
81 atomic_long_inc(&ima_htable.len);
82 key = ima_hash_key(entry->digest);
83 hlist_add_head_rcu(&qe->hnext, &ima_htable.queue[key]);
84 return 0;
85}
86
87static int ima_pcr_extend(const u8 *hash)
88{
89 int result = 0;
90
91 if (!ima_used_chip)
92 return result;
93
94 result = tpm_pcr_extend(TPM_ANY_NUM, CONFIG_IMA_MEASURE_PCR_IDX, hash);
95 if (result != 0)
96 pr_err("Error Communicating to TPM chip\n");
97 return result;
98}
99
100/* Add template entry to the measurement list and hash table,
101 * and extend the pcr.
102 */
103int ima_add_template_entry(struct ima_template_entry *entry, int violation,
104 const char *op, struct inode *inode)
105{
106 u8 digest[IMA_DIGEST_SIZE];
107 const char *audit_cause = "hash_added";
108 int audit_info = 1;
109 int result = 0;
110
111 mutex_lock(&ima_extend_list_mutex);
112 if (!violation) {
113 memcpy(digest, entry->digest, sizeof digest);
114 if (ima_lookup_digest_entry(digest)) {
115 audit_cause = "hash_exists";
116 goto out;
117 }
118 }
119
120 result = ima_add_digest_entry(entry);
121 if (result < 0) {
122 audit_cause = "ENOMEM";
123 audit_info = 0;
124 goto out;
125 }
126
127 if (violation) /* invalidate pcr */
128 memset(digest, 0xff, sizeof digest);
129
130 result = ima_pcr_extend(digest);
131 if (result != 0) {
132 audit_cause = "TPM error";
133 audit_info = 0;
134 }
135out:
136 mutex_unlock(&ima_extend_list_mutex);
137 integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, entry->template_name,
138 op, audit_cause, result, audit_info);
139 return result;
140}
diff --git a/security/keys/internal.h b/security/keys/internal.h
index 81932abefe7b..9fb679c66b8a 100644
--- a/security/keys/internal.h
+++ b/security/keys/internal.h
@@ -53,6 +53,7 @@ struct key_user {
53 atomic_t nkeys; /* number of keys */ 53 atomic_t nkeys; /* number of keys */
54 atomic_t nikeys; /* number of instantiated keys */ 54 atomic_t nikeys; /* number of instantiated keys */
55 uid_t uid; 55 uid_t uid;
56 struct user_namespace *user_ns;
56 int qnkeys; /* number of keys allocated to this user */ 57 int qnkeys; /* number of keys allocated to this user */
57 int qnbytes; /* number of bytes allocated to this user */ 58 int qnbytes; /* number of bytes allocated to this user */
58}; 59};
@@ -61,7 +62,8 @@ extern struct rb_root key_user_tree;
61extern spinlock_t key_user_lock; 62extern spinlock_t key_user_lock;
62extern struct key_user root_key_user; 63extern struct key_user root_key_user;
63 64
64extern struct key_user *key_user_lookup(uid_t uid); 65extern struct key_user *key_user_lookup(uid_t uid,
66 struct user_namespace *user_ns);
65extern void key_user_put(struct key_user *user); 67extern void key_user_put(struct key_user *user);
66 68
67/* 69/*
diff --git a/security/keys/key.c b/security/keys/key.c
index f76c8a546fd3..4a1297d1ada4 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -18,6 +18,7 @@
18#include <linux/workqueue.h> 18#include <linux/workqueue.h>
19#include <linux/random.h> 19#include <linux/random.h>
20#include <linux/err.h> 20#include <linux/err.h>
21#include <linux/user_namespace.h>
21#include "internal.h" 22#include "internal.h"
22 23
23static struct kmem_cache *key_jar; 24static struct kmem_cache *key_jar;
@@ -60,7 +61,7 @@ void __key_check(const struct key *key)
60 * get the key quota record for a user, allocating a new record if one doesn't 61 * get the key quota record for a user, allocating a new record if one doesn't
61 * already exist 62 * already exist
62 */ 63 */
63struct key_user *key_user_lookup(uid_t uid) 64struct key_user *key_user_lookup(uid_t uid, struct user_namespace *user_ns)
64{ 65{
65 struct key_user *candidate = NULL, *user; 66 struct key_user *candidate = NULL, *user;
66 struct rb_node *parent = NULL; 67 struct rb_node *parent = NULL;
@@ -79,6 +80,10 @@ struct key_user *key_user_lookup(uid_t uid)
79 p = &(*p)->rb_left; 80 p = &(*p)->rb_left;
80 else if (uid > user->uid) 81 else if (uid > user->uid)
81 p = &(*p)->rb_right; 82 p = &(*p)->rb_right;
83 else if (user_ns < user->user_ns)
84 p = &(*p)->rb_left;
85 else if (user_ns > user->user_ns)
86 p = &(*p)->rb_right;
82 else 87 else
83 goto found; 88 goto found;
84 } 89 }
@@ -106,6 +111,7 @@ struct key_user *key_user_lookup(uid_t uid)
106 atomic_set(&candidate->nkeys, 0); 111 atomic_set(&candidate->nkeys, 0);
107 atomic_set(&candidate->nikeys, 0); 112 atomic_set(&candidate->nikeys, 0);
108 candidate->uid = uid; 113 candidate->uid = uid;
114 candidate->user_ns = get_user_ns(user_ns);
109 candidate->qnkeys = 0; 115 candidate->qnkeys = 0;
110 candidate->qnbytes = 0; 116 candidate->qnbytes = 0;
111 spin_lock_init(&candidate->lock); 117 spin_lock_init(&candidate->lock);
@@ -136,6 +142,7 @@ void key_user_put(struct key_user *user)
136 if (atomic_dec_and_lock(&user->usage, &key_user_lock)) { 142 if (atomic_dec_and_lock(&user->usage, &key_user_lock)) {
137 rb_erase(&user->node, &key_user_tree); 143 rb_erase(&user->node, &key_user_tree);
138 spin_unlock(&key_user_lock); 144 spin_unlock(&key_user_lock);
145 put_user_ns(user->user_ns);
139 146
140 kfree(user); 147 kfree(user);
141 } 148 }
@@ -234,7 +241,7 @@ struct key *key_alloc(struct key_type *type, const char *desc,
234 quotalen = desclen + type->def_datalen; 241 quotalen = desclen + type->def_datalen;
235 242
236 /* get hold of the key tracking for this user */ 243 /* get hold of the key tracking for this user */
237 user = key_user_lookup(uid); 244 user = key_user_lookup(uid, cred->user->user_ns);
238 if (!user) 245 if (!user)
239 goto no_memory_1; 246 goto no_memory_1;
240 247
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
index b1ec3b4ee17d..7f09fb897d2b 100644
--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -726,7 +726,7 @@ long keyctl_chown_key(key_serial_t id, uid_t uid, gid_t gid)
726 /* change the UID */ 726 /* change the UID */
727 if (uid != (uid_t) -1 && uid != key->uid) { 727 if (uid != (uid_t) -1 && uid != key->uid) {
728 ret = -ENOMEM; 728 ret = -ENOMEM;
729 newowner = key_user_lookup(uid); 729 newowner = key_user_lookup(uid, current_user_ns());
730 if (!newowner) 730 if (!newowner)
731 goto error_put; 731 goto error_put;
732 732
diff --git a/security/keys/keyring.c b/security/keys/keyring.c
index ed851574d073..3dba81c2eba3 100644
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -539,6 +539,9 @@ struct key *find_keyring_by_name(const char *name, bool skip_perm_check)
539 &keyring_name_hash[bucket], 539 &keyring_name_hash[bucket],
540 type_data.link 540 type_data.link
541 ) { 541 ) {
542 if (keyring->user->user_ns != current_user_ns())
543 continue;
544
542 if (test_bit(KEY_FLAG_REVOKED, &keyring->flags)) 545 if (test_bit(KEY_FLAG_REVOKED, &keyring->flags))
543 continue; 546 continue;
544 547
diff --git a/security/keys/permission.c b/security/keys/permission.c
index 5d9fc7b93f2e..0ed802c9e698 100644
--- a/security/keys/permission.c
+++ b/security/keys/permission.c
@@ -35,6 +35,9 @@ int key_task_permission(const key_ref_t key_ref, const struct cred *cred,
35 35
36 key = key_ref_to_ptr(key_ref); 36 key = key_ref_to_ptr(key_ref);
37 37
38 if (key->user->user_ns != cred->user->user_ns)
39 goto use_other_perms;
40
38 /* use the second 8-bits of permissions for keys the caller owns */ 41 /* use the second 8-bits of permissions for keys the caller owns */
39 if (key->uid == cred->fsuid) { 42 if (key->uid == cred->fsuid) {
40 kperm = key->perm >> 16; 43 kperm = key->perm >> 16;
@@ -56,6 +59,8 @@ int key_task_permission(const key_ref_t key_ref, const struct cred *cred,
56 } 59 }
57 } 60 }
58 61
62use_other_perms:
63
59 /* otherwise use the least-significant 8-bits */ 64 /* otherwise use the least-significant 8-bits */
60 kperm = key->perm; 65 kperm = key->perm;
61 66
diff --git a/security/keys/proc.c b/security/keys/proc.c
index 7f508def50e3..769f9bdfd2b3 100644
--- a/security/keys/proc.c
+++ b/security/keys/proc.c
@@ -91,6 +91,28 @@ __initcall(key_proc_init);
91 */ 91 */
92#ifdef CONFIG_KEYS_DEBUG_PROC_KEYS 92#ifdef CONFIG_KEYS_DEBUG_PROC_KEYS
93 93
94static struct rb_node *__key_serial_next(struct rb_node *n)
95{
96 while (n) {
97 struct key *key = rb_entry(n, struct key, serial_node);
98 if (key->user->user_ns == current_user_ns())
99 break;
100 n = rb_next(n);
101 }
102 return n;
103}
104
105static struct rb_node *key_serial_next(struct rb_node *n)
106{
107 return __key_serial_next(rb_next(n));
108}
109
110static struct rb_node *key_serial_first(struct rb_root *r)
111{
112 struct rb_node *n = rb_first(r);
113 return __key_serial_next(n);
114}
115
94static int proc_keys_open(struct inode *inode, struct file *file) 116static int proc_keys_open(struct inode *inode, struct file *file)
95{ 117{
96 return seq_open(file, &proc_keys_ops); 118 return seq_open(file, &proc_keys_ops);
@@ -104,10 +126,10 @@ static void *proc_keys_start(struct seq_file *p, loff_t *_pos)
104 126
105 spin_lock(&key_serial_lock); 127 spin_lock(&key_serial_lock);
106 128
107 _p = rb_first(&key_serial_tree); 129 _p = key_serial_first(&key_serial_tree);
108 while (pos > 0 && _p) { 130 while (pos > 0 && _p) {
109 pos--; 131 pos--;
110 _p = rb_next(_p); 132 _p = key_serial_next(_p);
111 } 133 }
112 134
113 return _p; 135 return _p;
@@ -117,7 +139,7 @@ static void *proc_keys_start(struct seq_file *p, loff_t *_pos)
117static void *proc_keys_next(struct seq_file *p, void *v, loff_t *_pos) 139static void *proc_keys_next(struct seq_file *p, void *v, loff_t *_pos)
118{ 140{
119 (*_pos)++; 141 (*_pos)++;
120 return rb_next((struct rb_node *) v); 142 return key_serial_next((struct rb_node *) v);
121 143
122} 144}
123 145
@@ -203,6 +225,27 @@ static int proc_keys_show(struct seq_file *m, void *v)
203 225
204#endif /* CONFIG_KEYS_DEBUG_PROC_KEYS */ 226#endif /* CONFIG_KEYS_DEBUG_PROC_KEYS */
205 227
228static struct rb_node *__key_user_next(struct rb_node *n)
229{
230 while (n) {
231 struct key_user *user = rb_entry(n, struct key_user, node);
232 if (user->user_ns == current_user_ns())
233 break;
234 n = rb_next(n);
235 }
236 return n;
237}
238
239static struct rb_node *key_user_next(struct rb_node *n)
240{
241 return __key_user_next(rb_next(n));
242}
243
244static struct rb_node *key_user_first(struct rb_root *r)
245{
246 struct rb_node *n = rb_first(r);
247 return __key_user_next(n);
248}
206/*****************************************************************************/ 249/*****************************************************************************/
207/* 250/*
208 * implement "/proc/key-users" to provides a list of the key users 251 * implement "/proc/key-users" to provides a list of the key users
@@ -220,10 +263,10 @@ static void *proc_key_users_start(struct seq_file *p, loff_t *_pos)
220 263
221 spin_lock(&key_user_lock); 264 spin_lock(&key_user_lock);
222 265
223 _p = rb_first(&key_user_tree); 266 _p = key_user_first(&key_user_tree);
224 while (pos > 0 && _p) { 267 while (pos > 0 && _p) {
225 pos--; 268 pos--;
226 _p = rb_next(_p); 269 _p = key_user_next(_p);
227 } 270 }
228 271
229 return _p; 272 return _p;
@@ -233,7 +276,7 @@ static void *proc_key_users_start(struct seq_file *p, loff_t *_pos)
233static void *proc_key_users_next(struct seq_file *p, void *v, loff_t *_pos) 276static void *proc_key_users_next(struct seq_file *p, void *v, loff_t *_pos)
234{ 277{
235 (*_pos)++; 278 (*_pos)++;
236 return rb_next((struct rb_node *) v); 279 return key_user_next((struct rb_node *) v);
237 280
238} 281}
239 282
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index 2f5d89e92b85..276d27882ce8 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -17,6 +17,7 @@
17#include <linux/fs.h> 17#include <linux/fs.h>
18#include <linux/err.h> 18#include <linux/err.h>
19#include <linux/mutex.h> 19#include <linux/mutex.h>
20#include <linux/user_namespace.h>
20#include <asm/uaccess.h> 21#include <asm/uaccess.h>
21#include "internal.h" 22#include "internal.h"
22 23
@@ -34,6 +35,7 @@ struct key_user root_key_user = {
34 .nkeys = ATOMIC_INIT(2), 35 .nkeys = ATOMIC_INIT(2),
35 .nikeys = ATOMIC_INIT(2), 36 .nikeys = ATOMIC_INIT(2),
36 .uid = 0, 37 .uid = 0,
38 .user_ns = &init_user_ns,
37}; 39};
38 40
39/*****************************************************************************/ 41/*****************************************************************************/
diff --git a/security/keys/request_key.c b/security/keys/request_key.c
index 0e04f72ef2d4..22a31582bfaa 100644
--- a/security/keys/request_key.c
+++ b/security/keys/request_key.c
@@ -365,7 +365,7 @@ static struct key *construct_key_and_link(struct key_type *type,
365 365
366 kenter(""); 366 kenter("");
367 367
368 user = key_user_lookup(current_fsuid()); 368 user = key_user_lookup(current_fsuid(), current_user_ns());
369 if (!user) 369 if (!user)
370 return ERR_PTR(-ENOMEM); 370 return ERR_PTR(-ENOMEM);
371 371
diff --git a/security/security.c b/security/security.c
index c3586c0d97e2..5284255c5cdf 100644
--- a/security/security.c
+++ b/security/security.c
@@ -445,6 +445,7 @@ int security_inode_create(struct inode *dir, struct dentry *dentry, int mode)
445 return 0; 445 return 0;
446 return security_ops->inode_create(dir, dentry, mode); 446 return security_ops->inode_create(dir, dentry, mode);
447} 447}
448EXPORT_SYMBOL_GPL(security_inode_create);
448 449
449int security_inode_link(struct dentry *old_dentry, struct inode *dir, 450int security_inode_link(struct dentry *old_dentry, struct inode *dir,
450 struct dentry *new_dentry) 451 struct dentry *new_dentry)
@@ -475,6 +476,7 @@ int security_inode_mkdir(struct inode *dir, struct dentry *dentry, int mode)
475 return 0; 476 return 0;
476 return security_ops->inode_mkdir(dir, dentry, mode); 477 return security_ops->inode_mkdir(dir, dentry, mode);
477} 478}
479EXPORT_SYMBOL_GPL(security_inode_mkdir);
478 480
479int security_inode_rmdir(struct inode *dir, struct dentry *dentry) 481int security_inode_rmdir(struct inode *dir, struct dentry *dentry)
480{ 482{
@@ -1007,11 +1009,6 @@ int security_socket_accept(struct socket *sock, struct socket *newsock)
1007 return security_ops->socket_accept(sock, newsock); 1009 return security_ops->socket_accept(sock, newsock);
1008} 1010}
1009 1011
1010void security_socket_post_accept(struct socket *sock, struct socket *newsock)
1011{
1012 security_ops->socket_post_accept(sock, newsock);
1013}
1014
1015int security_socket_sendmsg(struct socket *sock, struct msghdr *msg, int size) 1012int security_socket_sendmsg(struct socket *sock, struct msghdr *msg, int size)
1016{ 1013{
1017 return security_ops->socket_sendmsg(sock, msg, size); 1014 return security_ops->socket_sendmsg(sock, msg, size);
diff --git a/security/selinux/avc.c b/security/selinux/avc.c
index eb41f43e2772..7f9b5fac8779 100644
--- a/security/selinux/avc.c
+++ b/security/selinux/avc.c
@@ -88,17 +88,16 @@ struct avc_entry {
88 u32 tsid; 88 u32 tsid;
89 u16 tclass; 89 u16 tclass;
90 struct av_decision avd; 90 struct av_decision avd;
91 atomic_t used; /* used recently */
92}; 91};
93 92
94struct avc_node { 93struct avc_node {
95 struct avc_entry ae; 94 struct avc_entry ae;
96 struct list_head list; 95 struct hlist_node list; /* anchored in avc_cache->slots[i] */
97 struct rcu_head rhead; 96 struct rcu_head rhead;
98}; 97};
99 98
100struct avc_cache { 99struct avc_cache {
101 struct list_head slots[AVC_CACHE_SLOTS]; 100 struct hlist_head slots[AVC_CACHE_SLOTS]; /* head for avc_node->list */
102 spinlock_t slots_lock[AVC_CACHE_SLOTS]; /* lock for writes */ 101 spinlock_t slots_lock[AVC_CACHE_SLOTS]; /* lock for writes */
103 atomic_t lru_hint; /* LRU hint for reclaim scan */ 102 atomic_t lru_hint; /* LRU hint for reclaim scan */
104 atomic_t active_nodes; 103 atomic_t active_nodes;
@@ -234,7 +233,7 @@ void __init avc_init(void)
234 int i; 233 int i;
235 234
236 for (i = 0; i < AVC_CACHE_SLOTS; i++) { 235 for (i = 0; i < AVC_CACHE_SLOTS; i++) {
237 INIT_LIST_HEAD(&avc_cache.slots[i]); 236 INIT_HLIST_HEAD(&avc_cache.slots[i]);
238 spin_lock_init(&avc_cache.slots_lock[i]); 237 spin_lock_init(&avc_cache.slots_lock[i]);
239 } 238 }
240 atomic_set(&avc_cache.active_nodes, 0); 239 atomic_set(&avc_cache.active_nodes, 0);
@@ -250,16 +249,20 @@ int avc_get_hash_stats(char *page)
250{ 249{
251 int i, chain_len, max_chain_len, slots_used; 250 int i, chain_len, max_chain_len, slots_used;
252 struct avc_node *node; 251 struct avc_node *node;
252 struct hlist_head *head;
253 253
254 rcu_read_lock(); 254 rcu_read_lock();
255 255
256 slots_used = 0; 256 slots_used = 0;
257 max_chain_len = 0; 257 max_chain_len = 0;
258 for (i = 0; i < AVC_CACHE_SLOTS; i++) { 258 for (i = 0; i < AVC_CACHE_SLOTS; i++) {
259 if (!list_empty(&avc_cache.slots[i])) { 259 head = &avc_cache.slots[i];
260 if (!hlist_empty(head)) {
261 struct hlist_node *next;
262
260 slots_used++; 263 slots_used++;
261 chain_len = 0; 264 chain_len = 0;
262 list_for_each_entry_rcu(node, &avc_cache.slots[i], list) 265 hlist_for_each_entry_rcu(node, next, head, list)
263 chain_len++; 266 chain_len++;
264 if (chain_len > max_chain_len) 267 if (chain_len > max_chain_len)
265 max_chain_len = chain_len; 268 max_chain_len = chain_len;
@@ -283,7 +286,7 @@ static void avc_node_free(struct rcu_head *rhead)
283 286
284static void avc_node_delete(struct avc_node *node) 287static void avc_node_delete(struct avc_node *node)
285{ 288{
286 list_del_rcu(&node->list); 289 hlist_del_rcu(&node->list);
287 call_rcu(&node->rhead, avc_node_free); 290 call_rcu(&node->rhead, avc_node_free);
288 atomic_dec(&avc_cache.active_nodes); 291 atomic_dec(&avc_cache.active_nodes);
289} 292}
@@ -297,7 +300,7 @@ static void avc_node_kill(struct avc_node *node)
297 300
298static void avc_node_replace(struct avc_node *new, struct avc_node *old) 301static void avc_node_replace(struct avc_node *new, struct avc_node *old)
299{ 302{
300 list_replace_rcu(&old->list, &new->list); 303 hlist_replace_rcu(&old->list, &new->list);
301 call_rcu(&old->rhead, avc_node_free); 304 call_rcu(&old->rhead, avc_node_free);
302 atomic_dec(&avc_cache.active_nodes); 305 atomic_dec(&avc_cache.active_nodes);
303} 306}
@@ -307,29 +310,31 @@ static inline int avc_reclaim_node(void)
307 struct avc_node *node; 310 struct avc_node *node;
308 int hvalue, try, ecx; 311 int hvalue, try, ecx;
309 unsigned long flags; 312 unsigned long flags;
313 struct hlist_head *head;
314 struct hlist_node *next;
315 spinlock_t *lock;
310 316
311 for (try = 0, ecx = 0; try < AVC_CACHE_SLOTS; try++) { 317 for (try = 0, ecx = 0; try < AVC_CACHE_SLOTS; try++) {
312 hvalue = atomic_inc_return(&avc_cache.lru_hint) & (AVC_CACHE_SLOTS - 1); 318 hvalue = atomic_inc_return(&avc_cache.lru_hint) & (AVC_CACHE_SLOTS - 1);
319 head = &avc_cache.slots[hvalue];
320 lock = &avc_cache.slots_lock[hvalue];
313 321
314 if (!spin_trylock_irqsave(&avc_cache.slots_lock[hvalue], flags)) 322 if (!spin_trylock_irqsave(lock, flags))
315 continue; 323 continue;
316 324
317 rcu_read_lock(); 325 rcu_read_lock();
318 list_for_each_entry(node, &avc_cache.slots[hvalue], list) { 326 hlist_for_each_entry(node, next, head, list) {
319 if (atomic_dec_and_test(&node->ae.used)) { 327 avc_node_delete(node);
320 /* Recently Unused */ 328 avc_cache_stats_incr(reclaims);
321 avc_node_delete(node); 329 ecx++;
322 avc_cache_stats_incr(reclaims); 330 if (ecx >= AVC_CACHE_RECLAIM) {
323 ecx++; 331 rcu_read_unlock();
324 if (ecx >= AVC_CACHE_RECLAIM) { 332 spin_unlock_irqrestore(lock, flags);
325 rcu_read_unlock(); 333 goto out;
326 spin_unlock_irqrestore(&avc_cache.slots_lock[hvalue], flags);
327 goto out;
328 }
329 } 334 }
330 } 335 }
331 rcu_read_unlock(); 336 rcu_read_unlock();
332 spin_unlock_irqrestore(&avc_cache.slots_lock[hvalue], flags); 337 spin_unlock_irqrestore(lock, flags);
333 } 338 }
334out: 339out:
335 return ecx; 340 return ecx;
@@ -344,8 +349,7 @@ static struct avc_node *avc_alloc_node(void)
344 goto out; 349 goto out;
345 350
346 INIT_RCU_HEAD(&node->rhead); 351 INIT_RCU_HEAD(&node->rhead);
347 INIT_LIST_HEAD(&node->list); 352 INIT_HLIST_NODE(&node->list);
348 atomic_set(&node->ae.used, 1);
349 avc_cache_stats_incr(allocations); 353 avc_cache_stats_incr(allocations);
350 354
351 if (atomic_inc_return(&avc_cache.active_nodes) > avc_cache_threshold) 355 if (atomic_inc_return(&avc_cache.active_nodes) > avc_cache_threshold)
@@ -355,21 +359,24 @@ out:
355 return node; 359 return node;
356} 360}
357 361
358static void avc_node_populate(struct avc_node *node, u32 ssid, u32 tsid, u16 tclass, struct avc_entry *ae) 362static void avc_node_populate(struct avc_node *node, u32 ssid, u32 tsid, u16 tclass, struct av_decision *avd)
359{ 363{
360 node->ae.ssid = ssid; 364 node->ae.ssid = ssid;
361 node->ae.tsid = tsid; 365 node->ae.tsid = tsid;
362 node->ae.tclass = tclass; 366 node->ae.tclass = tclass;
363 memcpy(&node->ae.avd, &ae->avd, sizeof(node->ae.avd)); 367 memcpy(&node->ae.avd, avd, sizeof(node->ae.avd));
364} 368}
365 369
366static inline struct avc_node *avc_search_node(u32 ssid, u32 tsid, u16 tclass) 370static inline struct avc_node *avc_search_node(u32 ssid, u32 tsid, u16 tclass)
367{ 371{
368 struct avc_node *node, *ret = NULL; 372 struct avc_node *node, *ret = NULL;
369 int hvalue; 373 int hvalue;
374 struct hlist_head *head;
375 struct hlist_node *next;
370 376
371 hvalue = avc_hash(ssid, tsid, tclass); 377 hvalue = avc_hash(ssid, tsid, tclass);
372 list_for_each_entry_rcu(node, &avc_cache.slots[hvalue], list) { 378 head = &avc_cache.slots[hvalue];
379 hlist_for_each_entry_rcu(node, next, head, list) {
373 if (ssid == node->ae.ssid && 380 if (ssid == node->ae.ssid &&
374 tclass == node->ae.tclass && 381 tclass == node->ae.tclass &&
375 tsid == node->ae.tsid) { 382 tsid == node->ae.tsid) {
@@ -378,15 +385,6 @@ static inline struct avc_node *avc_search_node(u32 ssid, u32 tsid, u16 tclass)
378 } 385 }
379 } 386 }
380 387
381 if (ret == NULL) {
382 /* cache miss */
383 goto out;
384 }
385
386 /* cache hit */
387 if (atomic_read(&ret->ae.used) != 1)
388 atomic_set(&ret->ae.used, 1);
389out:
390 return ret; 388 return ret;
391} 389}
392 390
@@ -395,30 +393,25 @@ out:
395 * @ssid: source security identifier 393 * @ssid: source security identifier
396 * @tsid: target security identifier 394 * @tsid: target security identifier
397 * @tclass: target security class 395 * @tclass: target security class
398 * @requested: requested permissions, interpreted based on @tclass
399 * 396 *
400 * Look up an AVC entry that is valid for the 397 * Look up an AVC entry that is valid for the
401 * @requested permissions between the SID pair
402 * (@ssid, @tsid), interpreting the permissions 398 * (@ssid, @tsid), interpreting the permissions
403 * based on @tclass. If a valid AVC entry exists, 399 * based on @tclass. If a valid AVC entry exists,
404 * then this function return the avc_node. 400 * then this function return the avc_node.
405 * Otherwise, this function returns NULL. 401 * Otherwise, this function returns NULL.
406 */ 402 */
407static struct avc_node *avc_lookup(u32 ssid, u32 tsid, u16 tclass, u32 requested) 403static struct avc_node *avc_lookup(u32 ssid, u32 tsid, u16 tclass)
408{ 404{
409 struct avc_node *node; 405 struct avc_node *node;
410 406
411 avc_cache_stats_incr(lookups); 407 avc_cache_stats_incr(lookups);
412 node = avc_search_node(ssid, tsid, tclass); 408 node = avc_search_node(ssid, tsid, tclass);
413 409
414 if (node && ((node->ae.avd.decided & requested) == requested)) { 410 if (node)
415 avc_cache_stats_incr(hits); 411 avc_cache_stats_incr(hits);
416 goto out; 412 else
417 } 413 avc_cache_stats_incr(misses);
418 414
419 node = NULL;
420 avc_cache_stats_incr(misses);
421out:
422 return node; 415 return node;
423} 416}
424 417
@@ -449,34 +442,41 @@ static int avc_latest_notif_update(int seqno, int is_insert)
449 * @ssid: source security identifier 442 * @ssid: source security identifier
450 * @tsid: target security identifier 443 * @tsid: target security identifier
451 * @tclass: target security class 444 * @tclass: target security class
452 * @ae: AVC entry 445 * @avd: resulting av decision
453 * 446 *
454 * Insert an AVC entry for the SID pair 447 * Insert an AVC entry for the SID pair
455 * (@ssid, @tsid) and class @tclass. 448 * (@ssid, @tsid) and class @tclass.
456 * The access vectors and the sequence number are 449 * The access vectors and the sequence number are
457 * normally provided by the security server in 450 * normally provided by the security server in
458 * response to a security_compute_av() call. If the 451 * response to a security_compute_av() call. If the
459 * sequence number @ae->avd.seqno is not less than the latest 452 * sequence number @avd->seqno is not less than the latest
460 * revocation notification, then the function copies 453 * revocation notification, then the function copies
461 * the access vectors into a cache entry, returns 454 * the access vectors into a cache entry, returns
462 * avc_node inserted. Otherwise, this function returns NULL. 455 * avc_node inserted. Otherwise, this function returns NULL.
463 */ 456 */
464static struct avc_node *avc_insert(u32 ssid, u32 tsid, u16 tclass, struct avc_entry *ae) 457static struct avc_node *avc_insert(u32 ssid, u32 tsid, u16 tclass, struct av_decision *avd)
465{ 458{
466 struct avc_node *pos, *node = NULL; 459 struct avc_node *pos, *node = NULL;
467 int hvalue; 460 int hvalue;
468 unsigned long flag; 461 unsigned long flag;
469 462
470 if (avc_latest_notif_update(ae->avd.seqno, 1)) 463 if (avc_latest_notif_update(avd->seqno, 1))
471 goto out; 464 goto out;
472 465
473 node = avc_alloc_node(); 466 node = avc_alloc_node();
474 if (node) { 467 if (node) {
468 struct hlist_head *head;
469 struct hlist_node *next;
470 spinlock_t *lock;
471
475 hvalue = avc_hash(ssid, tsid, tclass); 472 hvalue = avc_hash(ssid, tsid, tclass);
476 avc_node_populate(node, ssid, tsid, tclass, ae); 473 avc_node_populate(node, ssid, tsid, tclass, avd);
474
475 head = &avc_cache.slots[hvalue];
476 lock = &avc_cache.slots_lock[hvalue];
477 477
478 spin_lock_irqsave(&avc_cache.slots_lock[hvalue], flag); 478 spin_lock_irqsave(lock, flag);
479 list_for_each_entry(pos, &avc_cache.slots[hvalue], list) { 479 hlist_for_each_entry(pos, next, head, list) {
480 if (pos->ae.ssid == ssid && 480 if (pos->ae.ssid == ssid &&
481 pos->ae.tsid == tsid && 481 pos->ae.tsid == tsid &&
482 pos->ae.tclass == tclass) { 482 pos->ae.tclass == tclass) {
@@ -484,9 +484,9 @@ static struct avc_node *avc_insert(u32 ssid, u32 tsid, u16 tclass, struct avc_en
484 goto found; 484 goto found;
485 } 485 }
486 } 486 }
487 list_add_rcu(&node->list, &avc_cache.slots[hvalue]); 487 hlist_add_head_rcu(&node->list, head);
488found: 488found:
489 spin_unlock_irqrestore(&avc_cache.slots_lock[hvalue], flag); 489 spin_unlock_irqrestore(lock, flag);
490 } 490 }
491out: 491out:
492 return node; 492 return node;
@@ -742,17 +742,22 @@ static inline int avc_sidcmp(u32 x, u32 y)
742 * @event : Updating event 742 * @event : Updating event
743 * @perms : Permission mask bits 743 * @perms : Permission mask bits
744 * @ssid,@tsid,@tclass : identifier of an AVC entry 744 * @ssid,@tsid,@tclass : identifier of an AVC entry
745 * @seqno : sequence number when decision was made
745 * 746 *
746 * if a valid AVC entry doesn't exist,this function returns -ENOENT. 747 * if a valid AVC entry doesn't exist,this function returns -ENOENT.
747 * if kmalloc() called internal returns NULL, this function returns -ENOMEM. 748 * if kmalloc() called internal returns NULL, this function returns -ENOMEM.
748 * otherwise, this function update the AVC entry. The original AVC-entry object 749 * otherwise, this function update the AVC entry. The original AVC-entry object
749 * will release later by RCU. 750 * will release later by RCU.
750 */ 751 */
751static int avc_update_node(u32 event, u32 perms, u32 ssid, u32 tsid, u16 tclass) 752static int avc_update_node(u32 event, u32 perms, u32 ssid, u32 tsid, u16 tclass,
753 u32 seqno)
752{ 754{
753 int hvalue, rc = 0; 755 int hvalue, rc = 0;
754 unsigned long flag; 756 unsigned long flag;
755 struct avc_node *pos, *node, *orig = NULL; 757 struct avc_node *pos, *node, *orig = NULL;
758 struct hlist_head *head;
759 struct hlist_node *next;
760 spinlock_t *lock;
756 761
757 node = avc_alloc_node(); 762 node = avc_alloc_node();
758 if (!node) { 763 if (!node) {
@@ -762,12 +767,17 @@ static int avc_update_node(u32 event, u32 perms, u32 ssid, u32 tsid, u16 tclass)
762 767
763 /* Lock the target slot */ 768 /* Lock the target slot */
764 hvalue = avc_hash(ssid, tsid, tclass); 769 hvalue = avc_hash(ssid, tsid, tclass);
765 spin_lock_irqsave(&avc_cache.slots_lock[hvalue], flag);
766 770
767 list_for_each_entry(pos, &avc_cache.slots[hvalue], list) { 771 head = &avc_cache.slots[hvalue];
772 lock = &avc_cache.slots_lock[hvalue];
773
774 spin_lock_irqsave(lock, flag);
775
776 hlist_for_each_entry(pos, next, head, list) {
768 if (ssid == pos->ae.ssid && 777 if (ssid == pos->ae.ssid &&
769 tsid == pos->ae.tsid && 778 tsid == pos->ae.tsid &&
770 tclass == pos->ae.tclass){ 779 tclass == pos->ae.tclass &&
780 seqno == pos->ae.avd.seqno){
771 orig = pos; 781 orig = pos;
772 break; 782 break;
773 } 783 }
@@ -783,7 +793,7 @@ static int avc_update_node(u32 event, u32 perms, u32 ssid, u32 tsid, u16 tclass)
783 * Copy and replace original node. 793 * Copy and replace original node.
784 */ 794 */
785 795
786 avc_node_populate(node, ssid, tsid, tclass, &orig->ae); 796 avc_node_populate(node, ssid, tsid, tclass, &orig->ae.avd);
787 797
788 switch (event) { 798 switch (event) {
789 case AVC_CALLBACK_GRANT: 799 case AVC_CALLBACK_GRANT:
@@ -808,7 +818,7 @@ static int avc_update_node(u32 event, u32 perms, u32 ssid, u32 tsid, u16 tclass)
808 } 818 }
809 avc_node_replace(node, orig); 819 avc_node_replace(node, orig);
810out_unlock: 820out_unlock:
811 spin_unlock_irqrestore(&avc_cache.slots_lock[hvalue], flag); 821 spin_unlock_irqrestore(lock, flag);
812out: 822out:
813 return rc; 823 return rc;
814} 824}
@@ -823,18 +833,24 @@ int avc_ss_reset(u32 seqno)
823 int i, rc = 0, tmprc; 833 int i, rc = 0, tmprc;
824 unsigned long flag; 834 unsigned long flag;
825 struct avc_node *node; 835 struct avc_node *node;
836 struct hlist_head *head;
837 struct hlist_node *next;
838 spinlock_t *lock;
826 839
827 for (i = 0; i < AVC_CACHE_SLOTS; i++) { 840 for (i = 0; i < AVC_CACHE_SLOTS; i++) {
828 spin_lock_irqsave(&avc_cache.slots_lock[i], flag); 841 head = &avc_cache.slots[i];
842 lock = &avc_cache.slots_lock[i];
843
844 spin_lock_irqsave(lock, flag);
829 /* 845 /*
830 * With preemptable RCU, the outer spinlock does not 846 * With preemptable RCU, the outer spinlock does not
831 * prevent RCU grace periods from ending. 847 * prevent RCU grace periods from ending.
832 */ 848 */
833 rcu_read_lock(); 849 rcu_read_lock();
834 list_for_each_entry(node, &avc_cache.slots[i], list) 850 hlist_for_each_entry(node, next, head, list)
835 avc_node_delete(node); 851 avc_node_delete(node);
836 rcu_read_unlock(); 852 rcu_read_unlock();
837 spin_unlock_irqrestore(&avc_cache.slots_lock[i], flag); 853 spin_unlock_irqrestore(lock, flag);
838 } 854 }
839 855
840 for (c = avc_callbacks; c; c = c->next) { 856 for (c = avc_callbacks; c; c = c->next) {
@@ -875,10 +891,10 @@ int avc_ss_reset(u32 seqno)
875int avc_has_perm_noaudit(u32 ssid, u32 tsid, 891int avc_has_perm_noaudit(u32 ssid, u32 tsid,
876 u16 tclass, u32 requested, 892 u16 tclass, u32 requested,
877 unsigned flags, 893 unsigned flags,
878 struct av_decision *avd) 894 struct av_decision *in_avd)
879{ 895{
880 struct avc_node *node; 896 struct avc_node *node;
881 struct avc_entry entry, *p_ae; 897 struct av_decision avd_entry, *avd;
882 int rc = 0; 898 int rc = 0;
883 u32 denied; 899 u32 denied;
884 900
@@ -886,29 +902,34 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid,
886 902
887 rcu_read_lock(); 903 rcu_read_lock();
888 904
889 node = avc_lookup(ssid, tsid, tclass, requested); 905 node = avc_lookup(ssid, tsid, tclass);
890 if (!node) { 906 if (!node) {
891 rcu_read_unlock(); 907 rcu_read_unlock();
892 rc = security_compute_av(ssid, tsid, tclass, requested, &entry.avd); 908
909 if (in_avd)
910 avd = in_avd;
911 else
912 avd = &avd_entry;
913
914 rc = security_compute_av(ssid, tsid, tclass, requested, avd);
893 if (rc) 915 if (rc)
894 goto out; 916 goto out;
895 rcu_read_lock(); 917 rcu_read_lock();
896 node = avc_insert(ssid, tsid, tclass, &entry); 918 node = avc_insert(ssid, tsid, tclass, avd);
919 } else {
920 if (in_avd)
921 memcpy(in_avd, &node->ae.avd, sizeof(*in_avd));
922 avd = &node->ae.avd;
897 } 923 }
898 924
899 p_ae = node ? &node->ae : &entry; 925 denied = requested & ~(avd->allowed);
900
901 if (avd)
902 memcpy(avd, &p_ae->avd, sizeof(*avd));
903
904 denied = requested & ~(p_ae->avd.allowed);
905 926
906 if (denied) { 927 if (denied) {
907 if (flags & AVC_STRICT) 928 if (flags & AVC_STRICT)
908 rc = -EACCES; 929 rc = -EACCES;
909 else if (!selinux_enforcing || security_permissive_sid(ssid)) 930 else if (!selinux_enforcing || security_permissive_sid(ssid))
910 avc_update_node(AVC_CALLBACK_GRANT, requested, ssid, 931 avc_update_node(AVC_CALLBACK_GRANT, requested, ssid,
911 tsid, tclass); 932 tsid, tclass, avd->seqno);
912 else 933 else
913 rc = -EACCES; 934 rc = -EACCES;
914 } 935 }
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 00815973d412..ba808ef6babb 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -89,11 +89,10 @@
89#define XATTR_SELINUX_SUFFIX "selinux" 89#define XATTR_SELINUX_SUFFIX "selinux"
90#define XATTR_NAME_SELINUX XATTR_SECURITY_PREFIX XATTR_SELINUX_SUFFIX 90#define XATTR_NAME_SELINUX XATTR_SECURITY_PREFIX XATTR_SELINUX_SUFFIX
91 91
92#define NUM_SEL_MNT_OPTS 4 92#define NUM_SEL_MNT_OPTS 5
93 93
94extern unsigned int policydb_loaded_version; 94extern unsigned int policydb_loaded_version;
95extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm); 95extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm);
96extern int selinux_compat_net;
97extern struct security_operations *security_ops; 96extern struct security_operations *security_ops;
98 97
99/* SECMARK reference count */ 98/* SECMARK reference count */
@@ -311,7 +310,7 @@ static int sk_alloc_security(struct sock *sk, int family, gfp_t priority)
311 ssec->sid = SECINITSID_UNLABELED; 310 ssec->sid = SECINITSID_UNLABELED;
312 sk->sk_security = ssec; 311 sk->sk_security = ssec;
313 312
314 selinux_netlbl_sk_security_reset(ssec, family); 313 selinux_netlbl_sk_security_reset(ssec);
315 314
316 return 0; 315 return 0;
317} 316}
@@ -353,6 +352,7 @@ enum {
353 Opt_fscontext = 2, 352 Opt_fscontext = 2,
354 Opt_defcontext = 3, 353 Opt_defcontext = 3,
355 Opt_rootcontext = 4, 354 Opt_rootcontext = 4,
355 Opt_labelsupport = 5,
356}; 356};
357 357
358static const match_table_t tokens = { 358static const match_table_t tokens = {
@@ -360,6 +360,7 @@ static const match_table_t tokens = {
360 {Opt_fscontext, FSCONTEXT_STR "%s"}, 360 {Opt_fscontext, FSCONTEXT_STR "%s"},
361 {Opt_defcontext, DEFCONTEXT_STR "%s"}, 361 {Opt_defcontext, DEFCONTEXT_STR "%s"},
362 {Opt_rootcontext, ROOTCONTEXT_STR "%s"}, 362 {Opt_rootcontext, ROOTCONTEXT_STR "%s"},
363 {Opt_labelsupport, LABELSUPP_STR},
363 {Opt_error, NULL}, 364 {Opt_error, NULL},
364}; 365};
365 366
@@ -431,7 +432,7 @@ static int sb_finish_set_opts(struct super_block *sb)
431 } 432 }
432 } 433 }
433 434
434 sbsec->initialized = 1; 435 sbsec->flags |= (SE_SBINITIALIZED | SE_SBLABELSUPP);
435 436
436 if (sbsec->behavior > ARRAY_SIZE(labeling_behaviors)) 437 if (sbsec->behavior > ARRAY_SIZE(labeling_behaviors))
437 printk(KERN_ERR "SELinux: initialized (dev %s, type %s), unknown behavior\n", 438 printk(KERN_ERR "SELinux: initialized (dev %s, type %s), unknown behavior\n",
@@ -441,6 +442,12 @@ static int sb_finish_set_opts(struct super_block *sb)
441 sb->s_id, sb->s_type->name, 442 sb->s_id, sb->s_type->name,
442 labeling_behaviors[sbsec->behavior-1]); 443 labeling_behaviors[sbsec->behavior-1]);
443 444
445 if (sbsec->behavior == SECURITY_FS_USE_GENFS ||
446 sbsec->behavior == SECURITY_FS_USE_MNTPOINT ||
447 sbsec->behavior == SECURITY_FS_USE_NONE ||
448 sbsec->behavior > ARRAY_SIZE(labeling_behaviors))
449 sbsec->flags &= ~SE_SBLABELSUPP;
450
444 /* Initialize the root inode. */ 451 /* Initialize the root inode. */
445 rc = inode_doinit_with_dentry(root_inode, root); 452 rc = inode_doinit_with_dentry(root_inode, root);
446 453
@@ -487,23 +494,22 @@ static int selinux_get_mnt_opts(const struct super_block *sb,
487 494
488 security_init_mnt_opts(opts); 495 security_init_mnt_opts(opts);
489 496
490 if (!sbsec->initialized) 497 if (!(sbsec->flags & SE_SBINITIALIZED))
491 return -EINVAL; 498 return -EINVAL;
492 499
493 if (!ss_initialized) 500 if (!ss_initialized)
494 return -EINVAL; 501 return -EINVAL;
495 502
496 /* 503 tmp = sbsec->flags & SE_MNTMASK;
497 * if we ever use sbsec flags for anything other than tracking mount
498 * settings this is going to need a mask
499 */
500 tmp = sbsec->flags;
501 /* count the number of mount options for this sb */ 504 /* count the number of mount options for this sb */
502 for (i = 0; i < 8; i++) { 505 for (i = 0; i < 8; i++) {
503 if (tmp & 0x01) 506 if (tmp & 0x01)
504 opts->num_mnt_opts++; 507 opts->num_mnt_opts++;
505 tmp >>= 1; 508 tmp >>= 1;
506 } 509 }
510 /* Check if the Label support flag is set */
511 if (sbsec->flags & SE_SBLABELSUPP)
512 opts->num_mnt_opts++;
507 513
508 opts->mnt_opts = kcalloc(opts->num_mnt_opts, sizeof(char *), GFP_ATOMIC); 514 opts->mnt_opts = kcalloc(opts->num_mnt_opts, sizeof(char *), GFP_ATOMIC);
509 if (!opts->mnt_opts) { 515 if (!opts->mnt_opts) {
@@ -549,6 +555,10 @@ static int selinux_get_mnt_opts(const struct super_block *sb,
549 opts->mnt_opts[i] = context; 555 opts->mnt_opts[i] = context;
550 opts->mnt_opts_flags[i++] = ROOTCONTEXT_MNT; 556 opts->mnt_opts_flags[i++] = ROOTCONTEXT_MNT;
551 } 557 }
558 if (sbsec->flags & SE_SBLABELSUPP) {
559 opts->mnt_opts[i] = NULL;
560 opts->mnt_opts_flags[i++] = SE_SBLABELSUPP;
561 }
552 562
553 BUG_ON(i != opts->num_mnt_opts); 563 BUG_ON(i != opts->num_mnt_opts);
554 564
@@ -562,8 +572,10 @@ out_free:
562static int bad_option(struct superblock_security_struct *sbsec, char flag, 572static int bad_option(struct superblock_security_struct *sbsec, char flag,
563 u32 old_sid, u32 new_sid) 573 u32 old_sid, u32 new_sid)
564{ 574{
575 char mnt_flags = sbsec->flags & SE_MNTMASK;
576
565 /* check if the old mount command had the same options */ 577 /* check if the old mount command had the same options */
566 if (sbsec->initialized) 578 if (sbsec->flags & SE_SBINITIALIZED)
567 if (!(sbsec->flags & flag) || 579 if (!(sbsec->flags & flag) ||
568 (old_sid != new_sid)) 580 (old_sid != new_sid))
569 return 1; 581 return 1;
@@ -571,8 +583,8 @@ static int bad_option(struct superblock_security_struct *sbsec, char flag,
571 /* check if we were passed the same options twice, 583 /* check if we were passed the same options twice,
572 * aka someone passed context=a,context=b 584 * aka someone passed context=a,context=b
573 */ 585 */
574 if (!sbsec->initialized) 586 if (!(sbsec->flags & SE_SBINITIALIZED))
575 if (sbsec->flags & flag) 587 if (mnt_flags & flag)
576 return 1; 588 return 1;
577 return 0; 589 return 0;
578} 590}
@@ -626,7 +638,7 @@ static int selinux_set_mnt_opts(struct super_block *sb,
626 * this sb does not set any security options. (The first options 638 * this sb does not set any security options. (The first options
627 * will be used for both mounts) 639 * will be used for both mounts)
628 */ 640 */
629 if (sbsec->initialized && (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA) 641 if ((sbsec->flags & SE_SBINITIALIZED) && (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)
630 && (num_opts == 0)) 642 && (num_opts == 0))
631 goto out; 643 goto out;
632 644
@@ -637,6 +649,9 @@ static int selinux_set_mnt_opts(struct super_block *sb,
637 */ 649 */
638 for (i = 0; i < num_opts; i++) { 650 for (i = 0; i < num_opts; i++) {
639 u32 sid; 651 u32 sid;
652
653 if (flags[i] == SE_SBLABELSUPP)
654 continue;
640 rc = security_context_to_sid(mount_options[i], 655 rc = security_context_to_sid(mount_options[i],
641 strlen(mount_options[i]), &sid); 656 strlen(mount_options[i]), &sid);
642 if (rc) { 657 if (rc) {
@@ -690,19 +705,19 @@ static int selinux_set_mnt_opts(struct super_block *sb,
690 } 705 }
691 } 706 }
692 707
693 if (sbsec->initialized) { 708 if (sbsec->flags & SE_SBINITIALIZED) {
694 /* previously mounted with options, but not on this attempt? */ 709 /* previously mounted with options, but not on this attempt? */
695 if (sbsec->flags && !num_opts) 710 if ((sbsec->flags & SE_MNTMASK) && !num_opts)
696 goto out_double_mount; 711 goto out_double_mount;
697 rc = 0; 712 rc = 0;
698 goto out; 713 goto out;
699 } 714 }
700 715
701 if (strcmp(sb->s_type->name, "proc") == 0) 716 if (strcmp(sb->s_type->name, "proc") == 0)
702 sbsec->proc = 1; 717 sbsec->flags |= SE_SBPROC;
703 718
704 /* Determine the labeling behavior to use for this filesystem type. */ 719 /* Determine the labeling behavior to use for this filesystem type. */
705 rc = security_fs_use(sbsec->proc ? "proc" : sb->s_type->name, &sbsec->behavior, &sbsec->sid); 720 rc = security_fs_use((sbsec->flags & SE_SBPROC) ? "proc" : sb->s_type->name, &sbsec->behavior, &sbsec->sid);
706 if (rc) { 721 if (rc) {
707 printk(KERN_WARNING "%s: security_fs_use(%s) returned %d\n", 722 printk(KERN_WARNING "%s: security_fs_use(%s) returned %d\n",
708 __func__, sb->s_type->name, rc); 723 __func__, sb->s_type->name, rc);
@@ -806,10 +821,10 @@ static void selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
806 } 821 }
807 822
808 /* how can we clone if the old one wasn't set up?? */ 823 /* how can we clone if the old one wasn't set up?? */
809 BUG_ON(!oldsbsec->initialized); 824 BUG_ON(!(oldsbsec->flags & SE_SBINITIALIZED));
810 825
811 /* if fs is reusing a sb, just let its options stand... */ 826 /* if fs is reusing a sb, just let its options stand... */
812 if (newsbsec->initialized) 827 if (newsbsec->flags & SE_SBINITIALIZED)
813 return; 828 return;
814 829
815 mutex_lock(&newsbsec->lock); 830 mutex_lock(&newsbsec->lock);
@@ -917,7 +932,8 @@ static int selinux_parse_opts_str(char *options,
917 goto out_err; 932 goto out_err;
918 } 933 }
919 break; 934 break;
920 935 case Opt_labelsupport:
936 break;
921 default: 937 default:
922 rc = -EINVAL; 938 rc = -EINVAL;
923 printk(KERN_WARNING "SELinux: unknown mount option\n"); 939 printk(KERN_WARNING "SELinux: unknown mount option\n");
@@ -999,7 +1015,12 @@ static void selinux_write_opts(struct seq_file *m,
999 char *prefix; 1015 char *prefix;
1000 1016
1001 for (i = 0; i < opts->num_mnt_opts; i++) { 1017 for (i = 0; i < opts->num_mnt_opts; i++) {
1002 char *has_comma = strchr(opts->mnt_opts[i], ','); 1018 char *has_comma;
1019
1020 if (opts->mnt_opts[i])
1021 has_comma = strchr(opts->mnt_opts[i], ',');
1022 else
1023 has_comma = NULL;
1003 1024
1004 switch (opts->mnt_opts_flags[i]) { 1025 switch (opts->mnt_opts_flags[i]) {
1005 case CONTEXT_MNT: 1026 case CONTEXT_MNT:
@@ -1014,6 +1035,10 @@ static void selinux_write_opts(struct seq_file *m,
1014 case DEFCONTEXT_MNT: 1035 case DEFCONTEXT_MNT:
1015 prefix = DEFCONTEXT_STR; 1036 prefix = DEFCONTEXT_STR;
1016 break; 1037 break;
1038 case SE_SBLABELSUPP:
1039 seq_putc(m, ',');
1040 seq_puts(m, LABELSUPP_STR);
1041 continue;
1017 default: 1042 default:
1018 BUG(); 1043 BUG();
1019 }; 1044 };
@@ -1209,7 +1234,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
1209 goto out_unlock; 1234 goto out_unlock;
1210 1235
1211 sbsec = inode->i_sb->s_security; 1236 sbsec = inode->i_sb->s_security;
1212 if (!sbsec->initialized) { 1237 if (!(sbsec->flags & SE_SBINITIALIZED)) {
1213 /* Defer initialization until selinux_complete_init, 1238 /* Defer initialization until selinux_complete_init,
1214 after the initial policy is loaded and the security 1239 after the initial policy is loaded and the security
1215 server is ready to handle calls. */ 1240 server is ready to handle calls. */
@@ -1237,19 +1262,26 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
1237 dentry = d_find_alias(inode); 1262 dentry = d_find_alias(inode);
1238 } 1263 }
1239 if (!dentry) { 1264 if (!dentry) {
1240 printk(KERN_WARNING "SELinux: %s: no dentry for dev=%s " 1265 /*
1241 "ino=%ld\n", __func__, inode->i_sb->s_id, 1266 * this is can be hit on boot when a file is accessed
1242 inode->i_ino); 1267 * before the policy is loaded. When we load policy we
1268 * may find inodes that have no dentry on the
1269 * sbsec->isec_head list. No reason to complain as these
1270 * will get fixed up the next time we go through
1271 * inode_doinit with a dentry, before these inodes could
1272 * be used again by userspace.
1273 */
1243 goto out_unlock; 1274 goto out_unlock;
1244 } 1275 }
1245 1276
1246 len = INITCONTEXTLEN; 1277 len = INITCONTEXTLEN;
1247 context = kmalloc(len, GFP_NOFS); 1278 context = kmalloc(len+1, GFP_NOFS);
1248 if (!context) { 1279 if (!context) {
1249 rc = -ENOMEM; 1280 rc = -ENOMEM;
1250 dput(dentry); 1281 dput(dentry);
1251 goto out_unlock; 1282 goto out_unlock;
1252 } 1283 }
1284 context[len] = '\0';
1253 rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX, 1285 rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX,
1254 context, len); 1286 context, len);
1255 if (rc == -ERANGE) { 1287 if (rc == -ERANGE) {
@@ -1262,12 +1294,13 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
1262 } 1294 }
1263 kfree(context); 1295 kfree(context);
1264 len = rc; 1296 len = rc;
1265 context = kmalloc(len, GFP_NOFS); 1297 context = kmalloc(len+1, GFP_NOFS);
1266 if (!context) { 1298 if (!context) {
1267 rc = -ENOMEM; 1299 rc = -ENOMEM;
1268 dput(dentry); 1300 dput(dentry);
1269 goto out_unlock; 1301 goto out_unlock;
1270 } 1302 }
1303 context[len] = '\0';
1271 rc = inode->i_op->getxattr(dentry, 1304 rc = inode->i_op->getxattr(dentry,
1272 XATTR_NAME_SELINUX, 1305 XATTR_NAME_SELINUX,
1273 context, len); 1306 context, len);
@@ -1289,10 +1322,19 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
1289 sbsec->def_sid, 1322 sbsec->def_sid,
1290 GFP_NOFS); 1323 GFP_NOFS);
1291 if (rc) { 1324 if (rc) {
1292 printk(KERN_WARNING "SELinux: %s: context_to_sid(%s) " 1325 char *dev = inode->i_sb->s_id;
1293 "returned %d for dev=%s ino=%ld\n", 1326 unsigned long ino = inode->i_ino;
1294 __func__, context, -rc, 1327
1295 inode->i_sb->s_id, inode->i_ino); 1328 if (rc == -EINVAL) {
1329 if (printk_ratelimit())
1330 printk(KERN_NOTICE "SELinux: inode=%lu on dev=%s was found to have an invalid "
1331 "context=%s. This indicates you may need to relabel the inode or the "
1332 "filesystem in question.\n", ino, dev, context);
1333 } else {
1334 printk(KERN_WARNING "SELinux: %s: context_to_sid(%s) "
1335 "returned %d for dev=%s ino=%ld\n",
1336 __func__, context, -rc, dev, ino);
1337 }
1296 kfree(context); 1338 kfree(context);
1297 /* Leave with the unlabeled SID */ 1339 /* Leave with the unlabeled SID */
1298 rc = 0; 1340 rc = 0;
@@ -1326,7 +1368,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
1326 /* Default to the fs superblock SID. */ 1368 /* Default to the fs superblock SID. */
1327 isec->sid = sbsec->sid; 1369 isec->sid = sbsec->sid;
1328 1370
1329 if (sbsec->proc && !S_ISLNK(inode->i_mode)) { 1371 if ((sbsec->flags & SE_SBPROC) && !S_ISLNK(inode->i_mode)) {
1330 struct proc_inode *proci = PROC_I(inode); 1372 struct proc_inode *proci = PROC_I(inode);
1331 if (proci->pde) { 1373 if (proci->pde) {
1332 isec->sclass = inode_mode_to_security_class(inode->i_mode); 1374 isec->sclass = inode_mode_to_security_class(inode->i_mode);
@@ -1587,7 +1629,7 @@ static int may_create(struct inode *dir,
1587 if (rc) 1629 if (rc)
1588 return rc; 1630 return rc;
1589 1631
1590 if (!newsid || sbsec->behavior == SECURITY_FS_USE_MNTPOINT) { 1632 if (!newsid || !(sbsec->flags & SE_SBLABELSUPP)) {
1591 rc = security_transition_sid(sid, dsec->sid, tclass, &newsid); 1633 rc = security_transition_sid(sid, dsec->sid, tclass, &newsid);
1592 if (rc) 1634 if (rc)
1593 return rc; 1635 return rc;
@@ -1801,6 +1843,8 @@ static inline u32 open_file_to_av(struct file *file)
1801 av |= FIFO_FILE__OPEN; 1843 av |= FIFO_FILE__OPEN;
1802 else if (S_ISDIR(mode)) 1844 else if (S_ISDIR(mode))
1803 av |= DIR__OPEN; 1845 av |= DIR__OPEN;
1846 else if (S_ISSOCK(mode))
1847 av |= SOCK_FILE__OPEN;
1804 else 1848 else
1805 printk(KERN_ERR "SELinux: WARNING: inside %s with " 1849 printk(KERN_ERR "SELinux: WARNING: inside %s with "
1806 "unknown mode:%o\n", __func__, mode); 1850 "unknown mode:%o\n", __func__, mode);
@@ -1815,7 +1859,7 @@ static int selinux_ptrace_may_access(struct task_struct *child,
1815{ 1859{
1816 int rc; 1860 int rc;
1817 1861
1818 rc = secondary_ops->ptrace_may_access(child, mode); 1862 rc = cap_ptrace_may_access(child, mode);
1819 if (rc) 1863 if (rc)
1820 return rc; 1864 return rc;
1821 1865
@@ -1832,7 +1876,7 @@ static int selinux_ptrace_traceme(struct task_struct *parent)
1832{ 1876{
1833 int rc; 1877 int rc;
1834 1878
1835 rc = secondary_ops->ptrace_traceme(parent); 1879 rc = cap_ptrace_traceme(parent);
1836 if (rc) 1880 if (rc)
1837 return rc; 1881 return rc;
1838 1882
@@ -1848,7 +1892,7 @@ static int selinux_capget(struct task_struct *target, kernel_cap_t *effective,
1848 if (error) 1892 if (error)
1849 return error; 1893 return error;
1850 1894
1851 return secondary_ops->capget(target, effective, inheritable, permitted); 1895 return cap_capget(target, effective, inheritable, permitted);
1852} 1896}
1853 1897
1854static int selinux_capset(struct cred *new, const struct cred *old, 1898static int selinux_capset(struct cred *new, const struct cred *old,
@@ -1858,7 +1902,7 @@ static int selinux_capset(struct cred *new, const struct cred *old,
1858{ 1902{
1859 int error; 1903 int error;
1860 1904
1861 error = secondary_ops->capset(new, old, 1905 error = cap_capset(new, old,
1862 effective, inheritable, permitted); 1906 effective, inheritable, permitted);
1863 if (error) 1907 if (error)
1864 return error; 1908 return error;
@@ -1866,12 +1910,22 @@ static int selinux_capset(struct cred *new, const struct cred *old,
1866 return cred_has_perm(old, new, PROCESS__SETCAP); 1910 return cred_has_perm(old, new, PROCESS__SETCAP);
1867} 1911}
1868 1912
1913/*
1914 * (This comment used to live with the selinux_task_setuid hook,
1915 * which was removed).
1916 *
1917 * Since setuid only affects the current process, and since the SELinux
1918 * controls are not based on the Linux identity attributes, SELinux does not
1919 * need to control this operation. However, SELinux does control the use of
1920 * the CAP_SETUID and CAP_SETGID capabilities using the capable hook.
1921 */
1922
1869static int selinux_capable(struct task_struct *tsk, const struct cred *cred, 1923static int selinux_capable(struct task_struct *tsk, const struct cred *cred,
1870 int cap, int audit) 1924 int cap, int audit)
1871{ 1925{
1872 int rc; 1926 int rc;
1873 1927
1874 rc = secondary_ops->capable(tsk, cred, cap, audit); 1928 rc = cap_capable(tsk, cred, cap, audit);
1875 if (rc) 1929 if (rc)
1876 return rc; 1930 return rc;
1877 1931
@@ -1997,7 +2051,7 @@ static int selinux_syslog(int type)
1997{ 2051{
1998 int rc; 2052 int rc;
1999 2053
2000 rc = secondary_ops->syslog(type); 2054 rc = cap_syslog(type);
2001 if (rc) 2055 if (rc)
2002 return rc; 2056 return rc;
2003 2057
@@ -2028,10 +2082,6 @@ static int selinux_syslog(int type)
2028 * mapping. 0 means there is enough memory for the allocation to 2082 * mapping. 0 means there is enough memory for the allocation to
2029 * succeed and -ENOMEM implies there is not. 2083 * succeed and -ENOMEM implies there is not.
2030 * 2084 *
2031 * Note that secondary_ops->capable and task_has_perm_noaudit return 0
2032 * if the capability is granted, but __vm_enough_memory requires 1 if
2033 * the capability is granted.
2034 *
2035 * Do not audit the selinux permission check, as this is applied to all 2085 * Do not audit the selinux permission check, as this is applied to all
2036 * processes that allocate mappings. 2086 * processes that allocate mappings.
2037 */ 2087 */
@@ -2058,7 +2108,7 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm)
2058 struct inode *inode = bprm->file->f_path.dentry->d_inode; 2108 struct inode *inode = bprm->file->f_path.dentry->d_inode;
2059 int rc; 2109 int rc;
2060 2110
2061 rc = secondary_ops->bprm_set_creds(bprm); 2111 rc = cap_bprm_set_creds(bprm);
2062 if (rc) 2112 if (rc)
2063 return rc; 2113 return rc;
2064 2114
@@ -2156,11 +2206,6 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm)
2156 return 0; 2206 return 0;
2157} 2207}
2158 2208
2159static int selinux_bprm_check_security(struct linux_binprm *bprm)
2160{
2161 return secondary_ops->bprm_check_security(bprm);
2162}
2163
2164static int selinux_bprm_secureexec(struct linux_binprm *bprm) 2209static int selinux_bprm_secureexec(struct linux_binprm *bprm)
2165{ 2210{
2166 const struct cred *cred = current_cred(); 2211 const struct cred *cred = current_cred();
@@ -2180,7 +2225,7 @@ static int selinux_bprm_secureexec(struct linux_binprm *bprm)
2180 PROCESS__NOATSECURE, NULL); 2225 PROCESS__NOATSECURE, NULL);
2181 } 2226 }
2182 2227
2183 return (atsecure || secondary_ops->bprm_secureexec(bprm)); 2228 return (atsecure || cap_bprm_secureexec(bprm));
2184} 2229}
2185 2230
2186extern struct vfsmount *selinuxfs_mount; 2231extern struct vfsmount *selinuxfs_mount;
@@ -2290,8 +2335,6 @@ static void selinux_bprm_committing_creds(struct linux_binprm *bprm)
2290 struct rlimit *rlim, *initrlim; 2335 struct rlimit *rlim, *initrlim;
2291 int rc, i; 2336 int rc, i;
2292 2337
2293 secondary_ops->bprm_committing_creds(bprm);
2294
2295 new_tsec = bprm->cred->security; 2338 new_tsec = bprm->cred->security;
2296 if (new_tsec->sid == new_tsec->osid) 2339 if (new_tsec->sid == new_tsec->osid)
2297 return; 2340 return;
@@ -2337,8 +2380,6 @@ static void selinux_bprm_committed_creds(struct linux_binprm *bprm)
2337 int rc, i; 2380 int rc, i;
2338 unsigned long flags; 2381 unsigned long flags;
2339 2382
2340 secondary_ops->bprm_committed_creds(bprm);
2341
2342 osid = tsec->osid; 2383 osid = tsec->osid;
2343 sid = tsec->sid; 2384 sid = tsec->sid;
2344 2385
@@ -2400,7 +2441,8 @@ static inline int selinux_option(char *option, int len)
2400 return (match_prefix(CONTEXT_STR, sizeof(CONTEXT_STR)-1, option, len) || 2441 return (match_prefix(CONTEXT_STR, sizeof(CONTEXT_STR)-1, option, len) ||
2401 match_prefix(FSCONTEXT_STR, sizeof(FSCONTEXT_STR)-1, option, len) || 2442 match_prefix(FSCONTEXT_STR, sizeof(FSCONTEXT_STR)-1, option, len) ||
2402 match_prefix(DEFCONTEXT_STR, sizeof(DEFCONTEXT_STR)-1, option, len) || 2443 match_prefix(DEFCONTEXT_STR, sizeof(DEFCONTEXT_STR)-1, option, len) ||
2403 match_prefix(ROOTCONTEXT_STR, sizeof(ROOTCONTEXT_STR)-1, option, len)); 2444 match_prefix(ROOTCONTEXT_STR, sizeof(ROOTCONTEXT_STR)-1, option, len) ||
2445 match_prefix(LABELSUPP_STR, sizeof(LABELSUPP_STR)-1, option, len));
2404} 2446}
2405 2447
2406static inline void take_option(char **to, char *from, int *first, int len) 2448static inline void take_option(char **to, char *from, int *first, int len)
@@ -2513,11 +2555,6 @@ static int selinux_mount(char *dev_name,
2513 void *data) 2555 void *data)
2514{ 2556{
2515 const struct cred *cred = current_cred(); 2557 const struct cred *cred = current_cred();
2516 int rc;
2517
2518 rc = secondary_ops->sb_mount(dev_name, path, type, flags, data);
2519 if (rc)
2520 return rc;
2521 2558
2522 if (flags & MS_REMOUNT) 2559 if (flags & MS_REMOUNT)
2523 return superblock_has_perm(cred, path->mnt->mnt_sb, 2560 return superblock_has_perm(cred, path->mnt->mnt_sb,
@@ -2530,11 +2567,6 @@ static int selinux_mount(char *dev_name,
2530static int selinux_umount(struct vfsmount *mnt, int flags) 2567static int selinux_umount(struct vfsmount *mnt, int flags)
2531{ 2568{
2532 const struct cred *cred = current_cred(); 2569 const struct cred *cred = current_cred();
2533 int rc;
2534
2535 rc = secondary_ops->sb_umount(mnt, flags);
2536 if (rc)
2537 return rc;
2538 2570
2539 return superblock_has_perm(cred, mnt->mnt_sb, 2571 return superblock_has_perm(cred, mnt->mnt_sb,
2540 FILESYSTEM__UNMOUNT, NULL); 2572 FILESYSTEM__UNMOUNT, NULL);
@@ -2570,7 +2602,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
2570 sid = tsec->sid; 2602 sid = tsec->sid;
2571 newsid = tsec->create_sid; 2603 newsid = tsec->create_sid;
2572 2604
2573 if (!newsid || sbsec->behavior == SECURITY_FS_USE_MNTPOINT) { 2605 if (!newsid || !(sbsec->flags & SE_SBLABELSUPP)) {
2574 rc = security_transition_sid(sid, dsec->sid, 2606 rc = security_transition_sid(sid, dsec->sid,
2575 inode_mode_to_security_class(inode->i_mode), 2607 inode_mode_to_security_class(inode->i_mode),
2576 &newsid); 2608 &newsid);
@@ -2585,14 +2617,14 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
2585 } 2617 }
2586 2618
2587 /* Possibly defer initialization to selinux_complete_init. */ 2619 /* Possibly defer initialization to selinux_complete_init. */
2588 if (sbsec->initialized) { 2620 if (sbsec->flags & SE_SBINITIALIZED) {
2589 struct inode_security_struct *isec = inode->i_security; 2621 struct inode_security_struct *isec = inode->i_security;
2590 isec->sclass = inode_mode_to_security_class(inode->i_mode); 2622 isec->sclass = inode_mode_to_security_class(inode->i_mode);
2591 isec->sid = newsid; 2623 isec->sid = newsid;
2592 isec->initialized = 1; 2624 isec->initialized = 1;
2593 } 2625 }
2594 2626
2595 if (!ss_initialized || sbsec->behavior == SECURITY_FS_USE_MNTPOINT) 2627 if (!ss_initialized || !(sbsec->flags & SE_SBLABELSUPP))
2596 return -EOPNOTSUPP; 2628 return -EOPNOTSUPP;
2597 2629
2598 if (name) { 2630 if (name) {
@@ -2622,21 +2654,11 @@ static int selinux_inode_create(struct inode *dir, struct dentry *dentry, int ma
2622 2654
2623static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry) 2655static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
2624{ 2656{
2625 int rc;
2626
2627 rc = secondary_ops->inode_link(old_dentry, dir, new_dentry);
2628 if (rc)
2629 return rc;
2630 return may_link(dir, old_dentry, MAY_LINK); 2657 return may_link(dir, old_dentry, MAY_LINK);
2631} 2658}
2632 2659
2633static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry) 2660static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry)
2634{ 2661{
2635 int rc;
2636
2637 rc = secondary_ops->inode_unlink(dir, dentry);
2638 if (rc)
2639 return rc;
2640 return may_link(dir, dentry, MAY_UNLINK); 2662 return may_link(dir, dentry, MAY_UNLINK);
2641} 2663}
2642 2664
@@ -2657,12 +2679,6 @@ static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry)
2657 2679
2658static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) 2680static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
2659{ 2681{
2660 int rc;
2661
2662 rc = secondary_ops->inode_mknod(dir, dentry, mode, dev);
2663 if (rc)
2664 return rc;
2665
2666 return may_create(dir, dentry, inode_mode_to_security_class(mode)); 2682 return may_create(dir, dentry, inode_mode_to_security_class(mode));
2667} 2683}
2668 2684
@@ -2682,22 +2698,13 @@ static int selinux_inode_readlink(struct dentry *dentry)
2682static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *nameidata) 2698static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *nameidata)
2683{ 2699{
2684 const struct cred *cred = current_cred(); 2700 const struct cred *cred = current_cred();
2685 int rc;
2686 2701
2687 rc = secondary_ops->inode_follow_link(dentry, nameidata);
2688 if (rc)
2689 return rc;
2690 return dentry_has_perm(cred, NULL, dentry, FILE__READ); 2702 return dentry_has_perm(cred, NULL, dentry, FILE__READ);
2691} 2703}
2692 2704
2693static int selinux_inode_permission(struct inode *inode, int mask) 2705static int selinux_inode_permission(struct inode *inode, int mask)
2694{ 2706{
2695 const struct cred *cred = current_cred(); 2707 const struct cred *cred = current_cred();
2696 int rc;
2697
2698 rc = secondary_ops->inode_permission(inode, mask);
2699 if (rc)
2700 return rc;
2701 2708
2702 if (!mask) { 2709 if (!mask) {
2703 /* No permission to check. Existence test. */ 2710 /* No permission to check. Existence test. */
@@ -2711,11 +2718,6 @@ static int selinux_inode_permission(struct inode *inode, int mask)
2711static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr) 2718static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
2712{ 2719{
2713 const struct cred *cred = current_cred(); 2720 const struct cred *cred = current_cred();
2714 int rc;
2715
2716 rc = secondary_ops->inode_setattr(dentry, iattr);
2717 if (rc)
2718 return rc;
2719 2721
2720 if (iattr->ia_valid & ATTR_FORCE) 2722 if (iattr->ia_valid & ATTR_FORCE)
2721 return 0; 2723 return 0;
@@ -2769,7 +2771,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
2769 return selinux_inode_setotherxattr(dentry, name); 2771 return selinux_inode_setotherxattr(dentry, name);
2770 2772
2771 sbsec = inode->i_sb->s_security; 2773 sbsec = inode->i_sb->s_security;
2772 if (sbsec->behavior == SECURITY_FS_USE_MNTPOINT) 2774 if (!(sbsec->flags & SE_SBLABELSUPP))
2773 return -EOPNOTSUPP; 2775 return -EOPNOTSUPP;
2774 2776
2775 if (!is_owner_or_cap(inode)) 2777 if (!is_owner_or_cap(inode))
@@ -2931,16 +2933,6 @@ static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t
2931 return len; 2933 return len;
2932} 2934}
2933 2935
2934static int selinux_inode_need_killpriv(struct dentry *dentry)
2935{
2936 return secondary_ops->inode_need_killpriv(dentry);
2937}
2938
2939static int selinux_inode_killpriv(struct dentry *dentry)
2940{
2941 return secondary_ops->inode_killpriv(dentry);
2942}
2943
2944static void selinux_inode_getsecid(const struct inode *inode, u32 *secid) 2936static void selinux_inode_getsecid(const struct inode *inode, u32 *secid)
2945{ 2937{
2946 struct inode_security_struct *isec = inode->i_security; 2938 struct inode_security_struct *isec = inode->i_security;
@@ -2952,7 +2944,6 @@ static void selinux_inode_getsecid(const struct inode *inode, u32 *secid)
2952static int selinux_revalidate_file_permission(struct file *file, int mask) 2944static int selinux_revalidate_file_permission(struct file *file, int mask)
2953{ 2945{
2954 const struct cred *cred = current_cred(); 2946 const struct cred *cred = current_cred();
2955 int rc;
2956 struct inode *inode = file->f_path.dentry->d_inode; 2947 struct inode *inode = file->f_path.dentry->d_inode;
2957 2948
2958 if (!mask) { 2949 if (!mask) {
@@ -2964,29 +2955,15 @@ static int selinux_revalidate_file_permission(struct file *file, int mask)
2964 if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE)) 2955 if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE))
2965 mask |= MAY_APPEND; 2956 mask |= MAY_APPEND;
2966 2957
2967 rc = file_has_perm(cred, file, 2958 return file_has_perm(cred, file,
2968 file_mask_to_av(inode->i_mode, mask)); 2959 file_mask_to_av(inode->i_mode, mask));
2969 if (rc)
2970 return rc;
2971
2972 return selinux_netlbl_inode_permission(inode, mask);
2973} 2960}
2974 2961
2975static int selinux_file_permission(struct file *file, int mask) 2962static int selinux_file_permission(struct file *file, int mask)
2976{ 2963{
2977 struct inode *inode = file->f_path.dentry->d_inode; 2964 if (!mask)
2978 struct file_security_struct *fsec = file->f_security;
2979 struct inode_security_struct *isec = inode->i_security;
2980 u32 sid = current_sid();
2981
2982 if (!mask) {
2983 /* No permission to check. Existence test. */ 2965 /* No permission to check. Existence test. */
2984 return 0; 2966 return 0;
2985 }
2986
2987 if (sid == fsec->sid && fsec->isid == isec->sid
2988 && fsec->pseqno == avc_policy_seqno())
2989 return selinux_netlbl_inode_permission(inode, mask);
2990 2967
2991 return selinux_revalidate_file_permission(file, mask); 2968 return selinux_revalidate_file_permission(file, mask);
2992} 2969}
@@ -3078,18 +3055,13 @@ static int selinux_file_mprotect(struct vm_area_struct *vma,
3078 unsigned long prot) 3055 unsigned long prot)
3079{ 3056{
3080 const struct cred *cred = current_cred(); 3057 const struct cred *cred = current_cred();
3081 int rc;
3082
3083 rc = secondary_ops->file_mprotect(vma, reqprot, prot);
3084 if (rc)
3085 return rc;
3086 3058
3087 if (selinux_checkreqprot) 3059 if (selinux_checkreqprot)
3088 prot = reqprot; 3060 prot = reqprot;
3089 3061
3090#ifndef CONFIG_PPC32 3062#ifndef CONFIG_PPC32
3091 if ((prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) { 3063 if ((prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) {
3092 rc = 0; 3064 int rc = 0;
3093 if (vma->vm_start >= vma->vm_mm->start_brk && 3065 if (vma->vm_start >= vma->vm_mm->start_brk &&
3094 vma->vm_end <= vma->vm_mm->brk) { 3066 vma->vm_end <= vma->vm_mm->brk) {
3095 rc = cred_has_perm(cred, cred, PROCESS__EXECHEAP); 3067 rc = cred_has_perm(cred, cred, PROCESS__EXECHEAP);
@@ -3239,12 +3211,6 @@ static int selinux_dentry_open(struct file *file, const struct cred *cred)
3239 3211
3240static int selinux_task_create(unsigned long clone_flags) 3212static int selinux_task_create(unsigned long clone_flags)
3241{ 3213{
3242 int rc;
3243
3244 rc = secondary_ops->task_create(clone_flags);
3245 if (rc)
3246 return rc;
3247
3248 return current_has_perm(current, PROCESS__FORK); 3214 return current_has_perm(current, PROCESS__FORK);
3249} 3215}
3250 3216
@@ -3278,14 +3244,6 @@ static int selinux_cred_prepare(struct cred *new, const struct cred *old,
3278} 3244}
3279 3245
3280/* 3246/*
3281 * commit new credentials
3282 */
3283static void selinux_cred_commit(struct cred *new, const struct cred *old)
3284{
3285 secondary_ops->cred_commit(new, old);
3286}
3287
3288/*
3289 * set the security data for a kernel service 3247 * set the security data for a kernel service
3290 * - all the creation contexts are set to unlabelled 3248 * - all the creation contexts are set to unlabelled
3291 */ 3249 */
@@ -3329,29 +3287,6 @@ static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode)
3329 return 0; 3287 return 0;
3330} 3288}
3331 3289
3332static int selinux_task_setuid(uid_t id0, uid_t id1, uid_t id2, int flags)
3333{
3334 /* Since setuid only affects the current process, and
3335 since the SELinux controls are not based on the Linux
3336 identity attributes, SELinux does not need to control
3337 this operation. However, SELinux does control the use
3338 of the CAP_SETUID and CAP_SETGID capabilities using the
3339 capable hook. */
3340 return 0;
3341}
3342
3343static int selinux_task_fix_setuid(struct cred *new, const struct cred *old,
3344 int flags)
3345{
3346 return secondary_ops->task_fix_setuid(new, old, flags);
3347}
3348
3349static int selinux_task_setgid(gid_t id0, gid_t id1, gid_t id2, int flags)
3350{
3351 /* See the comment for setuid above. */
3352 return 0;
3353}
3354
3355static int selinux_task_setpgid(struct task_struct *p, pid_t pgid) 3290static int selinux_task_setpgid(struct task_struct *p, pid_t pgid)
3356{ 3291{
3357 return current_has_perm(p, PROCESS__SETPGID); 3292 return current_has_perm(p, PROCESS__SETPGID);
@@ -3372,17 +3307,11 @@ static void selinux_task_getsecid(struct task_struct *p, u32 *secid)
3372 *secid = task_sid(p); 3307 *secid = task_sid(p);
3373} 3308}
3374 3309
3375static int selinux_task_setgroups(struct group_info *group_info)
3376{
3377 /* See the comment for setuid above. */
3378 return 0;
3379}
3380
3381static int selinux_task_setnice(struct task_struct *p, int nice) 3310static int selinux_task_setnice(struct task_struct *p, int nice)
3382{ 3311{
3383 int rc; 3312 int rc;
3384 3313
3385 rc = secondary_ops->task_setnice(p, nice); 3314 rc = cap_task_setnice(p, nice);
3386 if (rc) 3315 if (rc)
3387 return rc; 3316 return rc;
3388 3317
@@ -3393,7 +3322,7 @@ static int selinux_task_setioprio(struct task_struct *p, int ioprio)
3393{ 3322{
3394 int rc; 3323 int rc;
3395 3324
3396 rc = secondary_ops->task_setioprio(p, ioprio); 3325 rc = cap_task_setioprio(p, ioprio);
3397 if (rc) 3326 if (rc)
3398 return rc; 3327 return rc;
3399 3328
@@ -3408,11 +3337,6 @@ static int selinux_task_getioprio(struct task_struct *p)
3408static int selinux_task_setrlimit(unsigned int resource, struct rlimit *new_rlim) 3337static int selinux_task_setrlimit(unsigned int resource, struct rlimit *new_rlim)
3409{ 3338{
3410 struct rlimit *old_rlim = current->signal->rlim + resource; 3339 struct rlimit *old_rlim = current->signal->rlim + resource;
3411 int rc;
3412
3413 rc = secondary_ops->task_setrlimit(resource, new_rlim);
3414 if (rc)
3415 return rc;
3416 3340
3417 /* Control the ability to change the hard limit (whether 3341 /* Control the ability to change the hard limit (whether
3418 lowering or raising it), so that the hard limit can 3342 lowering or raising it), so that the hard limit can
@@ -3428,7 +3352,7 @@ static int selinux_task_setscheduler(struct task_struct *p, int policy, struct s
3428{ 3352{
3429 int rc; 3353 int rc;
3430 3354
3431 rc = secondary_ops->task_setscheduler(p, policy, lp); 3355 rc = cap_task_setscheduler(p, policy, lp);
3432 if (rc) 3356 if (rc)
3433 return rc; 3357 return rc;
3434 3358
@@ -3451,10 +3375,6 @@ static int selinux_task_kill(struct task_struct *p, struct siginfo *info,
3451 u32 perm; 3375 u32 perm;
3452 int rc; 3376 int rc;
3453 3377
3454 rc = secondary_ops->task_kill(p, info, sig, secid);
3455 if (rc)
3456 return rc;
3457
3458 if (!sig) 3378 if (!sig)
3459 perm = PROCESS__SIGNULL; /* null signal; existence test */ 3379 perm = PROCESS__SIGNULL; /* null signal; existence test */
3460 else 3380 else
@@ -3467,18 +3387,6 @@ static int selinux_task_kill(struct task_struct *p, struct siginfo *info,
3467 return rc; 3387 return rc;
3468} 3388}
3469 3389
3470static int selinux_task_prctl(int option,
3471 unsigned long arg2,
3472 unsigned long arg3,
3473 unsigned long arg4,
3474 unsigned long arg5)
3475{
3476 /* The current prctl operations do not appear to require
3477 any SELinux controls since they merely observe or modify
3478 the state of the current process. */
3479 return secondary_ops->task_prctl(option, arg2, arg3, arg4, arg5);
3480}
3481
3482static int selinux_task_wait(struct task_struct *p) 3390static int selinux_task_wait(struct task_struct *p)
3483{ 3391{
3484 return task_has_perm(p, current, PROCESS__SIGCHLD); 3392 return task_has_perm(p, current, PROCESS__SIGCHLD);
@@ -3799,7 +3707,7 @@ static int selinux_socket_post_create(struct socket *sock, int family,
3799 sksec = sock->sk->sk_security; 3707 sksec = sock->sk->sk_security;
3800 sksec->sid = isec->sid; 3708 sksec->sid = isec->sid;
3801 sksec->sclass = isec->sclass; 3709 sksec->sclass = isec->sclass;
3802 err = selinux_netlbl_socket_post_create(sock); 3710 err = selinux_netlbl_socket_post_create(sock->sk, family);
3803 } 3711 }
3804 3712
3805 return err; 3713 return err;
@@ -3990,13 +3898,7 @@ static int selinux_socket_accept(struct socket *sock, struct socket *newsock)
3990static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg, 3898static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg,
3991 int size) 3899 int size)
3992{ 3900{
3993 int rc; 3901 return socket_has_perm(current, sock, SOCKET__WRITE);
3994
3995 rc = socket_has_perm(current, sock, SOCKET__WRITE);
3996 if (rc)
3997 return rc;
3998
3999 return selinux_netlbl_inode_permission(SOCK_INODE(sock), MAY_WRITE);
4000} 3902}
4001 3903
4002static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg, 3904static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg,
@@ -4047,10 +3949,6 @@ static int selinux_socket_unix_stream_connect(struct socket *sock,
4047 struct avc_audit_data ad; 3949 struct avc_audit_data ad;
4048 int err; 3950 int err;
4049 3951
4050 err = secondary_ops->unix_stream_connect(sock, other, newsk);
4051 if (err)
4052 return err;
4053
4054 isec = SOCK_INODE(sock)->i_security; 3952 isec = SOCK_INODE(sock)->i_security;
4055 other_isec = SOCK_INODE(other)->i_security; 3953 other_isec = SOCK_INODE(other)->i_security;
4056 3954
@@ -4120,72 +4018,6 @@ static int selinux_inet_sys_rcv_skb(int ifindex, char *addrp, u16 family,
4120 SECCLASS_NODE, NODE__RECVFROM, ad); 4018 SECCLASS_NODE, NODE__RECVFROM, ad);
4121} 4019}
4122 4020
4123static int selinux_sock_rcv_skb_iptables_compat(struct sock *sk,
4124 struct sk_buff *skb,
4125 struct avc_audit_data *ad,
4126 u16 family,
4127 char *addrp)
4128{
4129 int err;
4130 struct sk_security_struct *sksec = sk->sk_security;
4131 u16 sk_class;
4132 u32 netif_perm, node_perm, recv_perm;
4133 u32 port_sid, node_sid, if_sid, sk_sid;
4134
4135 sk_sid = sksec->sid;
4136 sk_class = sksec->sclass;
4137
4138 switch (sk_class) {
4139 case SECCLASS_UDP_SOCKET:
4140 netif_perm = NETIF__UDP_RECV;
4141 node_perm = NODE__UDP_RECV;
4142 recv_perm = UDP_SOCKET__RECV_MSG;
4143 break;
4144 case SECCLASS_TCP_SOCKET:
4145 netif_perm = NETIF__TCP_RECV;
4146 node_perm = NODE__TCP_RECV;
4147 recv_perm = TCP_SOCKET__RECV_MSG;
4148 break;
4149 case SECCLASS_DCCP_SOCKET:
4150 netif_perm = NETIF__DCCP_RECV;
4151 node_perm = NODE__DCCP_RECV;
4152 recv_perm = DCCP_SOCKET__RECV_MSG;
4153 break;
4154 default:
4155 netif_perm = NETIF__RAWIP_RECV;
4156 node_perm = NODE__RAWIP_RECV;
4157 recv_perm = 0;
4158 break;
4159 }
4160
4161 err = sel_netif_sid(skb->iif, &if_sid);
4162 if (err)
4163 return err;
4164 err = avc_has_perm(sk_sid, if_sid, SECCLASS_NETIF, netif_perm, ad);
4165 if (err)
4166 return err;
4167
4168 err = sel_netnode_sid(addrp, family, &node_sid);
4169 if (err)
4170 return err;
4171 err = avc_has_perm(sk_sid, node_sid, SECCLASS_NODE, node_perm, ad);
4172 if (err)
4173 return err;
4174
4175 if (!recv_perm)
4176 return 0;
4177 err = sel_netport_sid(sk->sk_protocol,
4178 ntohs(ad->u.net.sport), &port_sid);
4179 if (unlikely(err)) {
4180 printk(KERN_WARNING
4181 "SELinux: failure in"
4182 " selinux_sock_rcv_skb_iptables_compat(),"
4183 " network port label not found\n");
4184 return err;
4185 }
4186 return avc_has_perm(sk_sid, port_sid, sk_class, recv_perm, ad);
4187}
4188
4189static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb, 4021static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
4190 u16 family) 4022 u16 family)
4191{ 4023{
@@ -4203,14 +4035,12 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
4203 if (err) 4035 if (err)
4204 return err; 4036 return err;
4205 4037
4206 if (selinux_compat_net) 4038 if (selinux_secmark_enabled()) {
4207 err = selinux_sock_rcv_skb_iptables_compat(sk, skb, &ad,
4208 family, addrp);
4209 else if (selinux_secmark_enabled())
4210 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET, 4039 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
4211 PACKET__RECV, &ad); 4040 PACKET__RECV, &ad);
4212 if (err) 4041 if (err)
4213 return err; 4042 return err;
4043 }
4214 4044
4215 if (selinux_policycap_netpeer) { 4045 if (selinux_policycap_netpeer) {
4216 err = selinux_skb_peerlbl_sid(skb, family, &peer_sid); 4046 err = selinux_skb_peerlbl_sid(skb, family, &peer_sid);
@@ -4252,7 +4082,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
4252 * to the selinux_sock_rcv_skb_compat() function to deal with the 4082 * to the selinux_sock_rcv_skb_compat() function to deal with the
4253 * special handling. We do this in an attempt to keep this function 4083 * special handling. We do this in an attempt to keep this function
4254 * as fast and as clean as possible. */ 4084 * as fast and as clean as possible. */
4255 if (selinux_compat_net || !selinux_policycap_netpeer) 4085 if (!selinux_policycap_netpeer)
4256 return selinux_sock_rcv_skb_compat(sk, skb, family); 4086 return selinux_sock_rcv_skb_compat(sk, skb, family);
4257 4087
4258 secmark_active = selinux_secmark_enabled(); 4088 secmark_active = selinux_secmark_enabled();
@@ -4384,7 +4214,7 @@ static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk)
4384 newssec->peer_sid = ssec->peer_sid; 4214 newssec->peer_sid = ssec->peer_sid;
4385 newssec->sclass = ssec->sclass; 4215 newssec->sclass = ssec->sclass;
4386 4216
4387 selinux_netlbl_sk_security_reset(newssec, newsk->sk_family); 4217 selinux_netlbl_sk_security_reset(newssec);
4388} 4218}
4389 4219
4390static void selinux_sk_getsecid(struct sock *sk, u32 *secid) 4220static void selinux_sk_getsecid(struct sock *sk, u32 *secid)
@@ -4428,16 +4258,15 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
4428 if (peersid == SECSID_NULL) { 4258 if (peersid == SECSID_NULL) {
4429 req->secid = sksec->sid; 4259 req->secid = sksec->sid;
4430 req->peer_secid = SECSID_NULL; 4260 req->peer_secid = SECSID_NULL;
4431 return 0; 4261 } else {
4262 err = security_sid_mls_copy(sksec->sid, peersid, &newsid);
4263 if (err)
4264 return err;
4265 req->secid = newsid;
4266 req->peer_secid = peersid;
4432 } 4267 }
4433 4268
4434 err = security_sid_mls_copy(sksec->sid, peersid, &newsid); 4269 return selinux_netlbl_inet_conn_request(req, family);
4435 if (err)
4436 return err;
4437
4438 req->secid = newsid;
4439 req->peer_secid = peersid;
4440 return 0;
4441} 4270}
4442 4271
4443static void selinux_inet_csk_clone(struct sock *newsk, 4272static void selinux_inet_csk_clone(struct sock *newsk,
@@ -4454,7 +4283,7 @@ static void selinux_inet_csk_clone(struct sock *newsk,
4454 4283
4455 /* We don't need to take any sort of lock here as we are the only 4284 /* We don't need to take any sort of lock here as we are the only
4456 * thread with access to newsksec */ 4285 * thread with access to newsksec */
4457 selinux_netlbl_sk_security_reset(newsksec, req->rsk_ops->family); 4286 selinux_netlbl_inet_csk_clone(newsk, req->rsk_ops->family);
4458} 4287}
4459 4288
4460static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb) 4289static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb)
@@ -4467,8 +4296,6 @@ static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb)
4467 family = PF_INET; 4296 family = PF_INET;
4468 4297
4469 selinux_skb_peerlbl_sid(skb, family, &sksec->peer_sid); 4298 selinux_skb_peerlbl_sid(skb, family, &sksec->peer_sid);
4470
4471 selinux_netlbl_inet_conn_established(sk, family);
4472} 4299}
4473 4300
4474static void selinux_req_classify_flow(const struct request_sock *req, 4301static void selinux_req_classify_flow(const struct request_sock *req,
@@ -4620,71 +4447,6 @@ static unsigned int selinux_ipv4_output(unsigned int hooknum,
4620 return selinux_ip_output(skb, PF_INET); 4447 return selinux_ip_output(skb, PF_INET);
4621} 4448}
4622 4449
4623static int selinux_ip_postroute_iptables_compat(struct sock *sk,
4624 int ifindex,
4625 struct avc_audit_data *ad,
4626 u16 family, char *addrp)
4627{
4628 int err;
4629 struct sk_security_struct *sksec = sk->sk_security;
4630 u16 sk_class;
4631 u32 netif_perm, node_perm, send_perm;
4632 u32 port_sid, node_sid, if_sid, sk_sid;
4633
4634 sk_sid = sksec->sid;
4635 sk_class = sksec->sclass;
4636
4637 switch (sk_class) {
4638 case SECCLASS_UDP_SOCKET:
4639 netif_perm = NETIF__UDP_SEND;
4640 node_perm = NODE__UDP_SEND;
4641 send_perm = UDP_SOCKET__SEND_MSG;
4642 break;
4643 case SECCLASS_TCP_SOCKET:
4644 netif_perm = NETIF__TCP_SEND;
4645 node_perm = NODE__TCP_SEND;
4646 send_perm = TCP_SOCKET__SEND_MSG;
4647 break;
4648 case SECCLASS_DCCP_SOCKET:
4649 netif_perm = NETIF__DCCP_SEND;
4650 node_perm = NODE__DCCP_SEND;
4651 send_perm = DCCP_SOCKET__SEND_MSG;
4652 break;
4653 default:
4654 netif_perm = NETIF__RAWIP_SEND;
4655 node_perm = NODE__RAWIP_SEND;
4656 send_perm = 0;
4657 break;
4658 }
4659
4660 err = sel_netif_sid(ifindex, &if_sid);
4661 if (err)
4662 return err;
4663 err = avc_has_perm(sk_sid, if_sid, SECCLASS_NETIF, netif_perm, ad);
4664 return err;
4665
4666 err = sel_netnode_sid(addrp, family, &node_sid);
4667 if (err)
4668 return err;
4669 err = avc_has_perm(sk_sid, node_sid, SECCLASS_NODE, node_perm, ad);
4670 if (err)
4671 return err;
4672
4673 if (send_perm != 0)
4674 return 0;
4675
4676 err = sel_netport_sid(sk->sk_protocol,
4677 ntohs(ad->u.net.dport), &port_sid);
4678 if (unlikely(err)) {
4679 printk(KERN_WARNING
4680 "SELinux: failure in"
4681 " selinux_ip_postroute_iptables_compat(),"
4682 " network port label not found\n");
4683 return err;
4684 }
4685 return avc_has_perm(sk_sid, port_sid, sk_class, send_perm, ad);
4686}
4687
4688static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb, 4450static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
4689 int ifindex, 4451 int ifindex,
4690 u16 family) 4452 u16 family)
@@ -4705,15 +4467,10 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
4705 if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto)) 4467 if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto))
4706 return NF_DROP; 4468 return NF_DROP;
4707 4469
4708 if (selinux_compat_net) { 4470 if (selinux_secmark_enabled())
4709 if (selinux_ip_postroute_iptables_compat(skb->sk, ifindex,
4710 &ad, family, addrp))
4711 return NF_DROP;
4712 } else if (selinux_secmark_enabled()) {
4713 if (avc_has_perm(sksec->sid, skb->secmark, 4471 if (avc_has_perm(sksec->sid, skb->secmark,
4714 SECCLASS_PACKET, PACKET__SEND, &ad)) 4472 SECCLASS_PACKET, PACKET__SEND, &ad))
4715 return NF_DROP; 4473 return NF_DROP;
4716 }
4717 4474
4718 if (selinux_policycap_netpeer) 4475 if (selinux_policycap_netpeer)
4719 if (selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto)) 4476 if (selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto))
@@ -4737,7 +4494,7 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
4737 * to the selinux_ip_postroute_compat() function to deal with the 4494 * to the selinux_ip_postroute_compat() function to deal with the
4738 * special handling. We do this in an attempt to keep this function 4495 * special handling. We do this in an attempt to keep this function
4739 * as fast and as clean as possible. */ 4496 * as fast and as clean as possible. */
4740 if (selinux_compat_net || !selinux_policycap_netpeer) 4497 if (!selinux_policycap_netpeer)
4741 return selinux_ip_postroute_compat(skb, ifindex, family); 4498 return selinux_ip_postroute_compat(skb, ifindex, family);
4742#ifdef CONFIG_XFRM 4499#ifdef CONFIG_XFRM
4743 /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec 4500 /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec
@@ -4844,7 +4601,7 @@ static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb)
4844{ 4601{
4845 int err; 4602 int err;
4846 4603
4847 err = secondary_ops->netlink_send(sk, skb); 4604 err = cap_netlink_send(sk, skb);
4848 if (err) 4605 if (err)
4849 return err; 4606 return err;
4850 4607
@@ -4859,7 +4616,7 @@ static int selinux_netlink_recv(struct sk_buff *skb, int capability)
4859 int err; 4616 int err;
4860 struct avc_audit_data ad; 4617 struct avc_audit_data ad;
4861 4618
4862 err = secondary_ops->netlink_recv(skb, capability); 4619 err = cap_netlink_recv(skb, capability);
4863 if (err) 4620 if (err)
4864 return err; 4621 return err;
4865 4622
@@ -5167,11 +4924,6 @@ static int selinux_shm_shmat(struct shmid_kernel *shp,
5167 char __user *shmaddr, int shmflg) 4924 char __user *shmaddr, int shmflg)
5168{ 4925{
5169 u32 perms; 4926 u32 perms;
5170 int rc;
5171
5172 rc = secondary_ops->shm_shmat(shp, shmaddr, shmflg);
5173 if (rc)
5174 return rc;
5175 4927
5176 if (shmflg & SHM_RDONLY) 4928 if (shmflg & SHM_RDONLY)
5177 perms = SHM__READ; 4929 perms = SHM__READ;
@@ -5581,7 +5333,6 @@ static struct security_operations selinux_ops = {
5581 .netlink_recv = selinux_netlink_recv, 5333 .netlink_recv = selinux_netlink_recv,
5582 5334
5583 .bprm_set_creds = selinux_bprm_set_creds, 5335 .bprm_set_creds = selinux_bprm_set_creds,
5584 .bprm_check_security = selinux_bprm_check_security,
5585 .bprm_committing_creds = selinux_bprm_committing_creds, 5336 .bprm_committing_creds = selinux_bprm_committing_creds,
5586 .bprm_committed_creds = selinux_bprm_committed_creds, 5337 .bprm_committed_creds = selinux_bprm_committed_creds,
5587 .bprm_secureexec = selinux_bprm_secureexec, 5338 .bprm_secureexec = selinux_bprm_secureexec,
@@ -5623,8 +5374,6 @@ static struct security_operations selinux_ops = {
5623 .inode_getsecurity = selinux_inode_getsecurity, 5374 .inode_getsecurity = selinux_inode_getsecurity,
5624 .inode_setsecurity = selinux_inode_setsecurity, 5375 .inode_setsecurity = selinux_inode_setsecurity,
5625 .inode_listsecurity = selinux_inode_listsecurity, 5376 .inode_listsecurity = selinux_inode_listsecurity,
5626 .inode_need_killpriv = selinux_inode_need_killpriv,
5627 .inode_killpriv = selinux_inode_killpriv,
5628 .inode_getsecid = selinux_inode_getsecid, 5377 .inode_getsecid = selinux_inode_getsecid,
5629 5378
5630 .file_permission = selinux_file_permission, 5379 .file_permission = selinux_file_permission,
@@ -5644,17 +5393,12 @@ static struct security_operations selinux_ops = {
5644 .task_create = selinux_task_create, 5393 .task_create = selinux_task_create,
5645 .cred_free = selinux_cred_free, 5394 .cred_free = selinux_cred_free,
5646 .cred_prepare = selinux_cred_prepare, 5395 .cred_prepare = selinux_cred_prepare,
5647 .cred_commit = selinux_cred_commit,
5648 .kernel_act_as = selinux_kernel_act_as, 5396 .kernel_act_as = selinux_kernel_act_as,
5649 .kernel_create_files_as = selinux_kernel_create_files_as, 5397 .kernel_create_files_as = selinux_kernel_create_files_as,
5650 .task_setuid = selinux_task_setuid,
5651 .task_fix_setuid = selinux_task_fix_setuid,
5652 .task_setgid = selinux_task_setgid,
5653 .task_setpgid = selinux_task_setpgid, 5398 .task_setpgid = selinux_task_setpgid,
5654 .task_getpgid = selinux_task_getpgid, 5399 .task_getpgid = selinux_task_getpgid,
5655 .task_getsid = selinux_task_getsid, 5400 .task_getsid = selinux_task_getsid,
5656 .task_getsecid = selinux_task_getsecid, 5401 .task_getsecid = selinux_task_getsecid,
5657 .task_setgroups = selinux_task_setgroups,
5658 .task_setnice = selinux_task_setnice, 5402 .task_setnice = selinux_task_setnice,
5659 .task_setioprio = selinux_task_setioprio, 5403 .task_setioprio = selinux_task_setioprio,
5660 .task_getioprio = selinux_task_getioprio, 5404 .task_getioprio = selinux_task_getioprio,
@@ -5664,7 +5408,6 @@ static struct security_operations selinux_ops = {
5664 .task_movememory = selinux_task_movememory, 5408 .task_movememory = selinux_task_movememory,
5665 .task_kill = selinux_task_kill, 5409 .task_kill = selinux_task_kill,
5666 .task_wait = selinux_task_wait, 5410 .task_wait = selinux_task_wait,
5667 .task_prctl = selinux_task_prctl,
5668 .task_to_inode = selinux_task_to_inode, 5411 .task_to_inode = selinux_task_to_inode,
5669 5412
5670 .ipc_permission = selinux_ipc_permission, 5413 .ipc_permission = selinux_ipc_permission,
diff --git a/security/selinux/include/av_perm_to_string.h b/security/selinux/include/av_perm_to_string.h
index c0c885427b91..31df1d7c1aee 100644
--- a/security/selinux/include/av_perm_to_string.h
+++ b/security/selinux/include/av_perm_to_string.h
@@ -24,6 +24,7 @@
24 S_(SECCLASS_CHR_FILE, CHR_FILE__EXECMOD, "execmod") 24 S_(SECCLASS_CHR_FILE, CHR_FILE__EXECMOD, "execmod")
25 S_(SECCLASS_CHR_FILE, CHR_FILE__OPEN, "open") 25 S_(SECCLASS_CHR_FILE, CHR_FILE__OPEN, "open")
26 S_(SECCLASS_BLK_FILE, BLK_FILE__OPEN, "open") 26 S_(SECCLASS_BLK_FILE, BLK_FILE__OPEN, "open")
27 S_(SECCLASS_SOCK_FILE, SOCK_FILE__OPEN, "open")
27 S_(SECCLASS_FIFO_FILE, FIFO_FILE__OPEN, "open") 28 S_(SECCLASS_FIFO_FILE, FIFO_FILE__OPEN, "open")
28 S_(SECCLASS_FD, FD__USE, "use") 29 S_(SECCLASS_FD, FD__USE, "use")
29 S_(SECCLASS_TCP_SOCKET, TCP_SOCKET__CONNECTTO, "connectto") 30 S_(SECCLASS_TCP_SOCKET, TCP_SOCKET__CONNECTTO, "connectto")
@@ -152,6 +153,7 @@
152 S_(SECCLASS_NETLINK_AUDIT_SOCKET, NETLINK_AUDIT_SOCKET__NLMSG_WRITE, "nlmsg_write") 153 S_(SECCLASS_NETLINK_AUDIT_SOCKET, NETLINK_AUDIT_SOCKET__NLMSG_WRITE, "nlmsg_write")
153 S_(SECCLASS_NETLINK_AUDIT_SOCKET, NETLINK_AUDIT_SOCKET__NLMSG_RELAY, "nlmsg_relay") 154 S_(SECCLASS_NETLINK_AUDIT_SOCKET, NETLINK_AUDIT_SOCKET__NLMSG_RELAY, "nlmsg_relay")
154 S_(SECCLASS_NETLINK_AUDIT_SOCKET, NETLINK_AUDIT_SOCKET__NLMSG_READPRIV, "nlmsg_readpriv") 155 S_(SECCLASS_NETLINK_AUDIT_SOCKET, NETLINK_AUDIT_SOCKET__NLMSG_READPRIV, "nlmsg_readpriv")
156 S_(SECCLASS_NETLINK_AUDIT_SOCKET, NETLINK_AUDIT_SOCKET__NLMSG_TTY_AUDIT, "nlmsg_tty_audit")
155 S_(SECCLASS_NETLINK_IP6FW_SOCKET, NETLINK_IP6FW_SOCKET__NLMSG_READ, "nlmsg_read") 157 S_(SECCLASS_NETLINK_IP6FW_SOCKET, NETLINK_IP6FW_SOCKET__NLMSG_READ, "nlmsg_read")
156 S_(SECCLASS_NETLINK_IP6FW_SOCKET, NETLINK_IP6FW_SOCKET__NLMSG_WRITE, "nlmsg_write") 158 S_(SECCLASS_NETLINK_IP6FW_SOCKET, NETLINK_IP6FW_SOCKET__NLMSG_WRITE, "nlmsg_write")
157 S_(SECCLASS_ASSOCIATION, ASSOCIATION__SENDTO, "sendto") 159 S_(SECCLASS_ASSOCIATION, ASSOCIATION__SENDTO, "sendto")
diff --git a/security/selinux/include/av_permissions.h b/security/selinux/include/av_permissions.h
index 0ba79fe00e11..d645192ee950 100644
--- a/security/selinux/include/av_permissions.h
+++ b/security/selinux/include/av_permissions.h
@@ -174,6 +174,7 @@
174#define SOCK_FILE__SWAPON 0x00004000UL 174#define SOCK_FILE__SWAPON 0x00004000UL
175#define SOCK_FILE__QUOTAON 0x00008000UL 175#define SOCK_FILE__QUOTAON 0x00008000UL
176#define SOCK_FILE__MOUNTON 0x00010000UL 176#define SOCK_FILE__MOUNTON 0x00010000UL
177#define SOCK_FILE__OPEN 0x00020000UL
177#define FIFO_FILE__IOCTL 0x00000001UL 178#define FIFO_FILE__IOCTL 0x00000001UL
178#define FIFO_FILE__READ 0x00000002UL 179#define FIFO_FILE__READ 0x00000002UL
179#define FIFO_FILE__WRITE 0x00000004UL 180#define FIFO_FILE__WRITE 0x00000004UL
@@ -707,6 +708,7 @@
707#define NETLINK_AUDIT_SOCKET__NLMSG_WRITE 0x00800000UL 708#define NETLINK_AUDIT_SOCKET__NLMSG_WRITE 0x00800000UL
708#define NETLINK_AUDIT_SOCKET__NLMSG_RELAY 0x01000000UL 709#define NETLINK_AUDIT_SOCKET__NLMSG_RELAY 0x01000000UL
709#define NETLINK_AUDIT_SOCKET__NLMSG_READPRIV 0x02000000UL 710#define NETLINK_AUDIT_SOCKET__NLMSG_READPRIV 0x02000000UL
711#define NETLINK_AUDIT_SOCKET__NLMSG_TTY_AUDIT 0x04000000UL
710#define NETLINK_IP6FW_SOCKET__IOCTL 0x00000001UL 712#define NETLINK_IP6FW_SOCKET__IOCTL 0x00000001UL
711#define NETLINK_IP6FW_SOCKET__READ 0x00000002UL 713#define NETLINK_IP6FW_SOCKET__READ 0x00000002UL
712#define NETLINK_IP6FW_SOCKET__WRITE 0x00000004UL 714#define NETLINK_IP6FW_SOCKET__WRITE 0x00000004UL
diff --git a/security/selinux/include/netlabel.h b/security/selinux/include/netlabel.h
index b913c8d06038..b4b5b9b2f0be 100644
--- a/security/selinux/include/netlabel.h
+++ b/security/selinux/include/netlabel.h
@@ -32,6 +32,7 @@
32#include <linux/net.h> 32#include <linux/net.h>
33#include <linux/skbuff.h> 33#include <linux/skbuff.h>
34#include <net/sock.h> 34#include <net/sock.h>
35#include <net/request_sock.h>
35 36
36#include "avc.h" 37#include "avc.h"
37#include "objsec.h" 38#include "objsec.h"
@@ -42,8 +43,7 @@ void selinux_netlbl_cache_invalidate(void);
42void selinux_netlbl_err(struct sk_buff *skb, int error, int gateway); 43void selinux_netlbl_err(struct sk_buff *skb, int error, int gateway);
43 44
44void selinux_netlbl_sk_security_free(struct sk_security_struct *ssec); 45void selinux_netlbl_sk_security_free(struct sk_security_struct *ssec);
45void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec, 46void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec);
46 int family);
47 47
48int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, 48int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
49 u16 family, 49 u16 family,
@@ -53,9 +53,9 @@ int selinux_netlbl_skbuff_setsid(struct sk_buff *skb,
53 u16 family, 53 u16 family,
54 u32 sid); 54 u32 sid);
55 55
56void selinux_netlbl_inet_conn_established(struct sock *sk, u16 family); 56int selinux_netlbl_inet_conn_request(struct request_sock *req, u16 family);
57int selinux_netlbl_socket_post_create(struct socket *sock); 57void selinux_netlbl_inet_csk_clone(struct sock *sk, u16 family);
58int selinux_netlbl_inode_permission(struct inode *inode, int mask); 58int selinux_netlbl_socket_post_create(struct sock *sk, u16 family);
59int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, 59int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
60 struct sk_buff *skb, 60 struct sk_buff *skb,
61 u16 family, 61 u16 family,
@@ -85,8 +85,7 @@ static inline void selinux_netlbl_sk_security_free(
85} 85}
86 86
87static inline void selinux_netlbl_sk_security_reset( 87static inline void selinux_netlbl_sk_security_reset(
88 struct sk_security_struct *ssec, 88 struct sk_security_struct *ssec)
89 int family)
90{ 89{
91 return; 90 return;
92} 91}
@@ -113,17 +112,17 @@ static inline int selinux_netlbl_conn_setsid(struct sock *sk,
113 return 0; 112 return 0;
114} 113}
115 114
116static inline void selinux_netlbl_inet_conn_established(struct sock *sk, 115static inline int selinux_netlbl_inet_conn_request(struct request_sock *req,
117 u16 family) 116 u16 family)
118{ 117{
119 return; 118 return 0;
120} 119}
121static inline int selinux_netlbl_socket_post_create(struct socket *sock) 120static inline void selinux_netlbl_inet_csk_clone(struct sock *sk, u16 family)
122{ 121{
123 return 0; 122 return;
124} 123}
125static inline int selinux_netlbl_inode_permission(struct inode *inode, 124static inline int selinux_netlbl_socket_post_create(struct sock *sk,
126 int mask) 125 u16 family)
127{ 126{
128 return 0; 127 return 0;
129} 128}
diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h
index 3cc45168f674..c4e062336ef3 100644
--- a/security/selinux/include/objsec.h
+++ b/security/selinux/include/objsec.h
@@ -60,9 +60,7 @@ struct superblock_security_struct {
60 u32 def_sid; /* default SID for labeling */ 60 u32 def_sid; /* default SID for labeling */
61 u32 mntpoint_sid; /* SECURITY_FS_USE_MNTPOINT context for files */ 61 u32 mntpoint_sid; /* SECURITY_FS_USE_MNTPOINT context for files */
62 unsigned int behavior; /* labeling behavior */ 62 unsigned int behavior; /* labeling behavior */
63 unsigned char initialized; /* initialization flag */
64 unsigned char flags; /* which mount options were specified */ 63 unsigned char flags; /* which mount options were specified */
65 unsigned char proc; /* proc fs */
66 struct mutex lock; 64 struct mutex lock;
67 struct list_head isec_head; 65 struct list_head isec_head;
68 spinlock_t isec_lock; 66 spinlock_t isec_lock;
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
index 72447370bc95..5c3434f7626f 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -37,15 +37,23 @@
37#define POLICYDB_VERSION_MAX POLICYDB_VERSION_BOUNDARY 37#define POLICYDB_VERSION_MAX POLICYDB_VERSION_BOUNDARY
38#endif 38#endif
39 39
40/* Mask for just the mount related flags */
41#define SE_MNTMASK 0x0f
42/* Super block security struct flags for mount options */
40#define CONTEXT_MNT 0x01 43#define CONTEXT_MNT 0x01
41#define FSCONTEXT_MNT 0x02 44#define FSCONTEXT_MNT 0x02
42#define ROOTCONTEXT_MNT 0x04 45#define ROOTCONTEXT_MNT 0x04
43#define DEFCONTEXT_MNT 0x08 46#define DEFCONTEXT_MNT 0x08
47/* Non-mount related flags */
48#define SE_SBINITIALIZED 0x10
49#define SE_SBPROC 0x20
50#define SE_SBLABELSUPP 0x40
44 51
45#define CONTEXT_STR "context=" 52#define CONTEXT_STR "context="
46#define FSCONTEXT_STR "fscontext=" 53#define FSCONTEXT_STR "fscontext="
47#define ROOTCONTEXT_STR "rootcontext=" 54#define ROOTCONTEXT_STR "rootcontext="
48#define DEFCONTEXT_STR "defcontext=" 55#define DEFCONTEXT_STR "defcontext="
56#define LABELSUPP_STR "seclabel"
49 57
50struct netlbl_lsm_secattr; 58struct netlbl_lsm_secattr;
51 59
@@ -80,7 +88,6 @@ int security_policycap_supported(unsigned int req_cap);
80#define SEL_VEC_MAX 32 88#define SEL_VEC_MAX 32
81struct av_decision { 89struct av_decision {
82 u32 allowed; 90 u32 allowed;
83 u32 decided;
84 u32 auditallow; 91 u32 auditallow;
85 u32 auditdeny; 92 u32 auditdeny;
86 u32 seqno; 93 u32 seqno;
diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c
index 350794ab9b42..2e984413c7b2 100644
--- a/security/selinux/netlabel.c
+++ b/security/selinux/netlabel.c
@@ -100,41 +100,6 @@ static struct netlbl_lsm_secattr *selinux_netlbl_sock_genattr(struct sock *sk)
100} 100}
101 101
102/** 102/**
103 * selinux_netlbl_sock_setsid - Label a socket using the NetLabel mechanism
104 * @sk: the socket to label
105 *
106 * Description:
107 * Attempt to label a socket using the NetLabel mechanism. Returns zero values
108 * on success, negative values on failure.
109 *
110 */
111static int selinux_netlbl_sock_setsid(struct sock *sk)
112{
113 int rc;
114 struct sk_security_struct *sksec = sk->sk_security;
115 struct netlbl_lsm_secattr *secattr;
116
117 if (sksec->nlbl_state != NLBL_REQUIRE)
118 return 0;
119
120 secattr = selinux_netlbl_sock_genattr(sk);
121 if (secattr == NULL)
122 return -ENOMEM;
123 rc = netlbl_sock_setattr(sk, secattr);
124 switch (rc) {
125 case 0:
126 sksec->nlbl_state = NLBL_LABELED;
127 break;
128 case -EDESTADDRREQ:
129 sksec->nlbl_state = NLBL_REQSKB;
130 rc = 0;
131 break;
132 }
133
134 return rc;
135}
136
137/**
138 * selinux_netlbl_cache_invalidate - Invalidate the NetLabel cache 103 * selinux_netlbl_cache_invalidate - Invalidate the NetLabel cache
139 * 104 *
140 * Description: 105 * Description:
@@ -188,13 +153,9 @@ void selinux_netlbl_sk_security_free(struct sk_security_struct *ssec)
188 * The caller is responsibile for all the NetLabel sk_security_struct locking. 153 * The caller is responsibile for all the NetLabel sk_security_struct locking.
189 * 154 *
190 */ 155 */
191void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec, 156void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec)
192 int family)
193{ 157{
194 if (family == PF_INET) 158 ssec->nlbl_state = NLBL_UNSET;
195 ssec->nlbl_state = NLBL_REQUIRE;
196 else
197 ssec->nlbl_state = NLBL_UNSET;
198} 159}
199 160
200/** 161/**
@@ -281,127 +242,86 @@ skbuff_setsid_return:
281} 242}
282 243
283/** 244/**
284 * selinux_netlbl_inet_conn_established - Netlabel the newly accepted connection 245 * selinux_netlbl_inet_conn_request - Label an incoming stream connection
285 * @sk: the new connection 246 * @req: incoming connection request socket
286 * 247 *
287 * Description: 248 * Description:
288 * A new connection has been established on @sk so make sure it is labeled 249 * A new incoming connection request is represented by @req, we need to label
289 * correctly with the NetLabel susbsystem. 250 * the new request_sock here and the stack will ensure the on-the-wire label
251 * will get preserved when a full sock is created once the connection handshake
252 * is complete. Returns zero on success, negative values on failure.
290 * 253 *
291 */ 254 */
292void selinux_netlbl_inet_conn_established(struct sock *sk, u16 family) 255int selinux_netlbl_inet_conn_request(struct request_sock *req, u16 family)
293{ 256{
294 int rc; 257 int rc;
295 struct sk_security_struct *sksec = sk->sk_security; 258 struct netlbl_lsm_secattr secattr;
296 struct netlbl_lsm_secattr *secattr;
297 struct inet_sock *sk_inet = inet_sk(sk);
298 struct sockaddr_in addr;
299
300 if (sksec->nlbl_state != NLBL_REQUIRE)
301 return;
302 259
303 secattr = selinux_netlbl_sock_genattr(sk); 260 if (family != PF_INET)
304 if (secattr == NULL) 261 return 0;
305 return;
306 262
307 rc = netlbl_sock_setattr(sk, secattr); 263 netlbl_secattr_init(&secattr);
308 switch (rc) { 264 rc = security_netlbl_sid_to_secattr(req->secid, &secattr);
309 case 0: 265 if (rc != 0)
310 sksec->nlbl_state = NLBL_LABELED; 266 goto inet_conn_request_return;
311 break; 267 rc = netlbl_req_setattr(req, &secattr);
312 case -EDESTADDRREQ: 268inet_conn_request_return:
313 /* no PF_INET6 support yet because we don't support any IPv6 269 netlbl_secattr_destroy(&secattr);
314 * labeling protocols */ 270 return rc;
315 if (family != PF_INET) {
316 sksec->nlbl_state = NLBL_UNSET;
317 return;
318 }
319
320 addr.sin_family = family;
321 addr.sin_addr.s_addr = sk_inet->daddr;
322 if (netlbl_conn_setattr(sk, (struct sockaddr *)&addr,
323 secattr) != 0) {
324 /* we failed to label the connected socket (could be
325 * for a variety of reasons, the actual "why" isn't
326 * important here) so we have to go to our backup plan,
327 * labeling the packets individually in the netfilter
328 * local output hook. this is okay but we need to
329 * adjust the MSS of the connection to take into
330 * account any labeling overhead, since we don't know
331 * the exact overhead at this point we'll use the worst
332 * case value which is 40 bytes for IPv4 */
333 struct inet_connection_sock *sk_conn = inet_csk(sk);
334 sk_conn->icsk_ext_hdr_len += 40 -
335 (sk_inet->opt ? sk_inet->opt->optlen : 0);
336 sk_conn->icsk_sync_mss(sk, sk_conn->icsk_pmtu_cookie);
337
338 sksec->nlbl_state = NLBL_REQSKB;
339 } else
340 sksec->nlbl_state = NLBL_CONNLABELED;
341 break;
342 default:
343 /* note that we are failing to label the socket which could be
344 * a bad thing since it means traffic could leave the system
345 * without the desired labeling, however, all is not lost as
346 * we have a check in selinux_netlbl_inode_permission() to
347 * pick up the pieces that we might drop here because we can't
348 * return an error code */
349 break;
350 }
351} 271}
352 272
353/** 273/**
354 * selinux_netlbl_socket_post_create - Label a socket using NetLabel 274 * selinux_netlbl_inet_csk_clone - Initialize the newly created sock
355 * @sock: the socket to label 275 * @sk: the new sock
356 * 276 *
357 * Description: 277 * Description:
358 * Attempt to label a socket using the NetLabel mechanism using the given 278 * A new connection has been established using @sk, we've already labeled the
359 * SID. Returns zero values on success, negative values on failure. 279 * socket via the request_sock struct in selinux_netlbl_inet_conn_request() but
280 * we need to set the NetLabel state here since we now have a sock structure.
360 * 281 *
361 */ 282 */
362int selinux_netlbl_socket_post_create(struct socket *sock) 283void selinux_netlbl_inet_csk_clone(struct sock *sk, u16 family)
363{ 284{
364 return selinux_netlbl_sock_setsid(sock->sk); 285 struct sk_security_struct *sksec = sk->sk_security;
286
287 if (family == PF_INET)
288 sksec->nlbl_state = NLBL_LABELED;
289 else
290 sksec->nlbl_state = NLBL_UNSET;
365} 291}
366 292
367/** 293/**
368 * selinux_netlbl_inode_permission - Verify the socket is NetLabel labeled 294 * selinux_netlbl_socket_post_create - Label a socket using NetLabel
369 * @inode: the file descriptor's inode 295 * @sock: the socket to label
370 * @mask: the permission mask 296 * @family: protocol family
371 * 297 *
372 * Description: 298 * Description:
373 * Looks at a file's inode and if it is marked as a socket protected by 299 * Attempt to label a socket using the NetLabel mechanism using the given
374 * NetLabel then verify that the socket has been labeled, if not try to label 300 * SID. Returns zero values on success, negative values on failure.
375 * the socket now with the inode's SID. Returns zero on success, negative
376 * values on failure.
377 * 301 *
378 */ 302 */
379int selinux_netlbl_inode_permission(struct inode *inode, int mask) 303int selinux_netlbl_socket_post_create(struct sock *sk, u16 family)
380{ 304{
381 int rc; 305 int rc;
382 struct sock *sk; 306 struct sk_security_struct *sksec = sk->sk_security;
383 struct socket *sock; 307 struct netlbl_lsm_secattr *secattr;
384 struct sk_security_struct *sksec;
385 308
386 if (!S_ISSOCK(inode->i_mode) || 309 if (family != PF_INET)
387 ((mask & (MAY_WRITE | MAY_APPEND)) == 0))
388 return 0;
389 sock = SOCKET_I(inode);
390 sk = sock->sk;
391 if (sk == NULL)
392 return 0;
393 sksec = sk->sk_security;
394 if (sksec == NULL || sksec->nlbl_state != NLBL_REQUIRE)
395 return 0; 310 return 0;
396 311
397 local_bh_disable(); 312 secattr = selinux_netlbl_sock_genattr(sk);
398 bh_lock_sock_nested(sk); 313 if (secattr == NULL)
399 if (likely(sksec->nlbl_state == NLBL_REQUIRE)) 314 return -ENOMEM;
400 rc = selinux_netlbl_sock_setsid(sk); 315 rc = netlbl_sock_setattr(sk, family, secattr);
401 else 316 switch (rc) {
317 case 0:
318 sksec->nlbl_state = NLBL_LABELED;
319 break;
320 case -EDESTADDRREQ:
321 sksec->nlbl_state = NLBL_REQSKB;
402 rc = 0; 322 rc = 0;
403 bh_unlock_sock(sk); 323 break;
404 local_bh_enable(); 324 }
405 325
406 return rc; 326 return rc;
407} 327}
diff --git a/security/selinux/nlmsgtab.c b/security/selinux/nlmsgtab.c
index 4ed7bab89c59..c6875fd3b9d6 100644
--- a/security/selinux/nlmsgtab.c
+++ b/security/selinux/nlmsgtab.c
@@ -113,7 +113,7 @@ static struct nlmsg_perm nlmsg_audit_perms[] =
113 { AUDIT_USER, NETLINK_AUDIT_SOCKET__NLMSG_RELAY }, 113 { AUDIT_USER, NETLINK_AUDIT_SOCKET__NLMSG_RELAY },
114 { AUDIT_SIGNAL_INFO, NETLINK_AUDIT_SOCKET__NLMSG_READ }, 114 { AUDIT_SIGNAL_INFO, NETLINK_AUDIT_SOCKET__NLMSG_READ },
115 { AUDIT_TTY_GET, NETLINK_AUDIT_SOCKET__NLMSG_READ }, 115 { AUDIT_TTY_GET, NETLINK_AUDIT_SOCKET__NLMSG_READ },
116 { AUDIT_TTY_SET, NETLINK_AUDIT_SOCKET__NLMSG_WRITE }, 116 { AUDIT_TTY_SET, NETLINK_AUDIT_SOCKET__NLMSG_TTY_AUDIT },
117}; 117};
118 118
119 119
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index 01ec6d2c6b97..2d5136ec3d54 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -47,8 +47,6 @@ static char *policycap_names[] = {
47 47
48unsigned int selinux_checkreqprot = CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE; 48unsigned int selinux_checkreqprot = CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE;
49 49
50int selinux_compat_net = 0;
51
52static int __init checkreqprot_setup(char *str) 50static int __init checkreqprot_setup(char *str)
53{ 51{
54 unsigned long checkreqprot; 52 unsigned long checkreqprot;
@@ -58,16 +56,6 @@ static int __init checkreqprot_setup(char *str)
58} 56}
59__setup("checkreqprot=", checkreqprot_setup); 57__setup("checkreqprot=", checkreqprot_setup);
60 58
61static int __init selinux_compat_net_setup(char *str)
62{
63 unsigned long compat_net;
64 if (!strict_strtoul(str, 0, &compat_net))
65 selinux_compat_net = compat_net ? 1 : 0;
66 return 1;
67}
68__setup("selinux_compat_net=", selinux_compat_net_setup);
69
70
71static DEFINE_MUTEX(sel_mutex); 59static DEFINE_MUTEX(sel_mutex);
72 60
73/* global data for booleans */ 61/* global data for booleans */
@@ -450,61 +438,6 @@ static const struct file_operations sel_checkreqprot_ops = {
450 .write = sel_write_checkreqprot, 438 .write = sel_write_checkreqprot,
451}; 439};
452 440
453static ssize_t sel_read_compat_net(struct file *filp, char __user *buf,
454 size_t count, loff_t *ppos)
455{
456 char tmpbuf[TMPBUFLEN];
457 ssize_t length;
458
459 length = scnprintf(tmpbuf, TMPBUFLEN, "%d", selinux_compat_net);
460 return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
461}
462
463static ssize_t sel_write_compat_net(struct file *file, const char __user *buf,
464 size_t count, loff_t *ppos)
465{
466 char *page;
467 ssize_t length;
468 int new_value;
469
470 length = task_has_security(current, SECURITY__LOAD_POLICY);
471 if (length)
472 return length;
473
474 if (count >= PAGE_SIZE)
475 return -ENOMEM;
476 if (*ppos != 0) {
477 /* No partial writes. */
478 return -EINVAL;
479 }
480 page = (char *)get_zeroed_page(GFP_KERNEL);
481 if (!page)
482 return -ENOMEM;
483 length = -EFAULT;
484 if (copy_from_user(page, buf, count))
485 goto out;
486
487 length = -EINVAL;
488 if (sscanf(page, "%d", &new_value) != 1)
489 goto out;
490
491 if (new_value) {
492 printk(KERN_NOTICE
493 "SELinux: compat_net is deprecated, please use secmark"
494 " instead\n");
495 selinux_compat_net = 1;
496 } else
497 selinux_compat_net = 0;
498 length = count;
499out:
500 free_page((unsigned long) page);
501 return length;
502}
503static const struct file_operations sel_compat_net_ops = {
504 .read = sel_read_compat_net,
505 .write = sel_write_compat_net,
506};
507
508/* 441/*
509 * Remaining nodes use transaction based IO methods like nfsd/nfsctl.c 442 * Remaining nodes use transaction based IO methods like nfsd/nfsctl.c
510 */ 443 */
@@ -595,7 +528,7 @@ static ssize_t sel_write_access(struct file *file, char *buf, size_t size)
595 528
596 length = scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, 529 length = scnprintf(buf, SIMPLE_TRANSACTION_LIMIT,
597 "%x %x %x %x %u", 530 "%x %x %x %x %u",
598 avd.allowed, avd.decided, 531 avd.allowed, 0xffffffff,
599 avd.auditallow, avd.auditdeny, 532 avd.auditallow, avd.auditdeny,
600 avd.seqno); 533 avd.seqno);
601out2: 534out2:
@@ -1665,7 +1598,6 @@ static int sel_fill_super(struct super_block *sb, void *data, int silent)
1665 [SEL_DISABLE] = {"disable", &sel_disable_ops, S_IWUSR}, 1598 [SEL_DISABLE] = {"disable", &sel_disable_ops, S_IWUSR},
1666 [SEL_MEMBER] = {"member", &transaction_ops, S_IRUGO|S_IWUGO}, 1599 [SEL_MEMBER] = {"member", &transaction_ops, S_IRUGO|S_IWUGO},
1667 [SEL_CHECKREQPROT] = {"checkreqprot", &sel_checkreqprot_ops, S_IRUGO|S_IWUSR}, 1600 [SEL_CHECKREQPROT] = {"checkreqprot", &sel_checkreqprot_ops, S_IRUGO|S_IWUSR},
1668 [SEL_COMPAT_NET] = {"compat_net", &sel_compat_net_ops, S_IRUGO|S_IWUSR},
1669 [SEL_REJECT_UNKNOWN] = {"reject_unknown", &sel_handle_unknown_ops, S_IRUGO}, 1601 [SEL_REJECT_UNKNOWN] = {"reject_unknown", &sel_handle_unknown_ops, S_IRUGO},
1670 [SEL_DENY_UNKNOWN] = {"deny_unknown", &sel_handle_unknown_ops, S_IRUGO}, 1602 [SEL_DENY_UNKNOWN] = {"deny_unknown", &sel_handle_unknown_ops, S_IRUGO},
1671 /* last one */ {""} 1603 /* last one */ {""}
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index c65e4fe4a0f1..deeec6c013ae 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -407,7 +407,6 @@ static int context_struct_compute_av(struct context *scontext,
407 * Initialize the access vectors to the default values. 407 * Initialize the access vectors to the default values.
408 */ 408 */
409 avd->allowed = 0; 409 avd->allowed = 0;
410 avd->decided = 0xffffffff;
411 avd->auditallow = 0; 410 avd->auditallow = 0;
412 avd->auditdeny = 0xffffffff; 411 avd->auditdeny = 0xffffffff;
413 avd->seqno = latest_granting; 412 avd->seqno = latest_granting;
@@ -743,7 +742,6 @@ int security_compute_av(u32 ssid,
743 742
744 if (!ss_initialized) { 743 if (!ss_initialized) {
745 avd->allowed = 0xffffffff; 744 avd->allowed = 0xffffffff;
746 avd->decided = 0xffffffff;
747 avd->auditallow = 0; 745 avd->auditallow = 0;
748 avd->auditdeny = 0xffffffff; 746 avd->auditdeny = 0xffffffff;
749 avd->seqno = latest_granting; 747 avd->seqno = latest_granting;
diff --git a/security/smack/smack.h b/security/smack/smack.h
index b79582e4fbfd..42ef313f9856 100644
--- a/security/smack/smack.h
+++ b/security/smack/smack.h
@@ -18,6 +18,8 @@
18#include <linux/security.h> 18#include <linux/security.h>
19#include <linux/in.h> 19#include <linux/in.h>
20#include <net/netlabel.h> 20#include <net/netlabel.h>
21#include <linux/list.h>
22#include <linux/rculist.h>
21 23
22/* 24/*
23 * Why 23? CIPSO is constrained to 30, so a 32 byte buffer is 25 * Why 23? CIPSO is constrained to 30, so a 32 byte buffer is
@@ -40,7 +42,6 @@ struct superblock_smack {
40struct socket_smack { 42struct socket_smack {
41 char *smk_out; /* outbound label */ 43 char *smk_out; /* outbound label */
42 char *smk_in; /* inbound label */ 44 char *smk_in; /* inbound label */
43 int smk_labeled; /* label scheme */
44 char smk_packet[SMK_LABELLEN]; /* TCP peer label */ 45 char smk_packet[SMK_LABELLEN]; /* TCP peer label */
45}; 46};
46 47
@@ -59,17 +60,10 @@ struct inode_smack {
59 * A label access rule. 60 * A label access rule.
60 */ 61 */
61struct smack_rule { 62struct smack_rule {
62 char *smk_subject; 63 struct list_head list;
63 char *smk_object; 64 char *smk_subject;
64 int smk_access; 65 char *smk_object;
65}; 66 int smk_access;
66
67/*
68 * An entry in the table of permitted label accesses.
69 */
70struct smk_list_entry {
71 struct smk_list_entry *smk_next;
72 struct smack_rule smk_rule;
73}; 67};
74 68
75/* 69/*
@@ -85,7 +79,7 @@ struct smack_cipso {
85 * An entry in the table identifying hosts. 79 * An entry in the table identifying hosts.
86 */ 80 */
87struct smk_netlbladdr { 81struct smk_netlbladdr {
88 struct smk_netlbladdr *smk_next; 82 struct list_head list;
89 struct sockaddr_in smk_host; /* network address */ 83 struct sockaddr_in smk_host; /* network address */
90 struct in_addr smk_mask; /* network mask */ 84 struct in_addr smk_mask; /* network mask */
91 char *smk_label; /* label */ 85 char *smk_label; /* label */
@@ -113,7 +107,7 @@ struct smk_netlbladdr {
113 * the cipso direct mapping in used internally. 107 * the cipso direct mapping in used internally.
114 */ 108 */
115struct smack_known { 109struct smack_known {
116 struct smack_known *smk_next; 110 struct list_head list;
117 char smk_known[SMK_LABELLEN]; 111 char smk_known[SMK_LABELLEN];
118 u32 smk_secid; 112 u32 smk_secid;
119 struct smack_cipso *smk_cipso; 113 struct smack_cipso *smk_cipso;
@@ -138,6 +132,8 @@ struct smack_known {
138#define XATTR_NAME_SMACKIPIN XATTR_SECURITY_PREFIX XATTR_SMACK_IPIN 132#define XATTR_NAME_SMACKIPIN XATTR_SECURITY_PREFIX XATTR_SMACK_IPIN
139#define XATTR_NAME_SMACKIPOUT XATTR_SECURITY_PREFIX XATTR_SMACK_IPOUT 133#define XATTR_NAME_SMACKIPOUT XATTR_SECURITY_PREFIX XATTR_SMACK_IPOUT
140 134
135#define SMACK_CIPSO_OPTION "-CIPSO"
136
141/* 137/*
142 * How communications on this socket are treated. 138 * How communications on this socket are treated.
143 * Usually it's determined by the underlying netlabel code 139 * Usually it's determined by the underlying netlabel code
@@ -205,8 +201,8 @@ u32 smack_to_secid(const char *);
205extern int smack_cipso_direct; 201extern int smack_cipso_direct;
206extern char *smack_net_ambient; 202extern char *smack_net_ambient;
207extern char *smack_onlycap; 203extern char *smack_onlycap;
204extern const char *smack_cipso_option;
208 205
209extern struct smack_known *smack_known;
210extern struct smack_known smack_known_floor; 206extern struct smack_known smack_known_floor;
211extern struct smack_known smack_known_hat; 207extern struct smack_known smack_known_hat;
212extern struct smack_known smack_known_huh; 208extern struct smack_known smack_known_huh;
@@ -214,8 +210,10 @@ extern struct smack_known smack_known_invalid;
214extern struct smack_known smack_known_star; 210extern struct smack_known smack_known_star;
215extern struct smack_known smack_known_web; 211extern struct smack_known smack_known_web;
216 212
217extern struct smk_list_entry *smack_list; 213extern struct list_head smack_known_list;
218extern struct smk_netlbladdr *smack_netlbladdrs; 214extern struct list_head smack_rule_list;
215extern struct list_head smk_netlbladdr_list;
216
219extern struct security_operations smack_ops; 217extern struct security_operations smack_ops;
220 218
221/* 219/*
diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c
index 2e0b83e77ffe..ac0a2707f6d4 100644
--- a/security/smack/smack_access.c
+++ b/security/smack/smack_access.c
@@ -16,48 +16,42 @@
16#include "smack.h" 16#include "smack.h"
17 17
18struct smack_known smack_known_huh = { 18struct smack_known smack_known_huh = {
19 .smk_next = NULL,
20 .smk_known = "?", 19 .smk_known = "?",
21 .smk_secid = 2, 20 .smk_secid = 2,
22 .smk_cipso = NULL, 21 .smk_cipso = NULL,
23}; 22};
24 23
25struct smack_known smack_known_hat = { 24struct smack_known smack_known_hat = {
26 .smk_next = &smack_known_huh,
27 .smk_known = "^", 25 .smk_known = "^",
28 .smk_secid = 3, 26 .smk_secid = 3,
29 .smk_cipso = NULL, 27 .smk_cipso = NULL,
30}; 28};
31 29
32struct smack_known smack_known_star = { 30struct smack_known smack_known_star = {
33 .smk_next = &smack_known_hat,
34 .smk_known = "*", 31 .smk_known = "*",
35 .smk_secid = 4, 32 .smk_secid = 4,
36 .smk_cipso = NULL, 33 .smk_cipso = NULL,
37}; 34};
38 35
39struct smack_known smack_known_floor = { 36struct smack_known smack_known_floor = {
40 .smk_next = &smack_known_star,
41 .smk_known = "_", 37 .smk_known = "_",
42 .smk_secid = 5, 38 .smk_secid = 5,
43 .smk_cipso = NULL, 39 .smk_cipso = NULL,
44}; 40};
45 41
46struct smack_known smack_known_invalid = { 42struct smack_known smack_known_invalid = {
47 .smk_next = &smack_known_floor,
48 .smk_known = "", 43 .smk_known = "",
49 .smk_secid = 6, 44 .smk_secid = 6,
50 .smk_cipso = NULL, 45 .smk_cipso = NULL,
51}; 46};
52 47
53struct smack_known smack_known_web = { 48struct smack_known smack_known_web = {
54 .smk_next = &smack_known_invalid,
55 .smk_known = "@", 49 .smk_known = "@",
56 .smk_secid = 7, 50 .smk_secid = 7,
57 .smk_cipso = NULL, 51 .smk_cipso = NULL,
58}; 52};
59 53
60struct smack_known *smack_known = &smack_known_web; 54LIST_HEAD(smack_known_list);
61 55
62/* 56/*
63 * The initial value needs to be bigger than any of the 57 * The initial value needs to be bigger than any of the
@@ -87,7 +81,6 @@ static u32 smack_next_secid = 10;
87int smk_access(char *subject_label, char *object_label, int request) 81int smk_access(char *subject_label, char *object_label, int request)
88{ 82{
89 u32 may = MAY_NOT; 83 u32 may = MAY_NOT;
90 struct smk_list_entry *sp;
91 struct smack_rule *srp; 84 struct smack_rule *srp;
92 85
93 /* 86 /*
@@ -139,9 +132,8 @@ int smk_access(char *subject_label, char *object_label, int request)
139 * access (e.g. read is included in readwrite) it's 132 * access (e.g. read is included in readwrite) it's
140 * good. 133 * good.
141 */ 134 */
142 for (sp = smack_list; sp != NULL; sp = sp->smk_next) { 135 rcu_read_lock();
143 srp = &sp->smk_rule; 136 list_for_each_entry_rcu(srp, &smack_rule_list, list) {
144
145 if (srp->smk_subject == subject_label || 137 if (srp->smk_subject == subject_label ||
146 strcmp(srp->smk_subject, subject_label) == 0) { 138 strcmp(srp->smk_subject, subject_label) == 0) {
147 if (srp->smk_object == object_label || 139 if (srp->smk_object == object_label ||
@@ -151,6 +143,7 @@ int smk_access(char *subject_label, char *object_label, int request)
151 } 143 }
152 } 144 }
153 } 145 }
146 rcu_read_unlock();
154 /* 147 /*
155 * This is a bit map operation. 148 * This is a bit map operation.
156 */ 149 */
@@ -162,8 +155,8 @@ int smk_access(char *subject_label, char *object_label, int request)
162 155
163/** 156/**
164 * smk_curacc - determine if current has a specific access to an object 157 * smk_curacc - determine if current has a specific access to an object
165 * @object_label: a pointer to the object's Smack label 158 * @obj_label: a pointer to the object's Smack label
166 * @request: the access requested, in "MAY" format 159 * @mode: the access requested, in "MAY" format
167 * 160 *
168 * This function checks the current subject label/object label pair 161 * This function checks the current subject label/object label pair
169 * in the access rule list and returns 0 if the access is permitted, 162 * in the access rule list and returns 0 if the access is permitted,
@@ -228,14 +221,17 @@ struct smack_known *smk_import_entry(const char *string, int len)
228 221
229 mutex_lock(&smack_known_lock); 222 mutex_lock(&smack_known_lock);
230 223
231 for (skp = smack_known; skp != NULL; skp = skp->smk_next) 224 found = 0;
232 if (strncmp(skp->smk_known, smack, SMK_MAXLEN) == 0) 225 list_for_each_entry_rcu(skp, &smack_known_list, list) {
226 if (strncmp(skp->smk_known, smack, SMK_MAXLEN) == 0) {
227 found = 1;
233 break; 228 break;
229 }
230 }
234 231
235 if (skp == NULL) { 232 if (found == 0) {
236 skp = kzalloc(sizeof(struct smack_known), GFP_KERNEL); 233 skp = kzalloc(sizeof(struct smack_known), GFP_KERNEL);
237 if (skp != NULL) { 234 if (skp != NULL) {
238 skp->smk_next = smack_known;
239 strncpy(skp->smk_known, smack, SMK_MAXLEN); 235 strncpy(skp->smk_known, smack, SMK_MAXLEN);
240 skp->smk_secid = smack_next_secid++; 236 skp->smk_secid = smack_next_secid++;
241 skp->smk_cipso = NULL; 237 skp->smk_cipso = NULL;
@@ -244,8 +240,7 @@ struct smack_known *smk_import_entry(const char *string, int len)
244 * Make sure that the entry is actually 240 * Make sure that the entry is actually
245 * filled before putting it on the list. 241 * filled before putting it on the list.
246 */ 242 */
247 smp_mb(); 243 list_add_rcu(&skp->list, &smack_known_list);
248 smack_known = skp;
249 } 244 }
250 } 245 }
251 246
@@ -266,6 +261,9 @@ char *smk_import(const char *string, int len)
266{ 261{
267 struct smack_known *skp; 262 struct smack_known *skp;
268 263
264 /* labels cannot begin with a '-' */
265 if (string[0] == '-')
266 return NULL;
269 skp = smk_import_entry(string, len); 267 skp = smk_import_entry(string, len);
270 if (skp == NULL) 268 if (skp == NULL)
271 return NULL; 269 return NULL;
@@ -283,14 +281,19 @@ char *smack_from_secid(const u32 secid)
283{ 281{
284 struct smack_known *skp; 282 struct smack_known *skp;
285 283
286 for (skp = smack_known; skp != NULL; skp = skp->smk_next) 284 rcu_read_lock();
287 if (skp->smk_secid == secid) 285 list_for_each_entry_rcu(skp, &smack_known_list, list) {
286 if (skp->smk_secid == secid) {
287 rcu_read_unlock();
288 return skp->smk_known; 288 return skp->smk_known;
289 }
290 }
289 291
290 /* 292 /*
291 * If we got this far someone asked for the translation 293 * If we got this far someone asked for the translation
292 * of a secid that is not on the list. 294 * of a secid that is not on the list.
293 */ 295 */
296 rcu_read_unlock();
294 return smack_known_invalid.smk_known; 297 return smack_known_invalid.smk_known;
295} 298}
296 299
@@ -305,9 +308,14 @@ u32 smack_to_secid(const char *smack)
305{ 308{
306 struct smack_known *skp; 309 struct smack_known *skp;
307 310
308 for (skp = smack_known; skp != NULL; skp = skp->smk_next) 311 rcu_read_lock();
309 if (strncmp(skp->smk_known, smack, SMK_MAXLEN) == 0) 312 list_for_each_entry_rcu(skp, &smack_known_list, list) {
313 if (strncmp(skp->smk_known, smack, SMK_MAXLEN) == 0) {
314 rcu_read_unlock();
310 return skp->smk_secid; 315 return skp->smk_secid;
316 }
317 }
318 rcu_read_unlock();
311 return 0; 319 return 0;
312} 320}
313 321
@@ -332,7 +340,8 @@ void smack_from_cipso(u32 level, char *cp, char *result)
332 struct smack_known *kp; 340 struct smack_known *kp;
333 char *final = NULL; 341 char *final = NULL;
334 342
335 for (kp = smack_known; final == NULL && kp != NULL; kp = kp->smk_next) { 343 rcu_read_lock();
344 list_for_each_entry(kp, &smack_known_list, list) {
336 if (kp->smk_cipso == NULL) 345 if (kp->smk_cipso == NULL)
337 continue; 346 continue;
338 347
@@ -344,6 +353,7 @@ void smack_from_cipso(u32 level, char *cp, char *result)
344 353
345 spin_unlock_bh(&kp->smk_cipsolock); 354 spin_unlock_bh(&kp->smk_cipsolock);
346 } 355 }
356 rcu_read_unlock();
347 if (final == NULL) 357 if (final == NULL)
348 final = smack_known_huh.smk_known; 358 final = smack_known_huh.smk_known;
349 strncpy(result, final, SMK_MAXLEN); 359 strncpy(result, final, SMK_MAXLEN);
@@ -360,13 +370,19 @@ void smack_from_cipso(u32 level, char *cp, char *result)
360int smack_to_cipso(const char *smack, struct smack_cipso *cp) 370int smack_to_cipso(const char *smack, struct smack_cipso *cp)
361{ 371{
362 struct smack_known *kp; 372 struct smack_known *kp;
373 int found = 0;
363 374
364 for (kp = smack_known; kp != NULL; kp = kp->smk_next) 375 rcu_read_lock();
376 list_for_each_entry_rcu(kp, &smack_known_list, list) {
365 if (kp->smk_known == smack || 377 if (kp->smk_known == smack ||
366 strcmp(kp->smk_known, smack) == 0) 378 strcmp(kp->smk_known, smack) == 0) {
379 found = 1;
367 break; 380 break;
381 }
382 }
383 rcu_read_unlock();
368 384
369 if (kp == NULL || kp->smk_cipso == NULL) 385 if (found == 0 || kp->smk_cipso == NULL)
370 return -ENOENT; 386 return -ENOENT;
371 387
372 memcpy(cp, kp->smk_cipso, sizeof(struct smack_cipso)); 388 memcpy(cp, kp->smk_cipso, sizeof(struct smack_cipso));
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index e7ded1326b0f..921514902eca 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -7,6 +7,8 @@
7 * Casey Schaufler <casey@schaufler-ca.com> 7 * Casey Schaufler <casey@schaufler-ca.com>
8 * 8 *
9 * Copyright (C) 2007 Casey Schaufler <casey@schaufler-ca.com> 9 * Copyright (C) 2007 Casey Schaufler <casey@schaufler-ca.com>
10 * Copyright (C) 2009 Hewlett-Packard Development Company, L.P.
11 * Paul Moore <paul.moore@hp.com>
10 * 12 *
11 * This program is free software; you can redistribute it and/or modify 13 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2, 14 * it under the terms of the GNU General Public License version 2,
@@ -20,6 +22,7 @@
20#include <linux/ext2_fs.h> 22#include <linux/ext2_fs.h>
21#include <linux/kd.h> 23#include <linux/kd.h>
22#include <asm/ioctls.h> 24#include <asm/ioctls.h>
25#include <linux/ip.h>
23#include <linux/tcp.h> 26#include <linux/tcp.h>
24#include <linux/udp.h> 27#include <linux/udp.h>
25#include <linux/mutex.h> 28#include <linux/mutex.h>
@@ -91,6 +94,7 @@ struct inode_smack *new_inode_smack(char *smack)
91/** 94/**
92 * smack_ptrace_may_access - Smack approval on PTRACE_ATTACH 95 * smack_ptrace_may_access - Smack approval on PTRACE_ATTACH
93 * @ctp: child task pointer 96 * @ctp: child task pointer
97 * @mode: ptrace attachment mode
94 * 98 *
95 * Returns 0 if access is OK, an error code otherwise 99 * Returns 0 if access is OK, an error code otherwise
96 * 100 *
@@ -203,9 +207,8 @@ static void smack_sb_free_security(struct super_block *sb)
203 207
204/** 208/**
205 * smack_sb_copy_data - copy mount options data for processing 209 * smack_sb_copy_data - copy mount options data for processing
206 * @type: file system type
207 * @orig: where to start 210 * @orig: where to start
208 * @smackopts 211 * @smackopts: mount options string
209 * 212 *
210 * Returns 0 on success or -ENOMEM on error. 213 * Returns 0 on success or -ENOMEM on error.
211 * 214 *
@@ -331,7 +334,7 @@ static int smack_sb_statfs(struct dentry *dentry)
331/** 334/**
332 * smack_sb_mount - Smack check for mounting 335 * smack_sb_mount - Smack check for mounting
333 * @dev_name: unused 336 * @dev_name: unused
334 * @nd: mount point 337 * @path: mount point
335 * @type: unused 338 * @type: unused
336 * @flags: unused 339 * @flags: unused
337 * @data: unused 340 * @data: unused
@@ -370,7 +373,7 @@ static int smack_sb_umount(struct vfsmount *mnt, int flags)
370 373
371/** 374/**
372 * smack_inode_alloc_security - allocate an inode blob 375 * smack_inode_alloc_security - allocate an inode blob
373 * @inode - the inode in need of a blob 376 * @inode: the inode in need of a blob
374 * 377 *
375 * Returns 0 if it gets a blob, -ENOMEM otherwise 378 * Returns 0 if it gets a blob, -ENOMEM otherwise
376 */ 379 */
@@ -384,7 +387,7 @@ static int smack_inode_alloc_security(struct inode *inode)
384 387
385/** 388/**
386 * smack_inode_free_security - free an inode blob 389 * smack_inode_free_security - free an inode blob
387 * @inode - the inode with a blob 390 * @inode: the inode with a blob
388 * 391 *
389 * Clears the blob pointer in inode 392 * Clears the blob pointer in inode
390 */ 393 */
@@ -538,7 +541,6 @@ static int smack_inode_rename(struct inode *old_inode,
538 * smack_inode_permission - Smack version of permission() 541 * smack_inode_permission - Smack version of permission()
539 * @inode: the inode in question 542 * @inode: the inode in question
540 * @mask: the access requested 543 * @mask: the access requested
541 * @nd: unused
542 * 544 *
543 * This is the important Smack hook. 545 * This is the important Smack hook.
544 * 546 *
@@ -607,6 +609,9 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name,
607 strcmp(name, XATTR_NAME_SMACKIPOUT) == 0) { 609 strcmp(name, XATTR_NAME_SMACKIPOUT) == 0) {
608 if (!capable(CAP_MAC_ADMIN)) 610 if (!capable(CAP_MAC_ADMIN))
609 rc = -EPERM; 611 rc = -EPERM;
612 /* a label cannot be void and cannot begin with '-' */
613 if (size == 0 || (size > 0 && ((char *)value)[0] == '-'))
614 rc = -EINVAL;
610 } else 615 } else
611 rc = cap_inode_setxattr(dentry, name, value, size, flags); 616 rc = cap_inode_setxattr(dentry, name, value, size, flags);
612 617
@@ -701,8 +706,7 @@ static int smack_inode_removexattr(struct dentry *dentry, const char *name)
701 * @inode: the object 706 * @inode: the object
702 * @name: attribute name 707 * @name: attribute name
703 * @buffer: where to put the result 708 * @buffer: where to put the result
704 * @size: size of the buffer 709 * @alloc: unused
705 * @err: unused
706 * 710 *
707 * Returns the size of the attribute or an error code 711 * Returns the size of the attribute or an error code
708 */ 712 */
@@ -864,7 +868,7 @@ static int smack_file_ioctl(struct file *file, unsigned int cmd,
864/** 868/**
865 * smack_file_lock - Smack check on file locking 869 * smack_file_lock - Smack check on file locking
866 * @file: the object 870 * @file: the object
867 * @cmd unused 871 * @cmd: unused
868 * 872 *
869 * Returns 0 if current has write access, error code otherwise 873 * Returns 0 if current has write access, error code otherwise
870 */ 874 */
@@ -1003,8 +1007,8 @@ static int smack_cred_prepare(struct cred *new, const struct cred *old,
1003 return 0; 1007 return 0;
1004} 1008}
1005 1009
1006/* 1010/**
1007 * commit new credentials 1011 * smack_cred_commit - commit new credentials
1008 * @new: the new credentials 1012 * @new: the new credentials
1009 * @old: the original credentials 1013 * @old: the original credentials
1010 */ 1014 */
@@ -1014,8 +1018,8 @@ static void smack_cred_commit(struct cred *new, const struct cred *old)
1014 1018
1015/** 1019/**
1016 * smack_kernel_act_as - Set the subjective context in a set of credentials 1020 * smack_kernel_act_as - Set the subjective context in a set of credentials
1017 * @new points to the set of credentials to be modified. 1021 * @new: points to the set of credentials to be modified.
1018 * @secid specifies the security ID to be set 1022 * @secid: specifies the security ID to be set
1019 * 1023 *
1020 * Set the security data for a kernel service. 1024 * Set the security data for a kernel service.
1021 */ 1025 */
@@ -1032,8 +1036,8 @@ static int smack_kernel_act_as(struct cred *new, u32 secid)
1032 1036
1033/** 1037/**
1034 * smack_kernel_create_files_as - Set the file creation label in a set of creds 1038 * smack_kernel_create_files_as - Set the file creation label in a set of creds
1035 * @new points to the set of credentials to be modified 1039 * @new: points to the set of credentials to be modified
1036 * @inode points to the inode to use as a reference 1040 * @inode: points to the inode to use as a reference
1037 * 1041 *
1038 * Set the file creation context in a set of credentials to the same 1042 * Set the file creation context in a set of credentials to the same
1039 * as the objective context of the specified inode 1043 * as the objective context of the specified inode
@@ -1242,7 +1246,7 @@ static int smack_task_wait(struct task_struct *p)
1242/** 1246/**
1243 * smack_task_to_inode - copy task smack into the inode blob 1247 * smack_task_to_inode - copy task smack into the inode blob
1244 * @p: task to copy from 1248 * @p: task to copy from
1245 * inode: inode to copy to 1249 * @inode: inode to copy to
1246 * 1250 *
1247 * Sets the smack pointer in the inode security blob 1251 * Sets the smack pointer in the inode security blob
1248 */ 1252 */
@@ -1260,7 +1264,7 @@ static void smack_task_to_inode(struct task_struct *p, struct inode *inode)
1260 * smack_sk_alloc_security - Allocate a socket blob 1264 * smack_sk_alloc_security - Allocate a socket blob
1261 * @sk: the socket 1265 * @sk: the socket
1262 * @family: unused 1266 * @family: unused
1263 * @priority: memory allocation priority 1267 * @gfp_flags: memory allocation flags
1264 * 1268 *
1265 * Assign Smack pointers to current 1269 * Assign Smack pointers to current
1266 * 1270 *
@@ -1277,7 +1281,6 @@ static int smack_sk_alloc_security(struct sock *sk, int family, gfp_t gfp_flags)
1277 1281
1278 ssp->smk_in = csp; 1282 ssp->smk_in = csp;
1279 ssp->smk_out = csp; 1283 ssp->smk_out = csp;
1280 ssp->smk_labeled = SMACK_CIPSO_SOCKET;
1281 ssp->smk_packet[0] = '\0'; 1284 ssp->smk_packet[0] = '\0';
1282 1285
1283 sk->sk_security = ssp; 1286 sk->sk_security = ssp;
@@ -1297,6 +1300,43 @@ static void smack_sk_free_security(struct sock *sk)
1297} 1300}
1298 1301
1299/** 1302/**
1303* smack_host_label - check host based restrictions
1304* @sip: the object end
1305*
1306* looks for host based access restrictions
1307*
1308* This version will only be appropriate for really small sets of single label
1309* hosts. The caller is responsible for ensuring that the RCU read lock is
1310* taken before calling this function.
1311*
1312* Returns the label of the far end or NULL if it's not special.
1313*/
1314static char *smack_host_label(struct sockaddr_in *sip)
1315{
1316 struct smk_netlbladdr *snp;
1317 struct in_addr *siap = &sip->sin_addr;
1318
1319 if (siap->s_addr == 0)
1320 return NULL;
1321
1322 list_for_each_entry_rcu(snp, &smk_netlbladdr_list, list)
1323 /*
1324 * we break after finding the first match because
1325 * the list is sorted from longest to shortest mask
1326 * so we have found the most specific match
1327 */
1328 if ((&snp->smk_host.sin_addr)->s_addr ==
1329 (siap->s_addr & (&snp->smk_mask)->s_addr)) {
1330 /* we have found the special CIPSO option */
1331 if (snp->smk_label == smack_cipso_option)
1332 return NULL;
1333 return snp->smk_label;
1334 }
1335
1336 return NULL;
1337}
1338
1339/**
1300 * smack_set_catset - convert a capset to netlabel mls categories 1340 * smack_set_catset - convert a capset to netlabel mls categories
1301 * @catset: the Smack categories 1341 * @catset: the Smack categories
1302 * @sap: where to put the netlabel categories 1342 * @sap: where to put the netlabel categories
@@ -1367,11 +1407,10 @@ static void smack_to_secattr(char *smack, struct netlbl_lsm_secattr *nlsp)
1367 */ 1407 */
1368static int smack_netlabel(struct sock *sk, int labeled) 1408static int smack_netlabel(struct sock *sk, int labeled)
1369{ 1409{
1370 struct socket_smack *ssp; 1410 struct socket_smack *ssp = sk->sk_security;
1371 struct netlbl_lsm_secattr secattr; 1411 struct netlbl_lsm_secattr secattr;
1372 int rc = 0; 1412 int rc = 0;
1373 1413
1374 ssp = sk->sk_security;
1375 /* 1414 /*
1376 * Usually the netlabel code will handle changing the 1415 * Usually the netlabel code will handle changing the
1377 * packet labeling based on the label. 1416 * packet labeling based on the label.
@@ -1389,27 +1428,51 @@ static int smack_netlabel(struct sock *sk, int labeled)
1389 else { 1428 else {
1390 netlbl_secattr_init(&secattr); 1429 netlbl_secattr_init(&secattr);
1391 smack_to_secattr(ssp->smk_out, &secattr); 1430 smack_to_secattr(ssp->smk_out, &secattr);
1392 rc = netlbl_sock_setattr(sk, &secattr); 1431 rc = netlbl_sock_setattr(sk, sk->sk_family, &secattr);
1393 netlbl_secattr_destroy(&secattr); 1432 netlbl_secattr_destroy(&secattr);
1394 } 1433 }
1395 1434
1396 bh_unlock_sock(sk); 1435 bh_unlock_sock(sk);
1397 local_bh_enable(); 1436 local_bh_enable();
1398 /*
1399 * Remember the label scheme used so that it is not
1400 * necessary to do the netlabel setting if it has not
1401 * changed the next time through.
1402 *
1403 * The -EDESTADDRREQ case is an indication that there's
1404 * a single level host involved.
1405 */
1406 if (rc == 0)
1407 ssp->smk_labeled = labeled;
1408 1437
1409 return rc; 1438 return rc;
1410} 1439}
1411 1440
1412/** 1441/**
1442 * smack_netlbel_send - Set the secattr on a socket and perform access checks
1443 * @sk: the socket
1444 * @sap: the destination address
1445 *
1446 * Set the correct secattr for the given socket based on the destination
1447 * address and perform any outbound access checks needed.
1448 *
1449 * Returns 0 on success or an error code.
1450 *
1451 */
1452static int smack_netlabel_send(struct sock *sk, struct sockaddr_in *sap)
1453{
1454 int rc;
1455 int sk_lbl;
1456 char *hostsp;
1457 struct socket_smack *ssp = sk->sk_security;
1458
1459 rcu_read_lock();
1460 hostsp = smack_host_label(sap);
1461 if (hostsp != NULL) {
1462 sk_lbl = SMACK_UNLABELED_SOCKET;
1463 rc = smk_access(ssp->smk_out, hostsp, MAY_WRITE);
1464 } else {
1465 sk_lbl = SMACK_CIPSO_SOCKET;
1466 rc = 0;
1467 }
1468 rcu_read_unlock();
1469 if (rc != 0)
1470 return rc;
1471
1472 return smack_netlabel(sk, sk_lbl);
1473}
1474
1475/**
1413 * smack_inode_setsecurity - set smack xattrs 1476 * smack_inode_setsecurity - set smack xattrs
1414 * @inode: the object 1477 * @inode: the object
1415 * @name: attribute name 1478 * @name: attribute name
@@ -1430,7 +1493,7 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name,
1430 struct socket *sock; 1493 struct socket *sock;
1431 int rc = 0; 1494 int rc = 0;
1432 1495
1433 if (value == NULL || size > SMK_LABELLEN) 1496 if (value == NULL || size > SMK_LABELLEN || size == 0)
1434 return -EACCES; 1497 return -EACCES;
1435 1498
1436 sp = smk_import(value, size); 1499 sp = smk_import(value, size);
@@ -1490,41 +1553,6 @@ static int smack_socket_post_create(struct socket *sock, int family,
1490 return smack_netlabel(sock->sk, SMACK_CIPSO_SOCKET); 1553 return smack_netlabel(sock->sk, SMACK_CIPSO_SOCKET);
1491} 1554}
1492 1555
1493
1494/**
1495 * smack_host_label - check host based restrictions
1496 * @sip: the object end
1497 *
1498 * looks for host based access restrictions
1499 *
1500 * This version will only be appropriate for really small
1501 * sets of single label hosts.
1502 *
1503 * Returns the label of the far end or NULL if it's not special.
1504 */
1505static char *smack_host_label(struct sockaddr_in *sip)
1506{
1507 struct smk_netlbladdr *snp;
1508 struct in_addr *siap = &sip->sin_addr;
1509
1510 if (siap->s_addr == 0)
1511 return NULL;
1512
1513 for (snp = smack_netlbladdrs; snp != NULL; snp = snp->smk_next) {
1514 /*
1515 * we break after finding the first match because
1516 * the list is sorted from longest to shortest mask
1517 * so we have found the most specific match
1518 */
1519 if ((&snp->smk_host.sin_addr)->s_addr ==
1520 (siap->s_addr & (&snp->smk_mask)->s_addr)) {
1521 return snp->smk_label;
1522 }
1523 }
1524
1525 return NULL;
1526}
1527
1528/** 1556/**
1529 * smack_socket_connect - connect access check 1557 * smack_socket_connect - connect access check
1530 * @sock: the socket 1558 * @sock: the socket
@@ -1538,30 +1566,12 @@ static char *smack_host_label(struct sockaddr_in *sip)
1538static int smack_socket_connect(struct socket *sock, struct sockaddr *sap, 1566static int smack_socket_connect(struct socket *sock, struct sockaddr *sap,
1539 int addrlen) 1567 int addrlen)
1540{ 1568{
1541 struct socket_smack *ssp = sock->sk->sk_security;
1542 char *hostsp;
1543 int rc;
1544
1545 if (sock->sk == NULL || sock->sk->sk_family != PF_INET) 1569 if (sock->sk == NULL || sock->sk->sk_family != PF_INET)
1546 return 0; 1570 return 0;
1547
1548 if (addrlen < sizeof(struct sockaddr_in)) 1571 if (addrlen < sizeof(struct sockaddr_in))
1549 return -EINVAL; 1572 return -EINVAL;
1550 1573
1551 hostsp = smack_host_label((struct sockaddr_in *)sap); 1574 return smack_netlabel_send(sock->sk, (struct sockaddr_in *)sap);
1552 if (hostsp == NULL) {
1553 if (ssp->smk_labeled != SMACK_CIPSO_SOCKET)
1554 return smack_netlabel(sock->sk, SMACK_CIPSO_SOCKET);
1555 return 0;
1556 }
1557
1558 rc = smk_access(ssp->smk_out, hostsp, MAY_WRITE);
1559 if (rc != 0)
1560 return rc;
1561
1562 if (ssp->smk_labeled != SMACK_UNLABELED_SOCKET)
1563 return smack_netlabel(sock->sk, SMACK_UNLABELED_SOCKET);
1564 return 0;
1565} 1575}
1566 1576
1567/** 1577/**
@@ -1974,7 +1984,7 @@ static int smack_ipc_permission(struct kern_ipc_perm *ipp, short flag)
1974 1984
1975/** 1985/**
1976 * smack_ipc_getsecid - Extract smack security id 1986 * smack_ipc_getsecid - Extract smack security id
1977 * @ipcp: the object permissions 1987 * @ipp: the object permissions
1978 * @secid: where result will be saved 1988 * @secid: where result will be saved
1979 */ 1989 */
1980static void smack_ipc_getsecid(struct kern_ipc_perm *ipp, u32 *secid) 1990static void smack_ipc_getsecid(struct kern_ipc_perm *ipp, u32 *secid)
@@ -2251,7 +2261,7 @@ static int smack_unix_may_send(struct socket *sock, struct socket *other)
2251/** 2261/**
2252 * smack_socket_sendmsg - Smack check based on destination host 2262 * smack_socket_sendmsg - Smack check based on destination host
2253 * @sock: the socket 2263 * @sock: the socket
2254 * @msghdr: the message 2264 * @msg: the message
2255 * @size: the size of the message 2265 * @size: the size of the message
2256 * 2266 *
2257 * Return 0 if the current subject can write to the destination 2267 * Return 0 if the current subject can write to the destination
@@ -2262,9 +2272,6 @@ static int smack_socket_sendmsg(struct socket *sock, struct msghdr *msg,
2262 int size) 2272 int size)
2263{ 2273{
2264 struct sockaddr_in *sip = (struct sockaddr_in *) msg->msg_name; 2274 struct sockaddr_in *sip = (struct sockaddr_in *) msg->msg_name;
2265 struct socket_smack *ssp = sock->sk->sk_security;
2266 char *hostsp;
2267 int rc;
2268 2275
2269 /* 2276 /*
2270 * Perfectly reasonable for this to be NULL 2277 * Perfectly reasonable for this to be NULL
@@ -2272,28 +2279,12 @@ static int smack_socket_sendmsg(struct socket *sock, struct msghdr *msg,
2272 if (sip == NULL || sip->sin_family != PF_INET) 2279 if (sip == NULL || sip->sin_family != PF_INET)
2273 return 0; 2280 return 0;
2274 2281
2275 hostsp = smack_host_label(sip); 2282 return smack_netlabel_send(sock->sk, sip);
2276 if (hostsp == NULL) {
2277 if (ssp->smk_labeled != SMACK_CIPSO_SOCKET)
2278 return smack_netlabel(sock->sk, SMACK_CIPSO_SOCKET);
2279 return 0;
2280 }
2281
2282 rc = smk_access(ssp->smk_out, hostsp, MAY_WRITE);
2283 if (rc != 0)
2284 return rc;
2285
2286 if (ssp->smk_labeled != SMACK_UNLABELED_SOCKET)
2287 return smack_netlabel(sock->sk, SMACK_UNLABELED_SOCKET);
2288
2289 return 0;
2290
2291} 2283}
2292 2284
2293 2285
2294/** 2286/**
2295 * smack_from_secattr - Convert a netlabel attr.mls.lvl/attr.mls.cat 2287 * smack_from_secattr - Convert a netlabel attr.mls.lvl/attr.mls.cat pair to smack
2296 * pair to smack
2297 * @sap: netlabel secattr 2288 * @sap: netlabel secattr
2298 * @sip: where to put the result 2289 * @sip: where to put the result
2299 * 2290 *
@@ -2414,7 +2405,7 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
2414 * @sock: the socket 2405 * @sock: the socket
2415 * @optval: user's destination 2406 * @optval: user's destination
2416 * @optlen: size thereof 2407 * @optlen: size thereof
2417 * @len: max thereoe 2408 * @len: max thereof
2418 * 2409 *
2419 * returns zero on success, an error code otherwise 2410 * returns zero on success, an error code otherwise
2420 */ 2411 */
@@ -2493,31 +2484,24 @@ static int smack_socket_getpeersec_dgram(struct socket *sock,
2493} 2484}
2494 2485
2495/** 2486/**
2496 * smack_sock_graft - graft access state between two sockets 2487 * smack_sock_graft - Initialize a newly created socket with an existing sock
2497 * @sk: fresh sock 2488 * @sk: child sock
2498 * @parent: donor socket 2489 * @parent: parent socket
2499 * 2490 *
2500 * Sets the netlabel socket state on sk from parent 2491 * Set the smk_{in,out} state of an existing sock based on the process that
2492 * is creating the new socket.
2501 */ 2493 */
2502static void smack_sock_graft(struct sock *sk, struct socket *parent) 2494static void smack_sock_graft(struct sock *sk, struct socket *parent)
2503{ 2495{
2504 struct socket_smack *ssp; 2496 struct socket_smack *ssp;
2505 int rc;
2506 2497
2507 if (sk == NULL) 2498 if (sk == NULL ||
2508 return; 2499 (sk->sk_family != PF_INET && sk->sk_family != PF_INET6))
2509
2510 if (sk->sk_family != PF_INET && sk->sk_family != PF_INET6)
2511 return; 2500 return;
2512 2501
2513 ssp = sk->sk_security; 2502 ssp = sk->sk_security;
2514 ssp->smk_in = ssp->smk_out = current_security(); 2503 ssp->smk_in = ssp->smk_out = current_security();
2515 ssp->smk_packet[0] = '\0'; 2504 /* cssp->smk_packet is already set in smack_inet_csk_clone() */
2516
2517 rc = smack_netlabel(sk, SMACK_CIPSO_SOCKET);
2518 if (rc != 0)
2519 printk(KERN_WARNING "Smack: \"%s\" netlbl error %d.\n",
2520 __func__, -rc);
2521} 2505}
2522 2506
2523/** 2507/**
@@ -2532,35 +2516,82 @@ static void smack_sock_graft(struct sock *sk, struct socket *parent)
2532static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb, 2516static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
2533 struct request_sock *req) 2517 struct request_sock *req)
2534{ 2518{
2535 struct netlbl_lsm_secattr skb_secattr; 2519 u16 family = sk->sk_family;
2536 struct socket_smack *ssp = sk->sk_security; 2520 struct socket_smack *ssp = sk->sk_security;
2521 struct netlbl_lsm_secattr secattr;
2522 struct sockaddr_in addr;
2523 struct iphdr *hdr;
2537 char smack[SMK_LABELLEN]; 2524 char smack[SMK_LABELLEN];
2538 int rc; 2525 int rc;
2539 2526
2540 if (skb == NULL) 2527 /* handle mapped IPv4 packets arriving via IPv6 sockets */
2541 return -EACCES; 2528 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
2529 family = PF_INET;
2542 2530
2543 netlbl_secattr_init(&skb_secattr); 2531 netlbl_secattr_init(&secattr);
2544 rc = netlbl_skbuff_getattr(skb, sk->sk_family, &skb_secattr); 2532 rc = netlbl_skbuff_getattr(skb, family, &secattr);
2545 if (rc == 0) 2533 if (rc == 0)
2546 smack_from_secattr(&skb_secattr, smack); 2534 smack_from_secattr(&secattr, smack);
2547 else 2535 else
2548 strncpy(smack, smack_known_huh.smk_known, SMK_MAXLEN); 2536 strncpy(smack, smack_known_huh.smk_known, SMK_MAXLEN);
2549 netlbl_secattr_destroy(&skb_secattr); 2537 netlbl_secattr_destroy(&secattr);
2538
2550 /* 2539 /*
2551 * Receiving a packet requires that the other end 2540 * Receiving a packet requires that the other end be able to write
2552 * be able to write here. Read access is not required. 2541 * here. Read access is not required.
2553 *
2554 * If the request is successful save the peer's label
2555 * so that SO_PEERCRED can report it.
2556 */ 2542 */
2557 rc = smk_access(smack, ssp->smk_in, MAY_WRITE); 2543 rc = smk_access(smack, ssp->smk_in, MAY_WRITE);
2558 if (rc == 0) 2544 if (rc != 0)
2559 strncpy(ssp->smk_packet, smack, SMK_MAXLEN); 2545 return rc;
2546
2547 /*
2548 * Save the peer's label in the request_sock so we can later setup
2549 * smk_packet in the child socket so that SO_PEERCRED can report it.
2550 */
2551 req->peer_secid = smack_to_secid(smack);
2552
2553 /*
2554 * We need to decide if we want to label the incoming connection here
2555 * if we do we only need to label the request_sock and the stack will
2556 * propogate the wire-label to the sock when it is created.
2557 */
2558 hdr = ip_hdr(skb);
2559 addr.sin_addr.s_addr = hdr->saddr;
2560 rcu_read_lock();
2561 if (smack_host_label(&addr) == NULL) {
2562 rcu_read_unlock();
2563 netlbl_secattr_init(&secattr);
2564 smack_to_secattr(smack, &secattr);
2565 rc = netlbl_req_setattr(req, &secattr);
2566 netlbl_secattr_destroy(&secattr);
2567 } else {
2568 rcu_read_unlock();
2569 netlbl_req_delattr(req);
2570 }
2560 2571
2561 return rc; 2572 return rc;
2562} 2573}
2563 2574
2575/**
2576 * smack_inet_csk_clone - Copy the connection information to the new socket
2577 * @sk: the new socket
2578 * @req: the connection's request_sock
2579 *
2580 * Transfer the connection's peer label to the newly created socket.
2581 */
2582static void smack_inet_csk_clone(struct sock *sk,
2583 const struct request_sock *req)
2584{
2585 struct socket_smack *ssp = sk->sk_security;
2586 char *smack;
2587
2588 if (req->peer_secid != 0) {
2589 smack = smack_from_secid(req->peer_secid);
2590 strncpy(ssp->smk_packet, smack, SMK_MAXLEN);
2591 } else
2592 ssp->smk_packet[0] = '\0';
2593}
2594
2564/* 2595/*
2565 * Key management security hooks 2596 * Key management security hooks
2566 * 2597 *
@@ -2749,7 +2780,7 @@ static void smack_audit_rule_free(void *vrule)
2749 2780
2750#endif /* CONFIG_AUDIT */ 2781#endif /* CONFIG_AUDIT */
2751 2782
2752/* 2783/**
2753 * smack_secid_to_secctx - return the smack label for a secid 2784 * smack_secid_to_secctx - return the smack label for a secid
2754 * @secid: incoming integer 2785 * @secid: incoming integer
2755 * @secdata: destination 2786 * @secdata: destination
@@ -2766,7 +2797,7 @@ static int smack_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
2766 return 0; 2797 return 0;
2767} 2798}
2768 2799
2769/* 2800/**
2770 * smack_secctx_to_secid - return the secid for a smack label 2801 * smack_secctx_to_secid - return the secid for a smack label
2771 * @secdata: smack label 2802 * @secdata: smack label
2772 * @seclen: how long result is 2803 * @seclen: how long result is
@@ -2780,11 +2811,10 @@ static int smack_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
2780 return 0; 2811 return 0;
2781} 2812}
2782 2813
2783/* 2814/**
2784 * smack_release_secctx - don't do anything. 2815 * smack_release_secctx - don't do anything.
2785 * @key_ref: unused 2816 * @secdata: unused
2786 * @context: unused 2817 * @seclen: unused
2787 * @perm: unused
2788 * 2818 *
2789 * Exists to make sure nothing gets done, and properly 2819 * Exists to make sure nothing gets done, and properly
2790 */ 2820 */
@@ -2913,6 +2943,7 @@ struct security_operations smack_ops = {
2913 .sk_free_security = smack_sk_free_security, 2943 .sk_free_security = smack_sk_free_security,
2914 .sock_graft = smack_sock_graft, 2944 .sock_graft = smack_sock_graft,
2915 .inet_conn_request = smack_inet_conn_request, 2945 .inet_conn_request = smack_inet_conn_request,
2946 .inet_csk_clone = smack_inet_csk_clone,
2916 2947
2917 /* key management security hooks */ 2948 /* key management security hooks */
2918#ifdef CONFIG_KEYS 2949#ifdef CONFIG_KEYS
@@ -2934,6 +2965,17 @@ struct security_operations smack_ops = {
2934 .release_secctx = smack_release_secctx, 2965 .release_secctx = smack_release_secctx,
2935}; 2966};
2936 2967
2968
2969static __init void init_smack_know_list(void)
2970{
2971 list_add(&smack_known_huh.list, &smack_known_list);
2972 list_add(&smack_known_hat.list, &smack_known_list);
2973 list_add(&smack_known_star.list, &smack_known_list);
2974 list_add(&smack_known_floor.list, &smack_known_list);
2975 list_add(&smack_known_invalid.list, &smack_known_list);
2976 list_add(&smack_known_web.list, &smack_known_list);
2977}
2978
2937/** 2979/**
2938 * smack_init - initialize the smack system 2980 * smack_init - initialize the smack system
2939 * 2981 *
@@ -2954,6 +2996,8 @@ static __init int smack_init(void)
2954 cred = (struct cred *) current->cred; 2996 cred = (struct cred *) current->cred;
2955 cred->security = &smack_known_floor.smk_known; 2997 cred->security = &smack_known_floor.smk_known;
2956 2998
2999 /* initilize the smack_know_list */
3000 init_smack_know_list();
2957 /* 3001 /*
2958 * Initialize locks 3002 * Initialize locks
2959 */ 3003 */
diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c
index 51f0efc50dab..e03a7e19c73b 100644
--- a/security/smack/smackfs.c
+++ b/security/smack/smackfs.c
@@ -80,10 +80,14 @@ char *smack_onlycap;
80 * Packets are sent there unlabeled, but only from tasks that 80 * Packets are sent there unlabeled, but only from tasks that
81 * can write to the specified label. 81 * can write to the specified label.
82 */ 82 */
83struct smk_netlbladdr *smack_netlbladdrs; 83
84LIST_HEAD(smk_netlbladdr_list);
85LIST_HEAD(smack_rule_list);
84 86
85static int smk_cipso_doi_value = SMACK_CIPSO_DOI_DEFAULT; 87static int smk_cipso_doi_value = SMACK_CIPSO_DOI_DEFAULT;
86struct smk_list_entry *smack_list; 88
89const char *smack_cipso_option = SMACK_CIPSO_OPTION;
90
87 91
88#define SEQ_READ_FINISHED 1 92#define SEQ_READ_FINISHED 1
89 93
@@ -134,24 +138,27 @@ static void *load_seq_start(struct seq_file *s, loff_t *pos)
134{ 138{
135 if (*pos == SEQ_READ_FINISHED) 139 if (*pos == SEQ_READ_FINISHED)
136 return NULL; 140 return NULL;
137 141 if (list_empty(&smack_rule_list))
138 return smack_list; 142 return NULL;
143 return smack_rule_list.next;
139} 144}
140 145
141static void *load_seq_next(struct seq_file *s, void *v, loff_t *pos) 146static void *load_seq_next(struct seq_file *s, void *v, loff_t *pos)
142{ 147{
143 struct smk_list_entry *skp = ((struct smk_list_entry *) v)->smk_next; 148 struct list_head *list = v;
144 149
145 if (skp == NULL) 150 if (list_is_last(list, &smack_rule_list)) {
146 *pos = SEQ_READ_FINISHED; 151 *pos = SEQ_READ_FINISHED;
147 152 return NULL;
148 return skp; 153 }
154 return list->next;
149} 155}
150 156
151static int load_seq_show(struct seq_file *s, void *v) 157static int load_seq_show(struct seq_file *s, void *v)
152{ 158{
153 struct smk_list_entry *slp = (struct smk_list_entry *) v; 159 struct list_head *list = v;
154 struct smack_rule *srp = &slp->smk_rule; 160 struct smack_rule *srp =
161 list_entry(list, struct smack_rule, list);
155 162
156 seq_printf(s, "%s %s", (char *)srp->smk_subject, 163 seq_printf(s, "%s %s", (char *)srp->smk_subject,
157 (char *)srp->smk_object); 164 (char *)srp->smk_object);
@@ -212,32 +219,23 @@ static int smk_open_load(struct inode *inode, struct file *file)
212 */ 219 */
213static int smk_set_access(struct smack_rule *srp) 220static int smk_set_access(struct smack_rule *srp)
214{ 221{
215 struct smk_list_entry *sp; 222 struct smack_rule *sp;
216 struct smk_list_entry *newp;
217 int ret = 0; 223 int ret = 0;
218 224 int found;
219 mutex_lock(&smack_list_lock); 225 mutex_lock(&smack_list_lock);
220 226
221 for (sp = smack_list; sp != NULL; sp = sp->smk_next) 227 found = 0;
222 if (sp->smk_rule.smk_subject == srp->smk_subject && 228 list_for_each_entry_rcu(sp, &smack_rule_list, list) {
223 sp->smk_rule.smk_object == srp->smk_object) { 229 if (sp->smk_subject == srp->smk_subject &&
224 sp->smk_rule.smk_access = srp->smk_access; 230 sp->smk_object == srp->smk_object) {
231 found = 1;
232 sp->smk_access = srp->smk_access;
225 break; 233 break;
226 } 234 }
227
228 if (sp == NULL) {
229 newp = kzalloc(sizeof(struct smk_list_entry), GFP_KERNEL);
230 if (newp == NULL) {
231 ret = -ENOMEM;
232 goto out;
233 }
234
235 newp->smk_rule = *srp;
236 newp->smk_next = smack_list;
237 smack_list = newp;
238 } 235 }
236 if (found == 0)
237 list_add_rcu(&srp->list, &smack_rule_list);
239 238
240out:
241 mutex_unlock(&smack_list_lock); 239 mutex_unlock(&smack_list_lock);
242 240
243 return ret; 241 return ret;
@@ -245,7 +243,7 @@ out:
245 243
246/** 244/**
247 * smk_write_load - write() for /smack/load 245 * smk_write_load - write() for /smack/load
248 * @filp: file pointer, not actually used 246 * @file: file pointer, not actually used
249 * @buf: where to get the data from 247 * @buf: where to get the data from
250 * @count: bytes sent 248 * @count: bytes sent
251 * @ppos: where to start - must be 0 249 * @ppos: where to start - must be 0
@@ -261,7 +259,7 @@ out:
261static ssize_t smk_write_load(struct file *file, const char __user *buf, 259static ssize_t smk_write_load(struct file *file, const char __user *buf,
262 size_t count, loff_t *ppos) 260 size_t count, loff_t *ppos)
263{ 261{
264 struct smack_rule rule; 262 struct smack_rule *rule;
265 char *data; 263 char *data;
266 int rc = -EINVAL; 264 int rc = -EINVAL;
267 265
@@ -272,9 +270,8 @@ static ssize_t smk_write_load(struct file *file, const char __user *buf,
272 */ 270 */
273 if (!capable(CAP_MAC_ADMIN)) 271 if (!capable(CAP_MAC_ADMIN))
274 return -EPERM; 272 return -EPERM;
275 if (*ppos != 0) 273
276 return -EINVAL; 274 if (*ppos != 0 || count != SMK_LOADLEN)
277 if (count != SMK_LOADLEN)
278 return -EINVAL; 275 return -EINVAL;
279 276
280 data = kzalloc(count, GFP_KERNEL); 277 data = kzalloc(count, GFP_KERNEL);
@@ -286,25 +283,31 @@ static ssize_t smk_write_load(struct file *file, const char __user *buf,
286 goto out; 283 goto out;
287 } 284 }
288 285
289 rule.smk_subject = smk_import(data, 0); 286 rule = kzalloc(sizeof(*rule), GFP_KERNEL);
290 if (rule.smk_subject == NULL) 287 if (rule == NULL) {
288 rc = -ENOMEM;
291 goto out; 289 goto out;
290 }
292 291
293 rule.smk_object = smk_import(data + SMK_LABELLEN, 0); 292 rule->smk_subject = smk_import(data, 0);
294 if (rule.smk_object == NULL) 293 if (rule->smk_subject == NULL)
295 goto out; 294 goto out_free_rule;
296 295
297 rule.smk_access = 0; 296 rule->smk_object = smk_import(data + SMK_LABELLEN, 0);
297 if (rule->smk_object == NULL)
298 goto out_free_rule;
299
300 rule->smk_access = 0;
298 301
299 switch (data[SMK_LABELLEN + SMK_LABELLEN]) { 302 switch (data[SMK_LABELLEN + SMK_LABELLEN]) {
300 case '-': 303 case '-':
301 break; 304 break;
302 case 'r': 305 case 'r':
303 case 'R': 306 case 'R':
304 rule.smk_access |= MAY_READ; 307 rule->smk_access |= MAY_READ;
305 break; 308 break;
306 default: 309 default:
307 goto out; 310 goto out_free_rule;
308 } 311 }
309 312
310 switch (data[SMK_LABELLEN + SMK_LABELLEN + 1]) { 313 switch (data[SMK_LABELLEN + SMK_LABELLEN + 1]) {
@@ -312,10 +315,10 @@ static ssize_t smk_write_load(struct file *file, const char __user *buf,
312 break; 315 break;
313 case 'w': 316 case 'w':
314 case 'W': 317 case 'W':
315 rule.smk_access |= MAY_WRITE; 318 rule->smk_access |= MAY_WRITE;
316 break; 319 break;
317 default: 320 default:
318 goto out; 321 goto out_free_rule;
319 } 322 }
320 323
321 switch (data[SMK_LABELLEN + SMK_LABELLEN + 2]) { 324 switch (data[SMK_LABELLEN + SMK_LABELLEN + 2]) {
@@ -323,10 +326,10 @@ static ssize_t smk_write_load(struct file *file, const char __user *buf,
323 break; 326 break;
324 case 'x': 327 case 'x':
325 case 'X': 328 case 'X':
326 rule.smk_access |= MAY_EXEC; 329 rule->smk_access |= MAY_EXEC;
327 break; 330 break;
328 default: 331 default:
329 goto out; 332 goto out_free_rule;
330 } 333 }
331 334
332 switch (data[SMK_LABELLEN + SMK_LABELLEN + 3]) { 335 switch (data[SMK_LABELLEN + SMK_LABELLEN + 3]) {
@@ -334,17 +337,20 @@ static ssize_t smk_write_load(struct file *file, const char __user *buf,
334 break; 337 break;
335 case 'a': 338 case 'a':
336 case 'A': 339 case 'A':
337 rule.smk_access |= MAY_APPEND; 340 rule->smk_access |= MAY_APPEND;
338 break; 341 break;
339 default: 342 default:
340 goto out; 343 goto out_free_rule;
341 } 344 }
342 345
343 rc = smk_set_access(&rule); 346 rc = smk_set_access(rule);
344 347
345 if (!rc) 348 if (!rc)
346 rc = count; 349 rc = count;
350 goto out;
347 351
352out_free_rule:
353 kfree(rule);
348out: 354out:
349 kfree(data); 355 kfree(data);
350 return rc; 356 return rc;
@@ -402,6 +408,7 @@ static void smk_cipso_doi(void)
402 408
403/** 409/**
404 * smk_unlbl_ambient - initialize the unlabeled domain 410 * smk_unlbl_ambient - initialize the unlabeled domain
411 * @oldambient: previous domain string
405 */ 412 */
406static void smk_unlbl_ambient(char *oldambient) 413static void smk_unlbl_ambient(char *oldambient)
407{ 414{
@@ -432,24 +439,26 @@ static void *cipso_seq_start(struct seq_file *s, loff_t *pos)
432{ 439{
433 if (*pos == SEQ_READ_FINISHED) 440 if (*pos == SEQ_READ_FINISHED)
434 return NULL; 441 return NULL;
442 if (list_empty(&smack_known_list))
443 return NULL;
435 444
436 return smack_known; 445 return smack_known_list.next;
437} 446}
438 447
439static void *cipso_seq_next(struct seq_file *s, void *v, loff_t *pos) 448static void *cipso_seq_next(struct seq_file *s, void *v, loff_t *pos)
440{ 449{
441 struct smack_known *skp = ((struct smack_known *) v)->smk_next; 450 struct list_head *list = v;
442 451
443 /* 452 /*
444 * Omit labels with no associated cipso value 453 * labels with no associated cipso value wont be printed
454 * in cipso_seq_show
445 */ 455 */
446 while (skp != NULL && !skp->smk_cipso) 456 if (list_is_last(list, &smack_known_list)) {
447 skp = skp->smk_next;
448
449 if (skp == NULL)
450 *pos = SEQ_READ_FINISHED; 457 *pos = SEQ_READ_FINISHED;
458 return NULL;
459 }
451 460
452 return skp; 461 return list->next;
453} 462}
454 463
455/* 464/*
@@ -458,7 +467,9 @@ static void *cipso_seq_next(struct seq_file *s, void *v, loff_t *pos)
458 */ 467 */
459static int cipso_seq_show(struct seq_file *s, void *v) 468static int cipso_seq_show(struct seq_file *s, void *v)
460{ 469{
461 struct smack_known *skp = (struct smack_known *) v; 470 struct list_head *list = v;
471 struct smack_known *skp =
472 list_entry(list, struct smack_known, list);
462 struct smack_cipso *scp = skp->smk_cipso; 473 struct smack_cipso *scp = skp->smk_cipso;
463 char *cbp; 474 char *cbp;
464 char sep = '/'; 475 char sep = '/';
@@ -513,7 +524,7 @@ static int smk_open_cipso(struct inode *inode, struct file *file)
513 524
514/** 525/**
515 * smk_write_cipso - write() for /smack/cipso 526 * smk_write_cipso - write() for /smack/cipso
516 * @filp: file pointer, not actually used 527 * @file: file pointer, not actually used
517 * @buf: where to get the data from 528 * @buf: where to get the data from
518 * @count: bytes sent 529 * @count: bytes sent
519 * @ppos: where to start 530 * @ppos: where to start
@@ -557,6 +568,11 @@ static ssize_t smk_write_cipso(struct file *file, const char __user *buf,
557 goto unlockedout; 568 goto unlockedout;
558 } 569 }
559 570
571 /* labels cannot begin with a '-' */
572 if (data[0] == '-') {
573 rc = -EINVAL;
574 goto unlockedout;
575 }
560 data[count] = '\0'; 576 data[count] = '\0';
561 rule = data; 577 rule = data;
562 /* 578 /*
@@ -637,18 +653,21 @@ static void *netlbladdr_seq_start(struct seq_file *s, loff_t *pos)
637{ 653{
638 if (*pos == SEQ_READ_FINISHED) 654 if (*pos == SEQ_READ_FINISHED)
639 return NULL; 655 return NULL;
640 656 if (list_empty(&smk_netlbladdr_list))
641 return smack_netlbladdrs; 657 return NULL;
658 return smk_netlbladdr_list.next;
642} 659}
643 660
644static void *netlbladdr_seq_next(struct seq_file *s, void *v, loff_t *pos) 661static void *netlbladdr_seq_next(struct seq_file *s, void *v, loff_t *pos)
645{ 662{
646 struct smk_netlbladdr *skp = ((struct smk_netlbladdr *) v)->smk_next; 663 struct list_head *list = v;
647 664
648 if (skp == NULL) 665 if (list_is_last(list, &smk_netlbladdr_list)) {
649 *pos = SEQ_READ_FINISHED; 666 *pos = SEQ_READ_FINISHED;
667 return NULL;
668 }
650 669
651 return skp; 670 return list->next;
652} 671}
653#define BEBITS (sizeof(__be32) * 8) 672#define BEBITS (sizeof(__be32) * 8)
654 673
@@ -657,7 +676,9 @@ static void *netlbladdr_seq_next(struct seq_file *s, void *v, loff_t *pos)
657 */ 676 */
658static int netlbladdr_seq_show(struct seq_file *s, void *v) 677static int netlbladdr_seq_show(struct seq_file *s, void *v)
659{ 678{
660 struct smk_netlbladdr *skp = (struct smk_netlbladdr *) v; 679 struct list_head *list = v;
680 struct smk_netlbladdr *skp =
681 list_entry(list, struct smk_netlbladdr, list);
661 unsigned char *hp = (char *) &skp->smk_host.sin_addr.s_addr; 682 unsigned char *hp = (char *) &skp->smk_host.sin_addr.s_addr;
662 int maskn; 683 int maskn;
663 u32 temp_mask = be32_to_cpu(skp->smk_mask.s_addr); 684 u32 temp_mask = be32_to_cpu(skp->smk_mask.s_addr);
@@ -701,30 +722,36 @@ static int smk_open_netlbladdr(struct inode *inode, struct file *file)
701 * 722 *
702 * This helper insert netlabel in the smack_netlbladdrs list 723 * This helper insert netlabel in the smack_netlbladdrs list
703 * sorted by netmask length (longest to smallest) 724 * sorted by netmask length (longest to smallest)
725 * locked by &smk_netlbladdr_lock in smk_write_netlbladdr
726 *
704 */ 727 */
705static void smk_netlbladdr_insert(struct smk_netlbladdr *new) 728static void smk_netlbladdr_insert(struct smk_netlbladdr *new)
706{ 729{
707 struct smk_netlbladdr *m; 730 struct smk_netlbladdr *m, *m_next;
708 731
709 if (smack_netlbladdrs == NULL) { 732 if (list_empty(&smk_netlbladdr_list)) {
710 smack_netlbladdrs = new; 733 list_add_rcu(&new->list, &smk_netlbladdr_list);
711 return; 734 return;
712 } 735 }
713 736
737 m = list_entry(rcu_dereference(smk_netlbladdr_list.next),
738 struct smk_netlbladdr, list);
739
714 /* the comparison '>' is a bit hacky, but works */ 740 /* the comparison '>' is a bit hacky, but works */
715 if (new->smk_mask.s_addr > smack_netlbladdrs->smk_mask.s_addr) { 741 if (new->smk_mask.s_addr > m->smk_mask.s_addr) {
716 new->smk_next = smack_netlbladdrs; 742 list_add_rcu(&new->list, &smk_netlbladdr_list);
717 smack_netlbladdrs = new;
718 return; 743 return;
719 } 744 }
720 for (m = smack_netlbladdrs; m != NULL; m = m->smk_next) { 745
721 if (m->smk_next == NULL) { 746 list_for_each_entry_rcu(m, &smk_netlbladdr_list, list) {
722 m->smk_next = new; 747 if (list_is_last(&m->list, &smk_netlbladdr_list)) {
748 list_add_rcu(&new->list, &m->list);
723 return; 749 return;
724 } 750 }
725 if (new->smk_mask.s_addr > m->smk_next->smk_mask.s_addr) { 751 m_next = list_entry(rcu_dereference(m->list.next),
726 new->smk_next = m->smk_next; 752 struct smk_netlbladdr, list);
727 m->smk_next = new; 753 if (new->smk_mask.s_addr > m_next->smk_mask.s_addr) {
754 list_add_rcu(&new->list, &m->list);
728 return; 755 return;
729 } 756 }
730 } 757 }
@@ -733,7 +760,7 @@ static void smk_netlbladdr_insert(struct smk_netlbladdr *new)
733 760
734/** 761/**
735 * smk_write_netlbladdr - write() for /smack/netlabel 762 * smk_write_netlbladdr - write() for /smack/netlabel
736 * @filp: file pointer, not actually used 763 * @file: file pointer, not actually used
737 * @buf: where to get the data from 764 * @buf: where to get the data from
738 * @count: bytes sent 765 * @count: bytes sent
739 * @ppos: where to start 766 * @ppos: where to start
@@ -754,6 +781,7 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,
754 struct netlbl_audit audit_info; 781 struct netlbl_audit audit_info;
755 struct in_addr mask; 782 struct in_addr mask;
756 unsigned int m; 783 unsigned int m;
784 int found;
757 u32 mask_bits = (1<<31); 785 u32 mask_bits = (1<<31);
758 __be32 nsa; 786 __be32 nsa;
759 u32 temp_mask; 787 u32 temp_mask;
@@ -788,9 +816,18 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,
788 if (m > BEBITS) 816 if (m > BEBITS)
789 return -EINVAL; 817 return -EINVAL;
790 818
791 sp = smk_import(smack, 0); 819 /* if smack begins with '-', its an option, don't import it */
792 if (sp == NULL) 820 if (smack[0] != '-') {
793 return -EINVAL; 821 sp = smk_import(smack, 0);
822 if (sp == NULL)
823 return -EINVAL;
824 } else {
825 /* check known options */
826 if (strcmp(smack, smack_cipso_option) == 0)
827 sp = (char *)smack_cipso_option;
828 else
829 return -EINVAL;
830 }
794 831
795 for (temp_mask = 0; m > 0; m--) { 832 for (temp_mask = 0; m > 0; m--) {
796 temp_mask |= mask_bits; 833 temp_mask |= mask_bits;
@@ -807,14 +844,17 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,
807 844
808 nsa = newname.sin_addr.s_addr; 845 nsa = newname.sin_addr.s_addr;
809 /* try to find if the prefix is already in the list */ 846 /* try to find if the prefix is already in the list */
810 for (skp = smack_netlbladdrs; skp != NULL; skp = skp->smk_next) 847 found = 0;
848 list_for_each_entry_rcu(skp, &smk_netlbladdr_list, list) {
811 if (skp->smk_host.sin_addr.s_addr == nsa && 849 if (skp->smk_host.sin_addr.s_addr == nsa &&
812 skp->smk_mask.s_addr == mask.s_addr) 850 skp->smk_mask.s_addr == mask.s_addr) {
851 found = 1;
813 break; 852 break;
814 853 }
854 }
815 smk_netlabel_audit_set(&audit_info); 855 smk_netlabel_audit_set(&audit_info);
816 856
817 if (skp == NULL) { 857 if (found == 0) {
818 skp = kzalloc(sizeof(*skp), GFP_KERNEL); 858 skp = kzalloc(sizeof(*skp), GFP_KERNEL);
819 if (skp == NULL) 859 if (skp == NULL)
820 rc = -ENOMEM; 860 rc = -ENOMEM;
@@ -826,18 +866,23 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,
826 smk_netlbladdr_insert(skp); 866 smk_netlbladdr_insert(skp);
827 } 867 }
828 } else { 868 } else {
829 rc = netlbl_cfg_unlbl_static_del(&init_net, NULL, 869 /* we delete the unlabeled entry, only if the previous label
830 &skp->smk_host.sin_addr, &skp->smk_mask, 870 * wasnt the special CIPSO option */
831 PF_INET, &audit_info); 871 if (skp->smk_label != smack_cipso_option)
872 rc = netlbl_cfg_unlbl_static_del(&init_net, NULL,
873 &skp->smk_host.sin_addr, &skp->smk_mask,
874 PF_INET, &audit_info);
875 else
876 rc = 0;
832 skp->smk_label = sp; 877 skp->smk_label = sp;
833 } 878 }
834 879
835 /* 880 /*
836 * Now tell netlabel about the single label nature of 881 * Now tell netlabel about the single label nature of
837 * this host so that incoming packets get labeled. 882 * this host so that incoming packets get labeled.
883 * but only if we didn't get the special CIPSO option
838 */ 884 */
839 885 if (rc == 0 && sp != smack_cipso_option)
840 if (rc == 0)
841 rc = netlbl_cfg_unlbl_static_add(&init_net, NULL, 886 rc = netlbl_cfg_unlbl_static_add(&init_net, NULL,
842 &skp->smk_host.sin_addr, &skp->smk_mask, PF_INET, 887 &skp->smk_host.sin_addr, &skp->smk_mask, PF_INET,
843 smack_to_secid(skp->smk_label), &audit_info); 888 smack_to_secid(skp->smk_label), &audit_info);
@@ -884,7 +929,7 @@ static ssize_t smk_read_doi(struct file *filp, char __user *buf,
884 929
885/** 930/**
886 * smk_write_doi - write() for /smack/doi 931 * smk_write_doi - write() for /smack/doi
887 * @filp: file pointer, not actually used 932 * @file: file pointer, not actually used
888 * @buf: where to get the data from 933 * @buf: where to get the data from
889 * @count: bytes sent 934 * @count: bytes sent
890 * @ppos: where to start 935 * @ppos: where to start
@@ -949,7 +994,7 @@ static ssize_t smk_read_direct(struct file *filp, char __user *buf,
949 994
950/** 995/**
951 * smk_write_direct - write() for /smack/direct 996 * smk_write_direct - write() for /smack/direct
952 * @filp: file pointer, not actually used 997 * @file: file pointer, not actually used
953 * @buf: where to get the data from 998 * @buf: where to get the data from
954 * @count: bytes sent 999 * @count: bytes sent
955 * @ppos: where to start 1000 * @ppos: where to start
@@ -1024,7 +1069,7 @@ static ssize_t smk_read_ambient(struct file *filp, char __user *buf,
1024 1069
1025/** 1070/**
1026 * smk_write_ambient - write() for /smack/ambient 1071 * smk_write_ambient - write() for /smack/ambient
1027 * @filp: file pointer, not actually used 1072 * @file: file pointer, not actually used
1028 * @buf: where to get the data from 1073 * @buf: where to get the data from
1029 * @count: bytes sent 1074 * @count: bytes sent
1030 * @ppos: where to start 1075 * @ppos: where to start
@@ -1099,7 +1144,7 @@ static ssize_t smk_read_onlycap(struct file *filp, char __user *buf,
1099 1144
1100/** 1145/**
1101 * smk_write_onlycap - write() for /smack/onlycap 1146 * smk_write_onlycap - write() for /smack/onlycap
1102 * @filp: file pointer, not actually used 1147 * @file: file pointer, not actually used
1103 * @buf: where to get the data from 1148 * @buf: where to get the data from
1104 * @count: bytes sent 1149 * @count: bytes sent
1105 * @ppos: where to start 1150 * @ppos: where to start
diff --git a/security/tomoyo/Kconfig b/security/tomoyo/Kconfig
new file mode 100644
index 000000000000..c8f385793235
--- /dev/null
+++ b/security/tomoyo/Kconfig
@@ -0,0 +1,11 @@
1config SECURITY_TOMOYO
2 bool "TOMOYO Linux Support"
3 depends on SECURITY
4 select SECURITYFS
5 select SECURITY_PATH
6 default n
7 help
8 This selects TOMOYO Linux, pathname-based access control.
9 Required userspace tools and further information may be
10 found at <http://tomoyo.sourceforge.jp/>.
11 If you are unsure how to answer this question, answer N.
diff --git a/security/tomoyo/Makefile b/security/tomoyo/Makefile
new file mode 100644
index 000000000000..10ccd686b290
--- /dev/null
+++ b/security/tomoyo/Makefile
@@ -0,0 +1 @@
obj-y = common.o realpath.o tomoyo.o domain.o file.o
diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c
new file mode 100644
index 000000000000..92cea656ad21
--- /dev/null
+++ b/security/tomoyo/common.c
@@ -0,0 +1,2206 @@
1/*
2 * security/tomoyo/common.c
3 *
4 * Common functions for TOMOYO.
5 *
6 * Copyright (C) 2005-2009 NTT DATA CORPORATION
7 *
8 * Version: 2.2.0-pre 2009/02/01
9 *
10 */
11
12#include <linux/uaccess.h>
13#include <linux/security.h>
14#include <linux/hardirq.h>
15#include "realpath.h"
16#include "common.h"
17#include "tomoyo.h"
18
19/* Has loading policy done? */
20bool tomoyo_policy_loaded;
21
22/* String table for functionality that takes 4 modes. */
23static const char *tomoyo_mode_4[4] = {
24 "disabled", "learning", "permissive", "enforcing"
25};
26/* String table for functionality that takes 2 modes. */
27static const char *tomoyo_mode_2[4] = {
28 "disabled", "enabled", "enabled", "enabled"
29};
30
31/* Table for profile. */
32static struct {
33 const char *keyword;
34 unsigned int current_value;
35 const unsigned int max_value;
36} tomoyo_control_array[TOMOYO_MAX_CONTROL_INDEX] = {
37 [TOMOYO_MAC_FOR_FILE] = { "MAC_FOR_FILE", 0, 3 },
38 [TOMOYO_MAX_ACCEPT_ENTRY] = { "MAX_ACCEPT_ENTRY", 2048, INT_MAX },
39 [TOMOYO_VERBOSE] = { "TOMOYO_VERBOSE", 1, 1 },
40};
41
42/* Profile table. Memory is allocated as needed. */
43static struct tomoyo_profile {
44 unsigned int value[TOMOYO_MAX_CONTROL_INDEX];
45 const struct tomoyo_path_info *comment;
46} *tomoyo_profile_ptr[TOMOYO_MAX_PROFILES];
47
48/* Permit policy management by non-root user? */
49static bool tomoyo_manage_by_non_root;
50
51/* Utility functions. */
52
53/* Open operation for /sys/kernel/security/tomoyo/ interface. */
54static int tomoyo_open_control(const u8 type, struct file *file);
55/* Close /sys/kernel/security/tomoyo/ interface. */
56static int tomoyo_close_control(struct file *file);
57/* Read operation for /sys/kernel/security/tomoyo/ interface. */
58static int tomoyo_read_control(struct file *file, char __user *buffer,
59 const int buffer_len);
60/* Write operation for /sys/kernel/security/tomoyo/ interface. */
61static int tomoyo_write_control(struct file *file, const char __user *buffer,
62 const int buffer_len);
63
64/**
65 * tomoyo_is_byte_range - Check whether the string isa \ooo style octal value.
66 *
67 * @str: Pointer to the string.
68 *
69 * Returns true if @str is a \ooo style octal value, false otherwise.
70 *
71 * TOMOYO uses \ooo style representation for 0x01 - 0x20 and 0x7F - 0xFF.
72 * This function verifies that \ooo is in valid range.
73 */
74static inline bool tomoyo_is_byte_range(const char *str)
75{
76 return *str >= '0' && *str++ <= '3' &&
77 *str >= '0' && *str++ <= '7' &&
78 *str >= '0' && *str <= '7';
79}
80
81/**
82 * tomoyo_is_alphabet_char - Check whether the character is an alphabet.
83 *
84 * @c: The character to check.
85 *
86 * Returns true if @c is an alphabet character, false otherwise.
87 */
88static inline bool tomoyo_is_alphabet_char(const char c)
89{
90 return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
91}
92
93/**
94 * tomoyo_make_byte - Make byte value from three octal characters.
95 *
96 * @c1: The first character.
97 * @c2: The second character.
98 * @c3: The third character.
99 *
100 * Returns byte value.
101 */
102static inline u8 tomoyo_make_byte(const u8 c1, const u8 c2, const u8 c3)
103{
104 return ((c1 - '0') << 6) + ((c2 - '0') << 3) + (c3 - '0');
105}
106
107/**
108 * tomoyo_str_starts - Check whether the given string starts with the given keyword.
109 *
110 * @src: Pointer to pointer to the string.
111 * @find: Pointer to the keyword.
112 *
113 * Returns true if @src starts with @find, false otherwise.
114 *
115 * The @src is updated to point the first character after the @find
116 * if @src starts with @find.
117 */
118static bool tomoyo_str_starts(char **src, const char *find)
119{
120 const int len = strlen(find);
121 char *tmp = *src;
122
123 if (strncmp(tmp, find, len))
124 return false;
125 tmp += len;
126 *src = tmp;
127 return true;
128}
129
130/**
131 * tomoyo_normalize_line - Format string.
132 *
133 * @buffer: The line to normalize.
134 *
135 * Leading and trailing whitespaces are removed.
136 * Multiple whitespaces are packed into single space.
137 *
138 * Returns nothing.
139 */
140static void tomoyo_normalize_line(unsigned char *buffer)
141{
142 unsigned char *sp = buffer;
143 unsigned char *dp = buffer;
144 bool first = true;
145
146 while (tomoyo_is_invalid(*sp))
147 sp++;
148 while (*sp) {
149 if (!first)
150 *dp++ = ' ';
151 first = false;
152 while (tomoyo_is_valid(*sp))
153 *dp++ = *sp++;
154 while (tomoyo_is_invalid(*sp))
155 sp++;
156 }
157 *dp = '\0';
158}
159
160/**
161 * tomoyo_is_correct_path - Validate a pathname.
162 * @filename: The pathname to check.
163 * @start_type: Should the pathname start with '/'?
164 * 1 = must / -1 = must not / 0 = don't care
165 * @pattern_type: Can the pathname contain a wildcard?
166 * 1 = must / -1 = must not / 0 = don't care
167 * @end_type: Should the pathname end with '/'?
168 * 1 = must / -1 = must not / 0 = don't care
169 * @function: The name of function calling me.
170 *
171 * Check whether the given filename follows the naming rules.
172 * Returns true if @filename follows the naming rules, false otherwise.
173 */
174bool tomoyo_is_correct_path(const char *filename, const s8 start_type,
175 const s8 pattern_type, const s8 end_type,
176 const char *function)
177{
178 bool contains_pattern = false;
179 unsigned char c;
180 unsigned char d;
181 unsigned char e;
182 const char *original_filename = filename;
183
184 if (!filename)
185 goto out;
186 c = *filename;
187 if (start_type == 1) { /* Must start with '/' */
188 if (c != '/')
189 goto out;
190 } else if (start_type == -1) { /* Must not start with '/' */
191 if (c == '/')
192 goto out;
193 }
194 if (c)
195 c = *(filename + strlen(filename) - 1);
196 if (end_type == 1) { /* Must end with '/' */
197 if (c != '/')
198 goto out;
199 } else if (end_type == -1) { /* Must not end with '/' */
200 if (c == '/')
201 goto out;
202 }
203 while ((c = *filename++) != '\0') {
204 if (c == '\\') {
205 switch ((c = *filename++)) {
206 case '\\': /* "\\" */
207 continue;
208 case '$': /* "\$" */
209 case '+': /* "\+" */
210 case '?': /* "\?" */
211 case '*': /* "\*" */
212 case '@': /* "\@" */
213 case 'x': /* "\x" */
214 case 'X': /* "\X" */
215 case 'a': /* "\a" */
216 case 'A': /* "\A" */
217 case '-': /* "\-" */
218 if (pattern_type == -1)
219 break; /* Must not contain pattern */
220 contains_pattern = true;
221 continue;
222 case '0': /* "\ooo" */
223 case '1':
224 case '2':
225 case '3':
226 d = *filename++;
227 if (d < '0' || d > '7')
228 break;
229 e = *filename++;
230 if (e < '0' || e > '7')
231 break;
232 c = tomoyo_make_byte(c, d, e);
233 if (tomoyo_is_invalid(c))
234 continue; /* pattern is not \000 */
235 }
236 goto out;
237 } else if (tomoyo_is_invalid(c)) {
238 goto out;
239 }
240 }
241 if (pattern_type == 1) { /* Must contain pattern */
242 if (!contains_pattern)
243 goto out;
244 }
245 return true;
246 out:
247 printk(KERN_DEBUG "%s: Invalid pathname '%s'\n", function,
248 original_filename);
249 return false;
250}
251
252/**
253 * tomoyo_is_correct_domain - Check whether the given domainname follows the naming rules.
254 * @domainname: The domainname to check.
255 * @function: The name of function calling me.
256 *
257 * Returns true if @domainname follows the naming rules, false otherwise.
258 */
259bool tomoyo_is_correct_domain(const unsigned char *domainname,
260 const char *function)
261{
262 unsigned char c;
263 unsigned char d;
264 unsigned char e;
265 const char *org_domainname = domainname;
266
267 if (!domainname || strncmp(domainname, TOMOYO_ROOT_NAME,
268 TOMOYO_ROOT_NAME_LEN))
269 goto out;
270 domainname += TOMOYO_ROOT_NAME_LEN;
271 if (!*domainname)
272 return true;
273 do {
274 if (*domainname++ != ' ')
275 goto out;
276 if (*domainname++ != '/')
277 goto out;
278 while ((c = *domainname) != '\0' && c != ' ') {
279 domainname++;
280 if (c == '\\') {
281 c = *domainname++;
282 switch ((c)) {
283 case '\\': /* "\\" */
284 continue;
285 case '0': /* "\ooo" */
286 case '1':
287 case '2':
288 case '3':
289 d = *domainname++;
290 if (d < '0' || d > '7')
291 break;
292 e = *domainname++;
293 if (e < '0' || e > '7')
294 break;
295 c = tomoyo_make_byte(c, d, e);
296 if (tomoyo_is_invalid(c))
297 /* pattern is not \000 */
298 continue;
299 }
300 goto out;
301 } else if (tomoyo_is_invalid(c)) {
302 goto out;
303 }
304 }
305 } while (*domainname);
306 return true;
307 out:
308 printk(KERN_DEBUG "%s: Invalid domainname '%s'\n", function,
309 org_domainname);
310 return false;
311}
312
313/**
314 * tomoyo_is_domain_def - Check whether the given token can be a domainname.
315 *
316 * @buffer: The token to check.
317 *
318 * Returns true if @buffer possibly be a domainname, false otherwise.
319 */
320bool tomoyo_is_domain_def(const unsigned char *buffer)
321{
322 return !strncmp(buffer, TOMOYO_ROOT_NAME, TOMOYO_ROOT_NAME_LEN);
323}
324
325/**
326 * tomoyo_find_domain - Find a domain by the given name.
327 *
328 * @domainname: The domainname to find.
329 *
330 * Caller must call down_read(&tomoyo_domain_list_lock); or
331 * down_write(&tomoyo_domain_list_lock); .
332 *
333 * Returns pointer to "struct tomoyo_domain_info" if found, NULL otherwise.
334 */
335struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname)
336{
337 struct tomoyo_domain_info *domain;
338 struct tomoyo_path_info name;
339
340 name.name = domainname;
341 tomoyo_fill_path_info(&name);
342 list_for_each_entry(domain, &tomoyo_domain_list, list) {
343 if (!domain->is_deleted &&
344 !tomoyo_pathcmp(&name, domain->domainname))
345 return domain;
346 }
347 return NULL;
348}
349
350/**
351 * tomoyo_path_depth - Evaluate the number of '/' in a string.
352 *
353 * @pathname: The string to evaluate.
354 *
355 * Returns path depth of the string.
356 *
357 * I score 2 for each of the '/' in the @pathname
358 * and score 1 if the @pathname ends with '/'.
359 */
360static int tomoyo_path_depth(const char *pathname)
361{
362 int i = 0;
363
364 if (pathname) {
365 const char *ep = pathname + strlen(pathname);
366 if (pathname < ep--) {
367 if (*ep != '/')
368 i++;
369 while (pathname <= ep)
370 if (*ep-- == '/')
371 i += 2;
372 }
373 }
374 return i;
375}
376
377/**
378 * tomoyo_const_part_length - Evaluate the initial length without a pattern in a token.
379 *
380 * @filename: The string to evaluate.
381 *
382 * Returns the initial length without a pattern in @filename.
383 */
384static int tomoyo_const_part_length(const char *filename)
385{
386 char c;
387 int len = 0;
388
389 if (!filename)
390 return 0;
391 while ((c = *filename++) != '\0') {
392 if (c != '\\') {
393 len++;
394 continue;
395 }
396 c = *filename++;
397 switch (c) {
398 case '\\': /* "\\" */
399 len += 2;
400 continue;
401 case '0': /* "\ooo" */
402 case '1':
403 case '2':
404 case '3':
405 c = *filename++;
406 if (c < '0' || c > '7')
407 break;
408 c = *filename++;
409 if (c < '0' || c > '7')
410 break;
411 len += 4;
412 continue;
413 }
414 break;
415 }
416 return len;
417}
418
419/**
420 * tomoyo_fill_path_info - Fill in "struct tomoyo_path_info" members.
421 *
422 * @ptr: Pointer to "struct tomoyo_path_info" to fill in.
423 *
424 * The caller sets "struct tomoyo_path_info"->name.
425 */
426void tomoyo_fill_path_info(struct tomoyo_path_info *ptr)
427{
428 const char *name = ptr->name;
429 const int len = strlen(name);
430
431 ptr->total_len = len;
432 ptr->const_len = tomoyo_const_part_length(name);
433 ptr->is_dir = len && (name[len - 1] == '/');
434 ptr->is_patterned = (ptr->const_len < len);
435 ptr->hash = full_name_hash(name, len);
436 ptr->depth = tomoyo_path_depth(name);
437}
438
439/**
440 * tomoyo_file_matches_to_pattern2 - Pattern matching without '/' character
441 * and "\-" pattern.
442 *
443 * @filename: The start of string to check.
444 * @filename_end: The end of string to check.
445 * @pattern: The start of pattern to compare.
446 * @pattern_end: The end of pattern to compare.
447 *
448 * Returns true if @filename matches @pattern, false otherwise.
449 */
450static bool tomoyo_file_matches_to_pattern2(const char *filename,
451 const char *filename_end,
452 const char *pattern,
453 const char *pattern_end)
454{
455 while (filename < filename_end && pattern < pattern_end) {
456 char c;
457 if (*pattern != '\\') {
458 if (*filename++ != *pattern++)
459 return false;
460 continue;
461 }
462 c = *filename;
463 pattern++;
464 switch (*pattern) {
465 int i;
466 int j;
467 case '?':
468 if (c == '/') {
469 return false;
470 } else if (c == '\\') {
471 if (filename[1] == '\\')
472 filename++;
473 else if (tomoyo_is_byte_range(filename + 1))
474 filename += 3;
475 else
476 return false;
477 }
478 break;
479 case '\\':
480 if (c != '\\')
481 return false;
482 if (*++filename != '\\')
483 return false;
484 break;
485 case '+':
486 if (!isdigit(c))
487 return false;
488 break;
489 case 'x':
490 if (!isxdigit(c))
491 return false;
492 break;
493 case 'a':
494 if (!tomoyo_is_alphabet_char(c))
495 return false;
496 break;
497 case '0':
498 case '1':
499 case '2':
500 case '3':
501 if (c == '\\' && tomoyo_is_byte_range(filename + 1)
502 && strncmp(filename + 1, pattern, 3) == 0) {
503 filename += 3;
504 pattern += 2;
505 break;
506 }
507 return false; /* Not matched. */
508 case '*':
509 case '@':
510 for (i = 0; i <= filename_end - filename; i++) {
511 if (tomoyo_file_matches_to_pattern2(
512 filename + i, filename_end,
513 pattern + 1, pattern_end))
514 return true;
515 c = filename[i];
516 if (c == '.' && *pattern == '@')
517 break;
518 if (c != '\\')
519 continue;
520 if (filename[i + 1] == '\\')
521 i++;
522 else if (tomoyo_is_byte_range(filename + i + 1))
523 i += 3;
524 else
525 break; /* Bad pattern. */
526 }
527 return false; /* Not matched. */
528 default:
529 j = 0;
530 c = *pattern;
531 if (c == '$') {
532 while (isdigit(filename[j]))
533 j++;
534 } else if (c == 'X') {
535 while (isxdigit(filename[j]))
536 j++;
537 } else if (c == 'A') {
538 while (tomoyo_is_alphabet_char(filename[j]))
539 j++;
540 }
541 for (i = 1; i <= j; i++) {
542 if (tomoyo_file_matches_to_pattern2(
543 filename + i, filename_end,
544 pattern + 1, pattern_end))
545 return true;
546 }
547 return false; /* Not matched or bad pattern. */
548 }
549 filename++;
550 pattern++;
551 }
552 while (*pattern == '\\' &&
553 (*(pattern + 1) == '*' || *(pattern + 1) == '@'))
554 pattern += 2;
555 return filename == filename_end && pattern == pattern_end;
556}
557
558/**
559 * tomoyo_file_matches_to_pattern - Pattern matching without without '/' character.
560 *
561 * @filename: The start of string to check.
562 * @filename_end: The end of string to check.
563 * @pattern: The start of pattern to compare.
564 * @pattern_end: The end of pattern to compare.
565 *
566 * Returns true if @filename matches @pattern, false otherwise.
567 */
568static bool tomoyo_file_matches_to_pattern(const char *filename,
569 const char *filename_end,
570 const char *pattern,
571 const char *pattern_end)
572{
573 const char *pattern_start = pattern;
574 bool first = true;
575 bool result;
576
577 while (pattern < pattern_end - 1) {
578 /* Split at "\-" pattern. */
579 if (*pattern++ != '\\' || *pattern++ != '-')
580 continue;
581 result = tomoyo_file_matches_to_pattern2(filename,
582 filename_end,
583 pattern_start,
584 pattern - 2);
585 if (first)
586 result = !result;
587 if (result)
588 return false;
589 first = false;
590 pattern_start = pattern;
591 }
592 result = tomoyo_file_matches_to_pattern2(filename, filename_end,
593 pattern_start, pattern_end);
594 return first ? result : !result;
595}
596
597/**
598 * tomoyo_path_matches_pattern - Check whether the given filename matches the given pattern.
599 * @filename: The filename to check.
600 * @pattern: The pattern to compare.
601 *
602 * Returns true if matches, false otherwise.
603 *
604 * The following patterns are available.
605 * \\ \ itself.
606 * \ooo Octal representation of a byte.
607 * \* More than or equals to 0 character other than '/'.
608 * \@ More than or equals to 0 character other than '/' or '.'.
609 * \? 1 byte character other than '/'.
610 * \$ More than or equals to 1 decimal digit.
611 * \+ 1 decimal digit.
612 * \X More than or equals to 1 hexadecimal digit.
613 * \x 1 hexadecimal digit.
614 * \A More than or equals to 1 alphabet character.
615 * \a 1 alphabet character.
616 * \- Subtraction operator.
617 */
618bool tomoyo_path_matches_pattern(const struct tomoyo_path_info *filename,
619 const struct tomoyo_path_info *pattern)
620{
621 /*
622 if (!filename || !pattern)
623 return false;
624 */
625 const char *f = filename->name;
626 const char *p = pattern->name;
627 const int len = pattern->const_len;
628
629 /* If @pattern doesn't contain pattern, I can use strcmp(). */
630 if (!pattern->is_patterned)
631 return !tomoyo_pathcmp(filename, pattern);
632 /* Dont compare if the number of '/' differs. */
633 if (filename->depth != pattern->depth)
634 return false;
635 /* Compare the initial length without patterns. */
636 if (strncmp(f, p, len))
637 return false;
638 f += len;
639 p += len;
640 /* Main loop. Compare each directory component. */
641 while (*f && *p) {
642 const char *f_delimiter = strchr(f, '/');
643 const char *p_delimiter = strchr(p, '/');
644 if (!f_delimiter)
645 f_delimiter = f + strlen(f);
646 if (!p_delimiter)
647 p_delimiter = p + strlen(p);
648 if (!tomoyo_file_matches_to_pattern(f, f_delimiter,
649 p, p_delimiter))
650 return false;
651 f = f_delimiter;
652 if (*f)
653 f++;
654 p = p_delimiter;
655 if (*p)
656 p++;
657 }
658 /* Ignore trailing "\*" and "\@" in @pattern. */
659 while (*p == '\\' &&
660 (*(p + 1) == '*' || *(p + 1) == '@'))
661 p += 2;
662 return !*f && !*p;
663}
664
665/**
666 * tomoyo_io_printf - Transactional printf() to "struct tomoyo_io_buffer" structure.
667 *
668 * @head: Pointer to "struct tomoyo_io_buffer".
669 * @fmt: The printf()'s format string, followed by parameters.
670 *
671 * Returns true if output was written, false otherwise.
672 *
673 * The snprintf() will truncate, but tomoyo_io_printf() won't.
674 */
675bool tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt, ...)
676{
677 va_list args;
678 int len;
679 int pos = head->read_avail;
680 int size = head->readbuf_size - pos;
681
682 if (size <= 0)
683 return false;
684 va_start(args, fmt);
685 len = vsnprintf(head->read_buf + pos, size, fmt, args);
686 va_end(args);
687 if (pos + len >= head->readbuf_size)
688 return false;
689 head->read_avail += len;
690 return true;
691}
692
693/**
694 * tomoyo_get_exe - Get tomoyo_realpath() of current process.
695 *
696 * Returns the tomoyo_realpath() of current process on success, NULL otherwise.
697 *
698 * This function uses tomoyo_alloc(), so the caller must call tomoyo_free()
699 * if this function didn't return NULL.
700 */
701static const char *tomoyo_get_exe(void)
702{
703 struct mm_struct *mm = current->mm;
704 struct vm_area_struct *vma;
705 const char *cp = NULL;
706
707 if (!mm)
708 return NULL;
709 down_read(&mm->mmap_sem);
710 for (vma = mm->mmap; vma; vma = vma->vm_next) {
711 if ((vma->vm_flags & VM_EXECUTABLE) && vma->vm_file) {
712 cp = tomoyo_realpath_from_path(&vma->vm_file->f_path);
713 break;
714 }
715 }
716 up_read(&mm->mmap_sem);
717 return cp;
718}
719
720/**
721 * tomoyo_get_msg - Get warning message.
722 *
723 * @is_enforce: Is it enforcing mode?
724 *
725 * Returns "ERROR" or "WARNING".
726 */
727const char *tomoyo_get_msg(const bool is_enforce)
728{
729 if (is_enforce)
730 return "ERROR";
731 else
732 return "WARNING";
733}
734
735/**
736 * tomoyo_check_flags - Check mode for specified functionality.
737 *
738 * @domain: Pointer to "struct tomoyo_domain_info".
739 * @index: The functionality to check mode.
740 *
741 * TOMOYO checks only process context.
742 * This code disables TOMOYO's enforcement in case the function is called from
743 * interrupt context.
744 */
745unsigned int tomoyo_check_flags(const struct tomoyo_domain_info *domain,
746 const u8 index)
747{
748 const u8 profile = domain->profile;
749
750 if (WARN_ON(in_interrupt()))
751 return 0;
752 return tomoyo_policy_loaded && index < TOMOYO_MAX_CONTROL_INDEX
753#if TOMOYO_MAX_PROFILES != 256
754 && profile < TOMOYO_MAX_PROFILES
755#endif
756 && tomoyo_profile_ptr[profile] ?
757 tomoyo_profile_ptr[profile]->value[index] : 0;
758}
759
760/**
761 * tomoyo_verbose_mode - Check whether TOMOYO is verbose mode.
762 *
763 * @domain: Pointer to "struct tomoyo_domain_info".
764 *
765 * Returns true if domain policy violation warning should be printed to
766 * console.
767 */
768bool tomoyo_verbose_mode(const struct tomoyo_domain_info *domain)
769{
770 return tomoyo_check_flags(domain, TOMOYO_VERBOSE) != 0;
771}
772
773/**
774 * tomoyo_domain_quota_is_ok - Check for domain's quota.
775 *
776 * @domain: Pointer to "struct tomoyo_domain_info".
777 *
778 * Returns true if the domain is not exceeded quota, false otherwise.
779 */
780bool tomoyo_domain_quota_is_ok(struct tomoyo_domain_info * const domain)
781{
782 unsigned int count = 0;
783 struct tomoyo_acl_info *ptr;
784
785 if (!domain)
786 return true;
787 down_read(&tomoyo_domain_acl_info_list_lock);
788 list_for_each_entry(ptr, &domain->acl_info_list, list) {
789 if (ptr->type & TOMOYO_ACL_DELETED)
790 continue;
791 switch (tomoyo_acl_type2(ptr)) {
792 struct tomoyo_single_path_acl_record *acl1;
793 struct tomoyo_double_path_acl_record *acl2;
794 u16 perm;
795 case TOMOYO_TYPE_SINGLE_PATH_ACL:
796 acl1 = container_of(ptr,
797 struct tomoyo_single_path_acl_record,
798 head);
799 perm = acl1->perm;
800 if (perm & (1 << TOMOYO_TYPE_EXECUTE_ACL))
801 count++;
802 if (perm &
803 ((1 << TOMOYO_TYPE_READ_ACL) |
804 (1 << TOMOYO_TYPE_WRITE_ACL)))
805 count++;
806 if (perm & (1 << TOMOYO_TYPE_CREATE_ACL))
807 count++;
808 if (perm & (1 << TOMOYO_TYPE_UNLINK_ACL))
809 count++;
810 if (perm & (1 << TOMOYO_TYPE_MKDIR_ACL))
811 count++;
812 if (perm & (1 << TOMOYO_TYPE_RMDIR_ACL))
813 count++;
814 if (perm & (1 << TOMOYO_TYPE_MKFIFO_ACL))
815 count++;
816 if (perm & (1 << TOMOYO_TYPE_MKSOCK_ACL))
817 count++;
818 if (perm & (1 << TOMOYO_TYPE_MKBLOCK_ACL))
819 count++;
820 if (perm & (1 << TOMOYO_TYPE_MKCHAR_ACL))
821 count++;
822 if (perm & (1 << TOMOYO_TYPE_TRUNCATE_ACL))
823 count++;
824 if (perm & (1 << TOMOYO_TYPE_SYMLINK_ACL))
825 count++;
826 if (perm & (1 << TOMOYO_TYPE_REWRITE_ACL))
827 count++;
828 break;
829 case TOMOYO_TYPE_DOUBLE_PATH_ACL:
830 acl2 = container_of(ptr,
831 struct tomoyo_double_path_acl_record,
832 head);
833 perm = acl2->perm;
834 if (perm & (1 << TOMOYO_TYPE_LINK_ACL))
835 count++;
836 if (perm & (1 << TOMOYO_TYPE_RENAME_ACL))
837 count++;
838 break;
839 }
840 }
841 up_read(&tomoyo_domain_acl_info_list_lock);
842 if (count < tomoyo_check_flags(domain, TOMOYO_MAX_ACCEPT_ENTRY))
843 return true;
844 if (!domain->quota_warned) {
845 domain->quota_warned = true;
846 printk(KERN_WARNING "TOMOYO-WARNING: "
847 "Domain '%s' has so many ACLs to hold. "
848 "Stopped learning mode.\n", domain->domainname->name);
849 }
850 return false;
851}
852
853/**
854 * tomoyo_find_or_assign_new_profile - Create a new profile.
855 *
856 * @profile: Profile number to create.
857 *
858 * Returns pointer to "struct tomoyo_profile" on success, NULL otherwise.
859 */
860static struct tomoyo_profile *tomoyo_find_or_assign_new_profile(const unsigned
861 int profile)
862{
863 static DEFINE_MUTEX(lock);
864 struct tomoyo_profile *ptr = NULL;
865 int i;
866
867 if (profile >= TOMOYO_MAX_PROFILES)
868 return NULL;
869 /***** EXCLUSIVE SECTION START *****/
870 mutex_lock(&lock);
871 ptr = tomoyo_profile_ptr[profile];
872 if (ptr)
873 goto ok;
874 ptr = tomoyo_alloc_element(sizeof(*ptr));
875 if (!ptr)
876 goto ok;
877 for (i = 0; i < TOMOYO_MAX_CONTROL_INDEX; i++)
878 ptr->value[i] = tomoyo_control_array[i].current_value;
879 mb(); /* Avoid out-of-order execution. */
880 tomoyo_profile_ptr[profile] = ptr;
881 ok:
882 mutex_unlock(&lock);
883 /***** EXCLUSIVE SECTION END *****/
884 return ptr;
885}
886
887/**
888 * tomoyo_write_profile - Write to profile table.
889 *
890 * @head: Pointer to "struct tomoyo_io_buffer".
891 *
892 * Returns 0 on success, negative value otherwise.
893 */
894static int tomoyo_write_profile(struct tomoyo_io_buffer *head)
895{
896 char *data = head->write_buf;
897 unsigned int i;
898 unsigned int value;
899 char *cp;
900 struct tomoyo_profile *profile;
901 unsigned long num;
902
903 cp = strchr(data, '-');
904 if (cp)
905 *cp = '\0';
906 if (strict_strtoul(data, 10, &num))
907 return -EINVAL;
908 if (cp)
909 data = cp + 1;
910 profile = tomoyo_find_or_assign_new_profile(num);
911 if (!profile)
912 return -EINVAL;
913 cp = strchr(data, '=');
914 if (!cp)
915 return -EINVAL;
916 *cp = '\0';
917 if (!strcmp(data, "COMMENT")) {
918 profile->comment = tomoyo_save_name(cp + 1);
919 return 0;
920 }
921 for (i = 0; i < TOMOYO_MAX_CONTROL_INDEX; i++) {
922 if (strcmp(data, tomoyo_control_array[i].keyword))
923 continue;
924 if (sscanf(cp + 1, "%u", &value) != 1) {
925 int j;
926 const char **modes;
927 switch (i) {
928 case TOMOYO_VERBOSE:
929 modes = tomoyo_mode_2;
930 break;
931 default:
932 modes = tomoyo_mode_4;
933 break;
934 }
935 for (j = 0; j < 4; j++) {
936 if (strcmp(cp + 1, modes[j]))
937 continue;
938 value = j;
939 break;
940 }
941 if (j == 4)
942 return -EINVAL;
943 } else if (value > tomoyo_control_array[i].max_value) {
944 value = tomoyo_control_array[i].max_value;
945 }
946 profile->value[i] = value;
947 return 0;
948 }
949 return -EINVAL;
950}
951
952/**
953 * tomoyo_read_profile - Read from profile table.
954 *
955 * @head: Pointer to "struct tomoyo_io_buffer".
956 *
957 * Returns 0.
958 */
959static int tomoyo_read_profile(struct tomoyo_io_buffer *head)
960{
961 static const int total = TOMOYO_MAX_CONTROL_INDEX + 1;
962 int step;
963
964 if (head->read_eof)
965 return 0;
966 for (step = head->read_step; step < TOMOYO_MAX_PROFILES * total;
967 step++) {
968 const u8 index = step / total;
969 u8 type = step % total;
970 const struct tomoyo_profile *profile
971 = tomoyo_profile_ptr[index];
972 head->read_step = step;
973 if (!profile)
974 continue;
975 if (!type) { /* Print profile' comment tag. */
976 if (!tomoyo_io_printf(head, "%u-COMMENT=%s\n",
977 index, profile->comment ?
978 profile->comment->name : ""))
979 break;
980 continue;
981 }
982 type--;
983 if (type < TOMOYO_MAX_CONTROL_INDEX) {
984 const unsigned int value = profile->value[type];
985 const char **modes = NULL;
986 const char *keyword
987 = tomoyo_control_array[type].keyword;
988 switch (tomoyo_control_array[type].max_value) {
989 case 3:
990 modes = tomoyo_mode_4;
991 break;
992 case 1:
993 modes = tomoyo_mode_2;
994 break;
995 }
996 if (modes) {
997 if (!tomoyo_io_printf(head, "%u-%s=%s\n", index,
998 keyword, modes[value]))
999 break;
1000 } else {
1001 if (!tomoyo_io_printf(head, "%u-%s=%u\n", index,
1002 keyword, value))
1003 break;
1004 }
1005 }
1006 }
1007 if (step == TOMOYO_MAX_PROFILES * total)
1008 head->read_eof = true;
1009 return 0;
1010}
1011
1012/* Structure for policy manager. */
1013struct tomoyo_policy_manager_entry {
1014 struct list_head list;
1015 /* A path to program or a domainname. */
1016 const struct tomoyo_path_info *manager;
1017 bool is_domain; /* True if manager is a domainname. */
1018 bool is_deleted; /* True if this entry is deleted. */
1019};
1020
1021/* The list for "struct tomoyo_policy_manager_entry". */
1022static LIST_HEAD(tomoyo_policy_manager_list);
1023static DECLARE_RWSEM(tomoyo_policy_manager_list_lock);
1024
1025/**
1026 * tomoyo_update_manager_entry - Add a manager entry.
1027 *
1028 * @manager: The path to manager or the domainnamme.
1029 * @is_delete: True if it is a delete request.
1030 *
1031 * Returns 0 on success, negative value otherwise.
1032 */
1033static int tomoyo_update_manager_entry(const char *manager,
1034 const bool is_delete)
1035{
1036 struct tomoyo_policy_manager_entry *new_entry;
1037 struct tomoyo_policy_manager_entry *ptr;
1038 const struct tomoyo_path_info *saved_manager;
1039 int error = -ENOMEM;
1040 bool is_domain = false;
1041
1042 if (tomoyo_is_domain_def(manager)) {
1043 if (!tomoyo_is_correct_domain(manager, __func__))
1044 return -EINVAL;
1045 is_domain = true;
1046 } else {
1047 if (!tomoyo_is_correct_path(manager, 1, -1, -1, __func__))
1048 return -EINVAL;
1049 }
1050 saved_manager = tomoyo_save_name(manager);
1051 if (!saved_manager)
1052 return -ENOMEM;
1053 /***** EXCLUSIVE SECTION START *****/
1054 down_write(&tomoyo_policy_manager_list_lock);
1055 list_for_each_entry(ptr, &tomoyo_policy_manager_list, list) {
1056 if (ptr->manager != saved_manager)
1057 continue;
1058 ptr->is_deleted = is_delete;
1059 error = 0;
1060 goto out;
1061 }
1062 if (is_delete) {
1063 error = -ENOENT;
1064 goto out;
1065 }
1066 new_entry = tomoyo_alloc_element(sizeof(*new_entry));
1067 if (!new_entry)
1068 goto out;
1069 new_entry->manager = saved_manager;
1070 new_entry->is_domain = is_domain;
1071 list_add_tail(&new_entry->list, &tomoyo_policy_manager_list);
1072 error = 0;
1073 out:
1074 up_write(&tomoyo_policy_manager_list_lock);
1075 /***** EXCLUSIVE SECTION END *****/
1076 return error;
1077}
1078
1079/**
1080 * tomoyo_write_manager_policy - Write manager policy.
1081 *
1082 * @head: Pointer to "struct tomoyo_io_buffer".
1083 *
1084 * Returns 0 on success, negative value otherwise.
1085 */
1086static int tomoyo_write_manager_policy(struct tomoyo_io_buffer *head)
1087{
1088 char *data = head->write_buf;
1089 bool is_delete = tomoyo_str_starts(&data, TOMOYO_KEYWORD_DELETE);
1090
1091 if (!strcmp(data, "manage_by_non_root")) {
1092 tomoyo_manage_by_non_root = !is_delete;
1093 return 0;
1094 }
1095 return tomoyo_update_manager_entry(data, is_delete);
1096}
1097
1098/**
1099 * tomoyo_read_manager_policy - Read manager policy.
1100 *
1101 * @head: Pointer to "struct tomoyo_io_buffer".
1102 *
1103 * Returns 0.
1104 */
1105static int tomoyo_read_manager_policy(struct tomoyo_io_buffer *head)
1106{
1107 struct list_head *pos;
1108 bool done = true;
1109
1110 if (head->read_eof)
1111 return 0;
1112 down_read(&tomoyo_policy_manager_list_lock);
1113 list_for_each_cookie(pos, head->read_var2,
1114 &tomoyo_policy_manager_list) {
1115 struct tomoyo_policy_manager_entry *ptr;
1116 ptr = list_entry(pos, struct tomoyo_policy_manager_entry,
1117 list);
1118 if (ptr->is_deleted)
1119 continue;
1120 if (!tomoyo_io_printf(head, "%s\n", ptr->manager->name)) {
1121 done = false;
1122 break;
1123 }
1124 }
1125 up_read(&tomoyo_policy_manager_list_lock);
1126 head->read_eof = done;
1127 return 0;
1128}
1129
1130/**
1131 * tomoyo_is_policy_manager - Check whether the current process is a policy manager.
1132 *
1133 * Returns true if the current process is permitted to modify policy
1134 * via /sys/kernel/security/tomoyo/ interface.
1135 */
1136static bool tomoyo_is_policy_manager(void)
1137{
1138 struct tomoyo_policy_manager_entry *ptr;
1139 const char *exe;
1140 const struct task_struct *task = current;
1141 const struct tomoyo_path_info *domainname = tomoyo_domain()->domainname;
1142 bool found = false;
1143
1144 if (!tomoyo_policy_loaded)
1145 return true;
1146 if (!tomoyo_manage_by_non_root && (task->cred->uid || task->cred->euid))
1147 return false;
1148 down_read(&tomoyo_policy_manager_list_lock);
1149 list_for_each_entry(ptr, &tomoyo_policy_manager_list, list) {
1150 if (!ptr->is_deleted && ptr->is_domain
1151 && !tomoyo_pathcmp(domainname, ptr->manager)) {
1152 found = true;
1153 break;
1154 }
1155 }
1156 up_read(&tomoyo_policy_manager_list_lock);
1157 if (found)
1158 return true;
1159 exe = tomoyo_get_exe();
1160 if (!exe)
1161 return false;
1162 down_read(&tomoyo_policy_manager_list_lock);
1163 list_for_each_entry(ptr, &tomoyo_policy_manager_list, list) {
1164 if (!ptr->is_deleted && !ptr->is_domain
1165 && !strcmp(exe, ptr->manager->name)) {
1166 found = true;
1167 break;
1168 }
1169 }
1170 up_read(&tomoyo_policy_manager_list_lock);
1171 if (!found) { /* Reduce error messages. */
1172 static pid_t last_pid;
1173 const pid_t pid = current->pid;
1174 if (last_pid != pid) {
1175 printk(KERN_WARNING "%s ( %s ) is not permitted to "
1176 "update policies.\n", domainname->name, exe);
1177 last_pid = pid;
1178 }
1179 }
1180 tomoyo_free(exe);
1181 return found;
1182}
1183
1184/**
1185 * tomoyo_is_select_one - Parse select command.
1186 *
1187 * @head: Pointer to "struct tomoyo_io_buffer".
1188 * @data: String to parse.
1189 *
1190 * Returns true on success, false otherwise.
1191 */
1192static bool tomoyo_is_select_one(struct tomoyo_io_buffer *head,
1193 const char *data)
1194{
1195 unsigned int pid;
1196 struct tomoyo_domain_info *domain = NULL;
1197
1198 if (sscanf(data, "pid=%u", &pid) == 1) {
1199 struct task_struct *p;
1200 /***** CRITICAL SECTION START *****/
1201 read_lock(&tasklist_lock);
1202 p = find_task_by_vpid(pid);
1203 if (p)
1204 domain = tomoyo_real_domain(p);
1205 read_unlock(&tasklist_lock);
1206 /***** CRITICAL SECTION END *****/
1207 } else if (!strncmp(data, "domain=", 7)) {
1208 if (tomoyo_is_domain_def(data + 7)) {
1209 down_read(&tomoyo_domain_list_lock);
1210 domain = tomoyo_find_domain(data + 7);
1211 up_read(&tomoyo_domain_list_lock);
1212 }
1213 } else
1214 return false;
1215 head->write_var1 = domain;
1216 /* Accessing read_buf is safe because head->io_sem is held. */
1217 if (!head->read_buf)
1218 return true; /* Do nothing if open(O_WRONLY). */
1219 head->read_avail = 0;
1220 tomoyo_io_printf(head, "# select %s\n", data);
1221 head->read_single_domain = true;
1222 head->read_eof = !domain;
1223 if (domain) {
1224 struct tomoyo_domain_info *d;
1225 head->read_var1 = NULL;
1226 down_read(&tomoyo_domain_list_lock);
1227 list_for_each_entry(d, &tomoyo_domain_list, list) {
1228 if (d == domain)
1229 break;
1230 head->read_var1 = &d->list;
1231 }
1232 up_read(&tomoyo_domain_list_lock);
1233 head->read_var2 = NULL;
1234 head->read_bit = 0;
1235 head->read_step = 0;
1236 if (domain->is_deleted)
1237 tomoyo_io_printf(head, "# This is a deleted domain.\n");
1238 }
1239 return true;
1240}
1241
1242/**
1243 * tomoyo_write_domain_policy - Write domain policy.
1244 *
1245 * @head: Pointer to "struct tomoyo_io_buffer".
1246 *
1247 * Returns 0 on success, negative value otherwise.
1248 */
1249static int tomoyo_write_domain_policy(struct tomoyo_io_buffer *head)
1250{
1251 char *data = head->write_buf;
1252 struct tomoyo_domain_info *domain = head->write_var1;
1253 bool is_delete = false;
1254 bool is_select = false;
1255 bool is_undelete = false;
1256 unsigned int profile;
1257
1258 if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_DELETE))
1259 is_delete = true;
1260 else if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_SELECT))
1261 is_select = true;
1262 else if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_UNDELETE))
1263 is_undelete = true;
1264 if (is_select && tomoyo_is_select_one(head, data))
1265 return 0;
1266 /* Don't allow updating policies by non manager programs. */
1267 if (!tomoyo_is_policy_manager())
1268 return -EPERM;
1269 if (tomoyo_is_domain_def(data)) {
1270 domain = NULL;
1271 if (is_delete)
1272 tomoyo_delete_domain(data);
1273 else if (is_select) {
1274 down_read(&tomoyo_domain_list_lock);
1275 domain = tomoyo_find_domain(data);
1276 up_read(&tomoyo_domain_list_lock);
1277 } else if (is_undelete)
1278 domain = tomoyo_undelete_domain(data);
1279 else
1280 domain = tomoyo_find_or_assign_new_domain(data, 0);
1281 head->write_var1 = domain;
1282 return 0;
1283 }
1284 if (!domain)
1285 return -EINVAL;
1286
1287 if (sscanf(data, TOMOYO_KEYWORD_USE_PROFILE "%u", &profile) == 1
1288 && profile < TOMOYO_MAX_PROFILES) {
1289 if (tomoyo_profile_ptr[profile] || !tomoyo_policy_loaded)
1290 domain->profile = (u8) profile;
1291 return 0;
1292 }
1293 if (!strcmp(data, TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ)) {
1294 tomoyo_set_domain_flag(domain, is_delete,
1295 TOMOYO_DOMAIN_FLAGS_IGNORE_GLOBAL_ALLOW_READ);
1296 return 0;
1297 }
1298 return tomoyo_write_file_policy(data, domain, is_delete);
1299}
1300
1301/**
1302 * tomoyo_print_single_path_acl - Print a single path ACL entry.
1303 *
1304 * @head: Pointer to "struct tomoyo_io_buffer".
1305 * @ptr: Pointer to "struct tomoyo_single_path_acl_record".
1306 *
1307 * Returns true on success, false otherwise.
1308 */
1309static bool tomoyo_print_single_path_acl(struct tomoyo_io_buffer *head,
1310 struct tomoyo_single_path_acl_record *
1311 ptr)
1312{
1313 int pos;
1314 u8 bit;
1315 const char *atmark = "";
1316 const char *filename;
1317 const u16 perm = ptr->perm;
1318
1319 filename = ptr->filename->name;
1320 for (bit = head->read_bit; bit < TOMOYO_MAX_SINGLE_PATH_OPERATION;
1321 bit++) {
1322 const char *msg;
1323 if (!(perm & (1 << bit)))
1324 continue;
1325 /* Print "read/write" instead of "read" and "write". */
1326 if ((bit == TOMOYO_TYPE_READ_ACL ||
1327 bit == TOMOYO_TYPE_WRITE_ACL)
1328 && (perm & (1 << TOMOYO_TYPE_READ_WRITE_ACL)))
1329 continue;
1330 msg = tomoyo_sp2keyword(bit);
1331 pos = head->read_avail;
1332 if (!tomoyo_io_printf(head, "allow_%s %s%s\n", msg,
1333 atmark, filename))
1334 goto out;
1335 }
1336 head->read_bit = 0;
1337 return true;
1338 out:
1339 head->read_bit = bit;
1340 head->read_avail = pos;
1341 return false;
1342}
1343
1344/**
1345 * tomoyo_print_double_path_acl - Print a double path ACL entry.
1346 *
1347 * @head: Pointer to "struct tomoyo_io_buffer".
1348 * @ptr: Pointer to "struct tomoyo_double_path_acl_record".
1349 *
1350 * Returns true on success, false otherwise.
1351 */
1352static bool tomoyo_print_double_path_acl(struct tomoyo_io_buffer *head,
1353 struct tomoyo_double_path_acl_record *
1354 ptr)
1355{
1356 int pos;
1357 const char *atmark1 = "";
1358 const char *atmark2 = "";
1359 const char *filename1;
1360 const char *filename2;
1361 const u8 perm = ptr->perm;
1362 u8 bit;
1363
1364 filename1 = ptr->filename1->name;
1365 filename2 = ptr->filename2->name;
1366 for (bit = head->read_bit; bit < TOMOYO_MAX_DOUBLE_PATH_OPERATION;
1367 bit++) {
1368 const char *msg;
1369 if (!(perm & (1 << bit)))
1370 continue;
1371 msg = tomoyo_dp2keyword(bit);
1372 pos = head->read_avail;
1373 if (!tomoyo_io_printf(head, "allow_%s %s%s %s%s\n", msg,
1374 atmark1, filename1, atmark2, filename2))
1375 goto out;
1376 }
1377 head->read_bit = 0;
1378 return true;
1379 out:
1380 head->read_bit = bit;
1381 head->read_avail = pos;
1382 return false;
1383}
1384
1385/**
1386 * tomoyo_print_entry - Print an ACL entry.
1387 *
1388 * @head: Pointer to "struct tomoyo_io_buffer".
1389 * @ptr: Pointer to an ACL entry.
1390 *
1391 * Returns true on success, false otherwise.
1392 */
1393static bool tomoyo_print_entry(struct tomoyo_io_buffer *head,
1394 struct tomoyo_acl_info *ptr)
1395{
1396 const u8 acl_type = tomoyo_acl_type2(ptr);
1397
1398 if (acl_type & TOMOYO_ACL_DELETED)
1399 return true;
1400 if (acl_type == TOMOYO_TYPE_SINGLE_PATH_ACL) {
1401 struct tomoyo_single_path_acl_record *acl
1402 = container_of(ptr,
1403 struct tomoyo_single_path_acl_record,
1404 head);
1405 return tomoyo_print_single_path_acl(head, acl);
1406 }
1407 if (acl_type == TOMOYO_TYPE_DOUBLE_PATH_ACL) {
1408 struct tomoyo_double_path_acl_record *acl
1409 = container_of(ptr,
1410 struct tomoyo_double_path_acl_record,
1411 head);
1412 return tomoyo_print_double_path_acl(head, acl);
1413 }
1414 BUG(); /* This must not happen. */
1415 return false;
1416}
1417
1418/**
1419 * tomoyo_read_domain_policy - Read domain policy.
1420 *
1421 * @head: Pointer to "struct tomoyo_io_buffer".
1422 *
1423 * Returns 0.
1424 */
1425static int tomoyo_read_domain_policy(struct tomoyo_io_buffer *head)
1426{
1427 struct list_head *dpos;
1428 struct list_head *apos;
1429 bool done = true;
1430
1431 if (head->read_eof)
1432 return 0;
1433 if (head->read_step == 0)
1434 head->read_step = 1;
1435 down_read(&tomoyo_domain_list_lock);
1436 list_for_each_cookie(dpos, head->read_var1, &tomoyo_domain_list) {
1437 struct tomoyo_domain_info *domain;
1438 const char *quota_exceeded = "";
1439 const char *transition_failed = "";
1440 const char *ignore_global_allow_read = "";
1441 domain = list_entry(dpos, struct tomoyo_domain_info, list);
1442 if (head->read_step != 1)
1443 goto acl_loop;
1444 if (domain->is_deleted && !head->read_single_domain)
1445 continue;
1446 /* Print domainname and flags. */
1447 if (domain->quota_warned)
1448 quota_exceeded = "quota_exceeded\n";
1449 if (domain->flags & TOMOYO_DOMAIN_FLAGS_TRANSITION_FAILED)
1450 transition_failed = "transition_failed\n";
1451 if (domain->flags &
1452 TOMOYO_DOMAIN_FLAGS_IGNORE_GLOBAL_ALLOW_READ)
1453 ignore_global_allow_read
1454 = TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ "\n";
1455 if (!tomoyo_io_printf(head,
1456 "%s\n" TOMOYO_KEYWORD_USE_PROFILE "%u\n"
1457 "%s%s%s\n", domain->domainname->name,
1458 domain->profile, quota_exceeded,
1459 transition_failed,
1460 ignore_global_allow_read)) {
1461 done = false;
1462 break;
1463 }
1464 head->read_step = 2;
1465acl_loop:
1466 if (head->read_step == 3)
1467 goto tail_mark;
1468 /* Print ACL entries in the domain. */
1469 down_read(&tomoyo_domain_acl_info_list_lock);
1470 list_for_each_cookie(apos, head->read_var2,
1471 &domain->acl_info_list) {
1472 struct tomoyo_acl_info *ptr
1473 = list_entry(apos, struct tomoyo_acl_info,
1474 list);
1475 if (!tomoyo_print_entry(head, ptr)) {
1476 done = false;
1477 break;
1478 }
1479 }
1480 up_read(&tomoyo_domain_acl_info_list_lock);
1481 if (!done)
1482 break;
1483 head->read_step = 3;
1484tail_mark:
1485 if (!tomoyo_io_printf(head, "\n")) {
1486 done = false;
1487 break;
1488 }
1489 head->read_step = 1;
1490 if (head->read_single_domain)
1491 break;
1492 }
1493 up_read(&tomoyo_domain_list_lock);
1494 head->read_eof = done;
1495 return 0;
1496}
1497
1498/**
1499 * tomoyo_write_domain_profile - Assign profile for specified domain.
1500 *
1501 * @head: Pointer to "struct tomoyo_io_buffer".
1502 *
1503 * Returns 0 on success, -EINVAL otherwise.
1504 *
1505 * This is equivalent to doing
1506 *
1507 * ( echo "select " $domainname; echo "use_profile " $profile ) |
1508 * /usr/lib/ccs/loadpolicy -d
1509 */
1510static int tomoyo_write_domain_profile(struct tomoyo_io_buffer *head)
1511{
1512 char *data = head->write_buf;
1513 char *cp = strchr(data, ' ');
1514 struct tomoyo_domain_info *domain;
1515 unsigned long profile;
1516
1517 if (!cp)
1518 return -EINVAL;
1519 *cp = '\0';
1520 down_read(&tomoyo_domain_list_lock);
1521 domain = tomoyo_find_domain(cp + 1);
1522 up_read(&tomoyo_domain_list_lock);
1523 if (strict_strtoul(data, 10, &profile))
1524 return -EINVAL;
1525 if (domain && profile < TOMOYO_MAX_PROFILES
1526 && (tomoyo_profile_ptr[profile] || !tomoyo_policy_loaded))
1527 domain->profile = (u8) profile;
1528 return 0;
1529}
1530
1531/**
1532 * tomoyo_read_domain_profile - Read only domainname and profile.
1533 *
1534 * @head: Pointer to "struct tomoyo_io_buffer".
1535 *
1536 * Returns list of profile number and domainname pairs.
1537 *
1538 * This is equivalent to doing
1539 *
1540 * grep -A 1 '^<kernel>' /sys/kernel/security/tomoyo/domain_policy |
1541 * awk ' { if ( domainname == "" ) { if ( $1 == "<kernel>" )
1542 * domainname = $0; } else if ( $1 == "use_profile" ) {
1543 * print $2 " " domainname; domainname = ""; } } ; '
1544 */
1545static int tomoyo_read_domain_profile(struct tomoyo_io_buffer *head)
1546{
1547 struct list_head *pos;
1548 bool done = true;
1549
1550 if (head->read_eof)
1551 return 0;
1552 down_read(&tomoyo_domain_list_lock);
1553 list_for_each_cookie(pos, head->read_var1, &tomoyo_domain_list) {
1554 struct tomoyo_domain_info *domain;
1555 domain = list_entry(pos, struct tomoyo_domain_info, list);
1556 if (domain->is_deleted)
1557 continue;
1558 if (!tomoyo_io_printf(head, "%u %s\n", domain->profile,
1559 domain->domainname->name)) {
1560 done = false;
1561 break;
1562 }
1563 }
1564 up_read(&tomoyo_domain_list_lock);
1565 head->read_eof = done;
1566 return 0;
1567}
1568
1569/**
1570 * tomoyo_write_pid: Specify PID to obtain domainname.
1571 *
1572 * @head: Pointer to "struct tomoyo_io_buffer".
1573 *
1574 * Returns 0.
1575 */
1576static int tomoyo_write_pid(struct tomoyo_io_buffer *head)
1577{
1578 unsigned long pid;
1579 /* No error check. */
1580 strict_strtoul(head->write_buf, 10, &pid);
1581 head->read_step = (int) pid;
1582 head->read_eof = false;
1583 return 0;
1584}
1585
1586/**
1587 * tomoyo_read_pid - Get domainname of the specified PID.
1588 *
1589 * @head: Pointer to "struct tomoyo_io_buffer".
1590 *
1591 * Returns the domainname which the specified PID is in on success,
1592 * empty string otherwise.
1593 * The PID is specified by tomoyo_write_pid() so that the user can obtain
1594 * using read()/write() interface rather than sysctl() interface.
1595 */
1596static int tomoyo_read_pid(struct tomoyo_io_buffer *head)
1597{
1598 if (head->read_avail == 0 && !head->read_eof) {
1599 const int pid = head->read_step;
1600 struct task_struct *p;
1601 struct tomoyo_domain_info *domain = NULL;
1602 /***** CRITICAL SECTION START *****/
1603 read_lock(&tasklist_lock);
1604 p = find_task_by_vpid(pid);
1605 if (p)
1606 domain = tomoyo_real_domain(p);
1607 read_unlock(&tasklist_lock);
1608 /***** CRITICAL SECTION END *****/
1609 if (domain)
1610 tomoyo_io_printf(head, "%d %u %s", pid, domain->profile,
1611 domain->domainname->name);
1612 head->read_eof = true;
1613 }
1614 return 0;
1615}
1616
1617/**
1618 * tomoyo_write_exception_policy - Write exception policy.
1619 *
1620 * @head: Pointer to "struct tomoyo_io_buffer".
1621 *
1622 * Returns 0 on success, negative value otherwise.
1623 */
1624static int tomoyo_write_exception_policy(struct tomoyo_io_buffer *head)
1625{
1626 char *data = head->write_buf;
1627 bool is_delete = tomoyo_str_starts(&data, TOMOYO_KEYWORD_DELETE);
1628
1629 if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_KEEP_DOMAIN))
1630 return tomoyo_write_domain_keeper_policy(data, false,
1631 is_delete);
1632 if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_NO_KEEP_DOMAIN))
1633 return tomoyo_write_domain_keeper_policy(data, true, is_delete);
1634 if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_INITIALIZE_DOMAIN))
1635 return tomoyo_write_domain_initializer_policy(data, false,
1636 is_delete);
1637 if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_NO_INITIALIZE_DOMAIN))
1638 return tomoyo_write_domain_initializer_policy(data, true,
1639 is_delete);
1640 if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_ALIAS))
1641 return tomoyo_write_alias_policy(data, is_delete);
1642 if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_ALLOW_READ))
1643 return tomoyo_write_globally_readable_policy(data, is_delete);
1644 if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_FILE_PATTERN))
1645 return tomoyo_write_pattern_policy(data, is_delete);
1646 if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_DENY_REWRITE))
1647 return tomoyo_write_no_rewrite_policy(data, is_delete);
1648 return -EINVAL;
1649}
1650
1651/**
1652 * tomoyo_read_exception_policy - Read exception policy.
1653 *
1654 * @head: Pointer to "struct tomoyo_io_buffer".
1655 *
1656 * Returns 0 on success, -EINVAL otherwise.
1657 */
1658static int tomoyo_read_exception_policy(struct tomoyo_io_buffer *head)
1659{
1660 if (!head->read_eof) {
1661 switch (head->read_step) {
1662 case 0:
1663 head->read_var2 = NULL;
1664 head->read_step = 1;
1665 case 1:
1666 if (!tomoyo_read_domain_keeper_policy(head))
1667 break;
1668 head->read_var2 = NULL;
1669 head->read_step = 2;
1670 case 2:
1671 if (!tomoyo_read_globally_readable_policy(head))
1672 break;
1673 head->read_var2 = NULL;
1674 head->read_step = 3;
1675 case 3:
1676 head->read_var2 = NULL;
1677 head->read_step = 4;
1678 case 4:
1679 if (!tomoyo_read_domain_initializer_policy(head))
1680 break;
1681 head->read_var2 = NULL;
1682 head->read_step = 5;
1683 case 5:
1684 if (!tomoyo_read_alias_policy(head))
1685 break;
1686 head->read_var2 = NULL;
1687 head->read_step = 6;
1688 case 6:
1689 head->read_var2 = NULL;
1690 head->read_step = 7;
1691 case 7:
1692 if (!tomoyo_read_file_pattern(head))
1693 break;
1694 head->read_var2 = NULL;
1695 head->read_step = 8;
1696 case 8:
1697 if (!tomoyo_read_no_rewrite_policy(head))
1698 break;
1699 head->read_var2 = NULL;
1700 head->read_step = 9;
1701 case 9:
1702 head->read_eof = true;
1703 break;
1704 default:
1705 return -EINVAL;
1706 }
1707 }
1708 return 0;
1709}
1710
1711/* path to policy loader */
1712static const char *tomoyo_loader = "/sbin/tomoyo-init";
1713
1714/**
1715 * tomoyo_policy_loader_exists - Check whether /sbin/tomoyo-init exists.
1716 *
1717 * Returns true if /sbin/tomoyo-init exists, false otherwise.
1718 */
1719static bool tomoyo_policy_loader_exists(void)
1720{
1721 /*
1722 * Don't activate MAC if the policy loader doesn't exist.
1723 * If the initrd includes /sbin/init but real-root-dev has not
1724 * mounted on / yet, activating MAC will block the system since
1725 * policies are not loaded yet.
1726 * Thus, let do_execve() call this function everytime.
1727 */
1728 struct nameidata nd;
1729
1730 if (path_lookup(tomoyo_loader, LOOKUP_FOLLOW, &nd)) {
1731 printk(KERN_INFO "Not activating Mandatory Access Control now "
1732 "since %s doesn't exist.\n", tomoyo_loader);
1733 return false;
1734 }
1735 path_put(&nd.path);
1736 return true;
1737}
1738
1739/**
1740 * tomoyo_load_policy - Run external policy loader to load policy.
1741 *
1742 * @filename: The program about to start.
1743 *
1744 * This function checks whether @filename is /sbin/init , and if so
1745 * invoke /sbin/tomoyo-init and wait for the termination of /sbin/tomoyo-init
1746 * and then continues invocation of /sbin/init.
1747 * /sbin/tomoyo-init reads policy files in /etc/tomoyo/ directory and
1748 * writes to /sys/kernel/security/tomoyo/ interfaces.
1749 *
1750 * Returns nothing.
1751 */
1752void tomoyo_load_policy(const char *filename)
1753{
1754 char *argv[2];
1755 char *envp[3];
1756
1757 if (tomoyo_policy_loaded)
1758 return;
1759 /*
1760 * Check filename is /sbin/init or /sbin/tomoyo-start.
1761 * /sbin/tomoyo-start is a dummy filename in case where /sbin/init can't
1762 * be passed.
1763 * You can create /sbin/tomoyo-start by
1764 * "ln -s /bin/true /sbin/tomoyo-start".
1765 */
1766 if (strcmp(filename, "/sbin/init") &&
1767 strcmp(filename, "/sbin/tomoyo-start"))
1768 return;
1769 if (!tomoyo_policy_loader_exists())
1770 return;
1771
1772 printk(KERN_INFO "Calling %s to load policy. Please wait.\n",
1773 tomoyo_loader);
1774 argv[0] = (char *) tomoyo_loader;
1775 argv[1] = NULL;
1776 envp[0] = "HOME=/";
1777 envp[1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
1778 envp[2] = NULL;
1779 call_usermodehelper(argv[0], argv, envp, 1);
1780
1781 printk(KERN_INFO "TOMOYO: 2.2.0-pre 2009/02/01\n");
1782 printk(KERN_INFO "Mandatory Access Control activated.\n");
1783 tomoyo_policy_loaded = true;
1784 { /* Check all profiles currently assigned to domains are defined. */
1785 struct tomoyo_domain_info *domain;
1786 down_read(&tomoyo_domain_list_lock);
1787 list_for_each_entry(domain, &tomoyo_domain_list, list) {
1788 const u8 profile = domain->profile;
1789 if (tomoyo_profile_ptr[profile])
1790 continue;
1791 panic("Profile %u (used by '%s') not defined.\n",
1792 profile, domain->domainname->name);
1793 }
1794 up_read(&tomoyo_domain_list_lock);
1795 }
1796}
1797
1798/**
1799 * tomoyo_read_version: Get version.
1800 *
1801 * @head: Pointer to "struct tomoyo_io_buffer".
1802 *
1803 * Returns version information.
1804 */
1805static int tomoyo_read_version(struct tomoyo_io_buffer *head)
1806{
1807 if (!head->read_eof) {
1808 tomoyo_io_printf(head, "2.2.0-pre");
1809 head->read_eof = true;
1810 }
1811 return 0;
1812}
1813
1814/**
1815 * tomoyo_read_self_domain - Get the current process's domainname.
1816 *
1817 * @head: Pointer to "struct tomoyo_io_buffer".
1818 *
1819 * Returns the current process's domainname.
1820 */
1821static int tomoyo_read_self_domain(struct tomoyo_io_buffer *head)
1822{
1823 if (!head->read_eof) {
1824 /*
1825 * tomoyo_domain()->domainname != NULL
1826 * because every process belongs to a domain and
1827 * the domain's name cannot be NULL.
1828 */
1829 tomoyo_io_printf(head, "%s", tomoyo_domain()->domainname->name);
1830 head->read_eof = true;
1831 }
1832 return 0;
1833}
1834
1835/**
1836 * tomoyo_open_control - open() for /sys/kernel/security/tomoyo/ interface.
1837 *
1838 * @type: Type of interface.
1839 * @file: Pointer to "struct file".
1840 *
1841 * Associates policy handler and returns 0 on success, -ENOMEM otherwise.
1842 */
1843static int tomoyo_open_control(const u8 type, struct file *file)
1844{
1845 struct tomoyo_io_buffer *head = tomoyo_alloc(sizeof(*head));
1846
1847 if (!head)
1848 return -ENOMEM;
1849 mutex_init(&head->io_sem);
1850 switch (type) {
1851 case TOMOYO_DOMAINPOLICY:
1852 /* /sys/kernel/security/tomoyo/domain_policy */
1853 head->write = tomoyo_write_domain_policy;
1854 head->read = tomoyo_read_domain_policy;
1855 break;
1856 case TOMOYO_EXCEPTIONPOLICY:
1857 /* /sys/kernel/security/tomoyo/exception_policy */
1858 head->write = tomoyo_write_exception_policy;
1859 head->read = tomoyo_read_exception_policy;
1860 break;
1861 case TOMOYO_SELFDOMAIN:
1862 /* /sys/kernel/security/tomoyo/self_domain */
1863 head->read = tomoyo_read_self_domain;
1864 break;
1865 case TOMOYO_DOMAIN_STATUS:
1866 /* /sys/kernel/security/tomoyo/.domain_status */
1867 head->write = tomoyo_write_domain_profile;
1868 head->read = tomoyo_read_domain_profile;
1869 break;
1870 case TOMOYO_PROCESS_STATUS:
1871 /* /sys/kernel/security/tomoyo/.process_status */
1872 head->write = tomoyo_write_pid;
1873 head->read = tomoyo_read_pid;
1874 break;
1875 case TOMOYO_VERSION:
1876 /* /sys/kernel/security/tomoyo/version */
1877 head->read = tomoyo_read_version;
1878 head->readbuf_size = 128;
1879 break;
1880 case TOMOYO_MEMINFO:
1881 /* /sys/kernel/security/tomoyo/meminfo */
1882 head->write = tomoyo_write_memory_quota;
1883 head->read = tomoyo_read_memory_counter;
1884 head->readbuf_size = 512;
1885 break;
1886 case TOMOYO_PROFILE:
1887 /* /sys/kernel/security/tomoyo/profile */
1888 head->write = tomoyo_write_profile;
1889 head->read = tomoyo_read_profile;
1890 break;
1891 case TOMOYO_MANAGER:
1892 /* /sys/kernel/security/tomoyo/manager */
1893 head->write = tomoyo_write_manager_policy;
1894 head->read = tomoyo_read_manager_policy;
1895 break;
1896 }
1897 if (!(file->f_mode & FMODE_READ)) {
1898 /*
1899 * No need to allocate read_buf since it is not opened
1900 * for reading.
1901 */
1902 head->read = NULL;
1903 } else {
1904 if (!head->readbuf_size)
1905 head->readbuf_size = 4096 * 2;
1906 head->read_buf = tomoyo_alloc(head->readbuf_size);
1907 if (!head->read_buf) {
1908 tomoyo_free(head);
1909 return -ENOMEM;
1910 }
1911 }
1912 if (!(file->f_mode & FMODE_WRITE)) {
1913 /*
1914 * No need to allocate write_buf since it is not opened
1915 * for writing.
1916 */
1917 head->write = NULL;
1918 } else if (head->write) {
1919 head->writebuf_size = 4096 * 2;
1920 head->write_buf = tomoyo_alloc(head->writebuf_size);
1921 if (!head->write_buf) {
1922 tomoyo_free(head->read_buf);
1923 tomoyo_free(head);
1924 return -ENOMEM;
1925 }
1926 }
1927 file->private_data = head;
1928 /*
1929 * Call the handler now if the file is
1930 * /sys/kernel/security/tomoyo/self_domain
1931 * so that the user can use
1932 * cat < /sys/kernel/security/tomoyo/self_domain"
1933 * to know the current process's domainname.
1934 */
1935 if (type == TOMOYO_SELFDOMAIN)
1936 tomoyo_read_control(file, NULL, 0);
1937 return 0;
1938}
1939
1940/**
1941 * tomoyo_read_control - read() for /sys/kernel/security/tomoyo/ interface.
1942 *
1943 * @file: Pointer to "struct file".
1944 * @buffer: Poiner to buffer to write to.
1945 * @buffer_len: Size of @buffer.
1946 *
1947 * Returns bytes read on success, negative value otherwise.
1948 */
1949static int tomoyo_read_control(struct file *file, char __user *buffer,
1950 const int buffer_len)
1951{
1952 int len = 0;
1953 struct tomoyo_io_buffer *head = file->private_data;
1954 char *cp;
1955
1956 if (!head->read)
1957 return -ENOSYS;
1958 if (mutex_lock_interruptible(&head->io_sem))
1959 return -EINTR;
1960 /* Call the policy handler. */
1961 len = head->read(head);
1962 if (len < 0)
1963 goto out;
1964 /* Write to buffer. */
1965 len = head->read_avail;
1966 if (len > buffer_len)
1967 len = buffer_len;
1968 if (!len)
1969 goto out;
1970 /* head->read_buf changes by some functions. */
1971 cp = head->read_buf;
1972 if (copy_to_user(buffer, cp, len)) {
1973 len = -EFAULT;
1974 goto out;
1975 }
1976 head->read_avail -= len;
1977 memmove(cp, cp + len, head->read_avail);
1978 out:
1979 mutex_unlock(&head->io_sem);
1980 return len;
1981}
1982
1983/**
1984 * tomoyo_write_control - write() for /sys/kernel/security/tomoyo/ interface.
1985 *
1986 * @file: Pointer to "struct file".
1987 * @buffer: Pointer to buffer to read from.
1988 * @buffer_len: Size of @buffer.
1989 *
1990 * Returns @buffer_len on success, negative value otherwise.
1991 */
1992static int tomoyo_write_control(struct file *file, const char __user *buffer,
1993 const int buffer_len)
1994{
1995 struct tomoyo_io_buffer *head = file->private_data;
1996 int error = buffer_len;
1997 int avail_len = buffer_len;
1998 char *cp0 = head->write_buf;
1999
2000 if (!head->write)
2001 return -ENOSYS;
2002 if (!access_ok(VERIFY_READ, buffer, buffer_len))
2003 return -EFAULT;
2004 /* Don't allow updating policies by non manager programs. */
2005 if (head->write != tomoyo_write_pid &&
2006 head->write != tomoyo_write_domain_policy &&
2007 !tomoyo_is_policy_manager())
2008 return -EPERM;
2009 if (mutex_lock_interruptible(&head->io_sem))
2010 return -EINTR;
2011 /* Read a line and dispatch it to the policy handler. */
2012 while (avail_len > 0) {
2013 char c;
2014 if (head->write_avail >= head->writebuf_size - 1) {
2015 error = -ENOMEM;
2016 break;
2017 } else if (get_user(c, buffer)) {
2018 error = -EFAULT;
2019 break;
2020 }
2021 buffer++;
2022 avail_len--;
2023 cp0[head->write_avail++] = c;
2024 if (c != '\n')
2025 continue;
2026 cp0[head->write_avail - 1] = '\0';
2027 head->write_avail = 0;
2028 tomoyo_normalize_line(cp0);
2029 head->write(head);
2030 }
2031 mutex_unlock(&head->io_sem);
2032 return error;
2033}
2034
2035/**
2036 * tomoyo_close_control - close() for /sys/kernel/security/tomoyo/ interface.
2037 *
2038 * @file: Pointer to "struct file".
2039 *
2040 * Releases memory and returns 0.
2041 */
2042static int tomoyo_close_control(struct file *file)
2043{
2044 struct tomoyo_io_buffer *head = file->private_data;
2045
2046 /* Release memory used for policy I/O. */
2047 tomoyo_free(head->read_buf);
2048 head->read_buf = NULL;
2049 tomoyo_free(head->write_buf);
2050 head->write_buf = NULL;
2051 tomoyo_free(head);
2052 head = NULL;
2053 file->private_data = NULL;
2054 return 0;
2055}
2056
2057/**
2058 * tomoyo_alloc_acl_element - Allocate permanent memory for ACL entry.
2059 *
2060 * @acl_type: Type of ACL entry.
2061 *
2062 * Returns pointer to the ACL entry on success, NULL otherwise.
2063 */
2064void *tomoyo_alloc_acl_element(const u8 acl_type)
2065{
2066 int len;
2067 struct tomoyo_acl_info *ptr;
2068
2069 switch (acl_type) {
2070 case TOMOYO_TYPE_SINGLE_PATH_ACL:
2071 len = sizeof(struct tomoyo_single_path_acl_record);
2072 break;
2073 case TOMOYO_TYPE_DOUBLE_PATH_ACL:
2074 len = sizeof(struct tomoyo_double_path_acl_record);
2075 break;
2076 default:
2077 return NULL;
2078 }
2079 ptr = tomoyo_alloc_element(len);
2080 if (!ptr)
2081 return NULL;
2082 ptr->type = acl_type;
2083 return ptr;
2084}
2085
2086/**
2087 * tomoyo_open - open() for /sys/kernel/security/tomoyo/ interface.
2088 *
2089 * @inode: Pointer to "struct inode".
2090 * @file: Pointer to "struct file".
2091 *
2092 * Returns 0 on success, negative value otherwise.
2093 */
2094static int tomoyo_open(struct inode *inode, struct file *file)
2095{
2096 const int key = ((u8 *) file->f_path.dentry->d_inode->i_private)
2097 - ((u8 *) NULL);
2098 return tomoyo_open_control(key, file);
2099}
2100
2101/**
2102 * tomoyo_release - close() for /sys/kernel/security/tomoyo/ interface.
2103 *
2104 * @inode: Pointer to "struct inode".
2105 * @file: Pointer to "struct file".
2106 *
2107 * Returns 0 on success, negative value otherwise.
2108 */
2109static int tomoyo_release(struct inode *inode, struct file *file)
2110{
2111 return tomoyo_close_control(file);
2112}
2113
2114/**
2115 * tomoyo_read - read() for /sys/kernel/security/tomoyo/ interface.
2116 *
2117 * @file: Pointer to "struct file".
2118 * @buf: Pointer to buffer.
2119 * @count: Size of @buf.
2120 * @ppos: Unused.
2121 *
2122 * Returns bytes read on success, negative value otherwise.
2123 */
2124static ssize_t tomoyo_read(struct file *file, char __user *buf, size_t count,
2125 loff_t *ppos)
2126{
2127 return tomoyo_read_control(file, buf, count);
2128}
2129
2130/**
2131 * tomoyo_write - write() for /sys/kernel/security/tomoyo/ interface.
2132 *
2133 * @file: Pointer to "struct file".
2134 * @buf: Pointer to buffer.
2135 * @count: Size of @buf.
2136 * @ppos: Unused.
2137 *
2138 * Returns @count on success, negative value otherwise.
2139 */
2140static ssize_t tomoyo_write(struct file *file, const char __user *buf,
2141 size_t count, loff_t *ppos)
2142{
2143 return tomoyo_write_control(file, buf, count);
2144}
2145
2146/* Operations for /sys/kernel/security/tomoyo/ interface. */
2147static const struct file_operations tomoyo_operations = {
2148 .open = tomoyo_open,
2149 .release = tomoyo_release,
2150 .read = tomoyo_read,
2151 .write = tomoyo_write,
2152};
2153
2154/**
2155 * tomoyo_create_entry - Create interface files under /sys/kernel/security/tomoyo/ directory.
2156 *
2157 * @name: The name of the interface file.
2158 * @mode: The permission of the interface file.
2159 * @parent: The parent directory.
2160 * @key: Type of interface.
2161 *
2162 * Returns nothing.
2163 */
2164static void __init tomoyo_create_entry(const char *name, const mode_t mode,
2165 struct dentry *parent, const u8 key)
2166{
2167 securityfs_create_file(name, mode, parent, ((u8 *) NULL) + key,
2168 &tomoyo_operations);
2169}
2170
2171/**
2172 * tomoyo_initerface_init - Initialize /sys/kernel/security/tomoyo/ interface.
2173 *
2174 * Returns 0.
2175 */
2176static int __init tomoyo_initerface_init(void)
2177{
2178 struct dentry *tomoyo_dir;
2179
2180 /* Don't create securityfs entries unless registered. */
2181 if (current_cred()->security != &tomoyo_kernel_domain)
2182 return 0;
2183
2184 tomoyo_dir = securityfs_create_dir("tomoyo", NULL);
2185 tomoyo_create_entry("domain_policy", 0600, tomoyo_dir,
2186 TOMOYO_DOMAINPOLICY);
2187 tomoyo_create_entry("exception_policy", 0600, tomoyo_dir,
2188 TOMOYO_EXCEPTIONPOLICY);
2189 tomoyo_create_entry("self_domain", 0400, tomoyo_dir,
2190 TOMOYO_SELFDOMAIN);
2191 tomoyo_create_entry(".domain_status", 0600, tomoyo_dir,
2192 TOMOYO_DOMAIN_STATUS);
2193 tomoyo_create_entry(".process_status", 0600, tomoyo_dir,
2194 TOMOYO_PROCESS_STATUS);
2195 tomoyo_create_entry("meminfo", 0600, tomoyo_dir,
2196 TOMOYO_MEMINFO);
2197 tomoyo_create_entry("profile", 0600, tomoyo_dir,
2198 TOMOYO_PROFILE);
2199 tomoyo_create_entry("manager", 0600, tomoyo_dir,
2200 TOMOYO_MANAGER);
2201 tomoyo_create_entry("version", 0400, tomoyo_dir,
2202 TOMOYO_VERSION);
2203 return 0;
2204}
2205
2206fs_initcall(tomoyo_initerface_init);
diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h
new file mode 100644
index 000000000000..26a76d67aa1c
--- /dev/null
+++ b/security/tomoyo/common.h
@@ -0,0 +1,359 @@
1/*
2 * security/tomoyo/common.h
3 *
4 * Common functions for TOMOYO.
5 *
6 * Copyright (C) 2005-2009 NTT DATA CORPORATION
7 *
8 * Version: 2.2.0-pre 2009/02/01
9 *
10 */
11
12#ifndef _SECURITY_TOMOYO_COMMON_H
13#define _SECURITY_TOMOYO_COMMON_H
14
15#include <linux/ctype.h>
16#include <linux/string.h>
17#include <linux/mm.h>
18#include <linux/file.h>
19#include <linux/kmod.h>
20#include <linux/fs.h>
21#include <linux/sched.h>
22#include <linux/namei.h>
23#include <linux/mount.h>
24#include <linux/list.h>
25
26struct dentry;
27struct vfsmount;
28
29/* Temporary buffer for holding pathnames. */
30struct tomoyo_page_buffer {
31 char buffer[4096];
32};
33
34/* Structure for holding a token. */
35struct tomoyo_path_info {
36 const char *name;
37 u32 hash; /* = full_name_hash(name, strlen(name)) */
38 u16 total_len; /* = strlen(name) */
39 u16 const_len; /* = tomoyo_const_part_length(name) */
40 bool is_dir; /* = tomoyo_strendswith(name, "/") */
41 bool is_patterned; /* = tomoyo_path_contains_pattern(name) */
42 u16 depth; /* = tomoyo_path_depth(name) */
43};
44
45/*
46 * This is the max length of a token.
47 *
48 * A token consists of only ASCII printable characters.
49 * Non printable characters in a token is represented in \ooo style
50 * octal string. Thus, \ itself is represented as \\.
51 */
52#define TOMOYO_MAX_PATHNAME_LEN 4000
53
54/* Structure for holding requested pathname. */
55struct tomoyo_path_info_with_data {
56 /* Keep "head" first, for this pointer is passed to tomoyo_free(). */
57 struct tomoyo_path_info head;
58 char barrier1[16]; /* Safeguard for overrun. */
59 char body[TOMOYO_MAX_PATHNAME_LEN];
60 char barrier2[16]; /* Safeguard for overrun. */
61};
62
63/*
64 * Common header for holding ACL entries.
65 *
66 * Packing "struct tomoyo_acl_info" allows
67 * "struct tomoyo_single_path_acl_record" to embed "u16" and
68 * "struct tomoyo_double_path_acl_record" to embed "u8"
69 * without enlarging their structure size.
70 */
71struct tomoyo_acl_info {
72 struct list_head list;
73 /*
74 * Type of this ACL entry.
75 *
76 * MSB is is_deleted flag.
77 */
78 u8 type;
79} __packed;
80
81/* This ACL entry is deleted. */
82#define TOMOYO_ACL_DELETED 0x80
83
84/* Structure for domain information. */
85struct tomoyo_domain_info {
86 struct list_head list;
87 struct list_head acl_info_list;
88 /* Name of this domain. Never NULL. */
89 const struct tomoyo_path_info *domainname;
90 u8 profile; /* Profile number to use. */
91 u8 is_deleted; /* Delete flag.
92 0 = active.
93 1 = deleted but undeletable.
94 255 = deleted and no longer undeletable. */
95 bool quota_warned; /* Quota warnning flag. */
96 /* DOMAIN_FLAGS_*. Use tomoyo_set_domain_flag() to modify. */
97 u8 flags;
98};
99
100/* Profile number is an integer between 0 and 255. */
101#define TOMOYO_MAX_PROFILES 256
102
103/* Ignore "allow_read" directive in exception policy. */
104#define TOMOYO_DOMAIN_FLAGS_IGNORE_GLOBAL_ALLOW_READ 1
105/*
106 * This domain was unable to create a new domain at tomoyo_find_next_domain()
107 * because the name of the domain to be created was too long or
108 * it could not allocate memory.
109 * More than one process continued execve() without domain transition.
110 */
111#define TOMOYO_DOMAIN_FLAGS_TRANSITION_FAILED 2
112
113/*
114 * Structure for "allow_read/write", "allow_execute", "allow_read",
115 * "allow_write", "allow_create", "allow_unlink", "allow_mkdir", "allow_rmdir",
116 * "allow_mkfifo", "allow_mksock", "allow_mkblock", "allow_mkchar",
117 * "allow_truncate", "allow_symlink" and "allow_rewrite" directive.
118 */
119struct tomoyo_single_path_acl_record {
120 struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_SINGLE_PATH_ACL */
121 u16 perm;
122 /* Pointer to single pathname. */
123 const struct tomoyo_path_info *filename;
124};
125
126/* Structure for "allow_rename" and "allow_link" directive. */
127struct tomoyo_double_path_acl_record {
128 struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_DOUBLE_PATH_ACL */
129 u8 perm;
130 /* Pointer to single pathname. */
131 const struct tomoyo_path_info *filename1;
132 /* Pointer to single pathname. */
133 const struct tomoyo_path_info *filename2;
134};
135
136/* Keywords for ACLs. */
137#define TOMOYO_KEYWORD_ALIAS "alias "
138#define TOMOYO_KEYWORD_ALLOW_READ "allow_read "
139#define TOMOYO_KEYWORD_DELETE "delete "
140#define TOMOYO_KEYWORD_DENY_REWRITE "deny_rewrite "
141#define TOMOYO_KEYWORD_FILE_PATTERN "file_pattern "
142#define TOMOYO_KEYWORD_INITIALIZE_DOMAIN "initialize_domain "
143#define TOMOYO_KEYWORD_KEEP_DOMAIN "keep_domain "
144#define TOMOYO_KEYWORD_NO_INITIALIZE_DOMAIN "no_initialize_domain "
145#define TOMOYO_KEYWORD_NO_KEEP_DOMAIN "no_keep_domain "
146#define TOMOYO_KEYWORD_SELECT "select "
147#define TOMOYO_KEYWORD_UNDELETE "undelete "
148#define TOMOYO_KEYWORD_USE_PROFILE "use_profile "
149#define TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ "ignore_global_allow_read"
150/* A domain definition starts with <kernel>. */
151#define TOMOYO_ROOT_NAME "<kernel>"
152#define TOMOYO_ROOT_NAME_LEN (sizeof(TOMOYO_ROOT_NAME) - 1)
153
154/* Index numbers for Access Controls. */
155#define TOMOYO_MAC_FOR_FILE 0 /* domain_policy.conf */
156#define TOMOYO_MAX_ACCEPT_ENTRY 1
157#define TOMOYO_VERBOSE 2
158#define TOMOYO_MAX_CONTROL_INDEX 3
159
160/* Structure for reading/writing policy via securityfs interfaces. */
161struct tomoyo_io_buffer {
162 int (*read) (struct tomoyo_io_buffer *);
163 int (*write) (struct tomoyo_io_buffer *);
164 /* Exclusive lock for this structure. */
165 struct mutex io_sem;
166 /* The position currently reading from. */
167 struct list_head *read_var1;
168 /* Extra variables for reading. */
169 struct list_head *read_var2;
170 /* The position currently writing to. */
171 struct tomoyo_domain_info *write_var1;
172 /* The step for reading. */
173 int read_step;
174 /* Buffer for reading. */
175 char *read_buf;
176 /* EOF flag for reading. */
177 bool read_eof;
178 /* Read domain ACL of specified PID? */
179 bool read_single_domain;
180 /* Extra variable for reading. */
181 u8 read_bit;
182 /* Bytes available for reading. */
183 int read_avail;
184 /* Size of read buffer. */
185 int readbuf_size;
186 /* Buffer for writing. */
187 char *write_buf;
188 /* Bytes available for writing. */
189 int write_avail;
190 /* Size of write buffer. */
191 int writebuf_size;
192};
193
194/* Check whether the domain has too many ACL entries to hold. */
195bool tomoyo_domain_quota_is_ok(struct tomoyo_domain_info * const domain);
196/* Transactional sprintf() for policy dump. */
197bool tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt, ...)
198 __attribute__ ((format(printf, 2, 3)));
199/* Check whether the domainname is correct. */
200bool tomoyo_is_correct_domain(const unsigned char *domainname,
201 const char *function);
202/* Check whether the token is correct. */
203bool tomoyo_is_correct_path(const char *filename, const s8 start_type,
204 const s8 pattern_type, const s8 end_type,
205 const char *function);
206/* Check whether the token can be a domainname. */
207bool tomoyo_is_domain_def(const unsigned char *buffer);
208/* Check whether the given filename matches the given pattern. */
209bool tomoyo_path_matches_pattern(const struct tomoyo_path_info *filename,
210 const struct tomoyo_path_info *pattern);
211/* Read "alias" entry in exception policy. */
212bool tomoyo_read_alias_policy(struct tomoyo_io_buffer *head);
213/*
214 * Read "initialize_domain" and "no_initialize_domain" entry
215 * in exception policy.
216 */
217bool tomoyo_read_domain_initializer_policy(struct tomoyo_io_buffer *head);
218/* Read "keep_domain" and "no_keep_domain" entry in exception policy. */
219bool tomoyo_read_domain_keeper_policy(struct tomoyo_io_buffer *head);
220/* Read "file_pattern" entry in exception policy. */
221bool tomoyo_read_file_pattern(struct tomoyo_io_buffer *head);
222/* Read "allow_read" entry in exception policy. */
223bool tomoyo_read_globally_readable_policy(struct tomoyo_io_buffer *head);
224/* Read "deny_rewrite" entry in exception policy. */
225bool tomoyo_read_no_rewrite_policy(struct tomoyo_io_buffer *head);
226/* Write domain policy violation warning message to console? */
227bool tomoyo_verbose_mode(const struct tomoyo_domain_info *domain);
228/* Convert double path operation to operation name. */
229const char *tomoyo_dp2keyword(const u8 operation);
230/* Get the last component of the given domainname. */
231const char *tomoyo_get_last_name(const struct tomoyo_domain_info *domain);
232/* Get warning message. */
233const char *tomoyo_get_msg(const bool is_enforce);
234/* Convert single path operation to operation name. */
235const char *tomoyo_sp2keyword(const u8 operation);
236/* Delete a domain. */
237int tomoyo_delete_domain(char *data);
238/* Create "alias" entry in exception policy. */
239int tomoyo_write_alias_policy(char *data, const bool is_delete);
240/*
241 * Create "initialize_domain" and "no_initialize_domain" entry
242 * in exception policy.
243 */
244int tomoyo_write_domain_initializer_policy(char *data, const bool is_not,
245 const bool is_delete);
246/* Create "keep_domain" and "no_keep_domain" entry in exception policy. */
247int tomoyo_write_domain_keeper_policy(char *data, const bool is_not,
248 const bool is_delete);
249/*
250 * Create "allow_read/write", "allow_execute", "allow_read", "allow_write",
251 * "allow_create", "allow_unlink", "allow_mkdir", "allow_rmdir",
252 * "allow_mkfifo", "allow_mksock", "allow_mkblock", "allow_mkchar",
253 * "allow_truncate", "allow_symlink", "allow_rewrite", "allow_rename" and
254 * "allow_link" entry in domain policy.
255 */
256int tomoyo_write_file_policy(char *data, struct tomoyo_domain_info *domain,
257 const bool is_delete);
258/* Create "allow_read" entry in exception policy. */
259int tomoyo_write_globally_readable_policy(char *data, const bool is_delete);
260/* Create "deny_rewrite" entry in exception policy. */
261int tomoyo_write_no_rewrite_policy(char *data, const bool is_delete);
262/* Create "file_pattern" entry in exception policy. */
263int tomoyo_write_pattern_policy(char *data, const bool is_delete);
264/* Find a domain by the given name. */
265struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname);
266/* Find or create a domain by the given name. */
267struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char *
268 domainname,
269 const u8 profile);
270/* Undelete a domain. */
271struct tomoyo_domain_info *tomoyo_undelete_domain(const char *domainname);
272/* Check mode for specified functionality. */
273unsigned int tomoyo_check_flags(const struct tomoyo_domain_info *domain,
274 const u8 index);
275/* Allocate memory for structures. */
276void *tomoyo_alloc_acl_element(const u8 acl_type);
277/* Fill in "struct tomoyo_path_info" members. */
278void tomoyo_fill_path_info(struct tomoyo_path_info *ptr);
279/* Run policy loader when /sbin/init starts. */
280void tomoyo_load_policy(const char *filename);
281/* Change "struct tomoyo_domain_info"->flags. */
282void tomoyo_set_domain_flag(struct tomoyo_domain_info *domain,
283 const bool is_delete, const u8 flags);
284
285/* strcmp() for "struct tomoyo_path_info" structure. */
286static inline bool tomoyo_pathcmp(const struct tomoyo_path_info *a,
287 const struct tomoyo_path_info *b)
288{
289 return a->hash != b->hash || strcmp(a->name, b->name);
290}
291
292/* Get type of an ACL entry. */
293static inline u8 tomoyo_acl_type1(struct tomoyo_acl_info *ptr)
294{
295 return ptr->type & ~TOMOYO_ACL_DELETED;
296}
297
298/* Get type of an ACL entry. */
299static inline u8 tomoyo_acl_type2(struct tomoyo_acl_info *ptr)
300{
301 return ptr->type;
302}
303
304/**
305 * tomoyo_is_valid - Check whether the character is a valid char.
306 *
307 * @c: The character to check.
308 *
309 * Returns true if @c is a valid character, false otherwise.
310 */
311static inline bool tomoyo_is_valid(const unsigned char c)
312{
313 return c > ' ' && c < 127;
314}
315
316/**
317 * tomoyo_is_invalid - Check whether the character is an invalid char.
318 *
319 * @c: The character to check.
320 *
321 * Returns true if @c is an invalid character, false otherwise.
322 */
323static inline bool tomoyo_is_invalid(const unsigned char c)
324{
325 return c && (c <= ' ' || c >= 127);
326}
327
328/* The list for "struct tomoyo_domain_info". */
329extern struct list_head tomoyo_domain_list;
330extern struct rw_semaphore tomoyo_domain_list_lock;
331
332/* Lock for domain->acl_info_list. */
333extern struct rw_semaphore tomoyo_domain_acl_info_list_lock;
334
335/* Has /sbin/init started? */
336extern bool tomoyo_policy_loaded;
337
338/* The kernel's domain. */
339extern struct tomoyo_domain_info tomoyo_kernel_domain;
340
341/**
342 * list_for_each_cookie - iterate over a list with cookie.
343 * @pos: the &struct list_head to use as a loop cursor.
344 * @cookie: the &struct list_head to use as a cookie.
345 * @head: the head for your list.
346 *
347 * Same with list_for_each() except that this primitive uses @cookie
348 * so that we can continue iteration.
349 * @cookie must be NULL when iteration starts, and @cookie will become
350 * NULL when iteration finishes.
351 */
352#define list_for_each_cookie(pos, cookie, head) \
353 for (({ if (!cookie) \
354 cookie = head; }), \
355 pos = (cookie)->next; \
356 prefetch(pos->next), pos != (head) || ((cookie) = NULL); \
357 (cookie) = pos, pos = pos->next)
358
359#endif /* !defined(_SECURITY_TOMOYO_COMMON_H) */
diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c
new file mode 100644
index 000000000000..093a756030bd
--- /dev/null
+++ b/security/tomoyo/domain.c
@@ -0,0 +1,878 @@
1/*
2 * security/tomoyo/domain.c
3 *
4 * Implementation of the Domain-Based Mandatory Access Control.
5 *
6 * Copyright (C) 2005-2009 NTT DATA CORPORATION
7 *
8 * Version: 2.2.0-pre 2009/02/01
9 *
10 */
11
12#include "common.h"
13#include "tomoyo.h"
14#include "realpath.h"
15#include <linux/binfmts.h>
16
17/* Variables definitions.*/
18
19/* The initial domain. */
20struct tomoyo_domain_info tomoyo_kernel_domain;
21
22/* The list for "struct tomoyo_domain_info". */
23LIST_HEAD(tomoyo_domain_list);
24DECLARE_RWSEM(tomoyo_domain_list_lock);
25
26/* Structure for "initialize_domain" and "no_initialize_domain" keyword. */
27struct tomoyo_domain_initializer_entry {
28 struct list_head list;
29 const struct tomoyo_path_info *domainname; /* This may be NULL */
30 const struct tomoyo_path_info *program;
31 bool is_deleted;
32 bool is_not; /* True if this entry is "no_initialize_domain". */
33 /* True if the domainname is tomoyo_get_last_name(). */
34 bool is_last_name;
35};
36
37/* Structure for "keep_domain" and "no_keep_domain" keyword. */
38struct tomoyo_domain_keeper_entry {
39 struct list_head list;
40 const struct tomoyo_path_info *domainname;
41 const struct tomoyo_path_info *program; /* This may be NULL */
42 bool is_deleted;
43 bool is_not; /* True if this entry is "no_keep_domain". */
44 /* True if the domainname is tomoyo_get_last_name(). */
45 bool is_last_name;
46};
47
48/* Structure for "alias" keyword. */
49struct tomoyo_alias_entry {
50 struct list_head list;
51 const struct tomoyo_path_info *original_name;
52 const struct tomoyo_path_info *aliased_name;
53 bool is_deleted;
54};
55
56/**
57 * tomoyo_set_domain_flag - Set or clear domain's attribute flags.
58 *
59 * @domain: Pointer to "struct tomoyo_domain_info".
60 * @is_delete: True if it is a delete request.
61 * @flags: Flags to set or clear.
62 *
63 * Returns nothing.
64 */
65void tomoyo_set_domain_flag(struct tomoyo_domain_info *domain,
66 const bool is_delete, const u8 flags)
67{
68 /* We need to serialize because this is bitfield operation. */
69 static DEFINE_SPINLOCK(lock);
70 /***** CRITICAL SECTION START *****/
71 spin_lock(&lock);
72 if (!is_delete)
73 domain->flags |= flags;
74 else
75 domain->flags &= ~flags;
76 spin_unlock(&lock);
77 /***** CRITICAL SECTION END *****/
78}
79
80/**
81 * tomoyo_get_last_name - Get last component of a domainname.
82 *
83 * @domain: Pointer to "struct tomoyo_domain_info".
84 *
85 * Returns the last component of the domainname.
86 */
87const char *tomoyo_get_last_name(const struct tomoyo_domain_info *domain)
88{
89 const char *cp0 = domain->domainname->name;
90 const char *cp1 = strrchr(cp0, ' ');
91
92 if (cp1)
93 return cp1 + 1;
94 return cp0;
95}
96
97/* The list for "struct tomoyo_domain_initializer_entry". */
98static LIST_HEAD(tomoyo_domain_initializer_list);
99static DECLARE_RWSEM(tomoyo_domain_initializer_list_lock);
100
101/**
102 * tomoyo_update_domain_initializer_entry - Update "struct tomoyo_domain_initializer_entry" list.
103 *
104 * @domainname: The name of domain. May be NULL.
105 * @program: The name of program.
106 * @is_not: True if it is "no_initialize_domain" entry.
107 * @is_delete: True if it is a delete request.
108 *
109 * Returns 0 on success, negative value otherwise.
110 */
111static int tomoyo_update_domain_initializer_entry(const char *domainname,
112 const char *program,
113 const bool is_not,
114 const bool is_delete)
115{
116 struct tomoyo_domain_initializer_entry *new_entry;
117 struct tomoyo_domain_initializer_entry *ptr;
118 const struct tomoyo_path_info *saved_program;
119 const struct tomoyo_path_info *saved_domainname = NULL;
120 int error = -ENOMEM;
121 bool is_last_name = false;
122
123 if (!tomoyo_is_correct_path(program, 1, -1, -1, __func__))
124 return -EINVAL; /* No patterns allowed. */
125 if (domainname) {
126 if (!tomoyo_is_domain_def(domainname) &&
127 tomoyo_is_correct_path(domainname, 1, -1, -1, __func__))
128 is_last_name = true;
129 else if (!tomoyo_is_correct_domain(domainname, __func__))
130 return -EINVAL;
131 saved_domainname = tomoyo_save_name(domainname);
132 if (!saved_domainname)
133 return -ENOMEM;
134 }
135 saved_program = tomoyo_save_name(program);
136 if (!saved_program)
137 return -ENOMEM;
138 /***** EXCLUSIVE SECTION START *****/
139 down_write(&tomoyo_domain_initializer_list_lock);
140 list_for_each_entry(ptr, &tomoyo_domain_initializer_list, list) {
141 if (ptr->is_not != is_not ||
142 ptr->domainname != saved_domainname ||
143 ptr->program != saved_program)
144 continue;
145 ptr->is_deleted = is_delete;
146 error = 0;
147 goto out;
148 }
149 if (is_delete) {
150 error = -ENOENT;
151 goto out;
152 }
153 new_entry = tomoyo_alloc_element(sizeof(*new_entry));
154 if (!new_entry)
155 goto out;
156 new_entry->domainname = saved_domainname;
157 new_entry->program = saved_program;
158 new_entry->is_not = is_not;
159 new_entry->is_last_name = is_last_name;
160 list_add_tail(&new_entry->list, &tomoyo_domain_initializer_list);
161 error = 0;
162 out:
163 up_write(&tomoyo_domain_initializer_list_lock);
164 /***** EXCLUSIVE SECTION END *****/
165 return error;
166}
167
168/**
169 * tomoyo_read_domain_initializer_policy - Read "struct tomoyo_domain_initializer_entry" list.
170 *
171 * @head: Pointer to "struct tomoyo_io_buffer".
172 *
173 * Returns true on success, false otherwise.
174 */
175bool tomoyo_read_domain_initializer_policy(struct tomoyo_io_buffer *head)
176{
177 struct list_head *pos;
178 bool done = true;
179
180 down_read(&tomoyo_domain_initializer_list_lock);
181 list_for_each_cookie(pos, head->read_var2,
182 &tomoyo_domain_initializer_list) {
183 const char *no;
184 const char *from = "";
185 const char *domain = "";
186 struct tomoyo_domain_initializer_entry *ptr;
187 ptr = list_entry(pos, struct tomoyo_domain_initializer_entry,
188 list);
189 if (ptr->is_deleted)
190 continue;
191 no = ptr->is_not ? "no_" : "";
192 if (ptr->domainname) {
193 from = " from ";
194 domain = ptr->domainname->name;
195 }
196 if (!tomoyo_io_printf(head,
197 "%s" TOMOYO_KEYWORD_INITIALIZE_DOMAIN
198 "%s%s%s\n", no, ptr->program->name, from,
199 domain)) {
200 done = false;
201 break;
202 }
203 }
204 up_read(&tomoyo_domain_initializer_list_lock);
205 return done;
206}
207
208/**
209 * tomoyo_write_domain_initializer_policy - Write "struct tomoyo_domain_initializer_entry" list.
210 *
211 * @data: String to parse.
212 * @is_not: True if it is "no_initialize_domain" entry.
213 * @is_delete: True if it is a delete request.
214 *
215 * Returns 0 on success, negative value otherwise.
216 */
217int tomoyo_write_domain_initializer_policy(char *data, const bool is_not,
218 const bool is_delete)
219{
220 char *cp = strstr(data, " from ");
221
222 if (cp) {
223 *cp = '\0';
224 return tomoyo_update_domain_initializer_entry(cp + 6, data,
225 is_not,
226 is_delete);
227 }
228 return tomoyo_update_domain_initializer_entry(NULL, data, is_not,
229 is_delete);
230}
231
232/**
233 * tomoyo_is_domain_initializer - Check whether the given program causes domainname reinitialization.
234 *
235 * @domainname: The name of domain.
236 * @program: The name of program.
237 * @last_name: The last component of @domainname.
238 *
239 * Returns true if executing @program reinitializes domain transition,
240 * false otherwise.
241 */
242static bool tomoyo_is_domain_initializer(const struct tomoyo_path_info *
243 domainname,
244 const struct tomoyo_path_info *program,
245 const struct tomoyo_path_info *
246 last_name)
247{
248 struct tomoyo_domain_initializer_entry *ptr;
249 bool flag = false;
250
251 down_read(&tomoyo_domain_initializer_list_lock);
252 list_for_each_entry(ptr, &tomoyo_domain_initializer_list, list) {
253 if (ptr->is_deleted)
254 continue;
255 if (ptr->domainname) {
256 if (!ptr->is_last_name) {
257 if (ptr->domainname != domainname)
258 continue;
259 } else {
260 if (tomoyo_pathcmp(ptr->domainname, last_name))
261 continue;
262 }
263 }
264 if (tomoyo_pathcmp(ptr->program, program))
265 continue;
266 if (ptr->is_not) {
267 flag = false;
268 break;
269 }
270 flag = true;
271 }
272 up_read(&tomoyo_domain_initializer_list_lock);
273 return flag;
274}
275
276/* The list for "struct tomoyo_domain_keeper_entry". */
277static LIST_HEAD(tomoyo_domain_keeper_list);
278static DECLARE_RWSEM(tomoyo_domain_keeper_list_lock);
279
280/**
281 * tomoyo_update_domain_keeper_entry - Update "struct tomoyo_domain_keeper_entry" list.
282 *
283 * @domainname: The name of domain.
284 * @program: The name of program. May be NULL.
285 * @is_not: True if it is "no_keep_domain" entry.
286 * @is_delete: True if it is a delete request.
287 *
288 * Returns 0 on success, negative value otherwise.
289 */
290static int tomoyo_update_domain_keeper_entry(const char *domainname,
291 const char *program,
292 const bool is_not,
293 const bool is_delete)
294{
295 struct tomoyo_domain_keeper_entry *new_entry;
296 struct tomoyo_domain_keeper_entry *ptr;
297 const struct tomoyo_path_info *saved_domainname;
298 const struct tomoyo_path_info *saved_program = NULL;
299 static DEFINE_MUTEX(lock);
300 int error = -ENOMEM;
301 bool is_last_name = false;
302
303 if (!tomoyo_is_domain_def(domainname) &&
304 tomoyo_is_correct_path(domainname, 1, -1, -1, __func__))
305 is_last_name = true;
306 else if (!tomoyo_is_correct_domain(domainname, __func__))
307 return -EINVAL;
308 if (program) {
309 if (!tomoyo_is_correct_path(program, 1, -1, -1, __func__))
310 return -EINVAL;
311 saved_program = tomoyo_save_name(program);
312 if (!saved_program)
313 return -ENOMEM;
314 }
315 saved_domainname = tomoyo_save_name(domainname);
316 if (!saved_domainname)
317 return -ENOMEM;
318 /***** EXCLUSIVE SECTION START *****/
319 down_write(&tomoyo_domain_keeper_list_lock);
320 list_for_each_entry(ptr, &tomoyo_domain_keeper_list, list) {
321 if (ptr->is_not != is_not ||
322 ptr->domainname != saved_domainname ||
323 ptr->program != saved_program)
324 continue;
325 ptr->is_deleted = is_delete;
326 error = 0;
327 goto out;
328 }
329 if (is_delete) {
330 error = -ENOENT;
331 goto out;
332 }
333 new_entry = tomoyo_alloc_element(sizeof(*new_entry));
334 if (!new_entry)
335 goto out;
336 new_entry->domainname = saved_domainname;
337 new_entry->program = saved_program;
338 new_entry->is_not = is_not;
339 new_entry->is_last_name = is_last_name;
340 list_add_tail(&new_entry->list, &tomoyo_domain_keeper_list);
341 error = 0;
342 out:
343 up_write(&tomoyo_domain_keeper_list_lock);
344 /***** EXCLUSIVE SECTION END *****/
345 return error;
346}
347
348/**
349 * tomoyo_write_domain_keeper_policy - Write "struct tomoyo_domain_keeper_entry" list.
350 *
351 * @data: String to parse.
352 * @is_not: True if it is "no_keep_domain" entry.
353 * @is_delete: True if it is a delete request.
354 *
355 */
356int tomoyo_write_domain_keeper_policy(char *data, const bool is_not,
357 const bool is_delete)
358{
359 char *cp = strstr(data, " from ");
360
361 if (cp) {
362 *cp = '\0';
363 return tomoyo_update_domain_keeper_entry(cp + 6, data, is_not,
364 is_delete);
365 }
366 return tomoyo_update_domain_keeper_entry(data, NULL, is_not, is_delete);
367}
368
369/**
370 * tomoyo_read_domain_keeper_policy - Read "struct tomoyo_domain_keeper_entry" list.
371 *
372 * @head: Pointer to "struct tomoyo_io_buffer".
373 *
374 * Returns true on success, false otherwise.
375 */
376bool tomoyo_read_domain_keeper_policy(struct tomoyo_io_buffer *head)
377{
378 struct list_head *pos;
379 bool done = true;
380
381 down_read(&tomoyo_domain_keeper_list_lock);
382 list_for_each_cookie(pos, head->read_var2,
383 &tomoyo_domain_keeper_list) {
384 struct tomoyo_domain_keeper_entry *ptr;
385 const char *no;
386 const char *from = "";
387 const char *program = "";
388
389 ptr = list_entry(pos, struct tomoyo_domain_keeper_entry, list);
390 if (ptr->is_deleted)
391 continue;
392 no = ptr->is_not ? "no_" : "";
393 if (ptr->program) {
394 from = " from ";
395 program = ptr->program->name;
396 }
397 if (!tomoyo_io_printf(head,
398 "%s" TOMOYO_KEYWORD_KEEP_DOMAIN
399 "%s%s%s\n", no, program, from,
400 ptr->domainname->name)) {
401 done = false;
402 break;
403 }
404 }
405 up_read(&tomoyo_domain_keeper_list_lock);
406 return done;
407}
408
409/**
410 * tomoyo_is_domain_keeper - Check whether the given program causes domain transition suppression.
411 *
412 * @domainname: The name of domain.
413 * @program: The name of program.
414 * @last_name: The last component of @domainname.
415 *
416 * Returns true if executing @program supresses domain transition,
417 * false otherwise.
418 */
419static bool tomoyo_is_domain_keeper(const struct tomoyo_path_info *domainname,
420 const struct tomoyo_path_info *program,
421 const struct tomoyo_path_info *last_name)
422{
423 struct tomoyo_domain_keeper_entry *ptr;
424 bool flag = false;
425
426 down_read(&tomoyo_domain_keeper_list_lock);
427 list_for_each_entry(ptr, &tomoyo_domain_keeper_list, list) {
428 if (ptr->is_deleted)
429 continue;
430 if (!ptr->is_last_name) {
431 if (ptr->domainname != domainname)
432 continue;
433 } else {
434 if (tomoyo_pathcmp(ptr->domainname, last_name))
435 continue;
436 }
437 if (ptr->program && tomoyo_pathcmp(ptr->program, program))
438 continue;
439 if (ptr->is_not) {
440 flag = false;
441 break;
442 }
443 flag = true;
444 }
445 up_read(&tomoyo_domain_keeper_list_lock);
446 return flag;
447}
448
449/* The list for "struct tomoyo_alias_entry". */
450static LIST_HEAD(tomoyo_alias_list);
451static DECLARE_RWSEM(tomoyo_alias_list_lock);
452
453/**
454 * tomoyo_update_alias_entry - Update "struct tomoyo_alias_entry" list.
455 *
456 * @original_name: The original program's real name.
457 * @aliased_name: The symbolic program's symbolic link's name.
458 * @is_delete: True if it is a delete request.
459 *
460 * Returns 0 on success, negative value otherwise.
461 */
462static int tomoyo_update_alias_entry(const char *original_name,
463 const char *aliased_name,
464 const bool is_delete)
465{
466 struct tomoyo_alias_entry *new_entry;
467 struct tomoyo_alias_entry *ptr;
468 const struct tomoyo_path_info *saved_original_name;
469 const struct tomoyo_path_info *saved_aliased_name;
470 int error = -ENOMEM;
471
472 if (!tomoyo_is_correct_path(original_name, 1, -1, -1, __func__) ||
473 !tomoyo_is_correct_path(aliased_name, 1, -1, -1, __func__))
474 return -EINVAL; /* No patterns allowed. */
475 saved_original_name = tomoyo_save_name(original_name);
476 saved_aliased_name = tomoyo_save_name(aliased_name);
477 if (!saved_original_name || !saved_aliased_name)
478 return -ENOMEM;
479 /***** EXCLUSIVE SECTION START *****/
480 down_write(&tomoyo_alias_list_lock);
481 list_for_each_entry(ptr, &tomoyo_alias_list, list) {
482 if (ptr->original_name != saved_original_name ||
483 ptr->aliased_name != saved_aliased_name)
484 continue;
485 ptr->is_deleted = is_delete;
486 error = 0;
487 goto out;
488 }
489 if (is_delete) {
490 error = -ENOENT;
491 goto out;
492 }
493 new_entry = tomoyo_alloc_element(sizeof(*new_entry));
494 if (!new_entry)
495 goto out;
496 new_entry->original_name = saved_original_name;
497 new_entry->aliased_name = saved_aliased_name;
498 list_add_tail(&new_entry->list, &tomoyo_alias_list);
499 error = 0;
500 out:
501 up_write(&tomoyo_alias_list_lock);
502 /***** EXCLUSIVE SECTION END *****/
503 return error;
504}
505
506/**
507 * tomoyo_read_alias_policy - Read "struct tomoyo_alias_entry" list.
508 *
509 * @head: Pointer to "struct tomoyo_io_buffer".
510 *
511 * Returns true on success, false otherwise.
512 */
513bool tomoyo_read_alias_policy(struct tomoyo_io_buffer *head)
514{
515 struct list_head *pos;
516 bool done = true;
517
518 down_read(&tomoyo_alias_list_lock);
519 list_for_each_cookie(pos, head->read_var2, &tomoyo_alias_list) {
520 struct tomoyo_alias_entry *ptr;
521
522 ptr = list_entry(pos, struct tomoyo_alias_entry, list);
523 if (ptr->is_deleted)
524 continue;
525 if (!tomoyo_io_printf(head, TOMOYO_KEYWORD_ALIAS "%s %s\n",
526 ptr->original_name->name,
527 ptr->aliased_name->name)) {
528 done = false;
529 break;
530 }
531 }
532 up_read(&tomoyo_alias_list_lock);
533 return done;
534}
535
536/**
537 * tomoyo_write_alias_policy - Write "struct tomoyo_alias_entry" list.
538 *
539 * @data: String to parse.
540 * @is_delete: True if it is a delete request.
541 *
542 * Returns 0 on success, negative value otherwise.
543 */
544int tomoyo_write_alias_policy(char *data, const bool is_delete)
545{
546 char *cp = strchr(data, ' ');
547
548 if (!cp)
549 return -EINVAL;
550 *cp++ = '\0';
551 return tomoyo_update_alias_entry(data, cp, is_delete);
552}
553
554/* Domain create/delete/undelete handler. */
555
556/* #define TOMOYO_DEBUG_DOMAIN_UNDELETE */
557
558/**
559 * tomoyo_delete_domain - Delete a domain.
560 *
561 * @domainname: The name of domain.
562 *
563 * Returns 0.
564 */
565int tomoyo_delete_domain(char *domainname)
566{
567 struct tomoyo_domain_info *domain;
568 struct tomoyo_path_info name;
569
570 name.name = domainname;
571 tomoyo_fill_path_info(&name);
572 /***** EXCLUSIVE SECTION START *****/
573 down_write(&tomoyo_domain_list_lock);
574#ifdef TOMOYO_DEBUG_DOMAIN_UNDELETE
575 printk(KERN_DEBUG "tomoyo_delete_domain %s\n", domainname);
576 list_for_each_entry(domain, &tomoyo_domain_list, list) {
577 if (tomoyo_pathcmp(domain->domainname, &name))
578 continue;
579 printk(KERN_DEBUG "List: %p %u\n", domain, domain->is_deleted);
580 }
581#endif
582 /* Is there an active domain? */
583 list_for_each_entry(domain, &tomoyo_domain_list, list) {
584 struct tomoyo_domain_info *domain2;
585 /* Never delete tomoyo_kernel_domain */
586 if (domain == &tomoyo_kernel_domain)
587 continue;
588 if (domain->is_deleted ||
589 tomoyo_pathcmp(domain->domainname, &name))
590 continue;
591 /* Mark already deleted domains as non undeletable. */
592 list_for_each_entry(domain2, &tomoyo_domain_list, list) {
593 if (!domain2->is_deleted ||
594 tomoyo_pathcmp(domain2->domainname, &name))
595 continue;
596#ifdef TOMOYO_DEBUG_DOMAIN_UNDELETE
597 if (domain2->is_deleted != 255)
598 printk(KERN_DEBUG
599 "Marked %p as non undeletable\n",
600 domain2);
601#endif
602 domain2->is_deleted = 255;
603 }
604 /* Delete and mark active domain as undeletable. */
605 domain->is_deleted = 1;
606#ifdef TOMOYO_DEBUG_DOMAIN_UNDELETE
607 printk(KERN_DEBUG "Marked %p as undeletable\n", domain);
608#endif
609 break;
610 }
611 up_write(&tomoyo_domain_list_lock);
612 /***** EXCLUSIVE SECTION END *****/
613 return 0;
614}
615
616/**
617 * tomoyo_undelete_domain - Undelete a domain.
618 *
619 * @domainname: The name of domain.
620 *
621 * Returns pointer to "struct tomoyo_domain_info" on success, NULL otherwise.
622 */
623struct tomoyo_domain_info *tomoyo_undelete_domain(const char *domainname)
624{
625 struct tomoyo_domain_info *domain;
626 struct tomoyo_domain_info *candidate_domain = NULL;
627 struct tomoyo_path_info name;
628
629 name.name = domainname;
630 tomoyo_fill_path_info(&name);
631 /***** EXCLUSIVE SECTION START *****/
632 down_write(&tomoyo_domain_list_lock);
633#ifdef TOMOYO_DEBUG_DOMAIN_UNDELETE
634 printk(KERN_DEBUG "tomoyo_undelete_domain %s\n", domainname);
635 list_for_each_entry(domain, &tomoyo_domain_list, list) {
636 if (tomoyo_pathcmp(domain->domainname, &name))
637 continue;
638 printk(KERN_DEBUG "List: %p %u\n", domain, domain->is_deleted);
639 }
640#endif
641 list_for_each_entry(domain, &tomoyo_domain_list, list) {
642 if (tomoyo_pathcmp(&name, domain->domainname))
643 continue;
644 if (!domain->is_deleted) {
645 /* This domain is active. I can't undelete. */
646 candidate_domain = NULL;
647#ifdef TOMOYO_DEBUG_DOMAIN_UNDELETE
648 printk(KERN_DEBUG "%p is active. I can't undelete.\n",
649 domain);
650#endif
651 break;
652 }
653 /* Is this domain undeletable? */
654 if (domain->is_deleted == 1)
655 candidate_domain = domain;
656 }
657 if (candidate_domain) {
658 candidate_domain->is_deleted = 0;
659#ifdef TOMOYO_DEBUG_DOMAIN_UNDELETE
660 printk(KERN_DEBUG "%p was undeleted.\n", candidate_domain);
661#endif
662 }
663 up_write(&tomoyo_domain_list_lock);
664 /***** EXCLUSIVE SECTION END *****/
665 return candidate_domain;
666}
667
668/**
669 * tomoyo_find_or_assign_new_domain - Create a domain.
670 *
671 * @domainname: The name of domain.
672 * @profile: Profile number to assign if the domain was newly created.
673 *
674 * Returns pointer to "struct tomoyo_domain_info" on success, NULL otherwise.
675 */
676struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char *
677 domainname,
678 const u8 profile)
679{
680 struct tomoyo_domain_info *domain = NULL;
681 const struct tomoyo_path_info *saved_domainname;
682
683 /***** EXCLUSIVE SECTION START *****/
684 down_write(&tomoyo_domain_list_lock);
685 domain = tomoyo_find_domain(domainname);
686 if (domain)
687 goto out;
688 if (!tomoyo_is_correct_domain(domainname, __func__))
689 goto out;
690 saved_domainname = tomoyo_save_name(domainname);
691 if (!saved_domainname)
692 goto out;
693 /* Can I reuse memory of deleted domain? */
694 list_for_each_entry(domain, &tomoyo_domain_list, list) {
695 struct task_struct *p;
696 struct tomoyo_acl_info *ptr;
697 bool flag;
698 if (!domain->is_deleted ||
699 domain->domainname != saved_domainname)
700 continue;
701 flag = false;
702 /***** CRITICAL SECTION START *****/
703 read_lock(&tasklist_lock);
704 for_each_process(p) {
705 if (tomoyo_real_domain(p) != domain)
706 continue;
707 flag = true;
708 break;
709 }
710 read_unlock(&tasklist_lock);
711 /***** CRITICAL SECTION END *****/
712 if (flag)
713 continue;
714#ifdef TOMOYO_DEBUG_DOMAIN_UNDELETE
715 printk(KERN_DEBUG "Reusing %p %s\n", domain,
716 domain->domainname->name);
717#endif
718 list_for_each_entry(ptr, &domain->acl_info_list, list) {
719 ptr->type |= TOMOYO_ACL_DELETED;
720 }
721 tomoyo_set_domain_flag(domain, true, domain->flags);
722 domain->profile = profile;
723 domain->quota_warned = false;
724 mb(); /* Avoid out-of-order execution. */
725 domain->is_deleted = 0;
726 goto out;
727 }
728 /* No memory reusable. Create using new memory. */
729 domain = tomoyo_alloc_element(sizeof(*domain));
730 if (domain) {
731 INIT_LIST_HEAD(&domain->acl_info_list);
732 domain->domainname = saved_domainname;
733 domain->profile = profile;
734 list_add_tail(&domain->list, &tomoyo_domain_list);
735 }
736 out:
737 up_write(&tomoyo_domain_list_lock);
738 /***** EXCLUSIVE SECTION END *****/
739 return domain;
740}
741
742/**
743 * tomoyo_find_next_domain - Find a domain.
744 *
745 * @bprm: Pointer to "struct linux_binprm".
746 * @next_domain: Pointer to pointer to "struct tomoyo_domain_info".
747 *
748 * Returns 0 on success, negative value otherwise.
749 */
750int tomoyo_find_next_domain(struct linux_binprm *bprm,
751 struct tomoyo_domain_info **next_domain)
752{
753 /*
754 * This function assumes that the size of buffer returned by
755 * tomoyo_realpath() = TOMOYO_MAX_PATHNAME_LEN.
756 */
757 struct tomoyo_page_buffer *tmp = tomoyo_alloc(sizeof(*tmp));
758 struct tomoyo_domain_info *old_domain = tomoyo_domain();
759 struct tomoyo_domain_info *domain = NULL;
760 const char *old_domain_name = old_domain->domainname->name;
761 const char *original_name = bprm->filename;
762 char *new_domain_name = NULL;
763 char *real_program_name = NULL;
764 char *symlink_program_name = NULL;
765 const u8 mode = tomoyo_check_flags(old_domain, TOMOYO_MAC_FOR_FILE);
766 const bool is_enforce = (mode == 3);
767 int retval = -ENOMEM;
768 struct tomoyo_path_info r; /* real name */
769 struct tomoyo_path_info s; /* symlink name */
770 struct tomoyo_path_info l; /* last name */
771 static bool initialized;
772
773 if (!tmp)
774 goto out;
775
776 if (!initialized) {
777 /*
778 * Built-in initializers. This is needed because policies are
779 * not loaded until starting /sbin/init.
780 */
781 tomoyo_update_domain_initializer_entry(NULL, "/sbin/hotplug",
782 false, false);
783 tomoyo_update_domain_initializer_entry(NULL, "/sbin/modprobe",
784 false, false);
785 initialized = true;
786 }
787
788 /* Get tomoyo_realpath of program. */
789 retval = -ENOENT;
790 /* I hope tomoyo_realpath() won't fail with -ENOMEM. */
791 real_program_name = tomoyo_realpath(original_name);
792 if (!real_program_name)
793 goto out;
794 /* Get tomoyo_realpath of symbolic link. */
795 symlink_program_name = tomoyo_realpath_nofollow(original_name);
796 if (!symlink_program_name)
797 goto out;
798
799 r.name = real_program_name;
800 tomoyo_fill_path_info(&r);
801 s.name = symlink_program_name;
802 tomoyo_fill_path_info(&s);
803 l.name = tomoyo_get_last_name(old_domain);
804 tomoyo_fill_path_info(&l);
805
806 /* Check 'alias' directive. */
807 if (tomoyo_pathcmp(&r, &s)) {
808 struct tomoyo_alias_entry *ptr;
809 /* Is this program allowed to be called via symbolic links? */
810 down_read(&tomoyo_alias_list_lock);
811 list_for_each_entry(ptr, &tomoyo_alias_list, list) {
812 if (ptr->is_deleted ||
813 tomoyo_pathcmp(&r, ptr->original_name) ||
814 tomoyo_pathcmp(&s, ptr->aliased_name))
815 continue;
816 memset(real_program_name, 0, TOMOYO_MAX_PATHNAME_LEN);
817 strncpy(real_program_name, ptr->aliased_name->name,
818 TOMOYO_MAX_PATHNAME_LEN - 1);
819 tomoyo_fill_path_info(&r);
820 break;
821 }
822 up_read(&tomoyo_alias_list_lock);
823 }
824
825 /* Check execute permission. */
826 retval = tomoyo_check_exec_perm(old_domain, &r, tmp);
827 if (retval < 0)
828 goto out;
829
830 new_domain_name = tmp->buffer;
831 if (tomoyo_is_domain_initializer(old_domain->domainname, &r, &l)) {
832 /* Transit to the child of tomoyo_kernel_domain domain. */
833 snprintf(new_domain_name, TOMOYO_MAX_PATHNAME_LEN + 1,
834 TOMOYO_ROOT_NAME " " "%s", real_program_name);
835 } else if (old_domain == &tomoyo_kernel_domain &&
836 !tomoyo_policy_loaded) {
837 /*
838 * Needn't to transit from kernel domain before starting
839 * /sbin/init. But transit from kernel domain if executing
840 * initializers because they might start before /sbin/init.
841 */
842 domain = old_domain;
843 } else if (tomoyo_is_domain_keeper(old_domain->domainname, &r, &l)) {
844 /* Keep current domain. */
845 domain = old_domain;
846 } else {
847 /* Normal domain transition. */
848 snprintf(new_domain_name, TOMOYO_MAX_PATHNAME_LEN + 1,
849 "%s %s", old_domain_name, real_program_name);
850 }
851 if (domain || strlen(new_domain_name) >= TOMOYO_MAX_PATHNAME_LEN)
852 goto done;
853 down_read(&tomoyo_domain_list_lock);
854 domain = tomoyo_find_domain(new_domain_name);
855 up_read(&tomoyo_domain_list_lock);
856 if (domain)
857 goto done;
858 if (is_enforce)
859 goto done;
860 domain = tomoyo_find_or_assign_new_domain(new_domain_name,
861 old_domain->profile);
862 done:
863 if (domain)
864 goto out;
865 printk(KERN_WARNING "TOMOYO-ERROR: Domain '%s' not defined.\n",
866 new_domain_name);
867 if (is_enforce)
868 retval = -EPERM;
869 else
870 tomoyo_set_domain_flag(old_domain, false,
871 TOMOYO_DOMAIN_FLAGS_TRANSITION_FAILED);
872 out:
873 tomoyo_free(real_program_name);
874 tomoyo_free(symlink_program_name);
875 *next_domain = domain ? domain : old_domain;
876 tomoyo_free(tmp);
877 return retval;
878}
diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c
new file mode 100644
index 000000000000..65f50c1c5ee9
--- /dev/null
+++ b/security/tomoyo/file.c
@@ -0,0 +1,1241 @@
1/*
2 * security/tomoyo/file.c
3 *
4 * Implementation of the Domain-Based Mandatory Access Control.
5 *
6 * Copyright (C) 2005-2009 NTT DATA CORPORATION
7 *
8 * Version: 2.2.0-pre 2009/02/01
9 *
10 */
11
12#include "common.h"
13#include "tomoyo.h"
14#include "realpath.h"
15#define ACC_MODE(x) ("\000\004\002\006"[(x)&O_ACCMODE])
16
17/* Structure for "allow_read" keyword. */
18struct tomoyo_globally_readable_file_entry {
19 struct list_head list;
20 const struct tomoyo_path_info *filename;
21 bool is_deleted;
22};
23
24/* Structure for "file_pattern" keyword. */
25struct tomoyo_pattern_entry {
26 struct list_head list;
27 const struct tomoyo_path_info *pattern;
28 bool is_deleted;
29};
30
31/* Structure for "deny_rewrite" keyword. */
32struct tomoyo_no_rewrite_entry {
33 struct list_head list;
34 const struct tomoyo_path_info *pattern;
35 bool is_deleted;
36};
37
38/* Keyword array for single path operations. */
39static const char *tomoyo_sp_keyword[TOMOYO_MAX_SINGLE_PATH_OPERATION] = {
40 [TOMOYO_TYPE_READ_WRITE_ACL] = "read/write",
41 [TOMOYO_TYPE_EXECUTE_ACL] = "execute",
42 [TOMOYO_TYPE_READ_ACL] = "read",
43 [TOMOYO_TYPE_WRITE_ACL] = "write",
44 [TOMOYO_TYPE_CREATE_ACL] = "create",
45 [TOMOYO_TYPE_UNLINK_ACL] = "unlink",
46 [TOMOYO_TYPE_MKDIR_ACL] = "mkdir",
47 [TOMOYO_TYPE_RMDIR_ACL] = "rmdir",
48 [TOMOYO_TYPE_MKFIFO_ACL] = "mkfifo",
49 [TOMOYO_TYPE_MKSOCK_ACL] = "mksock",
50 [TOMOYO_TYPE_MKBLOCK_ACL] = "mkblock",
51 [TOMOYO_TYPE_MKCHAR_ACL] = "mkchar",
52 [TOMOYO_TYPE_TRUNCATE_ACL] = "truncate",
53 [TOMOYO_TYPE_SYMLINK_ACL] = "symlink",
54 [TOMOYO_TYPE_REWRITE_ACL] = "rewrite",
55};
56
57/* Keyword array for double path operations. */
58static const char *tomoyo_dp_keyword[TOMOYO_MAX_DOUBLE_PATH_OPERATION] = {
59 [TOMOYO_TYPE_LINK_ACL] = "link",
60 [TOMOYO_TYPE_RENAME_ACL] = "rename",
61};
62
63/**
64 * tomoyo_sp2keyword - Get the name of single path operation.
65 *
66 * @operation: Type of operation.
67 *
68 * Returns the name of single path operation.
69 */
70const char *tomoyo_sp2keyword(const u8 operation)
71{
72 return (operation < TOMOYO_MAX_SINGLE_PATH_OPERATION)
73 ? tomoyo_sp_keyword[operation] : NULL;
74}
75
76/**
77 * tomoyo_dp2keyword - Get the name of double path operation.
78 *
79 * @operation: Type of operation.
80 *
81 * Returns the name of double path operation.
82 */
83const char *tomoyo_dp2keyword(const u8 operation)
84{
85 return (operation < TOMOYO_MAX_DOUBLE_PATH_OPERATION)
86 ? tomoyo_dp_keyword[operation] : NULL;
87}
88
89/**
90 * tomoyo_strendswith - Check whether the token ends with the given token.
91 *
92 * @name: The token to check.
93 * @tail: The token to find.
94 *
95 * Returns true if @name ends with @tail, false otherwise.
96 */
97static bool tomoyo_strendswith(const char *name, const char *tail)
98{
99 int len;
100
101 if (!name || !tail)
102 return false;
103 len = strlen(name) - strlen(tail);
104 return len >= 0 && !strcmp(name + len, tail);
105}
106
107/**
108 * tomoyo_get_path - Get realpath.
109 *
110 * @path: Pointer to "struct path".
111 *
112 * Returns pointer to "struct tomoyo_path_info" on success, NULL otherwise.
113 */
114static struct tomoyo_path_info *tomoyo_get_path(struct path *path)
115{
116 int error;
117 struct tomoyo_path_info_with_data *buf = tomoyo_alloc(sizeof(*buf));
118
119 if (!buf)
120 return NULL;
121 /* Reserve one byte for appending "/". */
122 error = tomoyo_realpath_from_path2(path, buf->body,
123 sizeof(buf->body) - 2);
124 if (!error) {
125 buf->head.name = buf->body;
126 tomoyo_fill_path_info(&buf->head);
127 return &buf->head;
128 }
129 tomoyo_free(buf);
130 return NULL;
131}
132
133/* Lock for domain->acl_info_list. */
134DECLARE_RWSEM(tomoyo_domain_acl_info_list_lock);
135
136static int tomoyo_update_double_path_acl(const u8 type, const char *filename1,
137 const char *filename2,
138 struct tomoyo_domain_info *
139 const domain, const bool is_delete);
140static int tomoyo_update_single_path_acl(const u8 type, const char *filename,
141 struct tomoyo_domain_info *
142 const domain, const bool is_delete);
143
144/* The list for "struct tomoyo_globally_readable_file_entry". */
145static LIST_HEAD(tomoyo_globally_readable_list);
146static DECLARE_RWSEM(tomoyo_globally_readable_list_lock);
147
148/**
149 * tomoyo_update_globally_readable_entry - Update "struct tomoyo_globally_readable_file_entry" list.
150 *
151 * @filename: Filename unconditionally permitted to open() for reading.
152 * @is_delete: True if it is a delete request.
153 *
154 * Returns 0 on success, negative value otherwise.
155 */
156static int tomoyo_update_globally_readable_entry(const char *filename,
157 const bool is_delete)
158{
159 struct tomoyo_globally_readable_file_entry *new_entry;
160 struct tomoyo_globally_readable_file_entry *ptr;
161 const struct tomoyo_path_info *saved_filename;
162 int error = -ENOMEM;
163
164 if (!tomoyo_is_correct_path(filename, 1, 0, -1, __func__))
165 return -EINVAL;
166 saved_filename = tomoyo_save_name(filename);
167 if (!saved_filename)
168 return -ENOMEM;
169 /***** EXCLUSIVE SECTION START *****/
170 down_write(&tomoyo_globally_readable_list_lock);
171 list_for_each_entry(ptr, &tomoyo_globally_readable_list, list) {
172 if (ptr->filename != saved_filename)
173 continue;
174 ptr->is_deleted = is_delete;
175 error = 0;
176 goto out;
177 }
178 if (is_delete) {
179 error = -ENOENT;
180 goto out;
181 }
182 new_entry = tomoyo_alloc_element(sizeof(*new_entry));
183 if (!new_entry)
184 goto out;
185 new_entry->filename = saved_filename;
186 list_add_tail(&new_entry->list, &tomoyo_globally_readable_list);
187 error = 0;
188 out:
189 up_write(&tomoyo_globally_readable_list_lock);
190 /***** EXCLUSIVE SECTION END *****/
191 return error;
192}
193
194/**
195 * tomoyo_is_globally_readable_file - Check if the file is unconditionnaly permitted to be open()ed for reading.
196 *
197 * @filename: The filename to check.
198 *
199 * Returns true if any domain can open @filename for reading, false otherwise.
200 */
201static bool tomoyo_is_globally_readable_file(const struct tomoyo_path_info *
202 filename)
203{
204 struct tomoyo_globally_readable_file_entry *ptr;
205 bool found = false;
206 down_read(&tomoyo_globally_readable_list_lock);
207 list_for_each_entry(ptr, &tomoyo_globally_readable_list, list) {
208 if (!ptr->is_deleted &&
209 tomoyo_path_matches_pattern(filename, ptr->filename)) {
210 found = true;
211 break;
212 }
213 }
214 up_read(&tomoyo_globally_readable_list_lock);
215 return found;
216}
217
218/**
219 * tomoyo_write_globally_readable_policy - Write "struct tomoyo_globally_readable_file_entry" list.
220 *
221 * @data: String to parse.
222 * @is_delete: True if it is a delete request.
223 *
224 * Returns 0 on success, negative value otherwise.
225 */
226int tomoyo_write_globally_readable_policy(char *data, const bool is_delete)
227{
228 return tomoyo_update_globally_readable_entry(data, is_delete);
229}
230
231/**
232 * tomoyo_read_globally_readable_policy - Read "struct tomoyo_globally_readable_file_entry" list.
233 *
234 * @head: Pointer to "struct tomoyo_io_buffer".
235 *
236 * Returns true on success, false otherwise.
237 */
238bool tomoyo_read_globally_readable_policy(struct tomoyo_io_buffer *head)
239{
240 struct list_head *pos;
241 bool done = true;
242
243 down_read(&tomoyo_globally_readable_list_lock);
244 list_for_each_cookie(pos, head->read_var2,
245 &tomoyo_globally_readable_list) {
246 struct tomoyo_globally_readable_file_entry *ptr;
247 ptr = list_entry(pos,
248 struct tomoyo_globally_readable_file_entry,
249 list);
250 if (ptr->is_deleted)
251 continue;
252 if (!tomoyo_io_printf(head, TOMOYO_KEYWORD_ALLOW_READ "%s\n",
253 ptr->filename->name)) {
254 done = false;
255 break;
256 }
257 }
258 up_read(&tomoyo_globally_readable_list_lock);
259 return done;
260}
261
262/* The list for "struct tomoyo_pattern_entry". */
263static LIST_HEAD(tomoyo_pattern_list);
264static DECLARE_RWSEM(tomoyo_pattern_list_lock);
265
266/**
267 * tomoyo_update_file_pattern_entry - Update "struct tomoyo_pattern_entry" list.
268 *
269 * @pattern: Pathname pattern.
270 * @is_delete: True if it is a delete request.
271 *
272 * Returns 0 on success, negative value otherwise.
273 */
274static int tomoyo_update_file_pattern_entry(const char *pattern,
275 const bool is_delete)
276{
277 struct tomoyo_pattern_entry *new_entry;
278 struct tomoyo_pattern_entry *ptr;
279 const struct tomoyo_path_info *saved_pattern;
280 int error = -ENOMEM;
281
282 if (!tomoyo_is_correct_path(pattern, 0, 1, 0, __func__))
283 return -EINVAL;
284 saved_pattern = tomoyo_save_name(pattern);
285 if (!saved_pattern)
286 return -ENOMEM;
287 /***** EXCLUSIVE SECTION START *****/
288 down_write(&tomoyo_pattern_list_lock);
289 list_for_each_entry(ptr, &tomoyo_pattern_list, list) {
290 if (saved_pattern != ptr->pattern)
291 continue;
292 ptr->is_deleted = is_delete;
293 error = 0;
294 goto out;
295 }
296 if (is_delete) {
297 error = -ENOENT;
298 goto out;
299 }
300 new_entry = tomoyo_alloc_element(sizeof(*new_entry));
301 if (!new_entry)
302 goto out;
303 new_entry->pattern = saved_pattern;
304 list_add_tail(&new_entry->list, &tomoyo_pattern_list);
305 error = 0;
306 out:
307 up_write(&tomoyo_pattern_list_lock);
308 /***** EXCLUSIVE SECTION END *****/
309 return error;
310}
311
312/**
313 * tomoyo_get_file_pattern - Get patterned pathname.
314 *
315 * @filename: The filename to find patterned pathname.
316 *
317 * Returns pointer to pathname pattern if matched, @filename otherwise.
318 */
319static const struct tomoyo_path_info *
320tomoyo_get_file_pattern(const struct tomoyo_path_info *filename)
321{
322 struct tomoyo_pattern_entry *ptr;
323 const struct tomoyo_path_info *pattern = NULL;
324
325 down_read(&tomoyo_pattern_list_lock);
326 list_for_each_entry(ptr, &tomoyo_pattern_list, list) {
327 if (ptr->is_deleted)
328 continue;
329 if (!tomoyo_path_matches_pattern(filename, ptr->pattern))
330 continue;
331 pattern = ptr->pattern;
332 if (tomoyo_strendswith(pattern->name, "/\\*")) {
333 /* Do nothing. Try to find the better match. */
334 } else {
335 /* This would be the better match. Use this. */
336 break;
337 }
338 }
339 up_read(&tomoyo_pattern_list_lock);
340 if (pattern)
341 filename = pattern;
342 return filename;
343}
344
345/**
346 * tomoyo_write_pattern_policy - Write "struct tomoyo_pattern_entry" list.
347 *
348 * @data: String to parse.
349 * @is_delete: True if it is a delete request.
350 *
351 * Returns 0 on success, negative value otherwise.
352 */
353int tomoyo_write_pattern_policy(char *data, const bool is_delete)
354{
355 return tomoyo_update_file_pattern_entry(data, is_delete);
356}
357
358/**
359 * tomoyo_read_file_pattern - Read "struct tomoyo_pattern_entry" list.
360 *
361 * @head: Pointer to "struct tomoyo_io_buffer".
362 *
363 * Returns true on success, false otherwise.
364 */
365bool tomoyo_read_file_pattern(struct tomoyo_io_buffer *head)
366{
367 struct list_head *pos;
368 bool done = true;
369
370 down_read(&tomoyo_pattern_list_lock);
371 list_for_each_cookie(pos, head->read_var2, &tomoyo_pattern_list) {
372 struct tomoyo_pattern_entry *ptr;
373 ptr = list_entry(pos, struct tomoyo_pattern_entry, list);
374 if (ptr->is_deleted)
375 continue;
376 if (!tomoyo_io_printf(head, TOMOYO_KEYWORD_FILE_PATTERN "%s\n",
377 ptr->pattern->name)) {
378 done = false;
379 break;
380 }
381 }
382 up_read(&tomoyo_pattern_list_lock);
383 return done;
384}
385
386/* The list for "struct tomoyo_no_rewrite_entry". */
387static LIST_HEAD(tomoyo_no_rewrite_list);
388static DECLARE_RWSEM(tomoyo_no_rewrite_list_lock);
389
390/**
391 * tomoyo_update_no_rewrite_entry - Update "struct tomoyo_no_rewrite_entry" list.
392 *
393 * @pattern: Pathname pattern that are not rewritable by default.
394 * @is_delete: True if it is a delete request.
395 *
396 * Returns 0 on success, negative value otherwise.
397 */
398static int tomoyo_update_no_rewrite_entry(const char *pattern,
399 const bool is_delete)
400{
401 struct tomoyo_no_rewrite_entry *new_entry, *ptr;
402 const struct tomoyo_path_info *saved_pattern;
403 int error = -ENOMEM;
404
405 if (!tomoyo_is_correct_path(pattern, 0, 0, 0, __func__))
406 return -EINVAL;
407 saved_pattern = tomoyo_save_name(pattern);
408 if (!saved_pattern)
409 return -ENOMEM;
410 /***** EXCLUSIVE SECTION START *****/
411 down_write(&tomoyo_no_rewrite_list_lock);
412 list_for_each_entry(ptr, &tomoyo_no_rewrite_list, list) {
413 if (ptr->pattern != saved_pattern)
414 continue;
415 ptr->is_deleted = is_delete;
416 error = 0;
417 goto out;
418 }
419 if (is_delete) {
420 error = -ENOENT;
421 goto out;
422 }
423 new_entry = tomoyo_alloc_element(sizeof(*new_entry));
424 if (!new_entry)
425 goto out;
426 new_entry->pattern = saved_pattern;
427 list_add_tail(&new_entry->list, &tomoyo_no_rewrite_list);
428 error = 0;
429 out:
430 up_write(&tomoyo_no_rewrite_list_lock);
431 /***** EXCLUSIVE SECTION END *****/
432 return error;
433}
434
435/**
436 * tomoyo_is_no_rewrite_file - Check if the given pathname is not permitted to be rewrited.
437 *
438 * @filename: Filename to check.
439 *
440 * Returns true if @filename is specified by "deny_rewrite" directive,
441 * false otherwise.
442 */
443static bool tomoyo_is_no_rewrite_file(const struct tomoyo_path_info *filename)
444{
445 struct tomoyo_no_rewrite_entry *ptr;
446 bool found = false;
447
448 down_read(&tomoyo_no_rewrite_list_lock);
449 list_for_each_entry(ptr, &tomoyo_no_rewrite_list, list) {
450 if (ptr->is_deleted)
451 continue;
452 if (!tomoyo_path_matches_pattern(filename, ptr->pattern))
453 continue;
454 found = true;
455 break;
456 }
457 up_read(&tomoyo_no_rewrite_list_lock);
458 return found;
459}
460
461/**
462 * tomoyo_write_no_rewrite_policy - Write "struct tomoyo_no_rewrite_entry" list.
463 *
464 * @data: String to parse.
465 * @is_delete: True if it is a delete request.
466 *
467 * Returns 0 on success, negative value otherwise.
468 */
469int tomoyo_write_no_rewrite_policy(char *data, const bool is_delete)
470{
471 return tomoyo_update_no_rewrite_entry(data, is_delete);
472}
473
474/**
475 * tomoyo_read_no_rewrite_policy - Read "struct tomoyo_no_rewrite_entry" list.
476 *
477 * @head: Pointer to "struct tomoyo_io_buffer".
478 *
479 * Returns true on success, false otherwise.
480 */
481bool tomoyo_read_no_rewrite_policy(struct tomoyo_io_buffer *head)
482{
483 struct list_head *pos;
484 bool done = true;
485
486 down_read(&tomoyo_no_rewrite_list_lock);
487 list_for_each_cookie(pos, head->read_var2, &tomoyo_no_rewrite_list) {
488 struct tomoyo_no_rewrite_entry *ptr;
489 ptr = list_entry(pos, struct tomoyo_no_rewrite_entry, list);
490 if (ptr->is_deleted)
491 continue;
492 if (!tomoyo_io_printf(head, TOMOYO_KEYWORD_DENY_REWRITE "%s\n",
493 ptr->pattern->name)) {
494 done = false;
495 break;
496 }
497 }
498 up_read(&tomoyo_no_rewrite_list_lock);
499 return done;
500}
501
502/**
503 * tomoyo_update_file_acl - Update file's read/write/execute ACL.
504 *
505 * @filename: Filename.
506 * @perm: Permission (between 1 to 7).
507 * @domain: Pointer to "struct tomoyo_domain_info".
508 * @is_delete: True if it is a delete request.
509 *
510 * Returns 0 on success, negative value otherwise.
511 *
512 * This is legacy support interface for older policy syntax.
513 * Current policy syntax uses "allow_read/write" instead of "6",
514 * "allow_read" instead of "4", "allow_write" instead of "2",
515 * "allow_execute" instead of "1".
516 */
517static int tomoyo_update_file_acl(const char *filename, u8 perm,
518 struct tomoyo_domain_info * const domain,
519 const bool is_delete)
520{
521 if (perm > 7 || !perm) {
522 printk(KERN_DEBUG "%s: Invalid permission '%d %s'\n",
523 __func__, perm, filename);
524 return -EINVAL;
525 }
526 if (filename[0] != '@' && tomoyo_strendswith(filename, "/"))
527 /*
528 * Only 'allow_mkdir' and 'allow_rmdir' are valid for
529 * directory permissions.
530 */
531 return 0;
532 if (perm & 4)
533 tomoyo_update_single_path_acl(TOMOYO_TYPE_READ_ACL, filename,
534 domain, is_delete);
535 if (perm & 2)
536 tomoyo_update_single_path_acl(TOMOYO_TYPE_WRITE_ACL, filename,
537 domain, is_delete);
538 if (perm & 1)
539 tomoyo_update_single_path_acl(TOMOYO_TYPE_EXECUTE_ACL,
540 filename, domain, is_delete);
541 return 0;
542}
543
544/**
545 * tomoyo_check_single_path_acl2 - Check permission for single path operation.
546 *
547 * @domain: Pointer to "struct tomoyo_domain_info".
548 * @filename: Filename to check.
549 * @perm: Permission.
550 * @may_use_pattern: True if patterned ACL is permitted.
551 *
552 * Returns 0 on success, -EPERM otherwise.
553 */
554static int tomoyo_check_single_path_acl2(const struct tomoyo_domain_info *
555 domain,
556 const struct tomoyo_path_info *
557 filename,
558 const u16 perm,
559 const bool may_use_pattern)
560{
561 struct tomoyo_acl_info *ptr;
562 int error = -EPERM;
563
564 down_read(&tomoyo_domain_acl_info_list_lock);
565 list_for_each_entry(ptr, &domain->acl_info_list, list) {
566 struct tomoyo_single_path_acl_record *acl;
567 if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_SINGLE_PATH_ACL)
568 continue;
569 acl = container_of(ptr, struct tomoyo_single_path_acl_record,
570 head);
571 if (!(acl->perm & perm))
572 continue;
573 if (may_use_pattern || !acl->filename->is_patterned) {
574 if (!tomoyo_path_matches_pattern(filename,
575 acl->filename))
576 continue;
577 } else {
578 continue;
579 }
580 error = 0;
581 break;
582 }
583 up_read(&tomoyo_domain_acl_info_list_lock);
584 return error;
585}
586
587/**
588 * tomoyo_check_file_acl - Check permission for opening files.
589 *
590 * @domain: Pointer to "struct tomoyo_domain_info".
591 * @filename: Filename to check.
592 * @operation: Mode ("read" or "write" or "read/write" or "execute").
593 *
594 * Returns 0 on success, -EPERM otherwise.
595 */
596static int tomoyo_check_file_acl(const struct tomoyo_domain_info *domain,
597 const struct tomoyo_path_info *filename,
598 const u8 operation)
599{
600 u16 perm = 0;
601
602 if (!tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE))
603 return 0;
604 if (operation == 6)
605 perm = 1 << TOMOYO_TYPE_READ_WRITE_ACL;
606 else if (operation == 4)
607 perm = 1 << TOMOYO_TYPE_READ_ACL;
608 else if (operation == 2)
609 perm = 1 << TOMOYO_TYPE_WRITE_ACL;
610 else if (operation == 1)
611 perm = 1 << TOMOYO_TYPE_EXECUTE_ACL;
612 else
613 BUG();
614 return tomoyo_check_single_path_acl2(domain, filename, perm,
615 operation != 1);
616}
617
618/**
619 * tomoyo_check_file_perm2 - Check permission for opening files.
620 *
621 * @domain: Pointer to "struct tomoyo_domain_info".
622 * @filename: Filename to check.
623 * @perm: Mode ("read" or "write" or "read/write" or "execute").
624 * @operation: Operation name passed used for verbose mode.
625 * @mode: Access control mode.
626 *
627 * Returns 0 on success, negative value otherwise.
628 */
629static int tomoyo_check_file_perm2(struct tomoyo_domain_info * const domain,
630 const struct tomoyo_path_info *filename,
631 const u8 perm, const char *operation,
632 const u8 mode)
633{
634 const bool is_enforce = (mode == 3);
635 const char *msg = "<unknown>";
636 int error = 0;
637
638 if (!filename)
639 return 0;
640 error = tomoyo_check_file_acl(domain, filename, perm);
641 if (error && perm == 4 &&
642 (domain->flags & TOMOYO_DOMAIN_FLAGS_IGNORE_GLOBAL_ALLOW_READ) == 0
643 && tomoyo_is_globally_readable_file(filename))
644 error = 0;
645 if (perm == 6)
646 msg = tomoyo_sp2keyword(TOMOYO_TYPE_READ_WRITE_ACL);
647 else if (perm == 4)
648 msg = tomoyo_sp2keyword(TOMOYO_TYPE_READ_ACL);
649 else if (perm == 2)
650 msg = tomoyo_sp2keyword(TOMOYO_TYPE_WRITE_ACL);
651 else if (perm == 1)
652 msg = tomoyo_sp2keyword(TOMOYO_TYPE_EXECUTE_ACL);
653 else
654 BUG();
655 if (!error)
656 return 0;
657 if (tomoyo_verbose_mode(domain))
658 printk(KERN_WARNING "TOMOYO-%s: Access '%s(%s) %s' denied "
659 "for %s\n", tomoyo_get_msg(is_enforce), msg, operation,
660 filename->name, tomoyo_get_last_name(domain));
661 if (is_enforce)
662 return error;
663 if (mode == 1 && tomoyo_domain_quota_is_ok(domain)) {
664 /* Don't use patterns for execute permission. */
665 const struct tomoyo_path_info *patterned_file = (perm != 1) ?
666 tomoyo_get_file_pattern(filename) : filename;
667 tomoyo_update_file_acl(patterned_file->name, perm,
668 domain, false);
669 }
670 return 0;
671}
672
673/**
674 * tomoyo_write_file_policy - Update file related list.
675 *
676 * @data: String to parse.
677 * @domain: Pointer to "struct tomoyo_domain_info".
678 * @is_delete: True if it is a delete request.
679 *
680 * Returns 0 on success, negative value otherwise.
681 */
682int tomoyo_write_file_policy(char *data, struct tomoyo_domain_info *domain,
683 const bool is_delete)
684{
685 char *filename = strchr(data, ' ');
686 char *filename2;
687 unsigned int perm;
688 u8 type;
689
690 if (!filename)
691 return -EINVAL;
692 *filename++ = '\0';
693 if (sscanf(data, "%u", &perm) == 1)
694 return tomoyo_update_file_acl(filename, (u8) perm, domain,
695 is_delete);
696 if (strncmp(data, "allow_", 6))
697 goto out;
698 data += 6;
699 for (type = 0; type < TOMOYO_MAX_SINGLE_PATH_OPERATION; type++) {
700 if (strcmp(data, tomoyo_sp_keyword[type]))
701 continue;
702 return tomoyo_update_single_path_acl(type, filename,
703 domain, is_delete);
704 }
705 filename2 = strchr(filename, ' ');
706 if (!filename2)
707 goto out;
708 *filename2++ = '\0';
709 for (type = 0; type < TOMOYO_MAX_DOUBLE_PATH_OPERATION; type++) {
710 if (strcmp(data, tomoyo_dp_keyword[type]))
711 continue;
712 return tomoyo_update_double_path_acl(type, filename, filename2,
713 domain, is_delete);
714 }
715 out:
716 return -EINVAL;
717}
718
719/**
720 * tomoyo_update_single_path_acl - Update "struct tomoyo_single_path_acl_record" list.
721 *
722 * @type: Type of operation.
723 * @filename: Filename.
724 * @domain: Pointer to "struct tomoyo_domain_info".
725 * @is_delete: True if it is a delete request.
726 *
727 * Returns 0 on success, negative value otherwise.
728 */
729static int tomoyo_update_single_path_acl(const u8 type, const char *filename,
730 struct tomoyo_domain_info *
731 const domain, const bool is_delete)
732{
733 static const u16 rw_mask =
734 (1 << TOMOYO_TYPE_READ_ACL) | (1 << TOMOYO_TYPE_WRITE_ACL);
735 const struct tomoyo_path_info *saved_filename;
736 struct tomoyo_acl_info *ptr;
737 struct tomoyo_single_path_acl_record *acl;
738 int error = -ENOMEM;
739 const u16 perm = 1 << type;
740
741 if (!domain)
742 return -EINVAL;
743 if (!tomoyo_is_correct_path(filename, 0, 0, 0, __func__))
744 return -EINVAL;
745 saved_filename = tomoyo_save_name(filename);
746 if (!saved_filename)
747 return -ENOMEM;
748 /***** EXCLUSIVE SECTION START *****/
749 down_write(&tomoyo_domain_acl_info_list_lock);
750 if (is_delete)
751 goto delete;
752 list_for_each_entry(ptr, &domain->acl_info_list, list) {
753 if (tomoyo_acl_type1(ptr) != TOMOYO_TYPE_SINGLE_PATH_ACL)
754 continue;
755 acl = container_of(ptr, struct tomoyo_single_path_acl_record,
756 head);
757 if (acl->filename != saved_filename)
758 continue;
759 /* Special case. Clear all bits if marked as deleted. */
760 if (ptr->type & TOMOYO_ACL_DELETED)
761 acl->perm = 0;
762 acl->perm |= perm;
763 if ((acl->perm & rw_mask) == rw_mask)
764 acl->perm |= 1 << TOMOYO_TYPE_READ_WRITE_ACL;
765 else if (acl->perm & (1 << TOMOYO_TYPE_READ_WRITE_ACL))
766 acl->perm |= rw_mask;
767 ptr->type &= ~TOMOYO_ACL_DELETED;
768 error = 0;
769 goto out;
770 }
771 /* Not found. Append it to the tail. */
772 acl = tomoyo_alloc_acl_element(TOMOYO_TYPE_SINGLE_PATH_ACL);
773 if (!acl)
774 goto out;
775 acl->perm = perm;
776 if (perm == (1 << TOMOYO_TYPE_READ_WRITE_ACL))
777 acl->perm |= rw_mask;
778 acl->filename = saved_filename;
779 list_add_tail(&acl->head.list, &domain->acl_info_list);
780 error = 0;
781 goto out;
782 delete:
783 error = -ENOENT;
784 list_for_each_entry(ptr, &domain->acl_info_list, list) {
785 if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_SINGLE_PATH_ACL)
786 continue;
787 acl = container_of(ptr, struct tomoyo_single_path_acl_record,
788 head);
789 if (acl->filename != saved_filename)
790 continue;
791 acl->perm &= ~perm;
792 if ((acl->perm & rw_mask) != rw_mask)
793 acl->perm &= ~(1 << TOMOYO_TYPE_READ_WRITE_ACL);
794 else if (!(acl->perm & (1 << TOMOYO_TYPE_READ_WRITE_ACL)))
795 acl->perm &= ~rw_mask;
796 if (!acl->perm)
797 ptr->type |= TOMOYO_ACL_DELETED;
798 error = 0;
799 break;
800 }
801 out:
802 up_write(&tomoyo_domain_acl_info_list_lock);
803 /***** EXCLUSIVE SECTION END *****/
804 return error;
805}
806
807/**
808 * tomoyo_update_double_path_acl - Update "struct tomoyo_double_path_acl_record" list.
809 *
810 * @type: Type of operation.
811 * @filename1: First filename.
812 * @filename2: Second filename.
813 * @domain: Pointer to "struct tomoyo_domain_info".
814 * @is_delete: True if it is a delete request.
815 *
816 * Returns 0 on success, negative value otherwise.
817 */
818static int tomoyo_update_double_path_acl(const u8 type, const char *filename1,
819 const char *filename2,
820 struct tomoyo_domain_info *
821 const domain, const bool is_delete)
822{
823 const struct tomoyo_path_info *saved_filename1;
824 const struct tomoyo_path_info *saved_filename2;
825 struct tomoyo_acl_info *ptr;
826 struct tomoyo_double_path_acl_record *acl;
827 int error = -ENOMEM;
828 const u8 perm = 1 << type;
829
830 if (!domain)
831 return -EINVAL;
832 if (!tomoyo_is_correct_path(filename1, 0, 0, 0, __func__) ||
833 !tomoyo_is_correct_path(filename2, 0, 0, 0, __func__))
834 return -EINVAL;
835 saved_filename1 = tomoyo_save_name(filename1);
836 saved_filename2 = tomoyo_save_name(filename2);
837 if (!saved_filename1 || !saved_filename2)
838 return -ENOMEM;
839 /***** EXCLUSIVE SECTION START *****/
840 down_write(&tomoyo_domain_acl_info_list_lock);
841 if (is_delete)
842 goto delete;
843 list_for_each_entry(ptr, &domain->acl_info_list, list) {
844 if (tomoyo_acl_type1(ptr) != TOMOYO_TYPE_DOUBLE_PATH_ACL)
845 continue;
846 acl = container_of(ptr, struct tomoyo_double_path_acl_record,
847 head);
848 if (acl->filename1 != saved_filename1 ||
849 acl->filename2 != saved_filename2)
850 continue;
851 /* Special case. Clear all bits if marked as deleted. */
852 if (ptr->type & TOMOYO_ACL_DELETED)
853 acl->perm = 0;
854 acl->perm |= perm;
855 ptr->type &= ~TOMOYO_ACL_DELETED;
856 error = 0;
857 goto out;
858 }
859 /* Not found. Append it to the tail. */
860 acl = tomoyo_alloc_acl_element(TOMOYO_TYPE_DOUBLE_PATH_ACL);
861 if (!acl)
862 goto out;
863 acl->perm = perm;
864 acl->filename1 = saved_filename1;
865 acl->filename2 = saved_filename2;
866 list_add_tail(&acl->head.list, &domain->acl_info_list);
867 error = 0;
868 goto out;
869 delete:
870 error = -ENOENT;
871 list_for_each_entry(ptr, &domain->acl_info_list, list) {
872 if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_DOUBLE_PATH_ACL)
873 continue;
874 acl = container_of(ptr, struct tomoyo_double_path_acl_record,
875 head);
876 if (acl->filename1 != saved_filename1 ||
877 acl->filename2 != saved_filename2)
878 continue;
879 acl->perm &= ~perm;
880 if (!acl->perm)
881 ptr->type |= TOMOYO_ACL_DELETED;
882 error = 0;
883 break;
884 }
885 out:
886 up_write(&tomoyo_domain_acl_info_list_lock);
887 /***** EXCLUSIVE SECTION END *****/
888 return error;
889}
890
891/**
892 * tomoyo_check_single_path_acl - Check permission for single path operation.
893 *
894 * @domain: Pointer to "struct tomoyo_domain_info".
895 * @type: Type of operation.
896 * @filename: Filename to check.
897 *
898 * Returns 0 on success, negative value otherwise.
899 */
900static int tomoyo_check_single_path_acl(struct tomoyo_domain_info *domain,
901 const u8 type,
902 const struct tomoyo_path_info *filename)
903{
904 if (!tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE))
905 return 0;
906 return tomoyo_check_single_path_acl2(domain, filename, 1 << type, 1);
907}
908
909/**
910 * tomoyo_check_double_path_acl - Check permission for double path operation.
911 *
912 * @domain: Pointer to "struct tomoyo_domain_info".
913 * @type: Type of operation.
914 * @filename1: First filename to check.
915 * @filename2: Second filename to check.
916 *
917 * Returns 0 on success, -EPERM otherwise.
918 */
919static int tomoyo_check_double_path_acl(const struct tomoyo_domain_info *domain,
920 const u8 type,
921 const struct tomoyo_path_info *
922 filename1,
923 const struct tomoyo_path_info *
924 filename2)
925{
926 struct tomoyo_acl_info *ptr;
927 const u8 perm = 1 << type;
928 int error = -EPERM;
929
930 if (!tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE))
931 return 0;
932 down_read(&tomoyo_domain_acl_info_list_lock);
933 list_for_each_entry(ptr, &domain->acl_info_list, list) {
934 struct tomoyo_double_path_acl_record *acl;
935 if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_DOUBLE_PATH_ACL)
936 continue;
937 acl = container_of(ptr, struct tomoyo_double_path_acl_record,
938 head);
939 if (!(acl->perm & perm))
940 continue;
941 if (!tomoyo_path_matches_pattern(filename1, acl->filename1))
942 continue;
943 if (!tomoyo_path_matches_pattern(filename2, acl->filename2))
944 continue;
945 error = 0;
946 break;
947 }
948 up_read(&tomoyo_domain_acl_info_list_lock);
949 return error;
950}
951
952/**
953 * tomoyo_check_single_path_permission2 - Check permission for single path operation.
954 *
955 * @domain: Pointer to "struct tomoyo_domain_info".
956 * @operation: Type of operation.
957 * @filename: Filename to check.
958 * @mode: Access control mode.
959 *
960 * Returns 0 on success, negative value otherwise.
961 */
962static int tomoyo_check_single_path_permission2(struct tomoyo_domain_info *
963 const domain, u8 operation,
964 const struct tomoyo_path_info *
965 filename, const u8 mode)
966{
967 const char *msg;
968 int error;
969 const bool is_enforce = (mode == 3);
970
971 if (!mode)
972 return 0;
973 next:
974 error = tomoyo_check_single_path_acl(domain, operation, filename);
975 msg = tomoyo_sp2keyword(operation);
976 if (!error)
977 goto ok;
978 if (tomoyo_verbose_mode(domain))
979 printk(KERN_WARNING "TOMOYO-%s: Access '%s %s' denied for %s\n",
980 tomoyo_get_msg(is_enforce), msg, filename->name,
981 tomoyo_get_last_name(domain));
982 if (mode == 1 && tomoyo_domain_quota_is_ok(domain)) {
983 const char *name = tomoyo_get_file_pattern(filename)->name;
984 tomoyo_update_single_path_acl(operation, name, domain, false);
985 }
986 if (!is_enforce)
987 error = 0;
988 ok:
989 /*
990 * Since "allow_truncate" doesn't imply "allow_rewrite" permission,
991 * we need to check "allow_rewrite" permission if the filename is
992 * specified by "deny_rewrite" keyword.
993 */
994 if (!error && operation == TOMOYO_TYPE_TRUNCATE_ACL &&
995 tomoyo_is_no_rewrite_file(filename)) {
996 operation = TOMOYO_TYPE_REWRITE_ACL;
997 goto next;
998 }
999 return error;
1000}
1001
1002/**
1003 * tomoyo_check_file_perm - Check permission for sysctl()'s "read" and "write".
1004 *
1005 * @domain: Pointer to "struct tomoyo_domain_info".
1006 * @filename: Filename to check.
1007 * @perm: Mode ("read" or "write" or "read/write").
1008 * Returns 0 on success, negative value otherwise.
1009 */
1010int tomoyo_check_file_perm(struct tomoyo_domain_info *domain,
1011 const char *filename, const u8 perm)
1012{
1013 struct tomoyo_path_info name;
1014 const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE);
1015
1016 if (!mode)
1017 return 0;
1018 name.name = filename;
1019 tomoyo_fill_path_info(&name);
1020 return tomoyo_check_file_perm2(domain, &name, perm, "sysctl", mode);
1021}
1022
1023/**
1024 * tomoyo_check_exec_perm - Check permission for "execute".
1025 *
1026 * @domain: Pointer to "struct tomoyo_domain_info".
1027 * @filename: Check permission for "execute".
1028 * @tmp: Buffer for temporary use.
1029 *
1030 * Returns 0 on success, negativevalue otherwise.
1031 */
1032int tomoyo_check_exec_perm(struct tomoyo_domain_info *domain,
1033 const struct tomoyo_path_info *filename,
1034 struct tomoyo_page_buffer *tmp)
1035{
1036 const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE);
1037
1038 if (!mode)
1039 return 0;
1040 return tomoyo_check_file_perm2(domain, filename, 1, "do_execve", mode);
1041}
1042
1043/**
1044 * tomoyo_check_open_permission - Check permission for "read" and "write".
1045 *
1046 * @domain: Pointer to "struct tomoyo_domain_info".
1047 * @path: Pointer to "struct path".
1048 * @flag: Flags for open().
1049 *
1050 * Returns 0 on success, negative value otherwise.
1051 */
1052int tomoyo_check_open_permission(struct tomoyo_domain_info *domain,
1053 struct path *path, const int flag)
1054{
1055 const u8 acc_mode = ACC_MODE(flag);
1056 int error = -ENOMEM;
1057 struct tomoyo_path_info *buf;
1058 const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE);
1059 const bool is_enforce = (mode == 3);
1060
1061 if (!mode || !path->mnt)
1062 return 0;
1063 if (acc_mode == 0)
1064 return 0;
1065 if (path->dentry->d_inode && S_ISDIR(path->dentry->d_inode->i_mode))
1066 /*
1067 * I don't check directories here because mkdir() and rmdir()
1068 * don't call me.
1069 */
1070 return 0;
1071 buf = tomoyo_get_path(path);
1072 if (!buf)
1073 goto out;
1074 error = 0;
1075 /*
1076 * If the filename is specified by "deny_rewrite" keyword,
1077 * we need to check "allow_rewrite" permission when the filename is not
1078 * opened for append mode or the filename is truncated at open time.
1079 */
1080 if ((acc_mode & MAY_WRITE) &&
1081 ((flag & O_TRUNC) || !(flag & O_APPEND)) &&
1082 (tomoyo_is_no_rewrite_file(buf))) {
1083 error = tomoyo_check_single_path_permission2(domain,
1084 TOMOYO_TYPE_REWRITE_ACL,
1085 buf, mode);
1086 }
1087 if (!error)
1088 error = tomoyo_check_file_perm2(domain, buf, acc_mode, "open",
1089 mode);
1090 if (!error && (flag & O_TRUNC))
1091 error = tomoyo_check_single_path_permission2(domain,
1092 TOMOYO_TYPE_TRUNCATE_ACL,
1093 buf, mode);
1094 out:
1095 tomoyo_free(buf);
1096 if (!is_enforce)
1097 error = 0;
1098 return error;
1099}
1100
1101/**
1102 * tomoyo_check_1path_perm - Check permission for "create", "unlink", "mkdir", "rmdir", "mkfifo", "mksock", "mkblock", "mkchar", "truncate" and "symlink".
1103 *
1104 * @domain: Pointer to "struct tomoyo_domain_info".
1105 * @operation: Type of operation.
1106 * @path: Pointer to "struct path".
1107 *
1108 * Returns 0 on success, negative value otherwise.
1109 */
1110int tomoyo_check_1path_perm(struct tomoyo_domain_info *domain,
1111 const u8 operation, struct path *path)
1112{
1113 int error = -ENOMEM;
1114 struct tomoyo_path_info *buf;
1115 const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE);
1116 const bool is_enforce = (mode == 3);
1117
1118 if (!mode || !path->mnt)
1119 return 0;
1120 buf = tomoyo_get_path(path);
1121 if (!buf)
1122 goto out;
1123 switch (operation) {
1124 case TOMOYO_TYPE_MKDIR_ACL:
1125 case TOMOYO_TYPE_RMDIR_ACL:
1126 if (!buf->is_dir) {
1127 /*
1128 * tomoyo_get_path() reserves space for appending "/."
1129 */
1130 strcat((char *) buf->name, "/");
1131 tomoyo_fill_path_info(buf);
1132 }
1133 }
1134 error = tomoyo_check_single_path_permission2(domain, operation, buf,
1135 mode);
1136 out:
1137 tomoyo_free(buf);
1138 if (!is_enforce)
1139 error = 0;
1140 return error;
1141}
1142
1143/**
1144 * tomoyo_check_rewrite_permission - Check permission for "rewrite".
1145 *
1146 * @domain: Pointer to "struct tomoyo_domain_info".
1147 * @filp: Pointer to "struct file".
1148 *
1149 * Returns 0 on success, negative value otherwise.
1150 */
1151int tomoyo_check_rewrite_permission(struct tomoyo_domain_info *domain,
1152 struct file *filp)
1153{
1154 int error = -ENOMEM;
1155 const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE);
1156 const bool is_enforce = (mode == 3);
1157 struct tomoyo_path_info *buf;
1158
1159 if (!mode || !filp->f_path.mnt)
1160 return 0;
1161 buf = tomoyo_get_path(&filp->f_path);
1162 if (!buf)
1163 goto out;
1164 if (!tomoyo_is_no_rewrite_file(buf)) {
1165 error = 0;
1166 goto out;
1167 }
1168 error = tomoyo_check_single_path_permission2(domain,
1169 TOMOYO_TYPE_REWRITE_ACL,
1170 buf, mode);
1171 out:
1172 tomoyo_free(buf);
1173 if (!is_enforce)
1174 error = 0;
1175 return error;
1176}
1177
1178/**
1179 * tomoyo_check_2path_perm - Check permission for "rename" and "link".
1180 *
1181 * @domain: Pointer to "struct tomoyo_domain_info".
1182 * @operation: Type of operation.
1183 * @path1: Pointer to "struct path".
1184 * @path2: Pointer to "struct path".
1185 *
1186 * Returns 0 on success, negative value otherwise.
1187 */
1188int tomoyo_check_2path_perm(struct tomoyo_domain_info * const domain,
1189 const u8 operation, struct path *path1,
1190 struct path *path2)
1191{
1192 int error = -ENOMEM;
1193 struct tomoyo_path_info *buf1, *buf2;
1194 const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE);
1195 const bool is_enforce = (mode == 3);
1196 const char *msg;
1197
1198 if (!mode || !path1->mnt || !path2->mnt)
1199 return 0;
1200 buf1 = tomoyo_get_path(path1);
1201 buf2 = tomoyo_get_path(path2);
1202 if (!buf1 || !buf2)
1203 goto out;
1204 {
1205 struct dentry *dentry = path1->dentry;
1206 if (dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode)) {
1207 /*
1208 * tomoyo_get_path() reserves space for appending "/."
1209 */
1210 if (!buf1->is_dir) {
1211 strcat((char *) buf1->name, "/");
1212 tomoyo_fill_path_info(buf1);
1213 }
1214 if (!buf2->is_dir) {
1215 strcat((char *) buf2->name, "/");
1216 tomoyo_fill_path_info(buf2);
1217 }
1218 }
1219 }
1220 error = tomoyo_check_double_path_acl(domain, operation, buf1, buf2);
1221 msg = tomoyo_dp2keyword(operation);
1222 if (!error)
1223 goto out;
1224 if (tomoyo_verbose_mode(domain))
1225 printk(KERN_WARNING "TOMOYO-%s: Access '%s %s %s' "
1226 "denied for %s\n", tomoyo_get_msg(is_enforce),
1227 msg, buf1->name, buf2->name,
1228 tomoyo_get_last_name(domain));
1229 if (mode == 1 && tomoyo_domain_quota_is_ok(domain)) {
1230 const char *name1 = tomoyo_get_file_pattern(buf1)->name;
1231 const char *name2 = tomoyo_get_file_pattern(buf2)->name;
1232 tomoyo_update_double_path_acl(operation, name1, name2, domain,
1233 false);
1234 }
1235 out:
1236 tomoyo_free(buf1);
1237 tomoyo_free(buf2);
1238 if (!is_enforce)
1239 error = 0;
1240 return error;
1241}
diff --git a/security/tomoyo/realpath.c b/security/tomoyo/realpath.c
new file mode 100644
index 000000000000..3bbe01a7a4b5
--- /dev/null
+++ b/security/tomoyo/realpath.c
@@ -0,0 +1,483 @@
1/*
2 * security/tomoyo/realpath.c
3 *
4 * Get the canonicalized absolute pathnames. The basis for TOMOYO.
5 *
6 * Copyright (C) 2005-2009 NTT DATA CORPORATION
7 *
8 * Version: 2.2.0-pre 2009/02/01
9 *
10 */
11
12#include <linux/types.h>
13#include <linux/mount.h>
14#include <linux/mnt_namespace.h>
15#include <linux/fs_struct.h>
16#include "common.h"
17#include "realpath.h"
18
19/**
20 * tomoyo_encode: Convert binary string to ascii string.
21 *
22 * @buffer: Buffer for ASCII string.
23 * @buflen: Size of @buffer.
24 * @str: Binary string.
25 *
26 * Returns 0 on success, -ENOMEM otherwise.
27 */
28int tomoyo_encode(char *buffer, int buflen, const char *str)
29{
30 while (1) {
31 const unsigned char c = *(unsigned char *) str++;
32
33 if (tomoyo_is_valid(c)) {
34 if (--buflen <= 0)
35 break;
36 *buffer++ = (char) c;
37 if (c != '\\')
38 continue;
39 if (--buflen <= 0)
40 break;
41 *buffer++ = (char) c;
42 continue;
43 }
44 if (!c) {
45 if (--buflen <= 0)
46 break;
47 *buffer = '\0';
48 return 0;
49 }
50 buflen -= 4;
51 if (buflen <= 0)
52 break;
53 *buffer++ = '\\';
54 *buffer++ = (c >> 6) + '0';
55 *buffer++ = ((c >> 3) & 7) + '0';
56 *buffer++ = (c & 7) + '0';
57 }
58 return -ENOMEM;
59}
60
61/**
62 * tomoyo_realpath_from_path2 - Returns realpath(3) of the given dentry but ignores chroot'ed root.
63 *
64 * @path: Pointer to "struct path".
65 * @newname: Pointer to buffer to return value in.
66 * @newname_len: Size of @newname.
67 *
68 * Returns 0 on success, negative value otherwise.
69 *
70 * If dentry is a directory, trailing '/' is appended.
71 * Characters out of 0x20 < c < 0x7F range are converted to
72 * \ooo style octal string.
73 * Character \ is converted to \\ string.
74 */
75int tomoyo_realpath_from_path2(struct path *path, char *newname,
76 int newname_len)
77{
78 int error = -ENOMEM;
79 struct dentry *dentry = path->dentry;
80 char *sp;
81
82 if (!dentry || !path->mnt || !newname || newname_len <= 2048)
83 return -EINVAL;
84 if (dentry->d_op && dentry->d_op->d_dname) {
85 /* For "socket:[\$]" and "pipe:[\$]". */
86 static const int offset = 1536;
87 sp = dentry->d_op->d_dname(dentry, newname + offset,
88 newname_len - offset);
89 } else {
90 /* Taken from d_namespace_path(). */
91 struct path root;
92 struct path ns_root = { };
93 struct path tmp;
94
95 read_lock(&current->fs->lock);
96 root = current->fs->root;
97 path_get(&root);
98 read_unlock(&current->fs->lock);
99 spin_lock(&vfsmount_lock);
100 if (root.mnt && root.mnt->mnt_ns)
101 ns_root.mnt = mntget(root.mnt->mnt_ns->root);
102 if (ns_root.mnt)
103 ns_root.dentry = dget(ns_root.mnt->mnt_root);
104 spin_unlock(&vfsmount_lock);
105 spin_lock(&dcache_lock);
106 tmp = ns_root;
107 sp = __d_path(path, &tmp, newname, newname_len);
108 spin_unlock(&dcache_lock);
109 path_put(&root);
110 path_put(&ns_root);
111 }
112 if (IS_ERR(sp))
113 error = PTR_ERR(sp);
114 else
115 error = tomoyo_encode(newname, sp - newname, sp);
116 /* Append trailing '/' if dentry is a directory. */
117 if (!error && dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode)
118 && *newname) {
119 sp = newname + strlen(newname);
120 if (*(sp - 1) != '/') {
121 if (sp < newname + newname_len - 4) {
122 *sp++ = '/';
123 *sp = '\0';
124 } else {
125 error = -ENOMEM;
126 }
127 }
128 }
129 if (error)
130 printk(KERN_WARNING "tomoyo_realpath: Pathname too long.\n");
131 return error;
132}
133
134/**
135 * tomoyo_realpath_from_path - Returns realpath(3) of the given pathname but ignores chroot'ed root.
136 *
137 * @path: Pointer to "struct path".
138 *
139 * Returns the realpath of the given @path on success, NULL otherwise.
140 *
141 * These functions use tomoyo_alloc(), so the caller must call tomoyo_free()
142 * if these functions didn't return NULL.
143 */
144char *tomoyo_realpath_from_path(struct path *path)
145{
146 char *buf = tomoyo_alloc(sizeof(struct tomoyo_page_buffer));
147
148 BUILD_BUG_ON(sizeof(struct tomoyo_page_buffer)
149 <= TOMOYO_MAX_PATHNAME_LEN - 1);
150 if (!buf)
151 return NULL;
152 if (tomoyo_realpath_from_path2(path, buf,
153 TOMOYO_MAX_PATHNAME_LEN - 1) == 0)
154 return buf;
155 tomoyo_free(buf);
156 return NULL;
157}
158
159/**
160 * tomoyo_realpath - Get realpath of a pathname.
161 *
162 * @pathname: The pathname to solve.
163 *
164 * Returns the realpath of @pathname on success, NULL otherwise.
165 */
166char *tomoyo_realpath(const char *pathname)
167{
168 struct nameidata nd;
169
170 if (pathname && path_lookup(pathname, LOOKUP_FOLLOW, &nd) == 0) {
171 char *buf = tomoyo_realpath_from_path(&nd.path);
172 path_put(&nd.path);
173 return buf;
174 }
175 return NULL;
176}
177
178/**
179 * tomoyo_realpath_nofollow - Get realpath of a pathname.
180 *
181 * @pathname: The pathname to solve.
182 *
183 * Returns the realpath of @pathname on success, NULL otherwise.
184 */
185char *tomoyo_realpath_nofollow(const char *pathname)
186{
187 struct nameidata nd;
188
189 if (pathname && path_lookup(pathname, 0, &nd) == 0) {
190 char *buf = tomoyo_realpath_from_path(&nd.path);
191 path_put(&nd.path);
192 return buf;
193 }
194 return NULL;
195}
196
197/* Memory allocated for non-string data. */
198static unsigned int tomoyo_allocated_memory_for_elements;
199/* Quota for holding non-string data. */
200static unsigned int tomoyo_quota_for_elements;
201
202/**
203 * tomoyo_alloc_element - Allocate permanent memory for structures.
204 *
205 * @size: Size in bytes.
206 *
207 * Returns pointer to allocated memory on success, NULL otherwise.
208 *
209 * Memory has to be zeroed.
210 * The RAM is chunked, so NEVER try to kfree() the returned pointer.
211 */
212void *tomoyo_alloc_element(const unsigned int size)
213{
214 static char *buf;
215 static DEFINE_MUTEX(lock);
216 static unsigned int buf_used_len = PATH_MAX;
217 char *ptr = NULL;
218 /*Assumes sizeof(void *) >= sizeof(long) is true. */
219 const unsigned int word_aligned_size
220 = roundup(size, max(sizeof(void *), sizeof(long)));
221 if (word_aligned_size > PATH_MAX)
222 return NULL;
223 /***** EXCLUSIVE SECTION START *****/
224 mutex_lock(&lock);
225 if (buf_used_len + word_aligned_size > PATH_MAX) {
226 if (!tomoyo_quota_for_elements ||
227 tomoyo_allocated_memory_for_elements
228 + PATH_MAX <= tomoyo_quota_for_elements)
229 ptr = kzalloc(PATH_MAX, GFP_KERNEL);
230 if (!ptr) {
231 printk(KERN_WARNING "ERROR: Out of memory "
232 "for tomoyo_alloc_element().\n");
233 if (!tomoyo_policy_loaded)
234 panic("MAC Initialization failed.\n");
235 } else {
236 buf = ptr;
237 tomoyo_allocated_memory_for_elements += PATH_MAX;
238 buf_used_len = word_aligned_size;
239 ptr = buf;
240 }
241 } else if (word_aligned_size) {
242 int i;
243 ptr = buf + buf_used_len;
244 buf_used_len += word_aligned_size;
245 for (i = 0; i < word_aligned_size; i++) {
246 if (!ptr[i])
247 continue;
248 printk(KERN_ERR "WARNING: Reserved memory was tainted! "
249 "The system might go wrong.\n");
250 ptr[i] = '\0';
251 }
252 }
253 mutex_unlock(&lock);
254 /***** EXCLUSIVE SECTION END *****/
255 return ptr;
256}
257
258/* Memory allocated for string data in bytes. */
259static unsigned int tomoyo_allocated_memory_for_savename;
260/* Quota for holding string data in bytes. */
261static unsigned int tomoyo_quota_for_savename;
262
263/*
264 * TOMOYO uses this hash only when appending a string into the string
265 * table. Frequency of appending strings is very low. So we don't need
266 * large (e.g. 64k) hash size. 256 will be sufficient.
267 */
268#define TOMOYO_MAX_HASH 256
269
270/* Structure for string data. */
271struct tomoyo_name_entry {
272 struct list_head list;
273 struct tomoyo_path_info entry;
274};
275
276/* Structure for available memory region. */
277struct tomoyo_free_memory_block_list {
278 struct list_head list;
279 char *ptr; /* Pointer to a free area. */
280 int len; /* Length of the area. */
281};
282
283/*
284 * The list for "struct tomoyo_name_entry".
285 *
286 * This list is updated only inside tomoyo_save_name(), thus
287 * no global mutex exists.
288 */
289static struct list_head tomoyo_name_list[TOMOYO_MAX_HASH];
290
291/**
292 * tomoyo_save_name - Allocate permanent memory for string data.
293 *
294 * @name: The string to store into the permernent memory.
295 *
296 * Returns pointer to "struct tomoyo_path_info" on success, NULL otherwise.
297 *
298 * The RAM is shared, so NEVER try to modify or kfree() the returned name.
299 */
300const struct tomoyo_path_info *tomoyo_save_name(const char *name)
301{
302 static LIST_HEAD(fmb_list);
303 static DEFINE_MUTEX(lock);
304 struct tomoyo_name_entry *ptr;
305 unsigned int hash;
306 /* fmb contains available size in bytes.
307 fmb is removed from the fmb_list when fmb->len becomes 0. */
308 struct tomoyo_free_memory_block_list *fmb;
309 int len;
310 char *cp;
311
312 if (!name)
313 return NULL;
314 len = strlen(name) + 1;
315 if (len > TOMOYO_MAX_PATHNAME_LEN) {
316 printk(KERN_WARNING "ERROR: Name too long "
317 "for tomoyo_save_name().\n");
318 return NULL;
319 }
320 hash = full_name_hash((const unsigned char *) name, len - 1);
321 /***** EXCLUSIVE SECTION START *****/
322 mutex_lock(&lock);
323 list_for_each_entry(ptr, &tomoyo_name_list[hash % TOMOYO_MAX_HASH],
324 list) {
325 if (hash == ptr->entry.hash && !strcmp(name, ptr->entry.name))
326 goto out;
327 }
328 list_for_each_entry(fmb, &fmb_list, list) {
329 if (len <= fmb->len)
330 goto ready;
331 }
332 if (!tomoyo_quota_for_savename ||
333 tomoyo_allocated_memory_for_savename + PATH_MAX
334 <= tomoyo_quota_for_savename)
335 cp = kzalloc(PATH_MAX, GFP_KERNEL);
336 else
337 cp = NULL;
338 fmb = kzalloc(sizeof(*fmb), GFP_KERNEL);
339 if (!cp || !fmb) {
340 kfree(cp);
341 kfree(fmb);
342 printk(KERN_WARNING "ERROR: Out of memory "
343 "for tomoyo_save_name().\n");
344 if (!tomoyo_policy_loaded)
345 panic("MAC Initialization failed.\n");
346 ptr = NULL;
347 goto out;
348 }
349 tomoyo_allocated_memory_for_savename += PATH_MAX;
350 list_add(&fmb->list, &fmb_list);
351 fmb->ptr = cp;
352 fmb->len = PATH_MAX;
353 ready:
354 ptr = tomoyo_alloc_element(sizeof(*ptr));
355 if (!ptr)
356 goto out;
357 ptr->entry.name = fmb->ptr;
358 memmove(fmb->ptr, name, len);
359 tomoyo_fill_path_info(&ptr->entry);
360 fmb->ptr += len;
361 fmb->len -= len;
362 list_add_tail(&ptr->list, &tomoyo_name_list[hash % TOMOYO_MAX_HASH]);
363 if (fmb->len == 0) {
364 list_del(&fmb->list);
365 kfree(fmb);
366 }
367 out:
368 mutex_unlock(&lock);
369 /***** EXCLUSIVE SECTION END *****/
370 return ptr ? &ptr->entry : NULL;
371}
372
373/**
374 * tomoyo_realpath_init - Initialize realpath related code.
375 */
376void __init tomoyo_realpath_init(void)
377{
378 int i;
379
380 BUILD_BUG_ON(TOMOYO_MAX_PATHNAME_LEN > PATH_MAX);
381 for (i = 0; i < TOMOYO_MAX_HASH; i++)
382 INIT_LIST_HEAD(&tomoyo_name_list[i]);
383 INIT_LIST_HEAD(&tomoyo_kernel_domain.acl_info_list);
384 tomoyo_kernel_domain.domainname = tomoyo_save_name(TOMOYO_ROOT_NAME);
385 list_add_tail(&tomoyo_kernel_domain.list, &tomoyo_domain_list);
386 down_read(&tomoyo_domain_list_lock);
387 if (tomoyo_find_domain(TOMOYO_ROOT_NAME) != &tomoyo_kernel_domain)
388 panic("Can't register tomoyo_kernel_domain");
389 up_read(&tomoyo_domain_list_lock);
390}
391
392/* Memory allocated for temporary purpose. */
393static atomic_t tomoyo_dynamic_memory_size;
394
395/**
396 * tomoyo_alloc - Allocate memory for temporary purpose.
397 *
398 * @size: Size in bytes.
399 *
400 * Returns pointer to allocated memory on success, NULL otherwise.
401 */
402void *tomoyo_alloc(const size_t size)
403{
404 void *p = kzalloc(size, GFP_KERNEL);
405 if (p)
406 atomic_add(ksize(p), &tomoyo_dynamic_memory_size);
407 return p;
408}
409
410/**
411 * tomoyo_free - Release memory allocated by tomoyo_alloc().
412 *
413 * @p: Pointer returned by tomoyo_alloc(). May be NULL.
414 *
415 * Returns nothing.
416 */
417void tomoyo_free(const void *p)
418{
419 if (p) {
420 atomic_sub(ksize(p), &tomoyo_dynamic_memory_size);
421 kfree(p);
422 }
423}
424
425/**
426 * tomoyo_read_memory_counter - Check for memory usage in bytes.
427 *
428 * @head: Pointer to "struct tomoyo_io_buffer".
429 *
430 * Returns memory usage.
431 */
432int tomoyo_read_memory_counter(struct tomoyo_io_buffer *head)
433{
434 if (!head->read_eof) {
435 const unsigned int shared
436 = tomoyo_allocated_memory_for_savename;
437 const unsigned int private
438 = tomoyo_allocated_memory_for_elements;
439 const unsigned int dynamic
440 = atomic_read(&tomoyo_dynamic_memory_size);
441 char buffer[64];
442
443 memset(buffer, 0, sizeof(buffer));
444 if (tomoyo_quota_for_savename)
445 snprintf(buffer, sizeof(buffer) - 1,
446 " (Quota: %10u)",
447 tomoyo_quota_for_savename);
448 else
449 buffer[0] = '\0';
450 tomoyo_io_printf(head, "Shared: %10u%s\n", shared, buffer);
451 if (tomoyo_quota_for_elements)
452 snprintf(buffer, sizeof(buffer) - 1,
453 " (Quota: %10u)",
454 tomoyo_quota_for_elements);
455 else
456 buffer[0] = '\0';
457 tomoyo_io_printf(head, "Private: %10u%s\n", private, buffer);
458 tomoyo_io_printf(head, "Dynamic: %10u\n", dynamic);
459 tomoyo_io_printf(head, "Total: %10u\n",
460 shared + private + dynamic);
461 head->read_eof = true;
462 }
463 return 0;
464}
465
466/**
467 * tomoyo_write_memory_quota - Set memory quota.
468 *
469 * @head: Pointer to "struct tomoyo_io_buffer".
470 *
471 * Returns 0.
472 */
473int tomoyo_write_memory_quota(struct tomoyo_io_buffer *head)
474{
475 char *data = head->write_buf;
476 unsigned int size;
477
478 if (sscanf(data, "Shared: %u", &size) == 1)
479 tomoyo_quota_for_savename = size;
480 else if (sscanf(data, "Private: %u", &size) == 1)
481 tomoyo_quota_for_elements = size;
482 return 0;
483}
diff --git a/security/tomoyo/realpath.h b/security/tomoyo/realpath.h
new file mode 100644
index 000000000000..7ec9fc9cbc07
--- /dev/null
+++ b/security/tomoyo/realpath.h
@@ -0,0 +1,66 @@
1/*
2 * security/tomoyo/realpath.h
3 *
4 * Get the canonicalized absolute pathnames. The basis for TOMOYO.
5 *
6 * Copyright (C) 2005-2009 NTT DATA CORPORATION
7 *
8 * Version: 2.2.0-pre 2009/02/01
9 *
10 */
11
12#ifndef _SECURITY_TOMOYO_REALPATH_H
13#define _SECURITY_TOMOYO_REALPATH_H
14
15struct path;
16struct tomoyo_path_info;
17struct tomoyo_io_buffer;
18
19/* Convert binary string to ascii string. */
20int tomoyo_encode(char *buffer, int buflen, const char *str);
21
22/* Returns realpath(3) of the given pathname but ignores chroot'ed root. */
23int tomoyo_realpath_from_path2(struct path *path, char *newname,
24 int newname_len);
25
26/*
27 * Returns realpath(3) of the given pathname but ignores chroot'ed root.
28 * These functions use tomoyo_alloc(), so the caller must call tomoyo_free()
29 * if these functions didn't return NULL.
30 */
31char *tomoyo_realpath(const char *pathname);
32/*
33 * Same with tomoyo_realpath() except that it doesn't follow the final symlink.
34 */
35char *tomoyo_realpath_nofollow(const char *pathname);
36/* Same with tomoyo_realpath() except that the pathname is already solved. */
37char *tomoyo_realpath_from_path(struct path *path);
38
39/*
40 * Allocate memory for ACL entry.
41 * The RAM is chunked, so NEVER try to kfree() the returned pointer.
42 */
43void *tomoyo_alloc_element(const unsigned int size);
44
45/*
46 * Keep the given name on the RAM.
47 * The RAM is shared, so NEVER try to modify or kfree() the returned name.
48 */
49const struct tomoyo_path_info *tomoyo_save_name(const char *name);
50
51/* Allocate memory for temporary use (e.g. permission checks). */
52void *tomoyo_alloc(const size_t size);
53
54/* Free memory allocated by tomoyo_alloc(). */
55void tomoyo_free(const void *p);
56
57/* Check for memory usage. */
58int tomoyo_read_memory_counter(struct tomoyo_io_buffer *head);
59
60/* Set memory quota. */
61int tomoyo_write_memory_quota(struct tomoyo_io_buffer *head);
62
63/* Initialize realpath related code. */
64void __init tomoyo_realpath_init(void);
65
66#endif /* !defined(_SECURITY_TOMOYO_REALPATH_H) */
diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c
new file mode 100644
index 000000000000..3eeeae12c4dc
--- /dev/null
+++ b/security/tomoyo/tomoyo.c
@@ -0,0 +1,294 @@
1/*
2 * security/tomoyo/tomoyo.c
3 *
4 * LSM hooks for TOMOYO Linux.
5 *
6 * Copyright (C) 2005-2009 NTT DATA CORPORATION
7 *
8 * Version: 2.2.0-pre 2009/02/01
9 *
10 */
11
12#include <linux/security.h>
13#include "common.h"
14#include "tomoyo.h"
15#include "realpath.h"
16
17static int tomoyo_cred_prepare(struct cred *new, const struct cred *old,
18 gfp_t gfp)
19{
20 /*
21 * Since "struct tomoyo_domain_info *" is a sharable pointer,
22 * we don't need to duplicate.
23 */
24 new->security = old->security;
25 return 0;
26}
27
28static int tomoyo_bprm_set_creds(struct linux_binprm *bprm)
29{
30 /*
31 * Do only if this function is called for the first time of an execve
32 * operation.
33 */
34 if (bprm->cred_prepared)
35 return 0;
36 /*
37 * Load policy if /sbin/tomoyo-init exists and /sbin/init is requested
38 * for the first time.
39 */
40 if (!tomoyo_policy_loaded)
41 tomoyo_load_policy(bprm->filename);
42 /*
43 * Tell tomoyo_bprm_check_security() is called for the first time of an
44 * execve operation.
45 */
46 bprm->cred->security = NULL;
47 return 0;
48}
49
50static int tomoyo_bprm_check_security(struct linux_binprm *bprm)
51{
52 struct tomoyo_domain_info *domain = bprm->cred->security;
53
54 /*
55 * Execute permission is checked against pathname passed to do_execve()
56 * using current domain.
57 */
58 if (!domain) {
59 struct tomoyo_domain_info *next_domain = NULL;
60 int retval = tomoyo_find_next_domain(bprm, &next_domain);
61
62 if (!retval)
63 bprm->cred->security = next_domain;
64 return retval;
65 }
66 /*
67 * Read permission is checked against interpreters using next domain.
68 * '1' is the result of open_to_namei_flags(O_RDONLY).
69 */
70 return tomoyo_check_open_permission(domain, &bprm->file->f_path, 1);
71}
72
73#ifdef CONFIG_SYSCTL
74
75static int tomoyo_prepend(char **buffer, int *buflen, const char *str)
76{
77 int namelen = strlen(str);
78
79 if (*buflen < namelen)
80 return -ENOMEM;
81 *buflen -= namelen;
82 *buffer -= namelen;
83 memcpy(*buffer, str, namelen);
84 return 0;
85}
86
87/**
88 * tomoyo_sysctl_path - return the realpath of a ctl_table.
89 * @table: pointer to "struct ctl_table".
90 *
91 * Returns realpath(3) of the @table on success.
92 * Returns NULL on failure.
93 *
94 * This function uses tomoyo_alloc(), so the caller must call tomoyo_free()
95 * if this function didn't return NULL.
96 */
97static char *tomoyo_sysctl_path(struct ctl_table *table)
98{
99 int buflen = TOMOYO_MAX_PATHNAME_LEN;
100 char *buf = tomoyo_alloc(buflen);
101 char *end = buf + buflen;
102 int error = -ENOMEM;
103
104 if (!buf)
105 return NULL;
106
107 *--end = '\0';
108 buflen--;
109 while (table) {
110 char num[32];
111 const char *sp = table->procname;
112
113 if (!sp) {
114 memset(num, 0, sizeof(num));
115 snprintf(num, sizeof(num) - 1, "=%d=", table->ctl_name);
116 sp = num;
117 }
118 if (tomoyo_prepend(&end, &buflen, sp) ||
119 tomoyo_prepend(&end, &buflen, "/"))
120 goto out;
121 table = table->parent;
122 }
123 if (tomoyo_prepend(&end, &buflen, "/proc/sys"))
124 goto out;
125 error = tomoyo_encode(buf, end - buf, end);
126 out:
127 if (!error)
128 return buf;
129 tomoyo_free(buf);
130 return NULL;
131}
132
133static int tomoyo_sysctl(struct ctl_table *table, int op)
134{
135 int error;
136 char *name;
137
138 op &= MAY_READ | MAY_WRITE;
139 if (!op)
140 return 0;
141 name = tomoyo_sysctl_path(table);
142 if (!name)
143 return -ENOMEM;
144 error = tomoyo_check_file_perm(tomoyo_domain(), name, op);
145 tomoyo_free(name);
146 return error;
147}
148#endif
149
150static int tomoyo_path_truncate(struct path *path, loff_t length,
151 unsigned int time_attrs)
152{
153 return tomoyo_check_1path_perm(tomoyo_domain(),
154 TOMOYO_TYPE_TRUNCATE_ACL,
155 path);
156}
157
158static int tomoyo_path_unlink(struct path *parent, struct dentry *dentry)
159{
160 struct path path = { parent->mnt, dentry };
161 return tomoyo_check_1path_perm(tomoyo_domain(),
162 TOMOYO_TYPE_UNLINK_ACL,
163 &path);
164}
165
166static int tomoyo_path_mkdir(struct path *parent, struct dentry *dentry,
167 int mode)
168{
169 struct path path = { parent->mnt, dentry };
170 return tomoyo_check_1path_perm(tomoyo_domain(),
171 TOMOYO_TYPE_MKDIR_ACL,
172 &path);
173}
174
175static int tomoyo_path_rmdir(struct path *parent, struct dentry *dentry)
176{
177 struct path path = { parent->mnt, dentry };
178 return tomoyo_check_1path_perm(tomoyo_domain(),
179 TOMOYO_TYPE_RMDIR_ACL,
180 &path);
181}
182
183static int tomoyo_path_symlink(struct path *parent, struct dentry *dentry,
184 const char *old_name)
185{
186 struct path path = { parent->mnt, dentry };
187 return tomoyo_check_1path_perm(tomoyo_domain(),
188 TOMOYO_TYPE_SYMLINK_ACL,
189 &path);
190}
191
192static int tomoyo_path_mknod(struct path *parent, struct dentry *dentry,
193 int mode, unsigned int dev)
194{
195 struct path path = { parent->mnt, dentry };
196 int type = TOMOYO_TYPE_CREATE_ACL;
197
198 switch (mode & S_IFMT) {
199 case S_IFCHR:
200 type = TOMOYO_TYPE_MKCHAR_ACL;
201 break;
202 case S_IFBLK:
203 type = TOMOYO_TYPE_MKBLOCK_ACL;
204 break;
205 case S_IFIFO:
206 type = TOMOYO_TYPE_MKFIFO_ACL;
207 break;
208 case S_IFSOCK:
209 type = TOMOYO_TYPE_MKSOCK_ACL;
210 break;
211 }
212 return tomoyo_check_1path_perm(tomoyo_domain(),
213 type, &path);
214}
215
216static int tomoyo_path_link(struct dentry *old_dentry, struct path *new_dir,
217 struct dentry *new_dentry)
218{
219 struct path path1 = { new_dir->mnt, old_dentry };
220 struct path path2 = { new_dir->mnt, new_dentry };
221 return tomoyo_check_2path_perm(tomoyo_domain(),
222 TOMOYO_TYPE_LINK_ACL,
223 &path1, &path2);
224}
225
226static int tomoyo_path_rename(struct path *old_parent,
227 struct dentry *old_dentry,
228 struct path *new_parent,
229 struct dentry *new_dentry)
230{
231 struct path path1 = { old_parent->mnt, old_dentry };
232 struct path path2 = { new_parent->mnt, new_dentry };
233 return tomoyo_check_2path_perm(tomoyo_domain(),
234 TOMOYO_TYPE_RENAME_ACL,
235 &path1, &path2);
236}
237
238static int tomoyo_file_fcntl(struct file *file, unsigned int cmd,
239 unsigned long arg)
240{
241 if (cmd == F_SETFL && ((arg ^ file->f_flags) & O_APPEND))
242 return tomoyo_check_rewrite_permission(tomoyo_domain(), file);
243 return 0;
244}
245
246static int tomoyo_dentry_open(struct file *f, const struct cred *cred)
247{
248 int flags = f->f_flags;
249
250 if ((flags + 1) & O_ACCMODE)
251 flags++;
252 flags |= f->f_flags & (O_APPEND | O_TRUNC);
253 /* Don't check read permission here if called from do_execve(). */
254 if (current->in_execve)
255 return 0;
256 return tomoyo_check_open_permission(tomoyo_domain(), &f->f_path, flags);
257}
258
259static struct security_operations tomoyo_security_ops = {
260 .name = "tomoyo",
261 .cred_prepare = tomoyo_cred_prepare,
262 .bprm_set_creds = tomoyo_bprm_set_creds,
263 .bprm_check_security = tomoyo_bprm_check_security,
264#ifdef CONFIG_SYSCTL
265 .sysctl = tomoyo_sysctl,
266#endif
267 .file_fcntl = tomoyo_file_fcntl,
268 .dentry_open = tomoyo_dentry_open,
269 .path_truncate = tomoyo_path_truncate,
270 .path_unlink = tomoyo_path_unlink,
271 .path_mkdir = tomoyo_path_mkdir,
272 .path_rmdir = tomoyo_path_rmdir,
273 .path_symlink = tomoyo_path_symlink,
274 .path_mknod = tomoyo_path_mknod,
275 .path_link = tomoyo_path_link,
276 .path_rename = tomoyo_path_rename,
277};
278
279static int __init tomoyo_init(void)
280{
281 struct cred *cred = (struct cred *) current_cred();
282
283 if (!security_module_enable(&tomoyo_security_ops))
284 return 0;
285 /* register ourselves with the security framework */
286 if (register_security(&tomoyo_security_ops))
287 panic("Failure registering TOMOYO Linux");
288 printk(KERN_INFO "TOMOYO Linux initialized\n");
289 cred->security = &tomoyo_kernel_domain;
290 tomoyo_realpath_init();
291 return 0;
292}
293
294security_initcall(tomoyo_init);
diff --git a/security/tomoyo/tomoyo.h b/security/tomoyo/tomoyo.h
new file mode 100644
index 000000000000..a0c8f6e0bea4
--- /dev/null
+++ b/security/tomoyo/tomoyo.h
@@ -0,0 +1,106 @@
1/*
2 * security/tomoyo/tomoyo.h
3 *
4 * Implementation of the Domain-Based Mandatory Access Control.
5 *
6 * Copyright (C) 2005-2009 NTT DATA CORPORATION
7 *
8 * Version: 2.2.0-pre 2009/02/01
9 *
10 */
11
12#ifndef _SECURITY_TOMOYO_TOMOYO_H
13#define _SECURITY_TOMOYO_TOMOYO_H
14
15struct tomoyo_path_info;
16struct path;
17struct inode;
18struct linux_binprm;
19struct pt_regs;
20struct tomoyo_page_buffer;
21
22int tomoyo_check_file_perm(struct tomoyo_domain_info *domain,
23 const char *filename, const u8 perm);
24int tomoyo_check_exec_perm(struct tomoyo_domain_info *domain,
25 const struct tomoyo_path_info *filename,
26 struct tomoyo_page_buffer *buf);
27int tomoyo_check_open_permission(struct tomoyo_domain_info *domain,
28 struct path *path, const int flag);
29int tomoyo_check_1path_perm(struct tomoyo_domain_info *domain,
30 const u8 operation, struct path *path);
31int tomoyo_check_2path_perm(struct tomoyo_domain_info *domain,
32 const u8 operation, struct path *path1,
33 struct path *path2);
34int tomoyo_check_rewrite_permission(struct tomoyo_domain_info *domain,
35 struct file *filp);
36int tomoyo_find_next_domain(struct linux_binprm *bprm,
37 struct tomoyo_domain_info **next_domain);
38
39/* Index numbers for Access Controls. */
40
41#define TOMOYO_TYPE_SINGLE_PATH_ACL 0
42#define TOMOYO_TYPE_DOUBLE_PATH_ACL 1
43
44/* Index numbers for File Controls. */
45
46/*
47 * TYPE_READ_WRITE_ACL is special. TYPE_READ_WRITE_ACL is automatically set
48 * if both TYPE_READ_ACL and TYPE_WRITE_ACL are set. Both TYPE_READ_ACL and
49 * TYPE_WRITE_ACL are automatically set if TYPE_READ_WRITE_ACL is set.
50 * TYPE_READ_WRITE_ACL is automatically cleared if either TYPE_READ_ACL or
51 * TYPE_WRITE_ACL is cleared. Both TYPE_READ_ACL and TYPE_WRITE_ACL are
52 * automatically cleared if TYPE_READ_WRITE_ACL is cleared.
53 */
54
55#define TOMOYO_TYPE_READ_WRITE_ACL 0
56#define TOMOYO_TYPE_EXECUTE_ACL 1
57#define TOMOYO_TYPE_READ_ACL 2
58#define TOMOYO_TYPE_WRITE_ACL 3
59#define TOMOYO_TYPE_CREATE_ACL 4
60#define TOMOYO_TYPE_UNLINK_ACL 5
61#define TOMOYO_TYPE_MKDIR_ACL 6
62#define TOMOYO_TYPE_RMDIR_ACL 7
63#define TOMOYO_TYPE_MKFIFO_ACL 8
64#define TOMOYO_TYPE_MKSOCK_ACL 9
65#define TOMOYO_TYPE_MKBLOCK_ACL 10
66#define TOMOYO_TYPE_MKCHAR_ACL 11
67#define TOMOYO_TYPE_TRUNCATE_ACL 12
68#define TOMOYO_TYPE_SYMLINK_ACL 13
69#define TOMOYO_TYPE_REWRITE_ACL 14
70#define TOMOYO_MAX_SINGLE_PATH_OPERATION 15
71
72#define TOMOYO_TYPE_LINK_ACL 0
73#define TOMOYO_TYPE_RENAME_ACL 1
74#define TOMOYO_MAX_DOUBLE_PATH_OPERATION 2
75
76#define TOMOYO_DOMAINPOLICY 0
77#define TOMOYO_EXCEPTIONPOLICY 1
78#define TOMOYO_DOMAIN_STATUS 2
79#define TOMOYO_PROCESS_STATUS 3
80#define TOMOYO_MEMINFO 4
81#define TOMOYO_SELFDOMAIN 5
82#define TOMOYO_VERSION 6
83#define TOMOYO_PROFILE 7
84#define TOMOYO_MANAGER 8
85
86extern struct tomoyo_domain_info tomoyo_kernel_domain;
87
88static inline struct tomoyo_domain_info *tomoyo_domain(void)
89{
90 return current_cred()->security;
91}
92
93/* Caller holds tasklist_lock spinlock. */
94static inline struct tomoyo_domain_info *tomoyo_real_domain(struct task_struct
95 *task)
96{
97 /***** CRITICAL SECTION START *****/
98 const struct cred *cred = get_task_cred(task);
99 struct tomoyo_domain_info *domain = cred->security;
100
101 put_cred(cred);
102 return domain;
103 /***** CRITICAL SECTION END *****/
104}
105
106#endif /* !defined(_SECURITY_TOMOYO_TOMOYO_H) */