diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-07 11:41:15 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-07 11:41:15 -0700 |
commit | 755ae761c5519929a97567d61a379b87352c337c (patch) | |
tree | 6942ac77009d3cab1acf6e6bea8cc339368423a9 | |
parent | 4886b5b485ec78fe4a16fedaccfab39bdf55410f (diff) | |
parent | acd0c935178649f72c44ec49ca83bee35ce1f79e (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/security-testing-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/security-testing-2.6:
IMA: update ima_counts_put
-rw-r--r-- | fs/namei.c | 22 | ||||
-rw-r--r-- | security/integrity/ima/ima_main.c | 6 |
2 files changed, 20 insertions, 8 deletions
diff --git a/fs/namei.c b/fs/namei.c index f3c5b278895..1f13751693a 100644 --- a/fs/namei.c +++ b/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. */ 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; } /* diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 4732f5e5d12..b85e61bcf24 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -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) |