aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
Diffstat (limited to 'security')
-rw-r--r--security/Kconfig5
-rw-r--r--security/Makefile4
-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.c78
-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.c202
-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.c413
-rw-r--r--security/integrity/ima/ima_queue.c140
-rw-r--r--security/selinux/hooks.c241
-rw-r--r--security/selinux/include/objsec.h2
-rw-r--r--security/selinux/include/security.h8
18 files changed, 2277 insertions, 182 deletions
diff --git a/security/Kconfig b/security/Kconfig
index 9438535d7fd0..bf129f87de7e 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
@@ -135,5 +136,7 @@ config SECURITY_DEFAULT_MMAP_MIN_ADDR
135source security/selinux/Kconfig 136source security/selinux/Kconfig
136source security/smack/Kconfig 137source security/smack/Kconfig
137 138
139source security/integrity/ima/Kconfig
140
138endmenu 141endmenu
139 142
diff --git a/security/Makefile b/security/Makefile
index c05c127fff9a..595536cbffb2 100644
--- a/security/Makefile
+++ b/security/Makefile
@@ -17,3 +17,7 @@ obj-$(CONFIG_SECURITY_SELINUX) += selinux/built-in.o
17obj-$(CONFIG_SECURITY_SMACK) += smack/built-in.o 17obj-$(CONFIG_SECURITY_SMACK) += smack/built-in.o
18obj-$(CONFIG_SECURITY_ROOTPLUG) += root_plug.o 18obj-$(CONFIG_SECURITY_ROOTPLUG) += root_plug.o
19obj-$(CONFIG_CGROUP_DEVICE) += device_cgroup.o 19obj-$(CONFIG_CGROUP_DEVICE) += device_cgroup.o
20
21# Object integrity file lists
22subdir-$(CONFIG_IMA) += integrity/ima
23obj-$(CONFIG_IMA) += integrity/ima/built-in.o
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..3d2b6ee778a0
--- /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 && (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..e3c16a21a38e
--- /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 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..a148a25804f6
--- /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 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..8a0f1e23ccf1
--- /dev/null
+++ b/security/integrity/ima/ima_audit.c
@@ -0,0 +1,78 @@
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;
26 char *op;
27
28 rc = strict_strtoul(str, 0, &audit);
29 if (rc || audit > 1)
30 printk(KERN_INFO "ima: invalid ima_audit value\n");
31 else
32 ima_audit = audit;
33 op = ima_audit ? "ima_audit_enabled" : "ima_audit_not_enabled";
34 integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, NULL, NULL, op, 0, 0);
35 return 1;
36}
37__setup("ima_audit=", ima_audit_setup);
38#endif
39
40void integrity_audit_msg(int audit_msgno, struct inode *inode,
41 const unsigned char *fname, const char *op,
42 const char *cause, int result, int audit_info)
43{
44 struct audit_buffer *ab;
45
46 if (!ima_audit && audit_info == 1) /* Skip informational messages */
47 return;
48
49 ab = audit_log_start(current->audit_context, GFP_KERNEL, audit_msgno);
50 audit_log_format(ab, "integrity: pid=%d uid=%u auid=%u",
51 current->pid, current->cred->uid,
52 audit_get_loginuid(current));
53 audit_log_task_context(ab);
54 switch (audit_msgno) {
55 case AUDIT_INTEGRITY_DATA:
56 case AUDIT_INTEGRITY_METADATA:
57 case AUDIT_INTEGRITY_PCR:
58 audit_log_format(ab, " op=%s cause=%s", op, cause);
59 break;
60 case AUDIT_INTEGRITY_HASH:
61 audit_log_format(ab, " op=%s hash=%s", op, cause);
62 break;
63 case AUDIT_INTEGRITY_STATUS:
64 default:
65 audit_log_format(ab, " op=%s", op);
66 }
67 audit_log_format(ab, " comm=");
68 audit_log_untrustedstring(ab, current->comm);
69 if (fname) {
70 audit_log_format(ab, " name=");
71 audit_log_untrustedstring(ab, fname);
72 }
73 if (inode)
74 audit_log_format(ab, " dev=%s ino=%lu",
75 inode->i_sb->s_id, inode->i_ino);
76 audit_log_format(ab, " res=%d", result);
77 audit_log_end(ab);
78}
diff --git a/security/integrity/ima/ima_crypto.c b/security/integrity/ima/ima_crypto.c
new file mode 100644
index 000000000000..c2a46e40999d
--- /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_set_buf(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_set_buf(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..573780c76f1f
--- /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, 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..1f035e8d29c7
--- /dev/null
+++ b/security/integrity/ima/ima_iint.c
@@ -0,0 +1,202 @@
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 iint = radix_tree_lookup(&ima_iint_store,
77 (unsigned long)inode);
78 } else
79 iint = NULL;
80 }
81 radix_tree_preload_end();
82 return iint;
83}
84
85/**
86 * ima_inode_alloc - allocate an iint associated with an inode
87 * @inode: pointer to the inode
88 *
89 * Return 0 on success, 1 on failure.
90 */
91int ima_inode_alloc(struct inode *inode)
92{
93 struct ima_iint_cache *iint;
94
95 if (!ima_initialized)
96 return 0;
97
98 iint = ima_iint_insert(inode);
99 if (!iint)
100 return 1;
101 return 0;
102}
103
104/* ima_iint_find_insert_get - get the iint associated with an inode
105 *
106 * Most insertions are done at inode_alloc, except those allocated
107 * before late_initcall. When the iint does not exist, allocate it,
108 * initialize and insert it, and increment the iint refcount.
109 *
110 * (Can't initialize at security_initcall before any inodes are
111 * allocated, got to wait at least until proc_init.)
112 *
113 * Return the iint.
114 */
115struct ima_iint_cache *ima_iint_find_insert_get(struct inode *inode)
116{
117 struct ima_iint_cache *iint = NULL;
118
119 iint = ima_iint_find_get(inode);
120 if (iint)
121 return iint;
122
123 iint = ima_iint_insert(inode);
124 if (iint)
125 kref_get(&iint->refcount);
126
127 return iint;
128}
129EXPORT_SYMBOL_GPL(ima_iint_find_insert_get);
130
131/* iint_free - called when the iint refcount goes to zero */
132void iint_free(struct kref *kref)
133{
134 struct ima_iint_cache *iint = container_of(kref, struct ima_iint_cache,
135 refcount);
136 iint->version = 0;
137 iint->flags = 0UL;
138 if (iint->readcount != 0) {
139 printk(KERN_INFO "%s: readcount: %ld\n", __FUNCTION__,
140 iint->readcount);
141 iint->readcount = 0;
142 }
143 if (iint->writecount != 0) {
144 printk(KERN_INFO "%s: writecount: %ld\n", __FUNCTION__,
145 iint->writecount);
146 iint->writecount = 0;
147 }
148 if (iint->opencount != 0) {
149 printk(KERN_INFO "%s: opencount: %ld\n", __FUNCTION__,
150 iint->opencount);
151 iint->opencount = 0;
152 }
153 kref_set(&iint->refcount, 1);
154 kmem_cache_free(iint_cache, iint);
155}
156
157void iint_rcu_free(struct rcu_head *rcu_head)
158{
159 struct ima_iint_cache *iint = container_of(rcu_head,
160 struct ima_iint_cache, rcu);
161 kref_put(&iint->refcount, iint_free);
162}
163
164/**
165 * ima_iint_delete - called on integrity_inode_free
166 * @inode: pointer to the inode
167 *
168 * Free the integrity information(iint) associated with an inode.
169 */
170void ima_iint_delete(struct inode *inode)
171{
172 struct ima_iint_cache *iint;
173
174 if (!ima_initialized)
175 return;
176 spin_lock(&ima_iint_lock);
177 iint = radix_tree_delete(&ima_iint_store, (unsigned long)inode);
178 spin_unlock(&ima_iint_lock);
179 if (iint)
180 call_rcu(&iint->rcu, iint_rcu_free);
181}
182
183static void init_once(void *foo)
184{
185 struct ima_iint_cache *iint = foo;
186
187 memset(iint, 0, sizeof *iint);
188 iint->version = 0;
189 iint->flags = 0UL;
190 mutex_init(&iint->mutex);
191 iint->readcount = 0;
192 iint->writecount = 0;
193 iint->opencount = 0;
194 kref_set(&iint->refcount, 1);
195}
196
197void ima_iintcache_init(void)
198{
199 iint_cache =
200 kmem_cache_create("iint_cache", sizeof(struct ima_iint_cache), 0,
201 SLAB_PANIC, init_once);
202}
diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c
new file mode 100644
index 000000000000..cf227dbfac2c
--- /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 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..23810e0bfc68
--- /dev/null
+++ b/security/integrity/ima/ima_policy.c
@@ -0,0 +1,413 @@
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/audit.h>
16#include <linux/security.h>
17#include <linux/magic.h>
18#include <linux/parser.h>
19
20#include "ima.h"
21
22/* flags definitions */
23#define IMA_FUNC 0x0001
24#define IMA_MASK 0x0002
25#define IMA_FSMAGIC 0x0004
26#define IMA_UID 0x0008
27
28enum ima_action { UNKNOWN = -1, DONT_MEASURE = 0, MEASURE };
29
30#define MAX_LSM_RULES 6
31enum lsm_rule_types { LSM_OBJ_USER, LSM_OBJ_ROLE, LSM_OBJ_TYPE,
32 LSM_SUBJ_USER, LSM_SUBJ_ROLE, LSM_SUBJ_TYPE
33};
34
35struct ima_measure_rule_entry {
36 struct list_head list;
37 enum ima_action action;
38 unsigned int flags;
39 enum ima_hooks func;
40 int mask;
41 unsigned long fsmagic;
42 uid_t uid;
43 struct {
44 void *rule; /* LSM file metadata specific */
45 int type; /* audit type */
46 } lsm[MAX_LSM_RULES];
47};
48
49/* Without LSM specific knowledge, the default policy can only be
50 * written in terms of .action, .func, .mask, .fsmagic, and .uid
51 */
52static struct ima_measure_rule_entry default_rules[] = {
53 {.action = DONT_MEASURE,.fsmagic = PROC_SUPER_MAGIC,
54 .flags = IMA_FSMAGIC},
55 {.action = DONT_MEASURE,.fsmagic = SYSFS_MAGIC,.flags = IMA_FSMAGIC},
56 {.action = DONT_MEASURE,.fsmagic = DEBUGFS_MAGIC,.flags = IMA_FSMAGIC},
57 {.action = DONT_MEASURE,.fsmagic = TMPFS_MAGIC,.flags = IMA_FSMAGIC},
58 {.action = DONT_MEASURE,.fsmagic = SECURITYFS_MAGIC,
59 .flags = IMA_FSMAGIC},
60 {.action = DONT_MEASURE,.fsmagic = 0xF97CFF8C,.flags = IMA_FSMAGIC},
61 {.action = MEASURE,.func = FILE_MMAP,.mask = MAY_EXEC,
62 .flags = IMA_FUNC | IMA_MASK},
63 {.action = MEASURE,.func = BPRM_CHECK,.mask = MAY_EXEC,
64 .flags = IMA_FUNC | IMA_MASK},
65 {.action = MEASURE,.func = PATH_CHECK,.mask = MAY_READ,.uid = 0,
66 .flags = IMA_FUNC | IMA_MASK | IMA_UID}
67};
68
69static LIST_HEAD(measure_default_rules);
70static LIST_HEAD(measure_policy_rules);
71static struct list_head *ima_measure;
72
73static DEFINE_MUTEX(ima_measure_mutex);
74
75/**
76 * ima_match_rules - determine whether an inode matches the measure rule.
77 * @rule: a pointer to a rule
78 * @inode: a pointer to an inode
79 * @func: LIM hook identifier
80 * @mask: requested action (MAY_READ | MAY_WRITE | MAY_APPEND | MAY_EXEC)
81 *
82 * Returns true on rule match, false on failure.
83 */
84static bool ima_match_rules(struct ima_measure_rule_entry *rule,
85 struct inode *inode, enum ima_hooks func, int mask)
86{
87 struct task_struct *tsk = current;
88 int i;
89
90 if ((rule->flags & IMA_FUNC) && rule->func != func)
91 return false;
92 if ((rule->flags & IMA_MASK) && rule->mask != mask)
93 return false;
94 if ((rule->flags & IMA_FSMAGIC)
95 && rule->fsmagic != inode->i_sb->s_magic)
96 return false;
97 if ((rule->flags & IMA_UID) && rule->uid != tsk->cred->uid)
98 return false;
99 for (i = 0; i < MAX_LSM_RULES; i++) {
100 int rc;
101 u32 osid, sid;
102
103 if (!rule->lsm[i].rule)
104 continue;
105
106 switch (i) {
107 case LSM_OBJ_USER:
108 case LSM_OBJ_ROLE:
109 case LSM_OBJ_TYPE:
110 security_inode_getsecid(inode, &osid);
111 rc = security_filter_rule_match(osid,
112 rule->lsm[i].type,
113 AUDIT_EQUAL,
114 rule->lsm[i].rule,
115 NULL);
116 break;
117 case LSM_SUBJ_USER:
118 case LSM_SUBJ_ROLE:
119 case LSM_SUBJ_TYPE:
120 security_task_getsecid(tsk, &sid);
121 rc = security_filter_rule_match(sid,
122 rule->lsm[i].type,
123 AUDIT_EQUAL,
124 rule->lsm[i].rule,
125 NULL);
126 default:
127 break;
128 }
129 if (!rc)
130 return false;
131 }
132 return true;
133}
134
135/**
136 * ima_match_policy - decision based on LSM and other conditions
137 * @inode: pointer to an inode for which the policy decision is being made
138 * @func: IMA hook identifier
139 * @mask: requested action (MAY_READ | MAY_WRITE | MAY_APPEND | MAY_EXEC)
140 *
141 * Measure decision based on func/mask/fsmagic and LSM(subj/obj/type)
142 * conditions.
143 *
144 * (There is no need for locking when walking the policy list,
145 * as elements in the list are never deleted, nor does the list
146 * change.)
147 */
148int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask)
149{
150 struct ima_measure_rule_entry *entry;
151
152 list_for_each_entry(entry, ima_measure, list) {
153 bool rc;
154
155 rc = ima_match_rules(entry, inode, func, mask);
156 if (rc)
157 return entry->action;
158 }
159 return 0;
160}
161
162/**
163 * ima_init_policy - initialize the default measure rules.
164 *
165 * ima_measure points to either the measure_default_rules or the
166 * the new measure_policy_rules.
167 */
168void ima_init_policy(void)
169{
170 int i;
171
172 for (i = 0; i < ARRAY_SIZE(default_rules); i++)
173 list_add_tail(&default_rules[i].list, &measure_default_rules);
174 ima_measure = &measure_default_rules;
175}
176
177/**
178 * ima_update_policy - update default_rules with new measure rules
179 *
180 * Called on file .release to update the default rules with a complete new
181 * policy. Once updated, the policy is locked, no additional rules can be
182 * added to the policy.
183 */
184void ima_update_policy(void)
185{
186 const char *op = "policy_update";
187 const char *cause = "already exists";
188 int result = 1;
189 int audit_info = 0;
190
191 if (ima_measure == &measure_default_rules) {
192 ima_measure = &measure_policy_rules;
193 cause = "complete";
194 result = 0;
195 }
196 integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL,
197 NULL, op, cause, result, audit_info);
198}
199
200enum {
201 Opt_err = -1,
202 Opt_measure = 1, Opt_dont_measure,
203 Opt_obj_user, Opt_obj_role, Opt_obj_type,
204 Opt_subj_user, Opt_subj_role, Opt_subj_type,
205 Opt_func, Opt_mask, Opt_fsmagic, Opt_uid
206};
207
208static match_table_t policy_tokens = {
209 {Opt_measure, "measure"},
210 {Opt_dont_measure, "dont_measure"},
211 {Opt_obj_user, "obj_user=%s"},
212 {Opt_obj_role, "obj_role=%s"},
213 {Opt_obj_type, "obj_type=%s"},
214 {Opt_subj_user, "subj_user=%s"},
215 {Opt_subj_role, "subj_role=%s"},
216 {Opt_subj_type, "subj_type=%s"},
217 {Opt_func, "func=%s"},
218 {Opt_mask, "mask=%s"},
219 {Opt_fsmagic, "fsmagic=%s"},
220 {Opt_uid, "uid=%s"},
221 {Opt_err, NULL}
222};
223
224static int ima_lsm_rule_init(struct ima_measure_rule_entry *entry,
225 char *args, int lsm_rule, int audit_type)
226{
227 int result;
228
229 entry->lsm[lsm_rule].type = audit_type;
230 result = security_filter_rule_init(entry->lsm[lsm_rule].type,
231 AUDIT_EQUAL, args,
232 &entry->lsm[lsm_rule].rule);
233 return result;
234}
235
236static int ima_parse_rule(char *rule, struct ima_measure_rule_entry *entry)
237{
238 struct audit_buffer *ab;
239 char *p;
240 int result = 0;
241
242 ab = audit_log_start(current->audit_context, GFP_KERNEL,
243 AUDIT_INTEGRITY_STATUS);
244
245 entry->action = -1;
246 while ((p = strsep(&rule, " \n")) != NULL) {
247 substring_t args[MAX_OPT_ARGS];
248 int token;
249 unsigned long lnum;
250
251 if (result < 0)
252 break;
253 if (!*p)
254 continue;
255 token = match_token(p, policy_tokens, args);
256 switch (token) {
257 case Opt_measure:
258 audit_log_format(ab, "%s ", "measure");
259 entry->action = MEASURE;
260 break;
261 case Opt_dont_measure:
262 audit_log_format(ab, "%s ", "dont_measure");
263 entry->action = DONT_MEASURE;
264 break;
265 case Opt_func:
266 audit_log_format(ab, "func=%s ", args[0].from);
267 if (strcmp(args[0].from, "PATH_CHECK") == 0)
268 entry->func = PATH_CHECK;
269 else if (strcmp(args[0].from, "FILE_MMAP") == 0)
270 entry->func = FILE_MMAP;
271 else if (strcmp(args[0].from, "BPRM_CHECK") == 0)
272 entry->func = BPRM_CHECK;
273 else
274 result = -EINVAL;
275 if (!result)
276 entry->flags |= IMA_FUNC;
277 break;
278 case Opt_mask:
279 audit_log_format(ab, "mask=%s ", args[0].from);
280 if ((strcmp(args[0].from, "MAY_EXEC")) == 0)
281 entry->mask = MAY_EXEC;
282 else if (strcmp(args[0].from, "MAY_WRITE") == 0)
283 entry->mask = MAY_WRITE;
284 else if (strcmp(args[0].from, "MAY_READ") == 0)
285 entry->mask = MAY_READ;
286 else if (strcmp(args[0].from, "MAY_APPEND") == 0)
287 entry->mask = MAY_APPEND;
288 else
289 result = -EINVAL;
290 if (!result)
291 entry->flags |= IMA_MASK;
292 break;
293 case Opt_fsmagic:
294 audit_log_format(ab, "fsmagic=%s ", args[0].from);
295 result = strict_strtoul(args[0].from, 16,
296 &entry->fsmagic);
297 if (!result)
298 entry->flags |= IMA_FSMAGIC;
299 break;
300 case Opt_uid:
301 audit_log_format(ab, "uid=%s ", args[0].from);
302 result = strict_strtoul(args[0].from, 10, &lnum);
303 if (!result) {
304 entry->uid = (uid_t) lnum;
305 if (entry->uid != lnum)
306 result = -EINVAL;
307 else
308 entry->flags |= IMA_UID;
309 }
310 break;
311 case Opt_obj_user:
312 audit_log_format(ab, "obj_user=%s ", args[0].from);
313 result = ima_lsm_rule_init(entry, args[0].from,
314 LSM_OBJ_USER,
315 AUDIT_OBJ_USER);
316 break;
317 case Opt_obj_role:
318 audit_log_format(ab, "obj_role=%s ", args[0].from);
319 result = ima_lsm_rule_init(entry, args[0].from,
320 LSM_OBJ_ROLE,
321 AUDIT_OBJ_ROLE);
322 break;
323 case Opt_obj_type:
324 audit_log_format(ab, "obj_type=%s ", args[0].from);
325 result = ima_lsm_rule_init(entry, args[0].from,
326 LSM_OBJ_TYPE,
327 AUDIT_OBJ_TYPE);
328 break;
329 case Opt_subj_user:
330 audit_log_format(ab, "subj_user=%s ", args[0].from);
331 result = ima_lsm_rule_init(entry, args[0].from,
332 LSM_SUBJ_USER,
333 AUDIT_SUBJ_USER);
334 break;
335 case Opt_subj_role:
336 audit_log_format(ab, "subj_role=%s ", args[0].from);
337 result = ima_lsm_rule_init(entry, args[0].from,
338 LSM_SUBJ_ROLE,
339 AUDIT_SUBJ_ROLE);
340 break;
341 case Opt_subj_type:
342 audit_log_format(ab, "subj_type=%s ", args[0].from);
343 result = ima_lsm_rule_init(entry, args[0].from,
344 LSM_SUBJ_TYPE,
345 AUDIT_SUBJ_TYPE);
346 break;
347 case Opt_err:
348 printk(KERN_INFO "%s: unknown token: %s\n",
349 __FUNCTION__, p);
350 break;
351 }
352 }
353 if (entry->action == UNKNOWN)
354 result = -EINVAL;
355
356 audit_log_format(ab, "res=%d", result);
357 audit_log_end(ab);
358 return result;
359}
360
361/**
362 * ima_parse_add_rule - add a rule to measure_policy_rules
363 * @rule - ima measurement policy rule
364 *
365 * Uses a mutex to protect the policy list from multiple concurrent writers.
366 * Returns 0 on success, an error code on failure.
367 */
368int ima_parse_add_rule(char *rule)
369{
370 const char *op = "add_rule";
371 struct ima_measure_rule_entry *entry;
372 int result = 0;
373 int audit_info = 0;
374
375 /* Prevent installed policy from changing */
376 if (ima_measure != &measure_default_rules) {
377 integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL,
378 NULL, op, "already exists",
379 -EACCES, audit_info);
380 return -EACCES;
381 }
382
383 entry = kzalloc(sizeof(*entry), GFP_KERNEL);
384 if (!entry) {
385 integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL,
386 NULL, op, "-ENOMEM", -ENOMEM, audit_info);
387 return -ENOMEM;
388 }
389
390 INIT_LIST_HEAD(&entry->list);
391
392 result = ima_parse_rule(rule, entry);
393 if (!result) {
394 mutex_lock(&ima_measure_mutex);
395 list_add_tail(&entry->list, &measure_policy_rules);
396 mutex_unlock(&ima_measure_mutex);
397 } else
398 kfree(entry);
399 return result;
400}
401
402/* ima_delete_rules called to cleanup invalid policy */
403void ima_delete_rules(void)
404{
405 struct ima_measure_rule_entry *entry, *tmp;
406
407 mutex_lock(&ima_measure_mutex);
408 list_for_each_entry_safe(entry, tmp, &measure_policy_rules, list) {
409 list_del(&entry->list);
410 kfree(entry);
411 }
412 mutex_unlock(&ima_measure_mutex);
413}
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/selinux/hooks.c b/security/selinux/hooks.c
index 00815973d412..a69d6f8970ca 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -89,7 +89,7 @@
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);
@@ -353,6 +353,7 @@ enum {
353 Opt_fscontext = 2, 353 Opt_fscontext = 2,
354 Opt_defcontext = 3, 354 Opt_defcontext = 3,
355 Opt_rootcontext = 4, 355 Opt_rootcontext = 4,
356 Opt_labelsupport = 5,
356}; 357};
357 358
358static const match_table_t tokens = { 359static const match_table_t tokens = {
@@ -360,6 +361,7 @@ static const match_table_t tokens = {
360 {Opt_fscontext, FSCONTEXT_STR "%s"}, 361 {Opt_fscontext, FSCONTEXT_STR "%s"},
361 {Opt_defcontext, DEFCONTEXT_STR "%s"}, 362 {Opt_defcontext, DEFCONTEXT_STR "%s"},
362 {Opt_rootcontext, ROOTCONTEXT_STR "%s"}, 363 {Opt_rootcontext, ROOTCONTEXT_STR "%s"},
364 {Opt_labelsupport, LABELSUPP_STR},
363 {Opt_error, NULL}, 365 {Opt_error, NULL},
364}; 366};
365 367
@@ -431,7 +433,7 @@ static int sb_finish_set_opts(struct super_block *sb)
431 } 433 }
432 } 434 }
433 435
434 sbsec->initialized = 1; 436 sbsec->flags |= (SE_SBINITIALIZED | SE_SBLABELSUPP);
435 437
436 if (sbsec->behavior > ARRAY_SIZE(labeling_behaviors)) 438 if (sbsec->behavior > ARRAY_SIZE(labeling_behaviors))
437 printk(KERN_ERR "SELinux: initialized (dev %s, type %s), unknown behavior\n", 439 printk(KERN_ERR "SELinux: initialized (dev %s, type %s), unknown behavior\n",
@@ -441,6 +443,12 @@ static int sb_finish_set_opts(struct super_block *sb)
441 sb->s_id, sb->s_type->name, 443 sb->s_id, sb->s_type->name,
442 labeling_behaviors[sbsec->behavior-1]); 444 labeling_behaviors[sbsec->behavior-1]);
443 445
446 if (sbsec->behavior == SECURITY_FS_USE_GENFS ||
447 sbsec->behavior == SECURITY_FS_USE_MNTPOINT ||
448 sbsec->behavior == SECURITY_FS_USE_NONE ||
449 sbsec->behavior > ARRAY_SIZE(labeling_behaviors))
450 sbsec->flags &= ~SE_SBLABELSUPP;
451
444 /* Initialize the root inode. */ 452 /* Initialize the root inode. */
445 rc = inode_doinit_with_dentry(root_inode, root); 453 rc = inode_doinit_with_dentry(root_inode, root);
446 454
@@ -487,23 +495,22 @@ static int selinux_get_mnt_opts(const struct super_block *sb,
487 495
488 security_init_mnt_opts(opts); 496 security_init_mnt_opts(opts);
489 497
490 if (!sbsec->initialized) 498 if (!(sbsec->flags & SE_SBINITIALIZED))
491 return -EINVAL; 499 return -EINVAL;
492 500
493 if (!ss_initialized) 501 if (!ss_initialized)
494 return -EINVAL; 502 return -EINVAL;
495 503
496 /* 504 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 */ 505 /* count the number of mount options for this sb */
502 for (i = 0; i < 8; i++) { 506 for (i = 0; i < 8; i++) {
503 if (tmp & 0x01) 507 if (tmp & 0x01)
504 opts->num_mnt_opts++; 508 opts->num_mnt_opts++;
505 tmp >>= 1; 509 tmp >>= 1;
506 } 510 }
511 /* Check if the Label support flag is set */
512 if (sbsec->flags & SE_SBLABELSUPP)
513 opts->num_mnt_opts++;
507 514
508 opts->mnt_opts = kcalloc(opts->num_mnt_opts, sizeof(char *), GFP_ATOMIC); 515 opts->mnt_opts = kcalloc(opts->num_mnt_opts, sizeof(char *), GFP_ATOMIC);
509 if (!opts->mnt_opts) { 516 if (!opts->mnt_opts) {
@@ -549,6 +556,10 @@ static int selinux_get_mnt_opts(const struct super_block *sb,
549 opts->mnt_opts[i] = context; 556 opts->mnt_opts[i] = context;
550 opts->mnt_opts_flags[i++] = ROOTCONTEXT_MNT; 557 opts->mnt_opts_flags[i++] = ROOTCONTEXT_MNT;
551 } 558 }
559 if (sbsec->flags & SE_SBLABELSUPP) {
560 opts->mnt_opts[i] = NULL;
561 opts->mnt_opts_flags[i++] = SE_SBLABELSUPP;
562 }
552 563
553 BUG_ON(i != opts->num_mnt_opts); 564 BUG_ON(i != opts->num_mnt_opts);
554 565
@@ -562,8 +573,10 @@ out_free:
562static int bad_option(struct superblock_security_struct *sbsec, char flag, 573static int bad_option(struct superblock_security_struct *sbsec, char flag,
563 u32 old_sid, u32 new_sid) 574 u32 old_sid, u32 new_sid)
564{ 575{
576 char mnt_flags = sbsec->flags & SE_MNTMASK;
577
565 /* check if the old mount command had the same options */ 578 /* check if the old mount command had the same options */
566 if (sbsec->initialized) 579 if (sbsec->flags & SE_SBINITIALIZED)
567 if (!(sbsec->flags & flag) || 580 if (!(sbsec->flags & flag) ||
568 (old_sid != new_sid)) 581 (old_sid != new_sid))
569 return 1; 582 return 1;
@@ -571,8 +584,8 @@ static int bad_option(struct superblock_security_struct *sbsec, char flag,
571 /* check if we were passed the same options twice, 584 /* check if we were passed the same options twice,
572 * aka someone passed context=a,context=b 585 * aka someone passed context=a,context=b
573 */ 586 */
574 if (!sbsec->initialized) 587 if (!(sbsec->flags & SE_SBINITIALIZED))
575 if (sbsec->flags & flag) 588 if (mnt_flags & flag)
576 return 1; 589 return 1;
577 return 0; 590 return 0;
578} 591}
@@ -626,7 +639,7 @@ static int selinux_set_mnt_opts(struct super_block *sb,
626 * this sb does not set any security options. (The first options 639 * this sb does not set any security options. (The first options
627 * will be used for both mounts) 640 * will be used for both mounts)
628 */ 641 */
629 if (sbsec->initialized && (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA) 642 if ((sbsec->flags & SE_SBINITIALIZED) && (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)
630 && (num_opts == 0)) 643 && (num_opts == 0))
631 goto out; 644 goto out;
632 645
@@ -637,6 +650,9 @@ static int selinux_set_mnt_opts(struct super_block *sb,
637 */ 650 */
638 for (i = 0; i < num_opts; i++) { 651 for (i = 0; i < num_opts; i++) {
639 u32 sid; 652 u32 sid;
653
654 if (flags[i] == SE_SBLABELSUPP)
655 continue;
640 rc = security_context_to_sid(mount_options[i], 656 rc = security_context_to_sid(mount_options[i],
641 strlen(mount_options[i]), &sid); 657 strlen(mount_options[i]), &sid);
642 if (rc) { 658 if (rc) {
@@ -690,19 +706,19 @@ static int selinux_set_mnt_opts(struct super_block *sb,
690 } 706 }
691 } 707 }
692 708
693 if (sbsec->initialized) { 709 if (sbsec->flags & SE_SBINITIALIZED) {
694 /* previously mounted with options, but not on this attempt? */ 710 /* previously mounted with options, but not on this attempt? */
695 if (sbsec->flags && !num_opts) 711 if ((sbsec->flags & SE_MNTMASK) && !num_opts)
696 goto out_double_mount; 712 goto out_double_mount;
697 rc = 0; 713 rc = 0;
698 goto out; 714 goto out;
699 } 715 }
700 716
701 if (strcmp(sb->s_type->name, "proc") == 0) 717 if (strcmp(sb->s_type->name, "proc") == 0)
702 sbsec->proc = 1; 718 sbsec->flags |= SE_SBPROC;
703 719
704 /* Determine the labeling behavior to use for this filesystem type. */ 720 /* 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); 721 rc = security_fs_use((sbsec->flags & SE_SBPROC) ? "proc" : sb->s_type->name, &sbsec->behavior, &sbsec->sid);
706 if (rc) { 722 if (rc) {
707 printk(KERN_WARNING "%s: security_fs_use(%s) returned %d\n", 723 printk(KERN_WARNING "%s: security_fs_use(%s) returned %d\n",
708 __func__, sb->s_type->name, rc); 724 __func__, sb->s_type->name, rc);
@@ -806,10 +822,10 @@ static void selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
806 } 822 }
807 823
808 /* how can we clone if the old one wasn't set up?? */ 824 /* how can we clone if the old one wasn't set up?? */
809 BUG_ON(!oldsbsec->initialized); 825 BUG_ON(!(oldsbsec->flags & SE_SBINITIALIZED));
810 826
811 /* if fs is reusing a sb, just let its options stand... */ 827 /* if fs is reusing a sb, just let its options stand... */
812 if (newsbsec->initialized) 828 if (newsbsec->flags & SE_SBINITIALIZED)
813 return; 829 return;
814 830
815 mutex_lock(&newsbsec->lock); 831 mutex_lock(&newsbsec->lock);
@@ -917,7 +933,8 @@ static int selinux_parse_opts_str(char *options,
917 goto out_err; 933 goto out_err;
918 } 934 }
919 break; 935 break;
920 936 case Opt_labelsupport:
937 break;
921 default: 938 default:
922 rc = -EINVAL; 939 rc = -EINVAL;
923 printk(KERN_WARNING "SELinux: unknown mount option\n"); 940 printk(KERN_WARNING "SELinux: unknown mount option\n");
@@ -999,7 +1016,12 @@ static void selinux_write_opts(struct seq_file *m,
999 char *prefix; 1016 char *prefix;
1000 1017
1001 for (i = 0; i < opts->num_mnt_opts; i++) { 1018 for (i = 0; i < opts->num_mnt_opts; i++) {
1002 char *has_comma = strchr(opts->mnt_opts[i], ','); 1019 char *has_comma;
1020
1021 if (opts->mnt_opts[i])
1022 has_comma = strchr(opts->mnt_opts[i], ',');
1023 else
1024 has_comma = NULL;
1003 1025
1004 switch (opts->mnt_opts_flags[i]) { 1026 switch (opts->mnt_opts_flags[i]) {
1005 case CONTEXT_MNT: 1027 case CONTEXT_MNT:
@@ -1014,6 +1036,10 @@ static void selinux_write_opts(struct seq_file *m,
1014 case DEFCONTEXT_MNT: 1036 case DEFCONTEXT_MNT:
1015 prefix = DEFCONTEXT_STR; 1037 prefix = DEFCONTEXT_STR;
1016 break; 1038 break;
1039 case SE_SBLABELSUPP:
1040 seq_putc(m, ',');
1041 seq_puts(m, LABELSUPP_STR);
1042 continue;
1017 default: 1043 default:
1018 BUG(); 1044 BUG();
1019 }; 1045 };
@@ -1209,7 +1235,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
1209 goto out_unlock; 1235 goto out_unlock;
1210 1236
1211 sbsec = inode->i_sb->s_security; 1237 sbsec = inode->i_sb->s_security;
1212 if (!sbsec->initialized) { 1238 if (!(sbsec->flags & SE_SBINITIALIZED)) {
1213 /* Defer initialization until selinux_complete_init, 1239 /* Defer initialization until selinux_complete_init,
1214 after the initial policy is loaded and the security 1240 after the initial policy is loaded and the security
1215 server is ready to handle calls. */ 1241 server is ready to handle calls. */
@@ -1326,7 +1352,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
1326 /* Default to the fs superblock SID. */ 1352 /* Default to the fs superblock SID. */
1327 isec->sid = sbsec->sid; 1353 isec->sid = sbsec->sid;
1328 1354
1329 if (sbsec->proc && !S_ISLNK(inode->i_mode)) { 1355 if ((sbsec->flags & SE_SBPROC) && !S_ISLNK(inode->i_mode)) {
1330 struct proc_inode *proci = PROC_I(inode); 1356 struct proc_inode *proci = PROC_I(inode);
1331 if (proci->pde) { 1357 if (proci->pde) {
1332 isec->sclass = inode_mode_to_security_class(inode->i_mode); 1358 isec->sclass = inode_mode_to_security_class(inode->i_mode);
@@ -1587,7 +1613,7 @@ static int may_create(struct inode *dir,
1587 if (rc) 1613 if (rc)
1588 return rc; 1614 return rc;
1589 1615
1590 if (!newsid || sbsec->behavior == SECURITY_FS_USE_MNTPOINT) { 1616 if (!newsid || !(sbsec->flags & SE_SBLABELSUPP)) {
1591 rc = security_transition_sid(sid, dsec->sid, tclass, &newsid); 1617 rc = security_transition_sid(sid, dsec->sid, tclass, &newsid);
1592 if (rc) 1618 if (rc)
1593 return rc; 1619 return rc;
@@ -1866,6 +1892,16 @@ static int selinux_capset(struct cred *new, const struct cred *old,
1866 return cred_has_perm(old, new, PROCESS__SETCAP); 1892 return cred_has_perm(old, new, PROCESS__SETCAP);
1867} 1893}
1868 1894
1895/*
1896 * (This comment used to live with the selinux_task_setuid hook,
1897 * which was removed).
1898 *
1899 * Since setuid only affects the current process, and since the SELinux
1900 * controls are not based on the Linux identity attributes, SELinux does not
1901 * need to control this operation. However, SELinux does control the use of
1902 * the CAP_SETUID and CAP_SETGID capabilities using the capable hook.
1903 */
1904
1869static int selinux_capable(struct task_struct *tsk, const struct cred *cred, 1905static int selinux_capable(struct task_struct *tsk, const struct cred *cred,
1870 int cap, int audit) 1906 int cap, int audit)
1871{ 1907{
@@ -2156,11 +2192,6 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm)
2156 return 0; 2192 return 0;
2157} 2193}
2158 2194
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) 2195static int selinux_bprm_secureexec(struct linux_binprm *bprm)
2165{ 2196{
2166 const struct cred *cred = current_cred(); 2197 const struct cred *cred = current_cred();
@@ -2290,8 +2321,6 @@ static void selinux_bprm_committing_creds(struct linux_binprm *bprm)
2290 struct rlimit *rlim, *initrlim; 2321 struct rlimit *rlim, *initrlim;
2291 int rc, i; 2322 int rc, i;
2292 2323
2293 secondary_ops->bprm_committing_creds(bprm);
2294
2295 new_tsec = bprm->cred->security; 2324 new_tsec = bprm->cred->security;
2296 if (new_tsec->sid == new_tsec->osid) 2325 if (new_tsec->sid == new_tsec->osid)
2297 return; 2326 return;
@@ -2337,8 +2366,6 @@ static void selinux_bprm_committed_creds(struct linux_binprm *bprm)
2337 int rc, i; 2366 int rc, i;
2338 unsigned long flags; 2367 unsigned long flags;
2339 2368
2340 secondary_ops->bprm_committed_creds(bprm);
2341
2342 osid = tsec->osid; 2369 osid = tsec->osid;
2343 sid = tsec->sid; 2370 sid = tsec->sid;
2344 2371
@@ -2400,7 +2427,8 @@ static inline int selinux_option(char *option, int len)
2400 return (match_prefix(CONTEXT_STR, sizeof(CONTEXT_STR)-1, option, len) || 2427 return (match_prefix(CONTEXT_STR, sizeof(CONTEXT_STR)-1, option, len) ||
2401 match_prefix(FSCONTEXT_STR, sizeof(FSCONTEXT_STR)-1, option, len) || 2428 match_prefix(FSCONTEXT_STR, sizeof(FSCONTEXT_STR)-1, option, len) ||
2402 match_prefix(DEFCONTEXT_STR, sizeof(DEFCONTEXT_STR)-1, option, len) || 2429 match_prefix(DEFCONTEXT_STR, sizeof(DEFCONTEXT_STR)-1, option, len) ||
2403 match_prefix(ROOTCONTEXT_STR, sizeof(ROOTCONTEXT_STR)-1, option, len)); 2430 match_prefix(ROOTCONTEXT_STR, sizeof(ROOTCONTEXT_STR)-1, option, len) ||
2431 match_prefix(LABELSUPP_STR, sizeof(LABELSUPP_STR)-1, option, len));
2404} 2432}
2405 2433
2406static inline void take_option(char **to, char *from, int *first, int len) 2434static inline void take_option(char **to, char *from, int *first, int len)
@@ -2513,11 +2541,6 @@ static int selinux_mount(char *dev_name,
2513 void *data) 2541 void *data)
2514{ 2542{
2515 const struct cred *cred = current_cred(); 2543 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 2544
2522 if (flags & MS_REMOUNT) 2545 if (flags & MS_REMOUNT)
2523 return superblock_has_perm(cred, path->mnt->mnt_sb, 2546 return superblock_has_perm(cred, path->mnt->mnt_sb,
@@ -2530,11 +2553,6 @@ static int selinux_mount(char *dev_name,
2530static int selinux_umount(struct vfsmount *mnt, int flags) 2553static int selinux_umount(struct vfsmount *mnt, int flags)
2531{ 2554{
2532 const struct cred *cred = current_cred(); 2555 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 2556
2539 return superblock_has_perm(cred, mnt->mnt_sb, 2557 return superblock_has_perm(cred, mnt->mnt_sb,
2540 FILESYSTEM__UNMOUNT, NULL); 2558 FILESYSTEM__UNMOUNT, NULL);
@@ -2570,7 +2588,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
2570 sid = tsec->sid; 2588 sid = tsec->sid;
2571 newsid = tsec->create_sid; 2589 newsid = tsec->create_sid;
2572 2590
2573 if (!newsid || sbsec->behavior == SECURITY_FS_USE_MNTPOINT) { 2591 if (!newsid || !(sbsec->flags & SE_SBLABELSUPP)) {
2574 rc = security_transition_sid(sid, dsec->sid, 2592 rc = security_transition_sid(sid, dsec->sid,
2575 inode_mode_to_security_class(inode->i_mode), 2593 inode_mode_to_security_class(inode->i_mode),
2576 &newsid); 2594 &newsid);
@@ -2585,14 +2603,14 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
2585 } 2603 }
2586 2604
2587 /* Possibly defer initialization to selinux_complete_init. */ 2605 /* Possibly defer initialization to selinux_complete_init. */
2588 if (sbsec->initialized) { 2606 if (sbsec->flags & SE_SBINITIALIZED) {
2589 struct inode_security_struct *isec = inode->i_security; 2607 struct inode_security_struct *isec = inode->i_security;
2590 isec->sclass = inode_mode_to_security_class(inode->i_mode); 2608 isec->sclass = inode_mode_to_security_class(inode->i_mode);
2591 isec->sid = newsid; 2609 isec->sid = newsid;
2592 isec->initialized = 1; 2610 isec->initialized = 1;
2593 } 2611 }
2594 2612
2595 if (!ss_initialized || sbsec->behavior == SECURITY_FS_USE_MNTPOINT) 2613 if (!ss_initialized || !(sbsec->flags & SE_SBLABELSUPP))
2596 return -EOPNOTSUPP; 2614 return -EOPNOTSUPP;
2597 2615
2598 if (name) { 2616 if (name) {
@@ -2622,21 +2640,11 @@ static int selinux_inode_create(struct inode *dir, struct dentry *dentry, int ma
2622 2640
2623static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry) 2641static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
2624{ 2642{
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); 2643 return may_link(dir, old_dentry, MAY_LINK);
2631} 2644}
2632 2645
2633static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry) 2646static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry)
2634{ 2647{
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); 2648 return may_link(dir, dentry, MAY_UNLINK);
2641} 2649}
2642 2650
@@ -2657,12 +2665,6 @@ static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry)
2657 2665
2658static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) 2666static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
2659{ 2667{
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)); 2668 return may_create(dir, dentry, inode_mode_to_security_class(mode));
2667} 2669}
2668 2670
@@ -2682,22 +2684,13 @@ static int selinux_inode_readlink(struct dentry *dentry)
2682static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *nameidata) 2684static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *nameidata)
2683{ 2685{
2684 const struct cred *cred = current_cred(); 2686 const struct cred *cred = current_cred();
2685 int rc;
2686 2687
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); 2688 return dentry_has_perm(cred, NULL, dentry, FILE__READ);
2691} 2689}
2692 2690
2693static int selinux_inode_permission(struct inode *inode, int mask) 2691static int selinux_inode_permission(struct inode *inode, int mask)
2694{ 2692{
2695 const struct cred *cred = current_cred(); 2693 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 2694
2702 if (!mask) { 2695 if (!mask) {
2703 /* No permission to check. Existence test. */ 2696 /* No permission to check. Existence test. */
@@ -2711,11 +2704,6 @@ static int selinux_inode_permission(struct inode *inode, int mask)
2711static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr) 2704static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
2712{ 2705{
2713 const struct cred *cred = current_cred(); 2706 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 2707
2720 if (iattr->ia_valid & ATTR_FORCE) 2708 if (iattr->ia_valid & ATTR_FORCE)
2721 return 0; 2709 return 0;
@@ -2769,7 +2757,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
2769 return selinux_inode_setotherxattr(dentry, name); 2757 return selinux_inode_setotherxattr(dentry, name);
2770 2758
2771 sbsec = inode->i_sb->s_security; 2759 sbsec = inode->i_sb->s_security;
2772 if (sbsec->behavior == SECURITY_FS_USE_MNTPOINT) 2760 if (!(sbsec->flags & SE_SBLABELSUPP))
2773 return -EOPNOTSUPP; 2761 return -EOPNOTSUPP;
2774 2762
2775 if (!is_owner_or_cap(inode)) 2763 if (!is_owner_or_cap(inode))
@@ -2931,16 +2919,6 @@ static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t
2931 return len; 2919 return len;
2932} 2920}
2933 2921
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) 2922static void selinux_inode_getsecid(const struct inode *inode, u32 *secid)
2945{ 2923{
2946 struct inode_security_struct *isec = inode->i_security; 2924 struct inode_security_struct *isec = inode->i_security;
@@ -3078,18 +3056,13 @@ static int selinux_file_mprotect(struct vm_area_struct *vma,
3078 unsigned long prot) 3056 unsigned long prot)
3079{ 3057{
3080 const struct cred *cred = current_cred(); 3058 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 3059
3087 if (selinux_checkreqprot) 3060 if (selinux_checkreqprot)
3088 prot = reqprot; 3061 prot = reqprot;
3089 3062
3090#ifndef CONFIG_PPC32 3063#ifndef CONFIG_PPC32
3091 if ((prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) { 3064 if ((prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) {
3092 rc = 0; 3065 int rc = 0;
3093 if (vma->vm_start >= vma->vm_mm->start_brk && 3066 if (vma->vm_start >= vma->vm_mm->start_brk &&
3094 vma->vm_end <= vma->vm_mm->brk) { 3067 vma->vm_end <= vma->vm_mm->brk) {
3095 rc = cred_has_perm(cred, cred, PROCESS__EXECHEAP); 3068 rc = cred_has_perm(cred, cred, PROCESS__EXECHEAP);
@@ -3239,12 +3212,6 @@ static int selinux_dentry_open(struct file *file, const struct cred *cred)
3239 3212
3240static int selinux_task_create(unsigned long clone_flags) 3213static int selinux_task_create(unsigned long clone_flags)
3241{ 3214{
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); 3215 return current_has_perm(current, PROCESS__FORK);
3249} 3216}
3250 3217
@@ -3278,14 +3245,6 @@ static int selinux_cred_prepare(struct cred *new, const struct cred *old,
3278} 3245}
3279 3246
3280/* 3247/*
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 3248 * set the security data for a kernel service
3290 * - all the creation contexts are set to unlabelled 3249 * - all the creation contexts are set to unlabelled
3291 */ 3250 */
@@ -3329,29 +3288,6 @@ static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode)
3329 return 0; 3288 return 0;
3330} 3289}
3331 3290
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) 3291static int selinux_task_setpgid(struct task_struct *p, pid_t pgid)
3356{ 3292{
3357 return current_has_perm(p, PROCESS__SETPGID); 3293 return current_has_perm(p, PROCESS__SETPGID);
@@ -3372,12 +3308,6 @@ static void selinux_task_getsecid(struct task_struct *p, u32 *secid)
3372 *secid = task_sid(p); 3308 *secid = task_sid(p);
3373} 3309}
3374 3310
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) 3311static int selinux_task_setnice(struct task_struct *p, int nice)
3382{ 3312{
3383 int rc; 3313 int rc;
@@ -3408,11 +3338,6 @@ static int selinux_task_getioprio(struct task_struct *p)
3408static int selinux_task_setrlimit(unsigned int resource, struct rlimit *new_rlim) 3338static int selinux_task_setrlimit(unsigned int resource, struct rlimit *new_rlim)
3409{ 3339{
3410 struct rlimit *old_rlim = current->signal->rlim + resource; 3340 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 3341
3417 /* Control the ability to change the hard limit (whether 3342 /* Control the ability to change the hard limit (whether
3418 lowering or raising it), so that the hard limit can 3343 lowering or raising it), so that the hard limit can
@@ -3451,10 +3376,6 @@ static int selinux_task_kill(struct task_struct *p, struct siginfo *info,
3451 u32 perm; 3376 u32 perm;
3452 int rc; 3377 int rc;
3453 3378
3454 rc = secondary_ops->task_kill(p, info, sig, secid);
3455 if (rc)
3456 return rc;
3457
3458 if (!sig) 3379 if (!sig)
3459 perm = PROCESS__SIGNULL; /* null signal; existence test */ 3380 perm = PROCESS__SIGNULL; /* null signal; existence test */
3460 else 3381 else
@@ -3467,18 +3388,6 @@ static int selinux_task_kill(struct task_struct *p, struct siginfo *info,
3467 return rc; 3388 return rc;
3468} 3389}
3469 3390
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) 3391static int selinux_task_wait(struct task_struct *p)
3483{ 3392{
3484 return task_has_perm(p, current, PROCESS__SIGCHLD); 3393 return task_has_perm(p, current, PROCESS__SIGCHLD);
@@ -4047,10 +3956,6 @@ static int selinux_socket_unix_stream_connect(struct socket *sock,
4047 struct avc_audit_data ad; 3956 struct avc_audit_data ad;
4048 int err; 3957 int err;
4049 3958
4050 err = secondary_ops->unix_stream_connect(sock, other, newsk);
4051 if (err)
4052 return err;
4053
4054 isec = SOCK_INODE(sock)->i_security; 3959 isec = SOCK_INODE(sock)->i_security;
4055 other_isec = SOCK_INODE(other)->i_security; 3960 other_isec = SOCK_INODE(other)->i_security;
4056 3961
@@ -5167,11 +5072,6 @@ static int selinux_shm_shmat(struct shmid_kernel *shp,
5167 char __user *shmaddr, int shmflg) 5072 char __user *shmaddr, int shmflg)
5168{ 5073{
5169 u32 perms; 5074 u32 perms;
5170 int rc;
5171
5172 rc = secondary_ops->shm_shmat(shp, shmaddr, shmflg);
5173 if (rc)
5174 return rc;
5175 5075
5176 if (shmflg & SHM_RDONLY) 5076 if (shmflg & SHM_RDONLY)
5177 perms = SHM__READ; 5077 perms = SHM__READ;
@@ -5581,7 +5481,6 @@ static struct security_operations selinux_ops = {
5581 .netlink_recv = selinux_netlink_recv, 5481 .netlink_recv = selinux_netlink_recv,
5582 5482
5583 .bprm_set_creds = selinux_bprm_set_creds, 5483 .bprm_set_creds = selinux_bprm_set_creds,
5584 .bprm_check_security = selinux_bprm_check_security,
5585 .bprm_committing_creds = selinux_bprm_committing_creds, 5484 .bprm_committing_creds = selinux_bprm_committing_creds,
5586 .bprm_committed_creds = selinux_bprm_committed_creds, 5485 .bprm_committed_creds = selinux_bprm_committed_creds,
5587 .bprm_secureexec = selinux_bprm_secureexec, 5486 .bprm_secureexec = selinux_bprm_secureexec,
@@ -5623,8 +5522,6 @@ static struct security_operations selinux_ops = {
5623 .inode_getsecurity = selinux_inode_getsecurity, 5522 .inode_getsecurity = selinux_inode_getsecurity,
5624 .inode_setsecurity = selinux_inode_setsecurity, 5523 .inode_setsecurity = selinux_inode_setsecurity,
5625 .inode_listsecurity = selinux_inode_listsecurity, 5524 .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, 5525 .inode_getsecid = selinux_inode_getsecid,
5629 5526
5630 .file_permission = selinux_file_permission, 5527 .file_permission = selinux_file_permission,
@@ -5644,17 +5541,12 @@ static struct security_operations selinux_ops = {
5644 .task_create = selinux_task_create, 5541 .task_create = selinux_task_create,
5645 .cred_free = selinux_cred_free, 5542 .cred_free = selinux_cred_free,
5646 .cred_prepare = selinux_cred_prepare, 5543 .cred_prepare = selinux_cred_prepare,
5647 .cred_commit = selinux_cred_commit,
5648 .kernel_act_as = selinux_kernel_act_as, 5544 .kernel_act_as = selinux_kernel_act_as,
5649 .kernel_create_files_as = selinux_kernel_create_files_as, 5545 .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, 5546 .task_setpgid = selinux_task_setpgid,
5654 .task_getpgid = selinux_task_getpgid, 5547 .task_getpgid = selinux_task_getpgid,
5655 .task_getsid = selinux_task_getsid, 5548 .task_getsid = selinux_task_getsid,
5656 .task_getsecid = selinux_task_getsecid, 5549 .task_getsecid = selinux_task_getsecid,
5657 .task_setgroups = selinux_task_setgroups,
5658 .task_setnice = selinux_task_setnice, 5550 .task_setnice = selinux_task_setnice,
5659 .task_setioprio = selinux_task_setioprio, 5551 .task_setioprio = selinux_task_setioprio,
5660 .task_getioprio = selinux_task_getioprio, 5552 .task_getioprio = selinux_task_getioprio,
@@ -5664,7 +5556,6 @@ static struct security_operations selinux_ops = {
5664 .task_movememory = selinux_task_movememory, 5556 .task_movememory = selinux_task_movememory,
5665 .task_kill = selinux_task_kill, 5557 .task_kill = selinux_task_kill,
5666 .task_wait = selinux_task_wait, 5558 .task_wait = selinux_task_wait,
5667 .task_prctl = selinux_task_prctl,
5668 .task_to_inode = selinux_task_to_inode, 5559 .task_to_inode = selinux_task_to_inode,
5669 5560
5670 .ipc_permission = selinux_ipc_permission, 5561 .ipc_permission = selinux_ipc_permission,
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..e1d9db779983 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