Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 217418
b: refs/heads/master
c: bc7d2a3
h: refs/heads/master
v: v3
  • Loading branch information
Eric Paris authored and Linus Torvalds committed Oct 26, 2010
1 parent 404961a commit 36172ac
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 40 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: a178d2027d3198b0a04517d764326ab71cd73da2
refs/heads/master: bc7d2a3e66b40477270c3cbe3b89b47093276e7a
94 changes: 64 additions & 30 deletions trunk/security/integrity/ima/ima_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -141,41 +141,70 @@ void ima_counts_get(struct file *file)
/*
* Decrement ima counts
*/
static void ima_dec_counts(struct ima_iint_cache *iint, struct inode *inode,
struct file *file)
static void ima_dec_counts(struct inode *inode, struct file *file)
{
mode_t mode = file->f_mode;
bool dump = false;

BUG_ON(!mutex_is_locked(&iint->mutex));
assert_spin_locked(&inode->i_lock);

if ((mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) {
if (unlikely(inode->i_readcount == 0))
dump = true;
if (unlikely(inode->i_readcount == 0)) {
if (!ima_limit_imbalance(file)) {
printk(KERN_INFO "%s: open/free imbalance (r:%u)\n",
__func__, inode->i_readcount);
dump_stack();
}
return;
}
inode->i_readcount--;
}
if (mode & FMODE_WRITE) {
if (atomic_read(&inode->i_writecount) <= 0)
dump = true;
if (atomic_read(&inode->i_writecount) == 1 &&
iint->version != inode->i_version)
iint->flags &= ~IMA_MEASURED;
}
}

if (dump && !ima_limit_imbalance(file)) {
printk(KERN_INFO "%s: open/free imbalance (r:%u)\n",
__func__, inode->i_readcount);
dump_stack();
}
static void ima_check_last_writer(struct ima_iint_cache *iint,
struct inode *inode,
struct file *file)
{
mode_t mode = file->f_mode;

BUG_ON(!mutex_is_locked(&iint->mutex));
assert_spin_locked(&inode->i_lock);

if (mode & FMODE_WRITE &&
atomic_read(&inode->i_writecount) == 1 &&
iint->version != inode->i_version)
iint->flags &= ~IMA_MEASURED;
}

static void ima_file_free_iint(struct ima_iint_cache *iint, struct inode *inode,
struct file *file)
{
mutex_lock(&iint->mutex);
spin_lock(&inode->i_lock);

ima_dec_counts(inode, file);
ima_check_last_writer(iint, inode, file);

spin_unlock(&inode->i_lock);
mutex_unlock(&iint->mutex);

kref_put(&iint->refcount, iint_free);
}

static void ima_file_free_noiint(struct inode *inode, struct file *file)
{
spin_lock(&inode->i_lock);

ima_dec_counts(inode, file);

spin_unlock(&inode->i_lock);
}

/**
* ima_file_free - called on __fput()
* @file: pointer to file structure being freed
*
* Flag files that changed, based on i_version;
* and decrement the iint readcount/writecount.
* and decrement the i_readcount.
*/
void ima_file_free(struct file *file)
{
Expand All @@ -185,17 +214,12 @@ void ima_file_free(struct file *file)
if (!iint_initialized || !S_ISREG(inode->i_mode))
return;
iint = ima_iint_find_get(inode);
if (!iint)
return;

mutex_lock(&iint->mutex);
spin_lock(&inode->i_lock);

ima_dec_counts(iint, inode, file);
if (iint)
ima_file_free_iint(iint, inode, file);
else
ima_file_free_noiint(inode, file);

spin_unlock(&inode->i_lock);
mutex_unlock(&iint->mutex);
kref_put(&iint->refcount, iint_free);
}

static int process_measurement(struct file *file, const unsigned char *filename,
Expand All @@ -207,11 +231,21 @@ static int process_measurement(struct file *file, const unsigned char *filename,

if (!ima_initialized || !S_ISREG(inode->i_mode))
return 0;

rc = ima_must_measure(NULL, inode, mask, function);
if (rc != 0)
return rc;
retry:
iint = ima_iint_find_get(inode);
if (!iint)
return -ENOMEM;
if (!iint) {
rc = ima_inode_alloc(inode);
if (!rc || rc == -EEXIST)
goto retry;
return rc;
}

mutex_lock(&iint->mutex);

rc = ima_must_measure(iint, inode, mask, function);
if (rc != 0)
goto out;
Expand Down
10 changes: 1 addition & 9 deletions trunk/security/security.c
Original file line number Diff line number Diff line change
Expand Up @@ -333,16 +333,8 @@ EXPORT_SYMBOL(security_sb_parse_opts_str);

int security_inode_alloc(struct inode *inode)
{
int ret;

inode->i_security = NULL;
ret = security_ops->inode_alloc_security(inode);
if (ret)
return ret;
ret = ima_inode_alloc(inode);
if (ret)
security_inode_free(inode);
return ret;
return security_ops->inode_alloc_security(inode);
}

void security_inode_free(struct inode *inode)
Expand Down

0 comments on commit 36172ac

Please sign in to comment.