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

ima: Move file-change detection variables into new structure

Move all the variables used for file change detection into a structure
that can be used by IMA and EVM. Implement an inline function for storing
the identification of an inode and one for detecting changes to an inode
based on this new structure.

Co-developed-by: Mimi Zohar <zohar@linux.ibm.com>
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Signed-off-by: Mimi Zohar <zohar@linux.ibm.com>

authored by

Stefan Berger and committed by
Mimi Zohar
309e2b77 faf99481

+44 -13
+34
include/linux/integrity.h
··· 8 8 #define _LINUX_INTEGRITY_H 9 9 10 10 #include <linux/fs.h> 11 + #include <linux/iversion.h> 11 12 12 13 enum integrity_status { 13 14 INTEGRITY_PASS = 0, ··· 28 27 { 29 28 } 30 29 #endif /* CONFIG_INTEGRITY */ 30 + 31 + /* An inode's attributes for detection of changes */ 32 + struct integrity_inode_attributes { 33 + u64 version; /* track inode changes */ 34 + unsigned long ino; 35 + dev_t dev; 36 + }; 37 + 38 + /* 39 + * On stacked filesystems the i_version alone is not enough to detect file data 40 + * or metadata change. Additional metadata is required. 41 + */ 42 + static inline void 43 + integrity_inode_attrs_store(struct integrity_inode_attributes *attrs, 44 + u64 i_version, const struct inode *inode) 45 + { 46 + attrs->version = i_version; 47 + attrs->dev = inode->i_sb->s_dev; 48 + attrs->ino = inode->i_ino; 49 + } 50 + 51 + /* 52 + * On stacked filesystems detect whether the inode or its content has changed. 53 + */ 54 + static inline bool 55 + integrity_inode_attrs_changed(const struct integrity_inode_attributes *attrs, 56 + const struct inode *inode) 57 + { 58 + return (inode->i_sb->s_dev != attrs->dev || 59 + inode->i_ino != attrs->ino || 60 + !inode_eq_iversion(inode, attrs->version)); 61 + } 62 + 31 63 32 64 #endif /* _LINUX_INTEGRITY_H */
+1 -3
security/integrity/ima/ima.h
··· 175 175 /* IMA integrity metadata associated with an inode */ 176 176 struct ima_iint_cache { 177 177 struct mutex mutex; /* protects: version, flags, digest */ 178 - u64 version; /* track inode changes */ 178 + struct integrity_inode_attributes real_inode; 179 179 unsigned long flags; 180 180 unsigned long measured_pcrs; 181 181 unsigned long atomic_flags; 182 - unsigned long real_ino; 183 - dev_t real_dev; 184 182 enum integrity_status ima_file_status:4; 185 183 enum integrity_status ima_mmap_status:4; 186 184 enum integrity_status ima_bprm_status:4;
+5 -5
security/integrity/ima/ima_api.c
··· 305 305 306 306 iint->ima_hash = tmpbuf; 307 307 memcpy(iint->ima_hash, &hash, length); 308 - iint->version = i_version; 309 - if (real_inode != inode) { 310 - iint->real_ino = real_inode->i_ino; 311 - iint->real_dev = real_inode->i_sb->s_dev; 312 - } 308 + if (real_inode == inode) 309 + iint->real_inode.version = i_version; 310 + else 311 + integrity_inode_attrs_store(&iint->real_inode, i_version, 312 + real_inode); 313 313 314 314 /* Possibly temporary failure due to type of read (eg. O_DIRECT) */ 315 315 if (!result)
+1 -1
security/integrity/ima/ima_iint.c
··· 59 59 struct inode *inode) 60 60 { 61 61 iint->ima_hash = NULL; 62 - iint->version = 0; 62 + iint->real_inode.version = 0; 63 63 iint->flags = 0UL; 64 64 iint->atomic_flags = 0UL; 65 65 iint->ima_file_status = INTEGRITY_UNKNOWN;
+3 -4
security/integrity/ima/ima_main.c
··· 173 173 STATX_CHANGE_COOKIE, 174 174 AT_STATX_SYNC_AS_STAT) || 175 175 !(stat.result_mask & STATX_CHANGE_COOKIE) || 176 - stat.change_cookie != iint->version) { 176 + stat.change_cookie != iint->real_inode.version) { 177 177 iint->flags &= ~(IMA_DONE_MASK | IMA_NEW_FILE); 178 178 iint->measured_pcrs = 0; 179 179 if (update) ··· 292 292 if (real_inode != inode && 293 293 (action & IMA_DO_MASK) && (iint->flags & IMA_DONE_MASK)) { 294 294 if (!IS_I_VERSION(real_inode) || 295 - real_inode->i_sb->s_dev != iint->real_dev || 296 - real_inode->i_ino != iint->real_ino || 297 - !inode_eq_iversion(real_inode, iint->version)) { 295 + integrity_inode_attrs_changed(&iint->real_inode, 296 + real_inode)) { 298 297 iint->flags &= ~IMA_DONE_MASK; 299 298 iint->measured_pcrs = 0; 300 299 }