Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

ima: fallback to using i_version to detect file change

Commit db1d1e8b9867 ("IMA: use vfs_getattr_nosec to get the i_version")
replaced detecting file change based on i_version with
STATX_CHANGE_COOKIE.

On filesystems without STATX_CHANGE_COOKIE enabled, revert back to
detecting file change based on i_version.

On filesystems which do not support either, assume the file changed.

Reported-by: Frederick Lawler <fred@cloudflare.com>
Fixes: db1d1e8b9867 ("IMA: use vfs_getattr_nosec to get the i_version")
Cc: stable@vger.kernel.org
Reviewed-by: Frederick Lawler <fred@cloudflare.com>
Tested-by: Frederick Lawler <fred@cloudflare.com>
Signed-off-by: Mimi Zohar <zohar@linux.ibm.com>

+35 -12
+9 -4
security/integrity/ima/ima_api.c
··· 269 269 goto out; 270 270 271 271 /* 272 - * Detecting file change is based on i_version. On filesystems 273 - * which do not support i_version, support was originally limited 274 - * to an initial measurement/appraisal/audit, but was modified to 275 - * assume the file changed. 272 + * Detect file change based on STATX_CHANGE_COOKIE, when supported, 273 + * and fallback to detecting file change based on i_version. 274 + * 275 + * On filesystems which did not support i_version, support was 276 + * originally limited to an initial measurement/appraisal/audit, 277 + * but was later modified to assume the file changed. 276 278 */ 277 279 result = vfs_getattr_nosec(&file->f_path, &stat, STATX_CHANGE_COOKIE, 278 280 AT_STATX_SYNC_AS_STAT); 279 281 if (!result && (stat.result_mask & STATX_CHANGE_COOKIE)) 280 282 i_version = stat.change_cookie; 283 + else if (IS_I_VERSION(real_inode)) 284 + i_version = inode_peek_iversion(real_inode); 285 + 281 286 hash.hdr.algo = algo; 282 287 hash.hdr.length = hash_digest_size[algo]; 283 288
+26 -8
security/integrity/ima/ima_main.c
··· 180 180 "invalid_pcr", "open_writers"); 181 181 } 182 182 183 + /* 184 + * Detect file change based on STATX_CHANGE_COOKIE, when supported, and 185 + * fallback to detecting file change based on i_version. On filesystems 186 + * which do not support either, assume the file changed. 187 + */ 188 + static bool ima_detect_file_change(struct ima_iint_cache *iint, 189 + struct inode *inode, struct file *file) 190 + { 191 + struct kstat stat; 192 + int result; 193 + 194 + result = vfs_getattr_nosec(&file->f_path, &stat, STATX_CHANGE_COOKIE, 195 + AT_STATX_SYNC_AS_STAT); 196 + 197 + if (!result && stat.result_mask & STATX_CHANGE_COOKIE) 198 + return stat.change_cookie != iint->real_inode.version; 199 + 200 + if (IS_I_VERSION(inode)) 201 + return !inode_eq_iversion(inode, iint->real_inode.version); 202 + 203 + return true; 204 + } 205 + 183 206 static void ima_check_last_writer(struct ima_iint_cache *iint, 184 207 struct inode *inode, struct file *file) 185 208 { ··· 214 191 215 192 mutex_lock(&iint->mutex); 216 193 if (atomic_read(&inode->i_writecount) == 1) { 217 - struct kstat stat; 218 - 219 194 clear_bit(IMA_EMITTED_OPENWRITERS, &iint->atomic_flags); 220 195 221 196 update = test_and_clear_bit(IMA_UPDATE_XATTR, 222 197 &iint->atomic_flags); 223 - if ((iint->flags & IMA_NEW_FILE) || 224 - vfs_getattr_nosec(&file->f_path, &stat, 225 - STATX_CHANGE_COOKIE, 226 - AT_STATX_SYNC_AS_STAT) || 227 - !(stat.result_mask & STATX_CHANGE_COOKIE) || 228 - stat.change_cookie != iint->real_inode.version) { 198 + 199 + if (iint->flags & IMA_NEW_FILE || 200 + ima_detect_file_change(iint, inode, file)) { 229 201 iint->flags &= ~(IMA_DONE_MASK | IMA_NEW_FILE); 230 202 iint->measured_pcrs = 0; 231 203 if (update)