diff options
author | Mimi Zohar <zohar@linux.vnet.ibm.com> | 2009-02-04 09:06:57 -0500 |
---|---|---|
committer | James Morris <jmorris@namei.org> | 2009-02-05 17:05:30 -0500 |
commit | 6146f0d5e47ca4047ffded0fb79b6c25359b386c (patch) | |
tree | edd792e52ad56d4a5d3ac6caa8437d3283fc157e | |
parent | 659aaf2bb5496a425ba14036b5b5900f593e4484 (diff) |
integrity: IMA hooks
This patch replaces the generic integrity hooks, for which IMA registered
itself, with IMA integrity hooks in the appropriate places directly
in the fs directory.
Signed-off-by: Mimi Zohar <zohar@us.ibm.com>
Acked-by: Serge Hallyn <serue@us.ibm.com>
Signed-off-by: James Morris <jmorris@namei.org>
-rw-r--r-- | Documentation/kernel-parameters.txt | 1 | ||||
-rw-r--r-- | fs/exec.c | 10 | ||||
-rw-r--r-- | fs/file_table.c | 2 | ||||
-rw-r--r-- | fs/inode.c | 24 | ||||
-rw-r--r-- | fs/namei.c | 8 | ||||
-rw-r--r-- | include/linux/ima.h | 44 | ||||
-rw-r--r-- | mm/mmap.c | 4 |
7 files changed, 86 insertions, 7 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index a2d8805c03d5..7c67b94d1823 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt | |||
@@ -44,6 +44,7 @@ parameter is applicable: | |||
44 | FB The frame buffer device is enabled. | 44 | FB The frame buffer device is enabled. |
45 | HW Appropriate hardware is enabled. | 45 | HW Appropriate hardware is enabled. |
46 | IA-64 IA-64 architecture is enabled. | 46 | IA-64 IA-64 architecture is enabled. |
47 | IMA Integrity measurement architecture is enabled. | ||
47 | IOSCHED More than one I/O scheduler is enabled. | 48 | IOSCHED More than one I/O scheduler is enabled. |
48 | IP_PNP IP DHCP, BOOTP, or RARP is enabled. | 49 | IP_PNP IP DHCP, BOOTP, or RARP is enabled. |
49 | ISAPNP ISA PnP code is enabled. | 50 | ISAPNP ISA PnP code is enabled. |
@@ -45,6 +45,7 @@ | |||
45 | #include <linux/proc_fs.h> | 45 | #include <linux/proc_fs.h> |
46 | #include <linux/mount.h> | 46 | #include <linux/mount.h> |
47 | #include <linux/security.h> | 47 | #include <linux/security.h> |
48 | #include <linux/ima.h> | ||
48 | #include <linux/syscalls.h> | 49 | #include <linux/syscalls.h> |
49 | #include <linux/tsacct_kern.h> | 50 | #include <linux/tsacct_kern.h> |
50 | #include <linux/cn_proc.h> | 51 | #include <linux/cn_proc.h> |
@@ -130,6 +131,9 @@ asmlinkage long sys_uselib(const char __user * library) | |||
130 | error = vfs_permission(&nd, MAY_READ | MAY_EXEC | MAY_OPEN); | 131 | error = vfs_permission(&nd, MAY_READ | MAY_EXEC | MAY_OPEN); |
131 | if (error) | 132 | if (error) |
132 | goto exit; | 133 | goto exit; |
134 | error = ima_path_check(&nd.path, MAY_READ | MAY_EXEC | MAY_OPEN); | ||
135 | if (error) | ||
136 | goto exit; | ||
133 | 137 | ||
134 | file = nameidata_to_filp(&nd, O_RDONLY|O_LARGEFILE); | 138 | file = nameidata_to_filp(&nd, O_RDONLY|O_LARGEFILE); |
135 | error = PTR_ERR(file); | 139 | error = PTR_ERR(file); |
@@ -683,6 +687,9 @@ struct file *open_exec(const char *name) | |||
683 | err = vfs_permission(&nd, MAY_EXEC | MAY_OPEN); | 687 | err = vfs_permission(&nd, MAY_EXEC | MAY_OPEN); |
684 | if (err) | 688 | if (err) |
685 | goto out_path_put; | 689 | goto out_path_put; |
690 | err = ima_path_check(&nd.path, MAY_EXEC | MAY_OPEN); | ||
691 | if (err) | ||
692 | goto out_path_put; | ||
686 | 693 | ||
687 | file = nameidata_to_filp(&nd, O_RDONLY|O_LARGEFILE); | 694 | file = nameidata_to_filp(&nd, O_RDONLY|O_LARGEFILE); |
688 | if (IS_ERR(file)) | 695 | if (IS_ERR(file)) |
@@ -1209,6 +1216,9 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs) | |||
1209 | retval = security_bprm_check(bprm); | 1216 | retval = security_bprm_check(bprm); |
1210 | if (retval) | 1217 | if (retval) |
1211 | return retval; | 1218 | return retval; |
1219 | retval = ima_bprm_check(bprm); | ||
1220 | if (retval) | ||
1221 | return retval; | ||
1212 | 1222 | ||
1213 | /* kernel module loader fixup */ | 1223 | /* kernel module loader fixup */ |
1214 | /* so we don't try to load run modprobe in kernel space. */ | 1224 | /* so we don't try to load run modprobe in kernel space. */ |
diff --git a/fs/file_table.c b/fs/file_table.c index 0fbcacc3ea75..55895ccc08c6 100644 --- a/fs/file_table.c +++ b/fs/file_table.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/fs.h> | 14 | #include <linux/fs.h> |
15 | #include <linux/security.h> | 15 | #include <linux/security.h> |
16 | #include <linux/ima.h> | ||
16 | #include <linux/eventpoll.h> | 17 | #include <linux/eventpoll.h> |
17 | #include <linux/rcupdate.h> | 18 | #include <linux/rcupdate.h> |
18 | #include <linux/mount.h> | 19 | #include <linux/mount.h> |
@@ -276,6 +277,7 @@ void __fput(struct file *file) | |||
276 | if (file->f_op && file->f_op->release) | 277 | if (file->f_op && file->f_op->release) |
277 | file->f_op->release(inode, file); | 278 | file->f_op->release(inode, file); |
278 | security_file_free(file); | 279 | security_file_free(file); |
280 | ima_file_free(file); | ||
279 | if (unlikely(S_ISCHR(inode->i_mode) && inode->i_cdev != NULL)) | 281 | if (unlikely(S_ISCHR(inode->i_mode) && inode->i_cdev != NULL)) |
280 | cdev_put(inode->i_cdev); | 282 | cdev_put(inode->i_cdev); |
281 | fops_put(file->f_op); | 283 | fops_put(file->f_op); |
diff --git a/fs/inode.c b/fs/inode.c index 098a2443196f..ed22b14f2202 100644 --- a/fs/inode.c +++ b/fs/inode.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/hash.h> | 17 | #include <linux/hash.h> |
18 | #include <linux/swap.h> | 18 | #include <linux/swap.h> |
19 | #include <linux/security.h> | 19 | #include <linux/security.h> |
20 | #include <linux/ima.h> | ||
20 | #include <linux/pagemap.h> | 21 | #include <linux/pagemap.h> |
21 | #include <linux/cdev.h> | 22 | #include <linux/cdev.h> |
22 | #include <linux/bootmem.h> | 23 | #include <linux/bootmem.h> |
@@ -144,13 +145,13 @@ struct inode *inode_init_always(struct super_block *sb, struct inode *inode) | |||
144 | inode->i_cdev = NULL; | 145 | inode->i_cdev = NULL; |
145 | inode->i_rdev = 0; | 146 | inode->i_rdev = 0; |
146 | inode->dirtied_when = 0; | 147 | inode->dirtied_when = 0; |
147 | if (security_inode_alloc(inode)) { | 148 | |
148 | if (inode->i_sb->s_op->destroy_inode) | 149 | if (security_inode_alloc(inode)) |
149 | inode->i_sb->s_op->destroy_inode(inode); | 150 | goto out_free_inode; |
150 | else | 151 | |
151 | kmem_cache_free(inode_cachep, (inode)); | 152 | /* allocate and initialize an i_integrity */ |
152 | return NULL; | 153 | if (ima_inode_alloc(inode)) |
153 | } | 154 | goto out_free_security; |
154 | 155 | ||
155 | spin_lock_init(&inode->i_lock); | 156 | spin_lock_init(&inode->i_lock); |
156 | lockdep_set_class(&inode->i_lock, &sb->s_type->i_lock_key); | 157 | lockdep_set_class(&inode->i_lock, &sb->s_type->i_lock_key); |
@@ -186,6 +187,15 @@ struct inode *inode_init_always(struct super_block *sb, struct inode *inode) | |||
186 | inode->i_mapping = mapping; | 187 | inode->i_mapping = mapping; |
187 | 188 | ||
188 | return inode; | 189 | return inode; |
190 | |||
191 | out_free_security: | ||
192 | security_inode_free(inode); | ||
193 | out_free_inode: | ||
194 | if (inode->i_sb->s_op->destroy_inode) | ||
195 | inode->i_sb->s_op->destroy_inode(inode); | ||
196 | else | ||
197 | kmem_cache_free(inode_cachep, (inode)); | ||
198 | return NULL; | ||
189 | } | 199 | } |
190 | EXPORT_SYMBOL(inode_init_always); | 200 | EXPORT_SYMBOL(inode_init_always); |
191 | 201 | ||
diff --git a/fs/namei.c b/fs/namei.c index af3783fff1de..734f2b5591bf 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/fsnotify.h> | 24 | #include <linux/fsnotify.h> |
25 | #include <linux/personality.h> | 25 | #include <linux/personality.h> |
26 | #include <linux/security.h> | 26 | #include <linux/security.h> |
27 | #include <linux/ima.h> | ||
27 | #include <linux/syscalls.h> | 28 | #include <linux/syscalls.h> |
28 | #include <linux/mount.h> | 29 | #include <linux/mount.h> |
29 | #include <linux/audit.h> | 30 | #include <linux/audit.h> |
@@ -860,6 +861,8 @@ static int __link_path_walk(const char *name, struct nameidata *nd) | |||
860 | err = exec_permission_lite(inode); | 861 | err = exec_permission_lite(inode); |
861 | if (err == -EAGAIN) | 862 | if (err == -EAGAIN) |
862 | err = vfs_permission(nd, MAY_EXEC); | 863 | err = vfs_permission(nd, MAY_EXEC); |
864 | if (!err) | ||
865 | err = ima_path_check(&nd->path, MAY_EXEC); | ||
863 | if (err) | 866 | if (err) |
864 | break; | 867 | break; |
865 | 868 | ||
@@ -1525,6 +1528,11 @@ int may_open(struct nameidata *nd, int acc_mode, int flag) | |||
1525 | error = vfs_permission(nd, acc_mode); | 1528 | error = vfs_permission(nd, acc_mode); |
1526 | if (error) | 1529 | if (error) |
1527 | return error; | 1530 | return error; |
1531 | |||
1532 | error = ima_path_check(&nd->path, | ||
1533 | acc_mode & (MAY_READ | MAY_WRITE | MAY_EXEC)); | ||
1534 | if (error) | ||
1535 | return error; | ||
1528 | /* | 1536 | /* |
1529 | * An append-only file must be opened in append mode for writing. | 1537 | * An append-only file must be opened in append mode for writing. |
1530 | */ | 1538 | */ |
diff --git a/include/linux/ima.h b/include/linux/ima.h new file mode 100644 index 000000000000..4ed1e4d962e2 --- /dev/null +++ b/include/linux/ima.h | |||
@@ -0,0 +1,44 @@ | |||
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 | |||
10 | #include <linux/fs.h> | ||
11 | |||
12 | #ifndef _LINUX_IMA_H | ||
13 | #define _LINUX_IMA_H | ||
14 | |||
15 | static inline int ima_bprm_check(struct linux_binprm *bprm) | ||
16 | { | ||
17 | return 0; | ||
18 | } | ||
19 | |||
20 | static inline int ima_inode_alloc(struct inode *inode) | ||
21 | { | ||
22 | return 0; | ||
23 | } | ||
24 | |||
25 | static inline void ima_inode_free(struct inode *inode) | ||
26 | { | ||
27 | return; | ||
28 | } | ||
29 | |||
30 | static inline int ima_path_check(struct path *path, int mask) | ||
31 | { | ||
32 | return 0; | ||
33 | } | ||
34 | |||
35 | static inline void ima_file_free(struct file *file) | ||
36 | { | ||
37 | return; | ||
38 | } | ||
39 | |||
40 | static inline int ima_file_mmap(struct file *file, unsigned long prot) | ||
41 | { | ||
42 | return 0; | ||
43 | } | ||
44 | #endif /* _LINUX_IMA_H */ | ||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/fs.h> | 20 | #include <linux/fs.h> |
21 | #include <linux/personality.h> | 21 | #include <linux/personality.h> |
22 | #include <linux/security.h> | 22 | #include <linux/security.h> |
23 | #include <linux/ima.h> | ||
23 | #include <linux/hugetlb.h> | 24 | #include <linux/hugetlb.h> |
24 | #include <linux/profile.h> | 25 | #include <linux/profile.h> |
25 | #include <linux/module.h> | 26 | #include <linux/module.h> |
@@ -1050,6 +1051,9 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr, | |||
1050 | error = security_file_mmap(file, reqprot, prot, flags, addr, 0); | 1051 | error = security_file_mmap(file, reqprot, prot, flags, addr, 0); |
1051 | if (error) | 1052 | if (error) |
1052 | return error; | 1053 | return error; |
1054 | error = ima_file_mmap(file, prot); | ||
1055 | if (error) | ||
1056 | return error; | ||
1053 | 1057 | ||
1054 | return mmap_region(file, addr, len, flags, vm_flags, pgoff, | 1058 | return mmap_region(file, addr, len, flags, vm_flags, pgoff, |
1055 | accountable); | 1059 | accountable); |