IMA: use inode->i_lock to protect read and write counters
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>
This commit is contained in:
parent
15aac67677
commit
ad16ad00c3
2 changed files with 24 additions and 34 deletions
|
@ -106,6 +106,7 @@ struct ima_iint_cache {
|
||||||
unsigned char flags;
|
unsigned char flags;
|
||||||
u8 digest[IMA_DIGEST_SIZE];
|
u8 digest[IMA_DIGEST_SIZE];
|
||||||
struct mutex mutex; /* protects: version, flags, digest */
|
struct mutex mutex; /* protects: version, flags, digest */
|
||||||
|
/* protected by inode->i_lock */
|
||||||
unsigned int readcount; /* measured files readcount */
|
unsigned int readcount; /* measured files readcount */
|
||||||
unsigned int writecount;/* measured files writecount */
|
unsigned int writecount;/* measured files writecount */
|
||||||
struct kref refcount; /* ima_iint_cache reference count */
|
struct kref refcount; /* ima_iint_cache reference count */
|
||||||
|
|
|
@ -85,42 +85,12 @@ out:
|
||||||
return found;
|
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
|
* Update the counts given an fmode_t
|
||||||
*/
|
*/
|
||||||
static void ima_inc_counts(struct ima_iint_cache *iint, fmode_t mode)
|
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)
|
if ((mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
|
||||||
iint->readcount++;
|
iint->readcount++;
|
||||||
|
@ -146,6 +116,7 @@ void ima_counts_get(struct file *file)
|
||||||
fmode_t mode = file->f_mode;
|
fmode_t mode = file->f_mode;
|
||||||
struct ima_iint_cache *iint;
|
struct ima_iint_cache *iint;
|
||||||
int rc;
|
int rc;
|
||||||
|
bool send_tomtou = false, send_writers = false;
|
||||||
|
|
||||||
if (!iint_initialized || !S_ISREG(inode->i_mode))
|
if (!iint_initialized || !S_ISREG(inode->i_mode))
|
||||||
return;
|
return;
|
||||||
|
@ -153,22 +124,35 @@ void ima_counts_get(struct file *file)
|
||||||
if (!iint)
|
if (!iint)
|
||||||
return;
|
return;
|
||||||
mutex_lock(&iint->mutex);
|
mutex_lock(&iint->mutex);
|
||||||
|
spin_lock(&inode->i_lock);
|
||||||
|
|
||||||
if (!ima_initialized)
|
if (!ima_initialized)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
rc = ima_must_measure(iint, inode, MAY_READ, FILE_CHECK);
|
rc = ima_must_measure(iint, inode, MAY_READ, FILE_CHECK);
|
||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (mode & FMODE_WRITE) {
|
if (mode & FMODE_WRITE) {
|
||||||
ima_read_write_check(TOMTOU, iint, inode, dentry->d_name.name);
|
if (iint->readcount)
|
||||||
|
send_tomtou = true;
|
||||||
goto out;
|
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:
|
out:
|
||||||
ima_inc_counts(iint, file->f_mode);
|
ima_inc_counts(iint, file->f_mode);
|
||||||
|
spin_unlock(&inode->i_lock);
|
||||||
mutex_unlock(&iint->mutex);
|
mutex_unlock(&iint->mutex);
|
||||||
|
|
||||||
kref_put(&iint->refcount, iint_free);
|
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");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -181,6 +165,7 @@ static void ima_dec_counts(struct ima_iint_cache *iint, struct inode *inode,
|
||||||
bool dump = false;
|
bool dump = false;
|
||||||
|
|
||||||
BUG_ON(!mutex_is_locked(&iint->mutex));
|
BUG_ON(!mutex_is_locked(&iint->mutex));
|
||||||
|
assert_spin_locked(&inode->i_lock);
|
||||||
|
|
||||||
if ((mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) {
|
if ((mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) {
|
||||||
if (unlikely(iint->readcount == 0))
|
if (unlikely(iint->readcount == 0))
|
||||||
|
@ -223,7 +208,11 @@ void ima_file_free(struct file *file)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
mutex_lock(&iint->mutex);
|
mutex_lock(&iint->mutex);
|
||||||
|
spin_lock(&inode->i_lock);
|
||||||
|
|
||||||
ima_dec_counts(iint, inode, file);
|
ima_dec_counts(iint, inode, file);
|
||||||
|
|
||||||
|
spin_unlock(&inode->i_lock);
|
||||||
mutex_unlock(&iint->mutex);
|
mutex_unlock(&iint->mutex);
|
||||||
kref_put(&iint->refcount, iint_free);
|
kref_put(&iint->refcount, iint_free);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue