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: Ciprian Docan <docan@eden.rutgers.edu> Reported-by: J.R. Okajima <hooanon05@yahoo.co.jp> Signed-off-by: Mimi Zohar <zohar@us.ibm.com> Acked-by: Eric Paris <eparis@redhat.com Signed-off-by: James Morris <jmorris@namei.org>
This commit is contained in:
parent
e07cccf404
commit
acd0c93517
2 changed files with 20 additions and 8 deletions
22
fs/namei.c
22
fs/namei.c
|
@ -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.
|
* An append-only file must be opened in append mode for writing.
|
||||||
*/
|
*/
|
||||||
if (IS_APPEND(inode)) {
|
if (IS_APPEND(inode)) {
|
||||||
|
error = -EPERM;
|
||||||
if ((flag & FMODE_WRITE) && !(flag & O_APPEND))
|
if ((flag & FMODE_WRITE) && !(flag & O_APPEND))
|
||||||
return -EPERM;
|
goto err_out;
|
||||||
if (flag & O_TRUNC)
|
if (flag & O_TRUNC)
|
||||||
return -EPERM;
|
goto err_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* O_NOATIME can only be set by the owner or superuser */
|
/* O_NOATIME can only be set by the owner or superuser */
|
||||||
if (flag & O_NOATIME)
|
if (flag & O_NOATIME)
|
||||||
if (!is_owner_or_cap(inode))
|
if (!is_owner_or_cap(inode)) {
|
||||||
return -EPERM;
|
error = -EPERM;
|
||||||
|
goto err_out;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Ensure there are no outstanding leases on the file.
|
* Ensure there are no outstanding leases on the file.
|
||||||
*/
|
*/
|
||||||
error = break_lease(inode, flag);
|
error = break_lease(inode, flag);
|
||||||
if (error)
|
if (error)
|
||||||
return error;
|
goto err_out;
|
||||||
|
|
||||||
if (flag & O_TRUNC) {
|
if (flag & O_TRUNC) {
|
||||||
error = get_write_access(inode);
|
error = get_write_access(inode);
|
||||||
if (error)
|
if (error)
|
||||||
return error;
|
goto err_out;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Refuse to truncate files with mandatory locks held on them.
|
* 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);
|
put_write_access(inode);
|
||||||
if (error)
|
if (error)
|
||||||
return error;
|
goto err_out;
|
||||||
} else
|
} else
|
||||||
if (flag & FMODE_WRITE)
|
if (flag & FMODE_WRITE)
|
||||||
vfs_dq_init(inode);
|
vfs_dq_init(inode);
|
||||||
|
|
||||||
return 0;
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -249,7 +249,11 @@ void ima_counts_put(struct path *path, int mask)
|
||||||
struct inode *inode = path->dentry->d_inode;
|
struct inode *inode = path->dentry->d_inode;
|
||||||
struct ima_iint_cache *iint;
|
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;
|
return;
|
||||||
iint = ima_iint_find_insert_get(inode);
|
iint = ima_iint_find_insert_get(inode);
|
||||||
if (!iint)
|
if (!iint)
|
||||||
|
|
Loading…
Reference in a new issue