Commit 890275b5eb79e9933d12290473eab9ac38da0051
1 parent
a5c96ebf1d
Exists in
master
and in
4 other branches
IMA: maintain i_readcount in the VFS layer
ima_counts_get() updated the readcount and invalidated the PCR, as necessary. Only update the i_readcount in the VFS layer. Move the PCR invalidation checks to ima_file_check(), where it belongs. Maintaining the i_readcount in the VFS layer, will allow other subsystems to use i_readcount. Signed-off-by: Mimi Zohar <zohar@us.ibm.com> Acked-by: Eric Paris <eparis@redhat.com>
Showing 5 changed files with 14 additions and 27 deletions Side-by-side Diff
fs/file_table.c
... | ... | @@ -190,7 +190,8 @@ |
190 | 190 | file_take_write(file); |
191 | 191 | WARN_ON(mnt_clone_write(path->mnt)); |
192 | 192 | } |
193 | - ima_counts_get(file); | |
193 | + if ((mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) | |
194 | + i_readcount_inc(path->dentry->d_inode); | |
194 | 195 | return file; |
195 | 196 | } |
196 | 197 | EXPORT_SYMBOL(alloc_file); |
... | ... | @@ -251,6 +252,8 @@ |
251 | 252 | fops_put(file->f_op); |
252 | 253 | put_pid(file->f_owner.pid); |
253 | 254 | file_sb_list_del(file); |
255 | + if ((file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) | |
256 | + i_readcount_dec(inode); | |
254 | 257 | if (file->f_mode & FMODE_WRITE) |
255 | 258 | drop_file_write_access(file); |
256 | 259 | file->f_path.dentry = NULL; |
fs/open.c
include/linux/ima.h
... | ... | @@ -20,7 +20,6 @@ |
20 | 20 | extern int ima_file_check(struct file *file, int mask); |
21 | 21 | extern void ima_file_free(struct file *file); |
22 | 22 | extern int ima_file_mmap(struct file *file, unsigned long prot); |
23 | -extern void ima_counts_get(struct file *file); | |
24 | 23 | |
25 | 24 | #else |
26 | 25 | static inline int ima_bprm_check(struct linux_binprm *bprm) |
... | ... | @@ -51,11 +50,6 @@ |
51 | 50 | static inline int ima_file_mmap(struct file *file, unsigned long prot) |
52 | 51 | { |
53 | 52 | return 0; |
54 | -} | |
55 | - | |
56 | -static inline void ima_counts_get(struct file *file) | |
57 | -{ | |
58 | - return; | |
59 | 53 | } |
60 | 54 | |
61 | 55 | #endif /* CONFIG_IMA_H */ |
security/integrity/ima/ima_iint.c
security/integrity/ima/ima_main.c
... | ... | @@ -86,17 +86,16 @@ |
86 | 86 | } |
87 | 87 | |
88 | 88 | /* |
89 | - * ima_counts_get - increment file counts | |
89 | + * ima_rdwr_violation_check | |
90 | 90 | * |
91 | - * Maintain read/write counters for all files, but only | |
92 | - * invalidate the PCR for measured files: | |
91 | + * Only invalidate the PCR for measured files: | |
93 | 92 | * - Opening a file for write when already open for read, |
94 | 93 | * results in a time of measure, time of use (ToMToU) error. |
95 | 94 | * - Opening a file for read when already open for write, |
96 | 95 | * could result in a file measurement error. |
97 | 96 | * |
98 | 97 | */ |
99 | -void ima_counts_get(struct file *file) | |
98 | +static void ima_rdwr_violation_check(struct file *file) | |
100 | 99 | { |
101 | 100 | struct dentry *dentry = file->f_path.dentry; |
102 | 101 | struct inode *inode = dentry->d_inode; |
103 | 102 | |
104 | 103 | |
... | ... | @@ -104,14 +103,11 @@ |
104 | 103 | int rc; |
105 | 104 | bool send_tomtou = false, send_writers = false; |
106 | 105 | |
107 | - if (!S_ISREG(inode->i_mode)) | |
106 | + if (!S_ISREG(inode->i_mode) || !ima_initialized) | |
108 | 107 | return; |
109 | 108 | |
110 | - spin_lock(&inode->i_lock); | |
109 | + mutex_lock(&inode->i_mutex); /* file metadata: permissions, xattr */ | |
111 | 110 | |
112 | - if (!ima_initialized) | |
113 | - goto out; | |
114 | - | |
115 | 111 | if (mode & FMODE_WRITE) { |
116 | 112 | if (atomic_read(&inode->i_readcount) && IS_IMA(inode)) |
117 | 113 | send_tomtou = true; |
118 | 114 | |
... | ... | @@ -125,12 +121,8 @@ |
125 | 121 | if (atomic_read(&inode->i_writecount) > 0) |
126 | 122 | send_writers = true; |
127 | 123 | out: |
128 | - /* remember the vfs deals with i_writecount */ | |
129 | - if ((mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) | |
130 | - atomic_inc(&inode->i_readcount); | |
124 | + mutex_unlock(&inode->i_mutex); | |
131 | 125 | |
132 | - spin_unlock(&inode->i_lock); | |
133 | - | |
134 | 126 | if (send_tomtou) |
135 | 127 | ima_add_violation(inode, dentry->d_name.name, "invalid_pcr", |
136 | 128 | "ToMToU"); |
... | ... | @@ -158,7 +150,6 @@ |
158 | 150 | } |
159 | 151 | return; |
160 | 152 | } |
161 | - atomic_dec(&inode->i_readcount); | |
162 | 153 | } |
163 | 154 | } |
164 | 155 | |
... | ... | @@ -203,8 +194,7 @@ |
203 | 194 | * ima_file_free - called on __fput() |
204 | 195 | * @file: pointer to file structure being freed |
205 | 196 | * |
206 | - * Flag files that changed, based on i_version; | |
207 | - * and decrement the i_readcount. | |
197 | + * Flag files that changed, based on i_version | |
208 | 198 | */ |
209 | 199 | void ima_file_free(struct file *file) |
210 | 200 | { |
... | ... | @@ -318,6 +308,7 @@ |
318 | 308 | { |
319 | 309 | int rc; |
320 | 310 | |
311 | + ima_rdwr_violation_check(file); | |
321 | 312 | rc = process_measurement(file, file->f_dentry->d_name.name, |
322 | 313 | mask & (MAY_READ | MAY_WRITE | MAY_EXEC), |
323 | 314 | FILE_CHECK); |