Skip to content

Commit

Permalink
IMA: use inode->i_lock to protect read and write counters
Browse files Browse the repository at this point in the history
Currently IMA used the iint->mutex to protect the i_readcount and
i_writecount.  This patch uses the inode->i_lock since we are going to
start using in inode objects and that is the most appropriate lock.

Signed-off-by: Eric Paris <eparis@redhat.com>
Acked-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
  • Loading branch information
eparis authored and torvalds committed Oct 26, 2010
1 parent 15aac67 commit ad16ad0
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 34 deletions.
1 change: 1 addition & 0 deletions security/integrity/ima/ima.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ struct ima_iint_cache {
unsigned char flags;
u8 digest[IMA_DIGEST_SIZE];
struct mutex mutex; /* protects: version, flags, digest */
/* protected by inode->i_lock */
unsigned int readcount; /* measured files readcount */
unsigned int writecount;/* measured files writecount */
struct kref refcount; /* ima_iint_cache reference count */
Expand Down
57 changes: 23 additions & 34 deletions security/integrity/ima/ima_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,42 +85,12 @@ static bool ima_limit_imbalance(struct file *file)
return found;
}

/* ima_read_write_check - reflect possible reading/writing errors in the PCR.
*
* When opening a file for read, if the file is already open for write,
* the file could change, resulting in a file measurement error.
*
* Opening a file for write, if the file is already open for read, results
* in a time of measure, time of use (ToMToU) error.
*
* In either case invalidate the PCR.
*/
enum iint_pcr_error { TOMTOU, OPEN_WRITERS };
static void ima_read_write_check(enum iint_pcr_error error,
struct ima_iint_cache *iint,
struct inode *inode,
const unsigned char *filename)
{
switch (error) {
case TOMTOU:
if (iint->readcount > 0)
ima_add_violation(inode, filename, "invalid_pcr",
"ToMToU");
break;
case OPEN_WRITERS:
if (iint->writecount > 0)
ima_add_violation(inode, filename, "invalid_pcr",
"open_writers");
break;
}
}

/*
* Update the counts given an fmode_t
*/
static void ima_inc_counts(struct ima_iint_cache *iint, fmode_t mode)
{
BUG_ON(!mutex_is_locked(&iint->mutex));
assert_spin_locked(&iint->inode->i_lock);

if ((mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
iint->readcount++;
Expand All @@ -146,29 +116,43 @@ void ima_counts_get(struct file *file)
fmode_t mode = file->f_mode;
struct ima_iint_cache *iint;
int rc;
bool send_tomtou = false, send_writers = false;

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);

if (!ima_initialized)
goto out;

rc = ima_must_measure(iint, inode, MAY_READ, FILE_CHECK);
if (rc < 0)
goto out;

if (mode & FMODE_WRITE) {
ima_read_write_check(TOMTOU, iint, inode, dentry->d_name.name);
if (iint->readcount)
send_tomtou = true;
goto out;
}
ima_read_write_check(OPEN_WRITERS, iint, inode, dentry->d_name.name);

if (atomic_read(&inode->i_writecount) > 0)
send_writers = true;
out:
ima_inc_counts(iint, file->f_mode);
spin_unlock(&inode->i_lock);
mutex_unlock(&iint->mutex);

kref_put(&iint->refcount, iint_free);

if (send_tomtou)
ima_add_violation(inode, dentry->d_name.name, "invalid_pcr",
"ToMToU");
if (send_writers)
ima_add_violation(inode, dentry->d_name.name, "invalid_pcr",
"open_writers");
}

/*
Expand All @@ -181,6 +165,7 @@ static void ima_dec_counts(struct ima_iint_cache *iint, struct inode *inode,
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(iint->readcount == 0))
Expand Down Expand Up @@ -223,7 +208,11 @@ void ima_file_free(struct file *file)
return;

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

ima_dec_counts(iint, inode, file);

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

0 comments on commit ad16ad0

Please sign in to comment.