Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/security-testing-2.6

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/security-testing-2.6: (44 commits)
  nommu: Provide mmap_min_addr definition.
  TOMOYO: Add description of lists and structures.
  TOMOYO: Remove unused field.
  integrity: ima audit dentry_open failure
  TOMOYO: Remove unused parameter.
  security: use mmap_min_addr indepedently of security models
  TOMOYO: Simplify policy reader.
  TOMOYO: Remove redundant markers.
  SELinux: define audit permissions for audit tree netlink messages
  TOMOYO: Remove unused mutex.
  tomoyo: avoid get+put of task_struct
  smack: Remove redundant initialization.
  integrity: nfsd imbalance bug fix
  rootplug: Remove redundant initialization.
  smack: do not beyond ARRAY_SIZE of data
  integrity: move ima_counts_get
  integrity: path_check update
  IMA: Add __init notation to ima functions
  IMA: Minimal IMA policy and boot param for TCB IMA policy
  selinux: remove obsolete read buffer limit from sel_read_bool
  ...
This commit is contained in:
Linus Torvalds
2009-06-11 10:01:41 -07:00
58 changed files with 1945 additions and 476 deletions

View File

@@ -22,18 +22,9 @@ static int ima_audit;
static int __init ima_audit_setup(char *str)
{
unsigned long audit;
int rc, result = 0;
char *op = "ima_audit";
char *cause;
rc = strict_strtoul(str, 0, &audit);
if (rc || audit > 1)
result = 1;
else
ima_audit = audit;
cause = ima_audit ? "enabled" : "not_enabled";
integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, NULL,
op, cause, result, 0);
if (!strict_strtoul(str, 0, &audit))
ima_audit = audit ? 1 : 0;
return 1;
}
__setup("ima_audit=", ima_audit_setup);
@@ -50,23 +41,14 @@ void integrity_audit_msg(int audit_msgno, struct inode *inode,
ab = audit_log_start(current->audit_context, GFP_KERNEL, audit_msgno);
audit_log_format(ab, "integrity: pid=%d uid=%u auid=%u ses=%u",
current->pid, current->cred->uid,
current->pid, current_cred()->uid,
audit_get_loginuid(current),
audit_get_sessionid(current));
audit_log_task_context(ab);
switch (audit_msgno) {
case AUDIT_INTEGRITY_DATA:
case AUDIT_INTEGRITY_METADATA:
case AUDIT_INTEGRITY_PCR:
case AUDIT_INTEGRITY_STATUS:
audit_log_format(ab, " op=%s cause=%s", op, cause);
break;
case AUDIT_INTEGRITY_HASH:
audit_log_format(ab, " op=%s hash=%s", op, cause);
break;
default:
audit_log_format(ab, " op=%s", op);
}
audit_log_format(ab, " op=");
audit_log_string(ab, op);
audit_log_format(ab, " cause=");
audit_log_string(ab, cause);
audit_log_format(ab, " comm=");
audit_log_untrustedstring(ab, current->comm);
if (fname) {

View File

@@ -103,7 +103,7 @@ int ima_calc_template_hash(int template_len, void *template, char *digest)
return rc;
}
static void ima_pcrread(int idx, u8 *pcr)
static void __init ima_pcrread(int idx, u8 *pcr)
{
if (!ima_used_chip)
return;
@@ -115,7 +115,7 @@ static void ima_pcrread(int idx, u8 *pcr)
/*
* Calculate the boot aggregate hash
*/
int ima_calc_boot_aggregate(char *digest)
int __init ima_calc_boot_aggregate(char *digest)
{
struct hash_desc desc;
struct scatterlist sg;

View File

@@ -15,6 +15,7 @@
* implemenents security file system for reporting
* current measurement list and IMA statistics
*/
#include <linux/fcntl.h>
#include <linux/module.h>
#include <linux/seq_file.h>
#include <linux/rculist.h>
@@ -283,6 +284,9 @@ static atomic_t policy_opencount = ATOMIC_INIT(1);
*/
int ima_open_policy(struct inode * inode, struct file * filp)
{
/* No point in being allowed to open it if you aren't going to write */
if (!(filp->f_flags & O_WRONLY))
return -EACCES;
if (atomic_dec_and_test(&policy_opencount))
return 0;
return -EBUSY;
@@ -315,7 +319,7 @@ static struct file_operations ima_measure_policy_ops = {
.release = ima_release_policy
};
int ima_fs_init(void)
int __init ima_fs_init(void)
{
ima_dir = securityfs_create_dir("ima", NULL);
if (IS_ERR(ima_dir))
@@ -349,7 +353,7 @@ int ima_fs_init(void)
goto out;
ima_policy = securityfs_create_file("policy",
S_IRUSR | S_IRGRP | S_IWUSR,
S_IWUSR,
ima_dir, NULL,
&ima_measure_policy_ops);
if (IS_ERR(ima_policy))

View File

@@ -196,7 +196,7 @@ static void init_once(void *foo)
kref_set(&iint->refcount, 1);
}
void ima_iintcache_init(void)
void __init ima_iintcache_init(void)
{
iint_cache =
kmem_cache_create("iint_cache", sizeof(struct ima_iint_cache), 0,

View File

@@ -38,7 +38,7 @@ int ima_used_chip;
* a different value.) Violations add a zero entry to the measurement
* list and extend the aggregate PCR value with ff...ff's.
*/
static void ima_add_boot_aggregate(void)
static void __init ima_add_boot_aggregate(void)
{
struct ima_template_entry *entry;
const char *op = "add_boot_aggregate";
@@ -71,7 +71,7 @@ err_out:
audit_cause, result, 0);
}
int ima_init(void)
int __init ima_init(void)
{
u8 pcr_i[IMA_DIGEST_SIZE];
int rc;

View File

@@ -29,20 +29,8 @@ int ima_initialized;
char *ima_hash = "sha1";
static int __init hash_setup(char *str)
{
const char *op = "hash_setup";
const char *hash = "sha1";
int result = 0;
int audit_info = 0;
if (strncmp(str, "md5", 3) == 0) {
hash = "md5";
ima_hash = str;
} else if (strncmp(str, "sha1", 4) != 0) {
hash = "invalid_hash_type";
result = 1;
}
integrity_audit_msg(AUDIT_INTEGRITY_HASH, NULL, NULL, op, hash,
result, audit_info);
if (strncmp(str, "md5", 3) == 0)
ima_hash = "md5";
return 1;
}
__setup("ima_hash=", hash_setup);
@@ -128,10 +116,6 @@ static int get_path_measurement(struct ima_iint_cache *iint, struct file *file,
{
int rc = 0;
if (IS_ERR(file)) {
pr_info("%s dentry_open failed\n", filename);
return rc;
}
iint->opencount++;
iint->readcount++;
@@ -141,6 +125,15 @@ static int get_path_measurement(struct ima_iint_cache *iint, struct file *file,
return rc;
}
static void ima_update_counts(struct ima_iint_cache *iint, int mask)
{
iint->opencount++;
if ((mask & MAY_WRITE) || (mask == 0))
iint->writecount++;
else if (mask & (MAY_READ | MAY_EXEC))
iint->readcount++;
}
/**
* ima_path_check - based on policy, collect/store measurement.
* @path: contains a pointer to the path to be measured
@@ -156,10 +149,10 @@ static int get_path_measurement(struct ima_iint_cache *iint, struct file *file,
* - Opening a file for read when already open for write,
* could result in a file measurement error.
*
* Return 0 on success, an error code on failure.
* (Based on the results of appraise_measurement().)
* Always return 0 and audit dentry_open failures.
* (Return code will be based upon measurement appraisal.)
*/
int ima_path_check(struct path *path, int mask)
int ima_path_check(struct path *path, int mask, int update_counts)
{
struct inode *inode = path->dentry->d_inode;
struct ima_iint_cache *iint;
@@ -173,11 +166,8 @@ int ima_path_check(struct path *path, int mask)
return 0;
mutex_lock(&iint->mutex);
iint->opencount++;
if ((mask & MAY_WRITE) || (mask == 0))
iint->writecount++;
else if (mask & (MAY_READ | MAY_EXEC))
iint->readcount++;
if (update_counts)
ima_update_counts(iint, mask);
rc = ima_must_measure(iint, inode, MAY_READ, PATH_CHECK);
if (rc < 0)
@@ -196,7 +186,19 @@ int ima_path_check(struct path *path, int mask)
struct dentry *dentry = dget(path->dentry);
struct vfsmount *mnt = mntget(path->mnt);
file = dentry_open(dentry, mnt, O_RDONLY, current->cred);
file = dentry_open(dentry, mnt, O_RDONLY | O_LARGEFILE,
current_cred());
if (IS_ERR(file)) {
int audit_info = 0;
integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode,
dentry->d_name.name,
"add_measurement",
"dentry_open failed",
1, audit_info);
file = NULL;
goto out;
}
rc = get_path_measurement(iint, file, dentry->d_name.name);
}
out:
@@ -206,6 +208,7 @@ out:
kref_put(&iint->refcount, iint_free);
return 0;
}
EXPORT_SYMBOL_GPL(ima_path_check);
static int process_measurement(struct file *file, const unsigned char *filename,
int mask, int function)
@@ -234,7 +237,16 @@ out:
return rc;
}
static void opencount_get(struct file *file)
/*
* ima_opens_get - increment file counts
*
* - for IPC shm and shmat file.
* - for nfsd exported files.
*
* Increment the counts for these files to prevent unnecessary
* imbalance messages.
*/
void ima_counts_get(struct file *file)
{
struct inode *inode = file->f_dentry->d_inode;
struct ima_iint_cache *iint;
@@ -246,8 +258,14 @@ static void opencount_get(struct file *file)
return;
mutex_lock(&iint->mutex);
iint->opencount++;
if ((file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
iint->readcount++;
if (file->f_mode & FMODE_WRITE)
iint->writecount++;
mutex_unlock(&iint->mutex);
}
EXPORT_SYMBOL_GPL(ima_counts_get);
/**
* ima_file_mmap - based on policy, collect/store measurement.
@@ -272,18 +290,6 @@ int ima_file_mmap(struct file *file, unsigned long prot)
return 0;
}
/*
* ima_shm_check - IPC shm and shmat create/fput a file
*
* Maintain the opencount for these files to prevent unnecessary
* imbalance messages.
*/
void ima_shm_check(struct file *file)
{
opencount_get(file);
return;
}
/**
* ima_bprm_check - based on policy, collect/store measurement.
* @bprm: contains the linux_binprm structure

View File

@@ -45,24 +45,30 @@ struct ima_measure_rule_entry {
} lsm[MAX_LSM_RULES];
};
/* Without LSM specific knowledge, the default policy can only be
/*
* Without LSM specific knowledge, the default policy can only be
* written in terms of .action, .func, .mask, .fsmagic, and .uid
*/
/*
* The minimum rule set to allow for full TCB coverage. Measures all files
* opened or mmap for exec and everything read by root. Dangerous because
* normal users can easily run the machine out of memory simply building
* and running executables.
*/
static struct ima_measure_rule_entry default_rules[] = {
{.action = DONT_MEASURE,.fsmagic = PROC_SUPER_MAGIC,
.flags = IMA_FSMAGIC},
{.action = DONT_MEASURE,.fsmagic = PROC_SUPER_MAGIC,.flags = IMA_FSMAGIC},
{.action = DONT_MEASURE,.fsmagic = SYSFS_MAGIC,.flags = IMA_FSMAGIC},
{.action = DONT_MEASURE,.fsmagic = DEBUGFS_MAGIC,.flags = IMA_FSMAGIC},
{.action = DONT_MEASURE,.fsmagic = TMPFS_MAGIC,.flags = IMA_FSMAGIC},
{.action = DONT_MEASURE,.fsmagic = SECURITYFS_MAGIC,
.flags = IMA_FSMAGIC},
{.action = DONT_MEASURE,.fsmagic = 0xF97CFF8C,.flags = IMA_FSMAGIC},
{.action = DONT_MEASURE,.fsmagic = SECURITYFS_MAGIC,.flags = IMA_FSMAGIC},
{.action = DONT_MEASURE,.fsmagic = SELINUX_MAGIC,.flags = IMA_FSMAGIC},
{.action = MEASURE,.func = FILE_MMAP,.mask = MAY_EXEC,
.flags = IMA_FUNC | IMA_MASK},
{.action = MEASURE,.func = BPRM_CHECK,.mask = MAY_EXEC,
.flags = IMA_FUNC | IMA_MASK},
{.action = MEASURE,.func = PATH_CHECK,.mask = MAY_READ,.uid = 0,
.flags = IMA_FUNC | IMA_MASK | IMA_UID}
.flags = IMA_FUNC | IMA_MASK | IMA_UID},
};
static LIST_HEAD(measure_default_rules);
@@ -71,6 +77,14 @@ static struct list_head *ima_measure;
static DEFINE_MUTEX(ima_measure_mutex);
static bool ima_use_tcb __initdata;
static int __init default_policy_setup(char *str)
{
ima_use_tcb = 1;
return 1;
}
__setup("ima_tcb", default_policy_setup);
/**
* ima_match_rules - determine whether an inode matches the measure rule.
* @rule: a pointer to a rule
@@ -96,7 +110,7 @@ static bool ima_match_rules(struct ima_measure_rule_entry *rule,
if ((rule->flags & IMA_UID) && rule->uid != tsk->cred->uid)
return false;
for (i = 0; i < MAX_LSM_RULES; i++) {
int rc;
int rc = 0;
u32 osid, sid;
if (!rule->lsm[i].rule)
@@ -109,7 +123,7 @@ static bool ima_match_rules(struct ima_measure_rule_entry *rule,
security_inode_getsecid(inode, &osid);
rc = security_filter_rule_match(osid,
rule->lsm[i].type,
AUDIT_EQUAL,
Audit_equal,
rule->lsm[i].rule,
NULL);
break;
@@ -119,7 +133,7 @@ static bool ima_match_rules(struct ima_measure_rule_entry *rule,
security_task_getsecid(tsk, &sid);
rc = security_filter_rule_match(sid,
rule->lsm[i].type,
AUDIT_EQUAL,
Audit_equal,
rule->lsm[i].rule,
NULL);
default:
@@ -164,11 +178,17 @@ int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask)
* ima_measure points to either the measure_default_rules or the
* the new measure_policy_rules.
*/
void ima_init_policy(void)
void __init ima_init_policy(void)
{
int i;
int i, entries;
for (i = 0; i < ARRAY_SIZE(default_rules); i++)
/* if !ima_use_tcb set entries = 0 so we load NO default rules */
if (ima_use_tcb)
entries = ARRAY_SIZE(default_rules);
else
entries = 0;
for (i = 0; i < entries; i++)
list_add_tail(&default_rules[i].list, &measure_default_rules);
ima_measure = &measure_default_rules;
}
@@ -227,7 +247,7 @@ static int ima_lsm_rule_init(struct ima_measure_rule_entry *entry,
entry->lsm[lsm_rule].type = audit_type;
result = security_filter_rule_init(entry->lsm[lsm_rule].type,
AUDIT_EQUAL, args,
Audit_equal, args,
&entry->lsm[lsm_rule].rule);
return result;
}