diff options
author | Mimi Zohar <zohar@linux.vnet.ibm.com> | 2009-09-04 13:08:46 -0400 |
---|---|---|
committer | James Morris <jmorris@namei.org> | 2009-09-06 21:54:58 -0400 |
commit | acd0c935178649f72c44ec49ca83bee35ce1f79e (patch) | |
tree | c0cb2f8fbbaa54567785b5430e5be8c8b51f5724 | |
parent | e07cccf4046978df10f2e13fe2b99b2f9b3a65db (diff) |
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>
-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 f3c5b278895a..1f13751693a5 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -1542,28 +1542,31 @@ int may_open(struct path *path, int acc_mode, int flag) | |||
1542 | * An append-only file must be opened in append mode for writing. | 1542 | * An append-only file must be opened in append mode for writing. |
1543 | */ | 1543 | */ |
1544 | if (IS_APPEND(inode)) { | 1544 | if (IS_APPEND(inode)) { |
1545 | error = -EPERM; | ||
1545 | if ((flag & FMODE_WRITE) && !(flag & O_APPEND)) | 1546 | if ((flag & FMODE_WRITE) && !(flag & O_APPEND)) |
1546 | return -EPERM; | 1547 | goto err_out; |
1547 | if (flag & O_TRUNC) | 1548 | if (flag & O_TRUNC) |
1548 | return -EPERM; | 1549 | goto err_out; |
1549 | } | 1550 | } |
1550 | 1551 | ||
1551 | /* O_NOATIME can only be set by the owner or superuser */ | 1552 | /* O_NOATIME can only be set by the owner or superuser */ |
1552 | if (flag & O_NOATIME) | 1553 | if (flag & O_NOATIME) |
1553 | if (!is_owner_or_cap(inode)) | 1554 | if (!is_owner_or_cap(inode)) { |
1554 | return -EPERM; | 1555 | error = -EPERM; |
1556 | goto err_out; | ||
1557 | } | ||
1555 | 1558 | ||
1556 | /* | 1559 | /* |
1557 | * Ensure there are no outstanding leases on the file. | 1560 | * Ensure there are no outstanding leases on the file. |
1558 | */ | 1561 | */ |
1559 | error = break_lease(inode, flag); | 1562 | error = break_lease(inode, flag); |
1560 | if (error) | 1563 | if (error) |
1561 | return error; | 1564 | goto err_out; |
1562 | 1565 | ||
1563 | if (flag & O_TRUNC) { | 1566 | if (flag & O_TRUNC) { |
1564 | error = get_write_access(inode); | 1567 | error = get_write_access(inode); |
1565 | if (error) | 1568 | if (error) |
1566 | return error; | 1569 | goto err_out; |
1567 | 1570 | ||
1568 | /* | 1571 | /* |
1569 | * Refuse to truncate files with mandatory locks held on them. | 1572 | * 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) | |||
1581 | } | 1584 | } |
1582 | put_write_access(inode); | 1585 | put_write_access(inode); |
1583 | if (error) | 1586 | if (error) |
1584 | return error; | 1587 | goto err_out; |
1585 | } else | 1588 | } else |
1586 | if (flag & FMODE_WRITE) | 1589 | if (flag & FMODE_WRITE) |
1587 | vfs_dq_init(inode); | 1590 | vfs_dq_init(inode); |
1588 | 1591 | ||
1589 | return 0; | 1592 | return 0; |
1593 | err_out: | ||
1594 | ima_counts_put(path, acc_mode ? | ||
1595 | acc_mode & (MAY_READ | MAY_WRITE | MAY_EXEC) : | ||
1596 | ACC_MODE(flag) & (MAY_READ | MAY_WRITE)); | ||
1597 | return error; | ||
1590 | } | 1598 | } |
1591 | 1599 | ||
1592 | /* | 1600 | /* |
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 4732f5e5d127..b85e61bcf246 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) | |||
249 | struct inode *inode = path->dentry->d_inode; | 249 | struct inode *inode = path->dentry->d_inode; |
250 | struct ima_iint_cache *iint; | 250 | struct ima_iint_cache *iint; |
251 | 251 | ||
252 | if (!ima_initialized || !S_ISREG(inode->i_mode)) | 252 | /* The inode may already have been freed, freeing the iint |
253 | * with it. Verify the inode is not NULL before dereferencing | ||
254 | * it. | ||
255 | */ | ||
256 | if (!ima_initialized || !inode || !S_ISREG(inode->i_mode)) | ||
253 | return; | 257 | return; |
254 | iint = ima_iint_find_insert_get(inode); | 258 | iint = ima_iint_find_insert_get(inode); |
255 | if (!iint) | 259 | if (!iint) |