diff options
author | Mimi Zohar <zohar@linux.vnet.ibm.com> | 2009-05-19 13:25:57 -0400 |
---|---|---|
committer | James Morris <jmorris@namei.org> | 2009-05-21 19:43:41 -0400 |
commit | b9fc745db833bbf74b4988493b8cd902a84c9415 (patch) | |
tree | 45a15174efb3b1c3dcbe5f0dc503e790c4f6fd70 | |
parent | 932995f0ce52525b32ff5127b522c2c164de3810 (diff) |
integrity: path_check update
- Add support in ima_path_check() for integrity checking without
incrementing the counts. (Required for nfsd.)
- rename and export opencount_get to ima_counts_get
- replace ima_shm_check calls with ima_counts_get
- export ima_path_check
Signed-off-by: Mimi Zohar <zohar@us.ibm.com>
Signed-off-by: James Morris <jmorris@namei.org>
-rw-r--r-- | fs/exec.c | 5 | ||||
-rw-r--r-- | fs/namei.c | 6 | ||||
-rw-r--r-- | include/linux/ima.h | 11 | ||||
-rw-r--r-- | ipc/shm.c | 4 | ||||
-rw-r--r-- | mm/shmem.c | 2 | ||||
-rw-r--r-- | security/integrity/ima/ima_main.c | 48 |
6 files changed, 46 insertions, 30 deletions
@@ -130,7 +130,8 @@ SYSCALL_DEFINE1(uselib, const char __user *, library) | |||
130 | MAY_READ | MAY_EXEC | MAY_OPEN); | 130 | MAY_READ | MAY_EXEC | MAY_OPEN); |
131 | if (error) | 131 | if (error) |
132 | goto exit; | 132 | goto exit; |
133 | error = ima_path_check(&nd.path, MAY_READ | MAY_EXEC | MAY_OPEN); | 133 | error = ima_path_check(&nd.path, MAY_READ | MAY_EXEC | MAY_OPEN, |
134 | IMA_COUNT_UPDATE); | ||
134 | if (error) | 135 | if (error) |
135 | goto exit; | 136 | goto exit; |
136 | 137 | ||
@@ -680,7 +681,7 @@ struct file *open_exec(const char *name) | |||
680 | err = inode_permission(nd.path.dentry->d_inode, MAY_EXEC | MAY_OPEN); | 681 | err = inode_permission(nd.path.dentry->d_inode, MAY_EXEC | MAY_OPEN); |
681 | if (err) | 682 | if (err) |
682 | goto out_path_put; | 683 | goto out_path_put; |
683 | err = ima_path_check(&nd.path, MAY_EXEC | MAY_OPEN); | 684 | err = ima_path_check(&nd.path, MAY_EXEC | MAY_OPEN, IMA_COUNT_UPDATE); |
684 | if (err) | 685 | if (err) |
685 | goto out_path_put; | 686 | goto out_path_put; |
686 | 687 | ||
diff --git a/fs/namei.c b/fs/namei.c index 78f253cd2d4f..b05a2b1dea64 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -853,7 +853,8 @@ static int __link_path_walk(const char *name, struct nameidata *nd) | |||
853 | err = inode_permission(nd->path.dentry->d_inode, | 853 | err = inode_permission(nd->path.dentry->d_inode, |
854 | MAY_EXEC); | 854 | MAY_EXEC); |
855 | if (!err) | 855 | if (!err) |
856 | err = ima_path_check(&nd->path, MAY_EXEC); | 856 | err = ima_path_check(&nd->path, MAY_EXEC, |
857 | IMA_COUNT_UPDATE); | ||
857 | if (err) | 858 | if (err) |
858 | break; | 859 | break; |
859 | 860 | ||
@@ -1515,7 +1516,8 @@ int may_open(struct path *path, int acc_mode, int flag) | |||
1515 | return error; | 1516 | return error; |
1516 | 1517 | ||
1517 | error = ima_path_check(path, | 1518 | error = ima_path_check(path, |
1518 | acc_mode & (MAY_READ | MAY_WRITE | MAY_EXEC)); | 1519 | acc_mode & (MAY_READ | MAY_WRITE | MAY_EXEC), |
1520 | IMA_COUNT_UPDATE); | ||
1519 | if (error) | 1521 | if (error) |
1520 | return error; | 1522 | return error; |
1521 | /* | 1523 | /* |
diff --git a/include/linux/ima.h b/include/linux/ima.h index 0e2aa45cb0ce..b1b827d091a9 100644 --- a/include/linux/ima.h +++ b/include/linux/ima.h | |||
@@ -13,14 +13,17 @@ | |||
13 | #include <linux/fs.h> | 13 | #include <linux/fs.h> |
14 | struct linux_binprm; | 14 | struct linux_binprm; |
15 | 15 | ||
16 | #define IMA_COUNT_UPDATE 1 | ||
17 | #define IMA_COUNT_LEAVE 0 | ||
18 | |||
16 | #ifdef CONFIG_IMA | 19 | #ifdef CONFIG_IMA |
17 | extern int ima_bprm_check(struct linux_binprm *bprm); | 20 | extern int ima_bprm_check(struct linux_binprm *bprm); |
18 | extern int ima_inode_alloc(struct inode *inode); | 21 | extern int ima_inode_alloc(struct inode *inode); |
19 | extern void ima_inode_free(struct inode *inode); | 22 | extern void ima_inode_free(struct inode *inode); |
20 | extern int ima_path_check(struct path *path, int mask); | 23 | extern int ima_path_check(struct path *path, int mask, int update_counts); |
21 | extern void ima_file_free(struct file *file); | 24 | extern void ima_file_free(struct file *file); |
22 | extern int ima_file_mmap(struct file *file, unsigned long prot); | 25 | extern int ima_file_mmap(struct file *file, unsigned long prot); |
23 | extern void ima_shm_check(struct file *file); | 26 | extern void ima_counts_get(struct file *file); |
24 | 27 | ||
25 | #else | 28 | #else |
26 | static inline int ima_bprm_check(struct linux_binprm *bprm) | 29 | static inline int ima_bprm_check(struct linux_binprm *bprm) |
@@ -38,7 +41,7 @@ static inline void ima_inode_free(struct inode *inode) | |||
38 | return; | 41 | return; |
39 | } | 42 | } |
40 | 43 | ||
41 | static inline int ima_path_check(struct path *path, int mask) | 44 | static inline int ima_path_check(struct path *path, int mask, int update_counts) |
42 | { | 45 | { |
43 | return 0; | 46 | return 0; |
44 | } | 47 | } |
@@ -53,7 +56,7 @@ static inline int ima_file_mmap(struct file *file, unsigned long prot) | |||
53 | return 0; | 56 | return 0; |
54 | } | 57 | } |
55 | 58 | ||
56 | static inline void ima_shm_check(struct file *file) | 59 | static inline void ima_counts_get(struct file *file) |
57 | { | 60 | { |
58 | return; | 61 | return; |
59 | } | 62 | } |
@@ -384,7 +384,7 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params) | |||
384 | error = PTR_ERR(file); | 384 | error = PTR_ERR(file); |
385 | if (IS_ERR(file)) | 385 | if (IS_ERR(file)) |
386 | goto no_file; | 386 | goto no_file; |
387 | ima_shm_check(file); | 387 | ima_counts_get(file); |
388 | 388 | ||
389 | id = ipc_addid(&shm_ids(ns), &shp->shm_perm, ns->shm_ctlmni); | 389 | id = ipc_addid(&shm_ids(ns), &shp->shm_perm, ns->shm_ctlmni); |
390 | if (id < 0) { | 390 | if (id < 0) { |
@@ -891,7 +891,7 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr) | |||
891 | file = alloc_file(path.mnt, path.dentry, f_mode, &shm_file_operations); | 891 | file = alloc_file(path.mnt, path.dentry, f_mode, &shm_file_operations); |
892 | if (!file) | 892 | if (!file) |
893 | goto out_free; | 893 | goto out_free; |
894 | ima_shm_check(file); | 894 | ima_counts_get(file); |
895 | 895 | ||
896 | file->private_data = sfd; | 896 | file->private_data = sfd; |
897 | file->f_mapping = shp->shm_file->f_mapping; | 897 | file->f_mapping = shp->shm_file->f_mapping; |
diff --git a/mm/shmem.c b/mm/shmem.c index b25f95ce3db7..a817f75f1441 100644 --- a/mm/shmem.c +++ b/mm/shmem.c | |||
@@ -2684,7 +2684,7 @@ int shmem_zero_setup(struct vm_area_struct *vma) | |||
2684 | if (IS_ERR(file)) | 2684 | if (IS_ERR(file)) |
2685 | return PTR_ERR(file); | 2685 | return PTR_ERR(file); |
2686 | 2686 | ||
2687 | ima_shm_check(file); | 2687 | ima_counts_get(file); |
2688 | if (vma->vm_file) | 2688 | if (vma->vm_file) |
2689 | fput(vma->vm_file); | 2689 | fput(vma->vm_file); |
2690 | vma->vm_file = file; | 2690 | vma->vm_file = file; |
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index c4228c0eb2d0..a2eb23310eaf 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c | |||
@@ -125,6 +125,15 @@ static int get_path_measurement(struct ima_iint_cache *iint, struct file *file, | |||
125 | return rc; | 125 | return rc; |
126 | } | 126 | } |
127 | 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 | |||
128 | /** | 137 | /** |
129 | * ima_path_check - based on policy, collect/store measurement. | 138 | * ima_path_check - based on policy, collect/store measurement. |
130 | * @path: contains a pointer to the path to be measured | 139 | * @path: contains a pointer to the path to be measured |
@@ -143,7 +152,7 @@ static int get_path_measurement(struct ima_iint_cache *iint, struct file *file, | |||
143 | * Return 0 on success, an error code on failure. | 152 | * Return 0 on success, an error code on failure. |
144 | * (Based on the results of appraise_measurement().) | 153 | * (Based on the results of appraise_measurement().) |
145 | */ | 154 | */ |
146 | int ima_path_check(struct path *path, int mask) | 155 | int ima_path_check(struct path *path, int mask, int update_counts) |
147 | { | 156 | { |
148 | struct inode *inode = path->dentry->d_inode; | 157 | struct inode *inode = path->dentry->d_inode; |
149 | struct ima_iint_cache *iint; | 158 | struct ima_iint_cache *iint; |
@@ -157,11 +166,8 @@ int ima_path_check(struct path *path, int mask) | |||
157 | return 0; | 166 | return 0; |
158 | 167 | ||
159 | mutex_lock(&iint->mutex); | 168 | mutex_lock(&iint->mutex); |
160 | iint->opencount++; | 169 | if (update_counts) |
161 | if ((mask & MAY_WRITE) || (mask == 0)) | 170 | ima_update_counts(iint, mask); |
162 | iint->writecount++; | ||
163 | else if (mask & (MAY_READ | MAY_EXEC)) | ||
164 | iint->readcount++; | ||
165 | 171 | ||
166 | rc = ima_must_measure(iint, inode, MAY_READ, PATH_CHECK); | 172 | rc = ima_must_measure(iint, inode, MAY_READ, PATH_CHECK); |
167 | if (rc < 0) | 173 | if (rc < 0) |
@@ -197,6 +203,7 @@ out: | |||
197 | kref_put(&iint->refcount, iint_free); | 203 | kref_put(&iint->refcount, iint_free); |
198 | return 0; | 204 | return 0; |
199 | } | 205 | } |
206 | EXPORT_SYMBOL_GPL(ima_path_check); | ||
200 | 207 | ||
201 | static int process_measurement(struct file *file, const unsigned char *filename, | 208 | static int process_measurement(struct file *file, const unsigned char *filename, |
202 | int mask, int function) | 209 | int mask, int function) |
@@ -225,7 +232,16 @@ out: | |||
225 | return rc; | 232 | return rc; |
226 | } | 233 | } |
227 | 234 | ||
228 | static void opencount_get(struct file *file) | 235 | /* |
236 | * ima_opens_get - increment file counts | ||
237 | * | ||
238 | * - for IPC shm and shmat file. | ||
239 | * - for nfsd exported files. | ||
240 | * | ||
241 | * Increment the counts for these files to prevent unnecessary | ||
242 | * imbalance messages. | ||
243 | */ | ||
244 | void ima_counts_get(struct file *file) | ||
229 | { | 245 | { |
230 | struct inode *inode = file->f_dentry->d_inode; | 246 | struct inode *inode = file->f_dentry->d_inode; |
231 | struct ima_iint_cache *iint; | 247 | struct ima_iint_cache *iint; |
@@ -237,8 +253,14 @@ static void opencount_get(struct file *file) | |||
237 | return; | 253 | return; |
238 | mutex_lock(&iint->mutex); | 254 | mutex_lock(&iint->mutex); |
239 | iint->opencount++; | 255 | iint->opencount++; |
256 | if ((file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) | ||
257 | iint->readcount++; | ||
258 | |||
259 | if (file->f_mode & FMODE_WRITE) | ||
260 | iint->writecount++; | ||
240 | mutex_unlock(&iint->mutex); | 261 | mutex_unlock(&iint->mutex); |
241 | } | 262 | } |
263 | EXPORT_SYMBOL_GPL(ima_counts_get); | ||
242 | 264 | ||
243 | /** | 265 | /** |
244 | * ima_file_mmap - based on policy, collect/store measurement. | 266 | * ima_file_mmap - based on policy, collect/store measurement. |
@@ -263,18 +285,6 @@ int ima_file_mmap(struct file *file, unsigned long prot) | |||
263 | return 0; | 285 | return 0; |
264 | } | 286 | } |
265 | 287 | ||
266 | /* | ||
267 | * ima_shm_check - IPC shm and shmat create/fput a file | ||
268 | * | ||
269 | * Maintain the opencount for these files to prevent unnecessary | ||
270 | * imbalance messages. | ||
271 | */ | ||
272 | void ima_shm_check(struct file *file) | ||
273 | { | ||
274 | opencount_get(file); | ||
275 | return; | ||
276 | } | ||
277 | |||
278 | /** | 288 | /** |
279 | * ima_bprm_check - based on policy, collect/store measurement. | 289 | * ima_bprm_check - based on policy, collect/store measurement. |
280 | * @bprm: contains the linux_binprm structure | 290 | * @bprm: contains the linux_binprm structure |