Commit ad16ad00c34d3f320a5876b3d711ef6bc81362e1

Authored by Eric Paris
Committed by Linus Torvalds
1 parent 15aac67677

IMA: use inode->i_lock to protect read and write counters

Currently IMA used the iint->mutex to protect the i_readcount and
i_writecount.  This patch uses the inode->i_lock since we are going to
start using in inode objects and that is the most appropriate lock.

Signed-off-by: Eric Paris <eparis@redhat.com>
Acked-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

Showing 2 changed files with 24 additions and 34 deletions Side-by-side Diff

security/integrity/ima/ima.h
... ... @@ -106,6 +106,7 @@
106 106 unsigned char flags;
107 107 u8 digest[IMA_DIGEST_SIZE];
108 108 struct mutex mutex; /* protects: version, flags, digest */
  109 + /* protected by inode->i_lock */
109 110 unsigned int readcount; /* measured files readcount */
110 111 unsigned int writecount;/* measured files writecount */
111 112 struct kref refcount; /* ima_iint_cache reference count */
security/integrity/ima/ima_main.c
... ... @@ -85,42 +85,12 @@
85 85 return found;
86 86 }
87 87  
88   -/* ima_read_write_check - reflect possible reading/writing errors in the PCR.
89   - *
90   - * When opening a file for read, if the file is already open for write,
91   - * the file could change, resulting in a file measurement error.
92   - *
93   - * Opening a file for write, if the file is already open for read, results
94   - * in a time of measure, time of use (ToMToU) error.
95   - *
96   - * In either case invalidate the PCR.
97   - */
98   -enum iint_pcr_error { TOMTOU, OPEN_WRITERS };
99   -static void ima_read_write_check(enum iint_pcr_error error,
100   - struct ima_iint_cache *iint,
101   - struct inode *inode,
102   - const unsigned char *filename)
103   -{
104   - switch (error) {
105   - case TOMTOU:
106   - if (iint->readcount > 0)
107   - ima_add_violation(inode, filename, "invalid_pcr",
108   - "ToMToU");
109   - break;
110   - case OPEN_WRITERS:
111   - if (iint->writecount > 0)
112   - ima_add_violation(inode, filename, "invalid_pcr",
113   - "open_writers");
114   - break;
115   - }
116   -}
117   -
118 88 /*
119 89 * Update the counts given an fmode_t
120 90 */
121 91 static void ima_inc_counts(struct ima_iint_cache *iint, fmode_t mode)
122 92 {
123   - BUG_ON(!mutex_is_locked(&iint->mutex));
  93 + assert_spin_locked(&iint->inode->i_lock);
124 94  
125 95 if ((mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
126 96 iint->readcount++;
... ... @@ -146,6 +116,7 @@
146 116 fmode_t mode = file->f_mode;
147 117 struct ima_iint_cache *iint;
148 118 int rc;
  119 + bool send_tomtou = false, send_writers = false;
149 120  
150 121 if (!iint_initialized || !S_ISREG(inode->i_mode))
151 122 return;
152 123  
153 124  
154 125  
155 126  
156 127  
157 128  
... ... @@ -153,22 +124,35 @@
153 124 if (!iint)
154 125 return;
155 126 mutex_lock(&iint->mutex);
  127 + spin_lock(&inode->i_lock);
  128 +
156 129 if (!ima_initialized)
157 130 goto out;
  131 +
158 132 rc = ima_must_measure(iint, inode, MAY_READ, FILE_CHECK);
159 133 if (rc < 0)
160 134 goto out;
161 135  
162 136 if (mode & FMODE_WRITE) {
163   - ima_read_write_check(TOMTOU, iint, inode, dentry->d_name.name);
  137 + if (iint->readcount)
  138 + send_tomtou = true;
164 139 goto out;
165 140 }
166   - ima_read_write_check(OPEN_WRITERS, iint, inode, dentry->d_name.name);
  141 +
  142 + if (atomic_read(&inode->i_writecount) > 0)
  143 + send_writers = true;
167 144 out:
168 145 ima_inc_counts(iint, file->f_mode);
  146 + spin_unlock(&inode->i_lock);
169 147 mutex_unlock(&iint->mutex);
170   -
171 148 kref_put(&iint->refcount, iint_free);
  149 +
  150 + if (send_tomtou)
  151 + ima_add_violation(inode, dentry->d_name.name, "invalid_pcr",
  152 + "ToMToU");
  153 + if (send_writers)
  154 + ima_add_violation(inode, dentry->d_name.name, "invalid_pcr",
  155 + "open_writers");
172 156 }
173 157  
174 158 /*
... ... @@ -181,6 +165,7 @@
181 165 bool dump = false;
182 166  
183 167 BUG_ON(!mutex_is_locked(&iint->mutex));
  168 + assert_spin_locked(&inode->i_lock);
184 169  
185 170 if ((mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) {
186 171 if (unlikely(iint->readcount == 0))
187 172  
... ... @@ -223,7 +208,11 @@
223 208 return;
224 209  
225 210 mutex_lock(&iint->mutex);
  211 + spin_lock(&inode->i_lock);
  212 +
226 213 ima_dec_counts(iint, inode, file);
  214 +
  215 + spin_unlock(&inode->i_lock);
227 216 mutex_unlock(&iint->mutex);
228 217 kref_put(&iint->refcount, iint_free);
229 218 }