Skip to content

Commit

Permalink
integrity: move ima inode integrity data management
Browse files Browse the repository at this point in the history
Move the inode integrity data(iint) management up to the integrity directory
in order to share the iint among the different integrity models.

Changelog:
- don't define MAX_DIGEST_SIZE
- rename several globally visible 'ima_' prefixed functions, structs,
  locks, etc to 'integrity_'
- replace '20' with SHA1_DIGEST_SIZE
- reflect location change in appropriate Kconfig and Makefiles
- remove unnecessary initialization of iint_initialized to 0
- rebased on current ima_iint.c
- define integrity_iint_store/lock as static

There should be no other functional changes.

Signed-off-by: Mimi Zohar <zohar@us.ibm.com>
Acked-by: Serge Hallyn <serge.hallyn@ubuntu.com>
  • Loading branch information
Mimi Zohar committed Jul 18, 2011
1 parent 9d8f13b commit f381c27
Show file tree
Hide file tree
Showing 15 changed files with 277 additions and 216 deletions.
13 changes: 0 additions & 13 deletions include/linux/ima.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@ struct linux_binprm;

#ifdef CONFIG_IMA
extern int ima_bprm_check(struct linux_binprm *bprm);
extern int ima_inode_alloc(struct inode *inode);
extern void ima_inode_free(struct inode *inode);
extern int ima_file_check(struct file *file, int mask);
extern void ima_file_free(struct file *file);
extern int ima_file_mmap(struct file *file, unsigned long prot);
Expand All @@ -27,16 +25,6 @@ static inline int ima_bprm_check(struct linux_binprm *bprm)
return 0;
}

static inline int ima_inode_alloc(struct inode *inode)
{
return 0;
}

static inline void ima_inode_free(struct inode *inode)
{
return;
}

static inline int ima_file_check(struct file *file, int mask)
{
return 0;
Expand All @@ -51,6 +39,5 @@ static inline int ima_file_mmap(struct file *file, unsigned long prot)
{
return 0;
}

#endif /* CONFIG_IMA_H */
#endif /* _LINUX_IMA_H */
30 changes: 30 additions & 0 deletions include/linux/integrity.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright (C) 2009 IBM Corporation
* Author: Mimi Zohar <zohar@us.ibm.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 2 of the License.
*/

#ifndef _LINUX_INTEGRITY_H
#define _LINUX_INTEGRITY_H

#include <linux/fs.h>

#ifdef CONFIG_INTEGRITY
extern int integrity_inode_alloc(struct inode *inode);
extern void integrity_inode_free(struct inode *inode);

#else
static inline int integrity_inode_alloc(struct inode *inode)
{
return 0;
}

static inline void integrity_inode_free(struct inode *inode)
{
return;
}
#endif /* CONFIG_INTEGRITY_H */
#endif /* _LINUX_INTEGRITY_H */
2 changes: 1 addition & 1 deletion security/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ source security/smack/Kconfig
source security/tomoyo/Kconfig
source security/apparmor/Kconfig

source security/integrity/ima/Kconfig
source security/integrity/Kconfig

choice
prompt "Default security module"
Expand Down
4 changes: 2 additions & 2 deletions security/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,5 @@ obj-$(CONFIG_SECURITY_APPARMOR) += apparmor/built-in.o
obj-$(CONFIG_CGROUP_DEVICE) += device_cgroup.o

# Object integrity file lists
subdir-$(CONFIG_IMA) += integrity/ima
obj-$(CONFIG_IMA) += integrity/ima/built-in.o
subdir-$(CONFIG_INTEGRITY) += integrity
obj-$(CONFIG_INTEGRITY) += integrity/built-in.o
6 changes: 6 additions & 0 deletions security/integrity/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#
config INTEGRITY
def_bool y
depends on IMA

source security/integrity/ima/Kconfig
10 changes: 10 additions & 0 deletions security/integrity/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#
# Makefile for caching inode integrity data (iint)
#

obj-$(CONFIG_INTEGRITY) += integrity.o

integrity-y := iint.o

subdir-$(CONFIG_IMA) += ima
obj-$(CONFIG_IMA) += ima/built-in.o
170 changes: 170 additions & 0 deletions security/integrity/iint.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
/*
* Copyright (C) 2008 IBM Corporation
*
* Authors:
* Mimi Zohar <zohar@us.ibm.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, version 2 of the
* License.
*
* File: integrity_iint.c
* - implements the integrity hooks: integrity_inode_alloc,
* integrity_inode_free
* - cache integrity information associated with an inode
* using a rbtree tree.
*/
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/spinlock.h>
#include <linux/rbtree.h>
#include "integrity.h"

static struct rb_root integrity_iint_tree = RB_ROOT;
static DEFINE_SPINLOCK(integrity_iint_lock);
static struct kmem_cache *iint_cache __read_mostly;

int iint_initialized;

/*
* __integrity_iint_find - return the iint associated with an inode
*/
static struct integrity_iint_cache *__integrity_iint_find(struct inode *inode)
{
struct integrity_iint_cache *iint;
struct rb_node *n = integrity_iint_tree.rb_node;

assert_spin_locked(&integrity_iint_lock);

while (n) {
iint = rb_entry(n, struct integrity_iint_cache, rb_node);

if (inode < iint->inode)
n = n->rb_left;
else if (inode > iint->inode)
n = n->rb_right;
else
break;
}
if (!n)
return NULL;

return iint;
}

/*
* integrity_iint_find - return the iint associated with an inode
*/
struct integrity_iint_cache *integrity_iint_find(struct inode *inode)
{
struct integrity_iint_cache *iint;

if (!IS_IMA(inode))
return NULL;

spin_lock(&integrity_iint_lock);
iint = __integrity_iint_find(inode);
spin_unlock(&integrity_iint_lock);

return iint;
}

static void iint_free(struct integrity_iint_cache *iint)
{
iint->version = 0;
iint->flags = 0UL;
kmem_cache_free(iint_cache, iint);
}

/**
* integrity_inode_alloc - allocate an iint associated with an inode
* @inode: pointer to the inode
*/
int integrity_inode_alloc(struct inode *inode)
{
struct rb_node **p;
struct rb_node *new_node, *parent = NULL;
struct integrity_iint_cache *new_iint, *test_iint;
int rc;

new_iint = kmem_cache_alloc(iint_cache, GFP_NOFS);
if (!new_iint)
return -ENOMEM;

new_iint->inode = inode;
new_node = &new_iint->rb_node;

mutex_lock(&inode->i_mutex); /* i_flags */
spin_lock(&integrity_iint_lock);

p = &integrity_iint_tree.rb_node;
while (*p) {
parent = *p;
test_iint = rb_entry(parent, struct integrity_iint_cache,
rb_node);
rc = -EEXIST;
if (inode < test_iint->inode)
p = &(*p)->rb_left;
else if (inode > test_iint->inode)
p = &(*p)->rb_right;
else
goto out_err;
}

inode->i_flags |= S_IMA;
rb_link_node(new_node, parent, p);
rb_insert_color(new_node, &integrity_iint_tree);

spin_unlock(&integrity_iint_lock);
mutex_unlock(&inode->i_mutex); /* i_flags */

return 0;
out_err:
spin_unlock(&integrity_iint_lock);
mutex_unlock(&inode->i_mutex); /* i_flags */
iint_free(new_iint);

return rc;
}

/**
* integrity_inode_free - called on security_inode_free
* @inode: pointer to the inode
*
* Free the integrity information(iint) associated with an inode.
*/
void integrity_inode_free(struct inode *inode)
{
struct integrity_iint_cache *iint;

if (!IS_IMA(inode))
return;

spin_lock(&integrity_iint_lock);
iint = __integrity_iint_find(inode);
rb_erase(&iint->rb_node, &integrity_iint_tree);
spin_unlock(&integrity_iint_lock);

iint_free(iint);
}

static void init_once(void *foo)
{
struct integrity_iint_cache *iint = foo;

memset(iint, 0, sizeof *iint);
iint->version = 0;
iint->flags = 0UL;
mutex_init(&iint->mutex);
}

static int __init integrity_iintcache_init(void)
{
iint_cache =
kmem_cache_create("iint_cache", sizeof(struct integrity_iint_cache),
0, SLAB_PANIC, init_once);
iint_initialized = 1;
return 0;
}
security_initcall(integrity_iintcache_init);
1 change: 1 addition & 0 deletions security/integrity/ima/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
config IMA
bool "Integrity Measurement Architecture(IMA)"
depends on SECURITY
select INTEGRITY
select SECURITYFS
select CRYPTO
select CRYPTO_HMAC
Expand Down
2 changes: 1 addition & 1 deletion security/integrity/ima/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@
obj-$(CONFIG_IMA) += ima.o

ima-y := ima_fs.o ima_queue.o ima_init.o ima_main.o ima_crypto.o ima_api.o \
ima_policy.o ima_iint.o ima_audit.o
ima_policy.o ima_audit.o
29 changes: 9 additions & 20 deletions security/integrity/ima/ima.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,13 @@
#include <linux/tpm.h>
#include <linux/audit.h>

#include "../integrity.h"

enum ima_show_type { IMA_SHOW_BINARY, IMA_SHOW_ASCII };
enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8 };

/* digest size for IMA, fits SHA1 or MD5 */
#define IMA_DIGEST_SIZE 20
#define IMA_DIGEST_SIZE SHA1_DIGEST_SIZE
#define IMA_EVENT_NAME_LEN_MAX 255

#define IMA_HASH_BITS 9
Expand Down Expand Up @@ -96,34 +98,21 @@ static inline unsigned long ima_hash_key(u8 *digest)
return hash_long(*digest, IMA_HASH_BITS);
}

/* iint cache flags */
#define IMA_MEASURED 0x01

/* integrity data associated with an inode */
struct ima_iint_cache {
struct rb_node rb_node; /* rooted in ima_iint_tree */
struct inode *inode; /* back pointer to inode in question */
u64 version; /* track inode changes */
unsigned char flags;
u8 digest[IMA_DIGEST_SIZE];
struct mutex mutex; /* protects: version, flags, digest */
};

/* LIM API function definitions */
int ima_must_measure(struct inode *inode, int mask, int function);
int ima_collect_measurement(struct ima_iint_cache *iint, struct file *file);
void ima_store_measurement(struct ima_iint_cache *iint, struct file *file,
int ima_collect_measurement(struct integrity_iint_cache *iint,
struct file *file);
void ima_store_measurement(struct integrity_iint_cache *iint, struct file *file,
const unsigned char *filename);
int ima_store_template(struct ima_template_entry *entry, int violation,
struct inode *inode);
void ima_template_show(struct seq_file *m, void *e,
enum ima_show_type show);
void ima_template_show(struct seq_file *m, void *e, enum ima_show_type show);

/* rbtree tree calls to lookup, insert, delete
* integrity data associated with an inode.
*/
struct ima_iint_cache *ima_iint_insert(struct inode *inode);
struct ima_iint_cache *ima_iint_find(struct inode *inode);
struct integrity_iint_cache *integrity_iint_insert(struct inode *inode);
struct integrity_iint_cache *integrity_iint_find(struct inode *inode);

/* IMA policy related functions */
enum ima_hooks { FILE_CHECK = 1, FILE_MMAP, BPRM_CHECK };
Expand Down
7 changes: 4 additions & 3 deletions security/integrity/ima/ima_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,8 @@ int ima_must_measure(struct inode *inode, int mask, int function)
*
* Return 0 on success, error code otherwise
*/
int ima_collect_measurement(struct ima_iint_cache *iint, struct file *file)
int ima_collect_measurement(struct integrity_iint_cache *iint,
struct file *file)
{
int result = -EEXIST;

Expand Down Expand Up @@ -156,8 +157,8 @@ int ima_collect_measurement(struct ima_iint_cache *iint, struct file *file)
*
* Must be called with iint->mutex held.
*/
void ima_store_measurement(struct ima_iint_cache *iint, struct file *file,
const unsigned char *filename)
void ima_store_measurement(struct integrity_iint_cache *iint,
struct file *file, const unsigned char *filename)
{
const char *op = "add_template_measure";
const char *audit_cause = "ENOMEM";
Expand Down
Loading

0 comments on commit f381c27

Please sign in to comment.