diff options
Diffstat (limited to 'security/integrity/ima/ima_main.c')
-rw-r--r-- | security/integrity/ima/ima_main.c | 86 |
1 files changed, 46 insertions, 40 deletions
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index f4e7266f5aee..6f611874d10e 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c | |||
@@ -29,20 +29,8 @@ int ima_initialized; | |||
29 | char *ima_hash = "sha1"; | 29 | char *ima_hash = "sha1"; |
30 | static int __init hash_setup(char *str) | 30 | static int __init hash_setup(char *str) |
31 | { | 31 | { |
32 | const char *op = "hash_setup"; | 32 | if (strncmp(str, "md5", 3) == 0) |
33 | const char *hash = "sha1"; | 33 | ima_hash = "md5"; |
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; | 34 | return 1; |
47 | } | 35 | } |
48 | __setup("ima_hash=", hash_setup); | 36 | __setup("ima_hash=", hash_setup); |
@@ -128,10 +116,6 @@ static int get_path_measurement(struct ima_iint_cache *iint, struct file *file, | |||
128 | { | 116 | { |
129 | int rc = 0; | 117 | int rc = 0; |
130 | 118 | ||
131 | if (IS_ERR(file)) { | ||
132 | pr_info("%s dentry_open failed\n", filename); | ||
133 | return rc; | ||
134 | } | ||
135 | iint->opencount++; | 119 | iint->opencount++; |
136 | iint->readcount++; | 120 | iint->readcount++; |
137 | 121 | ||
@@ -141,6 +125,15 @@ static int get_path_measurement(struct ima_iint_cache *iint, struct file *file, | |||
141 | return rc; | 125 | return rc; |
142 | } | 126 | } |
143 | 127 | ||
128 | static void ima_update_counts(struct ima_iint_cache *iint, int mask) | ||
129 | { | ||
130 | iint->opencount++; | ||
131 | if ((mask & MAY_WRITE) || (mask == 0)) | ||
132 | iint->writecount++; | ||
133 | else if (mask & (MAY_READ | MAY_EXEC)) | ||
134 | iint->readcount++; | ||
135 | } | ||
136 | |||
144 | /** | 137 | /** |
145 | * ima_path_check - based on policy, collect/store measurement. | 138 | * ima_path_check - based on policy, collect/store measurement. |
146 | * @path: contains a pointer to the path to be measured | 139 | * @path: contains a pointer to the path to be measured |
@@ -156,10 +149,10 @@ static int get_path_measurement(struct ima_iint_cache *iint, struct file *file, | |||
156 | * - Opening a file for read when already open for write, | 149 | * - Opening a file for read when already open for write, |
157 | * could result in a file measurement error. | 150 | * could result in a file measurement error. |
158 | * | 151 | * |
159 | * Return 0 on success, an error code on failure. | 152 | * Always return 0 and audit dentry_open failures. |
160 | * (Based on the results of appraise_measurement().) | 153 | * (Return code will be based upon measurement appraisal.) |
161 | */ | 154 | */ |
162 | int ima_path_check(struct path *path, int mask) | 155 | int ima_path_check(struct path *path, int mask, int update_counts) |
163 | { | 156 | { |
164 | struct inode *inode = path->dentry->d_inode; | 157 | struct inode *inode = path->dentry->d_inode; |
165 | struct ima_iint_cache *iint; | 158 | struct ima_iint_cache *iint; |
@@ -173,11 +166,8 @@ int ima_path_check(struct path *path, int mask) | |||
173 | return 0; | 166 | return 0; |
174 | 167 | ||
175 | mutex_lock(&iint->mutex); | 168 | mutex_lock(&iint->mutex); |
176 | iint->opencount++; | 169 | if (update_counts) |
177 | if ((mask & MAY_WRITE) || (mask == 0)) | 170 | ima_update_counts(iint, mask); |
178 | iint->writecount++; | ||
179 | else if (mask & (MAY_READ | MAY_EXEC)) | ||
180 | iint->readcount++; | ||
181 | 171 | ||
182 | rc = ima_must_measure(iint, inode, MAY_READ, PATH_CHECK); | 172 | rc = ima_must_measure(iint, inode, MAY_READ, PATH_CHECK); |
183 | if (rc < 0) | 173 | if (rc < 0) |
@@ -196,7 +186,19 @@ int ima_path_check(struct path *path, int mask) | |||
196 | struct dentry *dentry = dget(path->dentry); | 186 | struct dentry *dentry = dget(path->dentry); |
197 | struct vfsmount *mnt = mntget(path->mnt); | 187 | struct vfsmount *mnt = mntget(path->mnt); |
198 | 188 | ||
199 | file = dentry_open(dentry, mnt, O_RDONLY, current->cred); | 189 | file = dentry_open(dentry, mnt, O_RDONLY | O_LARGEFILE, |
190 | current_cred()); | ||
191 | if (IS_ERR(file)) { | ||
192 | int audit_info = 0; | ||
193 | |||
194 | integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, | ||
195 | dentry->d_name.name, | ||
196 | "add_measurement", | ||
197 | "dentry_open failed", | ||
198 | 1, audit_info); | ||
199 | file = NULL; | ||
200 | goto out; | ||
201 | } | ||
200 | rc = get_path_measurement(iint, file, dentry->d_name.name); | 202 | rc = get_path_measurement(iint, file, dentry->d_name.name); |
201 | } | 203 | } |
202 | out: | 204 | out: |
@@ -206,6 +208,7 @@ out: | |||
206 | kref_put(&iint->refcount, iint_free); | 208 | kref_put(&iint->refcount, iint_free); |
207 | return 0; | 209 | return 0; |
208 | } | 210 | } |
211 | EXPORT_SYMBOL_GPL(ima_path_check); | ||
209 | 212 | ||
210 | static int process_measurement(struct file *file, const unsigned char *filename, | 213 | static int process_measurement(struct file *file, const unsigned char *filename, |
211 | int mask, int function) | 214 | int mask, int function) |
@@ -234,7 +237,16 @@ out: | |||
234 | return rc; | 237 | return rc; |
235 | } | 238 | } |
236 | 239 | ||
237 | static void opencount_get(struct file *file) | 240 | /* |
241 | * ima_opens_get - increment file counts | ||
242 | * | ||
243 | * - for IPC shm and shmat file. | ||
244 | * - for nfsd exported files. | ||
245 | * | ||
246 | * Increment the counts for these files to prevent unnecessary | ||
247 | * imbalance messages. | ||
248 | */ | ||
249 | void ima_counts_get(struct file *file) | ||
238 | { | 250 | { |
239 | struct inode *inode = file->f_dentry->d_inode; | 251 | struct inode *inode = file->f_dentry->d_inode; |
240 | struct ima_iint_cache *iint; | 252 | struct ima_iint_cache *iint; |
@@ -246,8 +258,14 @@ static void opencount_get(struct file *file) | |||
246 | return; | 258 | return; |
247 | mutex_lock(&iint->mutex); | 259 | mutex_lock(&iint->mutex); |
248 | iint->opencount++; | 260 | iint->opencount++; |
261 | if ((file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) | ||
262 | iint->readcount++; | ||
263 | |||
264 | if (file->f_mode & FMODE_WRITE) | ||
265 | iint->writecount++; | ||
249 | mutex_unlock(&iint->mutex); | 266 | mutex_unlock(&iint->mutex); |
250 | } | 267 | } |
268 | EXPORT_SYMBOL_GPL(ima_counts_get); | ||
251 | 269 | ||
252 | /** | 270 | /** |
253 | * ima_file_mmap - based on policy, collect/store measurement. | 271 | * ima_file_mmap - based on policy, collect/store measurement. |
@@ -272,18 +290,6 @@ int ima_file_mmap(struct file *file, unsigned long prot) | |||
272 | return 0; | 290 | return 0; |
273 | } | 291 | } |
274 | 292 | ||
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 | */ | ||
281 | void ima_shm_check(struct file *file) | ||
282 | { | ||
283 | opencount_get(file); | ||
284 | return; | ||
285 | } | ||
286 | |||
287 | /** | 293 | /** |
288 | * ima_bprm_check - based on policy, collect/store measurement. | 294 | * ima_bprm_check - based on policy, collect/store measurement. |
289 | * @bprm: contains the linux_binprm structure | 295 | * @bprm: contains the linux_binprm structure |