aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMimi Zohar <zohar@linux.vnet.ibm.com>2009-09-04 13:08:46 -0400
committerJames Morris <jmorris@namei.org>2009-09-06 21:54:58 -0400
commitacd0c935178649f72c44ec49ca83bee35ce1f79e (patch)
treec0cb2f8fbbaa54567785b5430e5be8c8b51f5724
parente07cccf4046978df10f2e13fe2b99b2f9b3a65db (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.c22
-rw-r--r--security/integrity/ima/ima_main.c6
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;
1593err_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)