Skip to content

Commit 309e2b7

Browse files
stefanbergermimizohar
authored andcommitted
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>
1 parent faf9948 commit 309e2b7

File tree

5 files changed

+44
-13
lines changed

5 files changed

+44
-13
lines changed

include/linux/integrity.h

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#define _LINUX_INTEGRITY_H
99

1010
#include <linux/fs.h>
11+
#include <linux/iversion.h>
1112

1213
enum integrity_status {
1314
INTEGRITY_PASS = 0,
@@ -28,4 +29,37 @@ static inline void integrity_load_keys(void)
2829
}
2930
#endif /* CONFIG_INTEGRITY */
3031

32+
/* An inode's attributes for detection of changes */
33+
struct integrity_inode_attributes {
34+
u64 version; /* track inode changes */
35+
unsigned long ino;
36+
dev_t dev;
37+
};
38+
39+
/*
40+
* On stacked filesystems the i_version alone is not enough to detect file data
41+
* or metadata change. Additional metadata is required.
42+
*/
43+
static inline void
44+
integrity_inode_attrs_store(struct integrity_inode_attributes *attrs,
45+
u64 i_version, const struct inode *inode)
46+
{
47+
attrs->version = i_version;
48+
attrs->dev = inode->i_sb->s_dev;
49+
attrs->ino = inode->i_ino;
50+
}
51+
52+
/*
53+
* On stacked filesystems detect whether the inode or its content has changed.
54+
*/
55+
static inline bool
56+
integrity_inode_attrs_changed(const struct integrity_inode_attributes *attrs,
57+
const struct inode *inode)
58+
{
59+
return (inode->i_sb->s_dev != attrs->dev ||
60+
inode->i_ino != attrs->ino ||
61+
!inode_eq_iversion(inode, attrs->version));
62+
}
63+
64+
3165
#endif /* _LINUX_INTEGRITY_H */

security/integrity/ima/ima.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -175,12 +175,10 @@ struct ima_kexec_hdr {
175175
/* IMA integrity metadata associated with an inode */
176176
struct ima_iint_cache {
177177
struct mutex mutex; /* protects: version, flags, digest */
178-
u64 version; /* track inode changes */
178+
struct integrity_inode_attributes real_inode;
179179
unsigned long flags;
180180
unsigned long measured_pcrs;
181181
unsigned long atomic_flags;
182-
unsigned long real_ino;
183-
dev_t real_dev;
184182
enum integrity_status ima_file_status:4;
185183
enum integrity_status ima_mmap_status:4;
186184
enum integrity_status ima_bprm_status:4;

security/integrity/ima/ima_api.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -305,11 +305,11 @@ int ima_collect_measurement(struct ima_iint_cache *iint, struct file *file,
305305

306306
iint->ima_hash = tmpbuf;
307307
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);
313313

314314
/* Possibly temporary failure due to type of read (eg. O_DIRECT) */
315315
if (!result)

security/integrity/ima/ima_iint.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ static void ima_iint_init_always(struct ima_iint_cache *iint,
5959
struct inode *inode)
6060
{
6161
iint->ima_hash = NULL;
62-
iint->version = 0;
62+
iint->real_inode.version = 0;
6363
iint->flags = 0UL;
6464
iint->atomic_flags = 0UL;
6565
iint->ima_file_status = INTEGRITY_UNKNOWN;

security/integrity/ima/ima_main.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ static void ima_check_last_writer(struct ima_iint_cache *iint,
173173
STATX_CHANGE_COOKIE,
174174
AT_STATX_SYNC_AS_STAT) ||
175175
!(stat.result_mask & STATX_CHANGE_COOKIE) ||
176-
stat.change_cookie != iint->version) {
176+
stat.change_cookie != iint->real_inode.version) {
177177
iint->flags &= ~(IMA_DONE_MASK | IMA_NEW_FILE);
178178
iint->measured_pcrs = 0;
179179
if (update)
@@ -292,9 +292,8 @@ static int process_measurement(struct file *file, const struct cred *cred,
292292
if (real_inode != inode &&
293293
(action & IMA_DO_MASK) && (iint->flags & IMA_DONE_MASK)) {
294294
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)) {
298297
iint->flags &= ~IMA_DONE_MASK;
299298
iint->measured_pcrs = 0;
300299
}

0 commit comments

Comments
 (0)