Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit acd0c935 authored by Mimi Zohar's avatar Mimi Zohar Committed by James Morris
Browse files

IMA: update ima_counts_put



- As ima_counts_put() may be called after the inode has been freed,
verify that the inode is not NULL, before dereferencing it.

- Maintain the IMA file counters in may_open() properly, decrementing
any counter increments on subsequent errors.

Reported-by: default avatarCiprian Docan <docan@eden.rutgers.edu>
Reported-by: default avatarJ.R. Okajima <hooanon05@yahoo.co.jp>
Signed-off-by: default avatarMimi Zohar <zohar@us.ibm.com>
Acked-by: default avatarEric Paris <eparis@redhat.com>
Signed-off-by: default avatarJames Morris <jmorris@namei.org>
parent e07cccf4
Loading
Loading
Loading
Loading
+15 −7
Original line number Diff line number Diff line
@@ -1542,28 +1542,31 @@ int may_open(struct path *path, int acc_mode, int flag)
	 * An append-only file must be opened in append mode for writing.
	 */
	if (IS_APPEND(inode)) {
		error = -EPERM;
		if  ((flag & FMODE_WRITE) && !(flag & O_APPEND))
			return -EPERM;
			goto err_out;
		if (flag & O_TRUNC)
			return -EPERM;
			goto err_out;
	}

	/* O_NOATIME can only be set by the owner or superuser */
	if (flag & O_NOATIME)
		if (!is_owner_or_cap(inode))
			return -EPERM;
		if (!is_owner_or_cap(inode)) {
			error = -EPERM;
			goto err_out;
		}

	/*
	 * Ensure there are no outstanding leases on the file.
	 */
	error = break_lease(inode, flag);
	if (error)
		return error;
		goto err_out;

	if (flag & O_TRUNC) {
		error = get_write_access(inode);
		if (error)
			return error;
			goto err_out;

		/*
		 * Refuse to truncate files with mandatory locks held on them.
@@ -1581,12 +1584,17 @@ int may_open(struct path *path, int acc_mode, int flag)
		}
		put_write_access(inode);
		if (error)
			return error;
			goto err_out;
	} else
		if (flag & FMODE_WRITE)
			vfs_dq_init(inode);

	return 0;
err_out:
	ima_counts_put(path, acc_mode ?
		       acc_mode & (MAY_READ | MAY_WRITE | MAY_EXEC) :
		       ACC_MODE(flag) & (MAY_READ | MAY_WRITE));
	return error;
}

/*
+5 −1
Original line number Diff line number Diff line
@@ -249,7 +249,11 @@ void ima_counts_put(struct path *path, int mask)
	struct inode *inode = path->dentry->d_inode;
	struct ima_iint_cache *iint;

	if (!ima_initialized || !S_ISREG(inode->i_mode))
	/* The inode may already have been freed, freeing the iint
	 * with it. Verify the inode is not NULL before dereferencing
	 * it.
	 */
	if (!ima_initialized || !inode || !S_ISREG(inode->i_mode))
		return;
	iint = ima_iint_find_insert_get(inode);
	if (!iint)