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:
@@ -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) {
|
||||
|
@@ -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;
|
||||
|
@@ -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))
|
||||
|
@@ -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,
|
||||
|
@@ -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;
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
}
|
||||
|
Reference in New Issue
Block a user