Blame view

security/integrity/ima/ima_main.c 5.77 KB
3323eec92   Mimi Zohar   integrity: IMA as...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
  /*
   * Copyright (C) 2005,2006,2007,2008 IBM Corporation
   *
   * Authors:
   * Reiner Sailer <sailer@watson.ibm.com>
   * Serge Hallyn <serue@us.ibm.com>
   * Kylene Hall <kylene@us.ibm.com>
   * Mimi Zohar <zohar@us.ibm.com>
   *
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of the GNU General Public License as
   * published by the Free Software Foundation, version 2 of the
   * License.
   *
   * File: ima_main.c
e0d5bd2ae   Eric Paris   IMA: clean up the...
16
   *	implements the IMA hooks: ima_bprm_check, ima_file_mmap,
9bbb6cad0   Mimi Zohar   ima: rename ima_p...
17
   *	and ima_file_check.
3323eec92   Mimi Zohar   integrity: IMA as...
18
19
20
21
22
23
   */
  #include <linux/module.h>
  #include <linux/file.h>
  #include <linux/binfmts.h>
  #include <linux/mount.h>
  #include <linux/mman.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
24
  #include <linux/slab.h>
d5813a571   James Morris   ima: sparse fix: ...
25
  #include <linux/ima.h>
3323eec92   Mimi Zohar   integrity: IMA as...
26
27
28
29
30
31
32
33
  
  #include "ima.h"
  
  int ima_initialized;
  
  char *ima_hash = "sha1";
  static int __init hash_setup(char *str)
  {
07ff7a0b1   Mimi Zohar   integrity: remove...
34
35
  	if (strncmp(str, "md5", 3) == 0)
  		ima_hash = "md5";
3323eec92   Mimi Zohar   integrity: IMA as...
36
37
38
  	return 1;
  }
  __setup("ima_hash=", hash_setup);
e0d5bd2ae   Eric Paris   IMA: clean up the...
39
  /*
890275b5e   Mimi Zohar   IMA: maintain i_r...
40
   * ima_rdwr_violation_check
8eb988c70   Mimi Zohar   fix ima breakage
41
   *
890275b5e   Mimi Zohar   IMA: maintain i_r...
42
   * Only invalidate the PCR for measured files:
8eb988c70   Mimi Zohar   fix ima breakage
43
44
45
46
47
48
   * 	- Opening a file for write when already open for read,
   *	  results in a time of measure, time of use (ToMToU) error.
   *	- Opening a file for read when already open for write,
   * 	  could result in a file measurement error.
   *
   */
890275b5e   Mimi Zohar   IMA: maintain i_r...
49
  static void ima_rdwr_violation_check(struct file *file)
8eb988c70   Mimi Zohar   fix ima breakage
50
51
52
53
  {
  	struct dentry *dentry = file->f_path.dentry;
  	struct inode *inode = dentry->d_inode;
  	fmode_t mode = file->f_mode;
8eb988c70   Mimi Zohar   fix ima breakage
54
  	int rc;
ad16ad00c   Eric Paris   IMA: use inode->i...
55
  	bool send_tomtou = false, send_writers = false;
8eb988c70   Mimi Zohar   fix ima breakage
56

890275b5e   Mimi Zohar   IMA: maintain i_r...
57
  	if (!S_ISREG(inode->i_mode) || !ima_initialized)
8eb988c70   Mimi Zohar   fix ima breakage
58
  		return;
a178d2027   Eric Paris   IMA: move read co...
59

890275b5e   Mimi Zohar   IMA: maintain i_r...
60
  	mutex_lock(&inode->i_mutex);	/* file metadata: permissions, xattr */
ad16ad00c   Eric Paris   IMA: use inode->i...
61

8eb988c70   Mimi Zohar   fix ima breakage
62
  	if (mode & FMODE_WRITE) {
a68a27b6f   Mimi Zohar   IMA: convert i_re...
63
  		if (atomic_read(&inode->i_readcount) && IS_IMA(inode))
ad16ad00c   Eric Paris   IMA: use inode->i...
64
  			send_tomtou = true;
8eb988c70   Mimi Zohar   fix ima breakage
65
66
  		goto out;
  	}
ad16ad00c   Eric Paris   IMA: use inode->i...
67

1adace9bb   Mimi Zohar   ima: remove unnec...
68
  	rc = ima_must_measure(inode, MAY_READ, FILE_CHECK);
bade72d60   Eric Paris   IMA: fix the ToMT...
69
70
  	if (rc < 0)
  		goto out;
ad16ad00c   Eric Paris   IMA: use inode->i...
71
72
  	if (atomic_read(&inode->i_writecount) > 0)
  		send_writers = true;
8eb988c70   Mimi Zohar   fix ima breakage
73
  out:
890275b5e   Mimi Zohar   IMA: maintain i_r...
74
  	mutex_unlock(&inode->i_mutex);
ad16ad00c   Eric Paris   IMA: use inode->i...
75
76
77
78
79
80
81
  
  	if (send_tomtou)
  		ima_add_violation(inode, dentry->d_name.name, "invalid_pcr",
  				  "ToMToU");
  	if (send_writers)
  		ima_add_violation(inode, dentry->d_name.name, "invalid_pcr",
  				  "open_writers");
8eb988c70   Mimi Zohar   fix ima breakage
82
  }
f381c2722   Mimi Zohar   integrity: move i...
83
  static void ima_check_last_writer(struct integrity_iint_cache *iint,
bc7d2a3e6   Eric Paris   IMA: only allocat...
84
85
86
  				  struct inode *inode,
  				  struct file *file)
  {
4b2a2c674   Al Viro   ima: fmode_t miss...
87
  	fmode_t mode = file->f_mode;
bc7d2a3e6   Eric Paris   IMA: only allocat...
88

854fdd55b   Mimi Zohar   IMA: remove IMA i...
89
  	mutex_lock(&iint->mutex);
bc7d2a3e6   Eric Paris   IMA: only allocat...
90
91
92
93
  	if (mode & FMODE_WRITE &&
  	    atomic_read(&inode->i_writecount) == 1 &&
  	    iint->version != inode->i_version)
  		iint->flags &= ~IMA_MEASURED;
bc7d2a3e6   Eric Paris   IMA: only allocat...
94
  	mutex_unlock(&iint->mutex);
bc7d2a3e6   Eric Paris   IMA: only allocat...
95
  }
3323eec92   Mimi Zohar   integrity: IMA as...
96
97
98
99
  /**
   * ima_file_free - called on __fput()
   * @file: pointer to file structure being freed
   *
890275b5e   Mimi Zohar   IMA: maintain i_r...
100
   * Flag files that changed, based on i_version
3323eec92   Mimi Zohar   integrity: IMA as...
101
102
103
104
   */
  void ima_file_free(struct file *file)
  {
  	struct inode *inode = file->f_dentry->d_inode;
f381c2722   Mimi Zohar   integrity: move i...
105
  	struct integrity_iint_cache *iint;
3323eec92   Mimi Zohar   integrity: IMA as...
106

e950598d4   Mimi Zohar   ima: always maint...
107
  	if (!iint_initialized || !S_ISREG(inode->i_mode))
3323eec92   Mimi Zohar   integrity: IMA as...
108
  		return;
196f51812   Eric Paris   IMA: explicit IMA...
109

f381c2722   Mimi Zohar   integrity: move i...
110
  	iint = integrity_iint_find(inode);
854fdd55b   Mimi Zohar   IMA: remove IMA i...
111
112
  	if (!iint)
  		return;
3323eec92   Mimi Zohar   integrity: IMA as...
113

854fdd55b   Mimi Zohar   IMA: remove IMA i...
114
  	ima_check_last_writer(iint, inode, file);
3323eec92   Mimi Zohar   integrity: IMA as...
115
  }
3323eec92   Mimi Zohar   integrity: IMA as...
116
117
118
119
  static int process_measurement(struct file *file, const unsigned char *filename,
  			       int mask, int function)
  {
  	struct inode *inode = file->f_dentry->d_inode;
f381c2722   Mimi Zohar   integrity: move i...
120
  	struct integrity_iint_cache *iint;
e950598d4   Mimi Zohar   ima: always maint...
121
  	int rc = 0;
3323eec92   Mimi Zohar   integrity: IMA as...
122
123
124
  
  	if (!ima_initialized || !S_ISREG(inode->i_mode))
  		return 0;
bc7d2a3e6   Eric Paris   IMA: only allocat...
125

1adace9bb   Mimi Zohar   ima: remove unnec...
126
  	rc = ima_must_measure(inode, mask, function);
bc7d2a3e6   Eric Paris   IMA: only allocat...
127
128
129
  	if (rc != 0)
  		return rc;
  retry:
f381c2722   Mimi Zohar   integrity: move i...
130
  	iint = integrity_iint_find(inode);
bc7d2a3e6   Eric Paris   IMA: only allocat...
131
  	if (!iint) {
f381c2722   Mimi Zohar   integrity: move i...
132
  		rc = integrity_inode_alloc(inode);
bc7d2a3e6   Eric Paris   IMA: only allocat...
133
134
135
136
  		if (!rc || rc == -EEXIST)
  			goto retry;
  		return rc;
  	}
3323eec92   Mimi Zohar   integrity: IMA as...
137
138
  
  	mutex_lock(&iint->mutex);
bc7d2a3e6   Eric Paris   IMA: only allocat...
139

1adace9bb   Mimi Zohar   ima: remove unnec...
140
  	rc = iint->flags & IMA_MEASURED ? 1 : 0;
3323eec92   Mimi Zohar   integrity: IMA as...
141
142
143
144
145
146
147
148
  	if (rc != 0)
  		goto out;
  
  	rc = ima_collect_measurement(iint, file);
  	if (!rc)
  		ima_store_measurement(iint, file, filename);
  out:
  	mutex_unlock(&iint->mutex);
3323eec92   Mimi Zohar   integrity: IMA as...
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
  	return rc;
  }
  
  /**
   * ima_file_mmap - based on policy, collect/store measurement.
   * @file: pointer to the file to be measured (May be NULL)
   * @prot: contains the protection that will be applied by the kernel.
   *
   * Measure files being mmapped executable based on the ima_must_measure()
   * policy decision.
   *
   * Return 0 on success, an error code on failure.
   * (Based on the results of appraise_measurement().)
   */
  int ima_file_mmap(struct file *file, unsigned long prot)
  {
  	int rc;
  
  	if (!file)
  		return 0;
  	if (prot & PROT_EXEC)
  		rc = process_measurement(file, file->f_dentry->d_name.name,
  					 MAY_EXEC, FILE_MMAP);
  	return 0;
  }
  
  /**
   * ima_bprm_check - based on policy, collect/store measurement.
   * @bprm: contains the linux_binprm structure
   *
   * The OS protects against an executable file, already open for write,
   * from being executed in deny_write_access() and an executable file,
   * already open for execute, from being modified in get_write_access().
   * So we can be certain that what we verify and measure here is actually
   * what is being executed.
   *
   * Return 0 on success, an error code on failure.
   * (Based on the results of appraise_measurement().)
   */
  int ima_bprm_check(struct linux_binprm *bprm)
  {
  	int rc;
  
  	rc = process_measurement(bprm->file, bprm->filename,
  				 MAY_EXEC, BPRM_CHECK);
  	return 0;
  }
8eb988c70   Mimi Zohar   fix ima breakage
196
197
198
199
200
201
202
203
204
205
  /**
   * ima_path_check - based on policy, collect/store measurement.
   * @file: pointer to the file to be measured
   * @mask: contains MAY_READ, MAY_WRITE or MAY_EXECUTE
   *
   * Measure files based on the ima_must_measure() policy decision.
   *
   * Always return 0 and audit dentry_open failures.
   * (Return code will be based upon measurement appraisal.)
   */
9bbb6cad0   Mimi Zohar   ima: rename ima_p...
206
  int ima_file_check(struct file *file, int mask)
8eb988c70   Mimi Zohar   fix ima breakage
207
208
  {
  	int rc;
890275b5e   Mimi Zohar   IMA: maintain i_r...
209
  	ima_rdwr_violation_check(file);
8eb988c70   Mimi Zohar   fix ima breakage
210
211
  	rc = process_measurement(file, file->f_dentry->d_name.name,
  				 mask & (MAY_READ | MAY_WRITE | MAY_EXEC),
1e93d0052   Mimi Zohar   ima: rename PATH_...
212
  				 FILE_CHECK);
8eb988c70   Mimi Zohar   fix ima breakage
213
214
  	return 0;
  }
9bbb6cad0   Mimi Zohar   ima: rename ima_p...
215
  EXPORT_SYMBOL_GPL(ima_file_check);
8eb988c70   Mimi Zohar   fix ima breakage
216

3323eec92   Mimi Zohar   integrity: IMA as...
217
218
219
  static int __init init_ima(void)
  {
  	int error;
3323eec92   Mimi Zohar   integrity: IMA as...
220
221
222
223
  	error = ima_init();
  	ima_initialized = 1;
  	return error;
  }
bab739378   Mimi Zohar   integrity: IMA di...
224
225
226
227
  static void __exit cleanup_ima(void)
  {
  	ima_cleanup();
  }
3323eec92   Mimi Zohar   integrity: IMA as...
228
229
230
231
  late_initcall(init_ima);	/* Start IMA after the TPM is available */
  
  MODULE_DESCRIPTION("Integrity Measurement Architecture");
  MODULE_LICENSE("GPL");