Commit 890275b5eb79e9933d12290473eab9ac38da0051

Authored by Mimi Zohar
1 parent a5c96ebf1d

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

... ... @@ -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;
... ... @@ -688,7 +688,8 @@
688 688 if (error)
689 689 goto cleanup_all;
690 690 }
691   - ima_counts_get(f);
  691 + if ((f->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
  692 + i_readcount_inc(inode);
692 693  
693 694 f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
694 695  
... ... @@ -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
... ... @@ -141,8 +141,6 @@
141 141 printk(KERN_INFO "%s: readcount: %u\n", __func__,
142 142 atomic_read(&inode->i_readcount));
143 143  
144   - atomic_set(&inode->i_readcount, 0);
145   -
146 144 if (!IS_IMA(inode))
147 145 return;
148 146  
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);