Commit db1d1e8b authored by Jeff Layton's avatar Jeff Layton Committed by Mimi Zohar
Browse files

IMA: use vfs_getattr_nosec to get the i_version



IMA currently accesses the i_version out of the inode directly when it
does a measurement. This is fine for most simple filesystems, but can be
problematic with more complex setups (e.g. overlayfs).

Make IMA instead call vfs_getattr_nosec to get this info. This allows
the filesystem to determine whether and how to report the i_version, and
should allow IMA to work properly with a broader class of filesystems in
the future.

Reported-and-Tested-by: default avatarStefan Berger <stefanb@linux.ibm.com>
Reviewed-by: default avatarChristian Brauner <brauner@kernel.org>
Signed-off-by: default avatarJeff Layton <jlayton@kernel.org>
Signed-off-by: default avatarMimi Zohar <zohar@linux.ibm.com>
parent f1fcbaa1
Loading
Loading
Loading
Loading
+6 −3
Original line number Diff line number Diff line
@@ -13,7 +13,6 @@
#include <linux/fs.h>
#include <linux/xattr.h>
#include <linux/evm.h>
#include <linux/iversion.h>
#include <linux/fsverity.h>

#include "ima.h"
@@ -246,10 +245,11 @@ int ima_collect_measurement(struct integrity_iint_cache *iint,
	struct inode *inode = file_inode(file);
	const char *filename = file->f_path.dentry->d_name.name;
	struct ima_max_digest_data hash;
	struct kstat stat;
	int result = 0;
	int length;
	void *tmpbuf;
	u64 i_version;
	u64 i_version = 0;

	/*
	 * Always collect the modsig, because IMA might have already collected
@@ -268,7 +268,10 @@ int ima_collect_measurement(struct integrity_iint_cache *iint,
	 * to an initial measurement/appraisal/audit, but was modified to
	 * assume the file changed.
	 */
	i_version = inode_query_iversion(inode);
	result = vfs_getattr_nosec(&file->f_path, &stat, STATX_CHANGE_COOKIE,
				   AT_STATX_SYNC_AS_STAT);
	if (!result && (stat.result_mask & STATX_CHANGE_COOKIE))
		i_version = stat.change_cookie;
	hash.hdr.algo = algo;
	hash.hdr.length = hash_digest_size[algo];

+8 −4
Original line number Diff line number Diff line
@@ -24,7 +24,6 @@
#include <linux/slab.h>
#include <linux/xattr.h>
#include <linux/ima.h>
#include <linux/iversion.h>
#include <linux/fs.h>

#include "ima.h"
@@ -164,11 +163,16 @@ static void ima_check_last_writer(struct integrity_iint_cache *iint,

	mutex_lock(&iint->mutex);
	if (atomic_read(&inode->i_writecount) == 1) {
		struct kstat stat;

		update = test_and_clear_bit(IMA_UPDATE_XATTR,
					    &iint->atomic_flags);
		if (!IS_I_VERSION(inode) ||
		    !inode_eq_iversion(inode, iint->version) ||
		    (iint->flags & IMA_NEW_FILE)) {
		if ((iint->flags & IMA_NEW_FILE) ||
		    vfs_getattr_nosec(&file->f_path, &stat,
				      STATX_CHANGE_COOKIE,
				      AT_STATX_SYNC_AS_STAT) ||
		    !(stat.result_mask & STATX_CHANGE_COOKIE) ||
		    stat.change_cookie != iint->version) {
			iint->flags &= ~(IMA_DONE_MASK | IMA_NEW_FILE);
			iint->measured_pcrs = 0;
			if (update)