Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity into next
This commit is contained in:
commit
b3bddffd35
Documentation
security/integrity/ima
@ -20,17 +20,19 @@ Description:
|
||||
action: measure | dont_measure | appraise | dont_appraise | audit
|
||||
condition:= base | lsm [option]
|
||||
base: [[func=] [mask=] [fsmagic=] [fsuuid=] [uid=]
|
||||
[fowner]]
|
||||
[euid=] [fowner=]]
|
||||
lsm: [[subj_user=] [subj_role=] [subj_type=]
|
||||
[obj_user=] [obj_role=] [obj_type=]]
|
||||
option: [[appraise_type=]] [permit_directio]
|
||||
|
||||
base: func:= [BPRM_CHECK][MMAP_CHECK][FILE_CHECK][MODULE_CHECK]
|
||||
[FIRMWARE_CHECK]
|
||||
mask:= [MAY_READ] [MAY_WRITE] [MAY_APPEND] [MAY_EXEC]
|
||||
mask:= [[^]MAY_READ] [[^]MAY_WRITE] [[^]MAY_APPEND]
|
||||
[[^]MAY_EXEC]
|
||||
fsmagic:= hex value
|
||||
fsuuid:= file system UUID (e.g 8bcbe394-4f13-4144-be8e-5aa9ea2ce2f6)
|
||||
uid:= decimal value
|
||||
euid:= decimal value
|
||||
fowner:=decimal value
|
||||
lsm: are LSM specific
|
||||
option: appraise_type:= [imasig]
|
||||
|
@ -1398,7 +1398,15 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
|
||||
The list of supported hash algorithms is defined
|
||||
in crypto/hash_info.h.
|
||||
|
||||
ima_tcb [IMA]
|
||||
ima_policy= [IMA]
|
||||
The builtin measurement policy to load during IMA
|
||||
setup. Specyfing "tcb" as the value, measures all
|
||||
programs exec'd, files mmap'd for exec, and all files
|
||||
opened with the read mode bit set by either the
|
||||
effective uid (euid=0) or uid=0.
|
||||
Format: "tcb"
|
||||
|
||||
ima_tcb [IMA] Deprecated. Use ima_policy= instead.
|
||||
Load a policy which meets the needs of the Trusted
|
||||
Computing Base. This means IMA will measure all
|
||||
programs exec'd, files mmap'd for exec, and all files
|
||||
|
@ -115,7 +115,7 @@ void ima_add_violation(struct file *file, const unsigned char *filename,
|
||||
const char *op, const char *cause);
|
||||
int ima_init_crypto(void);
|
||||
void ima_putc(struct seq_file *m, void *data, int datalen);
|
||||
void ima_print_digest(struct seq_file *m, u8 *digest, int size);
|
||||
void ima_print_digest(struct seq_file *m, u8 *digest, u32 size);
|
||||
struct ima_template_desc *ima_template_desc_current(void);
|
||||
int ima_init_template(void);
|
||||
|
||||
|
@ -190,9 +190,9 @@ static const struct file_operations ima_measurements_ops = {
|
||||
.release = seq_release,
|
||||
};
|
||||
|
||||
void ima_print_digest(struct seq_file *m, u8 *digest, int size)
|
||||
void ima_print_digest(struct seq_file *m, u8 *digest, u32 size)
|
||||
{
|
||||
int i;
|
||||
u32 i;
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
seq_printf(m, "%02x", *(digest + i));
|
||||
|
@ -27,6 +27,8 @@
|
||||
#define IMA_UID 0x0008
|
||||
#define IMA_FOWNER 0x0010
|
||||
#define IMA_FSUUID 0x0020
|
||||
#define IMA_INMASK 0x0040
|
||||
#define IMA_EUID 0x0080
|
||||
|
||||
#define UNKNOWN 0
|
||||
#define MEASURE 0x0001 /* same as IMA_MEASURE */
|
||||
@ -42,6 +44,8 @@ enum lsm_rule_types { LSM_OBJ_USER, LSM_OBJ_ROLE, LSM_OBJ_TYPE,
|
||||
LSM_SUBJ_USER, LSM_SUBJ_ROLE, LSM_SUBJ_TYPE
|
||||
};
|
||||
|
||||
enum policy_types { ORIGINAL_TCB = 1, DEFAULT_TCB };
|
||||
|
||||
struct ima_rule_entry {
|
||||
struct list_head list;
|
||||
int action;
|
||||
@ -70,7 +74,7 @@ struct ima_rule_entry {
|
||||
* normal users can easily run the machine out of memory simply building
|
||||
* and running executables.
|
||||
*/
|
||||
static struct ima_rule_entry default_rules[] = {
|
||||
static struct ima_rule_entry dont_measure_rules[] = {
|
||||
{.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},
|
||||
@ -81,13 +85,29 @@ static struct ima_rule_entry default_rules[] = {
|
||||
{.action = DONT_MEASURE, .fsmagic = SELINUX_MAGIC, .flags = IMA_FSMAGIC},
|
||||
{.action = DONT_MEASURE, .fsmagic = CGROUP_SUPER_MAGIC,
|
||||
.flags = IMA_FSMAGIC},
|
||||
{.action = DONT_MEASURE, .fsmagic = NSFS_MAGIC, .flags = IMA_FSMAGIC},
|
||||
{.action = DONT_MEASURE, .fsmagic = NSFS_MAGIC, .flags = IMA_FSMAGIC}
|
||||
};
|
||||
|
||||
static struct ima_rule_entry original_measurement_rules[] = {
|
||||
{.action = MEASURE, .func = MMAP_CHECK, .mask = MAY_EXEC,
|
||||
.flags = IMA_FUNC | IMA_MASK},
|
||||
{.action = MEASURE, .func = BPRM_CHECK, .mask = MAY_EXEC,
|
||||
.flags = IMA_FUNC | IMA_MASK},
|
||||
{.action = MEASURE, .func = FILE_CHECK, .mask = MAY_READ, .uid = GLOBAL_ROOT_UID,
|
||||
.flags = IMA_FUNC | IMA_MASK | IMA_UID},
|
||||
{.action = MEASURE, .func = FILE_CHECK, .mask = MAY_READ,
|
||||
.uid = GLOBAL_ROOT_UID, .flags = IMA_FUNC | IMA_MASK | IMA_UID},
|
||||
{.action = MEASURE, .func = MODULE_CHECK, .flags = IMA_FUNC},
|
||||
{.action = MEASURE, .func = FIRMWARE_CHECK, .flags = IMA_FUNC},
|
||||
};
|
||||
|
||||
static struct ima_rule_entry default_measurement_rules[] = {
|
||||
{.action = MEASURE, .func = MMAP_CHECK, .mask = MAY_EXEC,
|
||||
.flags = IMA_FUNC | IMA_MASK},
|
||||
{.action = MEASURE, .func = BPRM_CHECK, .mask = MAY_EXEC,
|
||||
.flags = IMA_FUNC | IMA_MASK},
|
||||
{.action = MEASURE, .func = FILE_CHECK, .mask = MAY_READ,
|
||||
.uid = GLOBAL_ROOT_UID, .flags = IMA_FUNC | IMA_INMASK | IMA_EUID},
|
||||
{.action = MEASURE, .func = FILE_CHECK, .mask = MAY_READ,
|
||||
.uid = GLOBAL_ROOT_UID, .flags = IMA_FUNC | IMA_INMASK | IMA_UID},
|
||||
{.action = MEASURE, .func = MODULE_CHECK, .flags = IMA_FUNC},
|
||||
{.action = MEASURE, .func = FIRMWARE_CHECK, .flags = IMA_FUNC},
|
||||
};
|
||||
@ -119,14 +139,29 @@ static struct list_head *ima_rules;
|
||||
|
||||
static DEFINE_MUTEX(ima_rules_mutex);
|
||||
|
||||
static bool ima_use_tcb __initdata;
|
||||
static int ima_policy __initdata;
|
||||
static int __init default_measure_policy_setup(char *str)
|
||||
{
|
||||
ima_use_tcb = 1;
|
||||
if (ima_policy)
|
||||
return 1;
|
||||
|
||||
ima_policy = ORIGINAL_TCB;
|
||||
return 1;
|
||||
}
|
||||
__setup("ima_tcb", default_measure_policy_setup);
|
||||
|
||||
static int __init policy_setup(char *str)
|
||||
{
|
||||
if (ima_policy)
|
||||
return 1;
|
||||
|
||||
if (strcmp(str, "tcb") == 0)
|
||||
ima_policy = DEFAULT_TCB;
|
||||
|
||||
return 1;
|
||||
}
|
||||
__setup("ima_policy=", policy_setup);
|
||||
|
||||
static bool ima_use_appraise_tcb __initdata;
|
||||
static int __init default_appraise_policy_setup(char *str)
|
||||
{
|
||||
@ -186,6 +221,9 @@ static bool ima_match_rules(struct ima_rule_entry *rule,
|
||||
if ((rule->flags & IMA_MASK) &&
|
||||
(rule->mask != mask && func != POST_SETATTR))
|
||||
return false;
|
||||
if ((rule->flags & IMA_INMASK) &&
|
||||
(!(rule->mask & mask) && func != POST_SETATTR))
|
||||
return false;
|
||||
if ((rule->flags & IMA_FSMAGIC)
|
||||
&& rule->fsmagic != inode->i_sb->s_magic)
|
||||
return false;
|
||||
@ -194,6 +232,16 @@ static bool ima_match_rules(struct ima_rule_entry *rule,
|
||||
return false;
|
||||
if ((rule->flags & IMA_UID) && !uid_eq(rule->uid, cred->uid))
|
||||
return false;
|
||||
if (rule->flags & IMA_EUID) {
|
||||
if (has_capability_noaudit(current, CAP_SETUID)) {
|
||||
if (!uid_eq(rule->uid, cred->euid)
|
||||
&& !uid_eq(rule->uid, cred->suid)
|
||||
&& !uid_eq(rule->uid, cred->uid))
|
||||
return false;
|
||||
} else if (!uid_eq(rule->uid, cred->euid))
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((rule->flags & IMA_FOWNER) && !uid_eq(rule->fowner, inode->i_uid))
|
||||
return false;
|
||||
for (i = 0; i < MAX_LSM_RULES; i++) {
|
||||
@ -337,13 +385,27 @@ void __init ima_init_policy(void)
|
||||
{
|
||||
int i, measure_entries, appraise_entries;
|
||||
|
||||
/* if !ima_use_tcb set entries = 0 so we load NO default rules */
|
||||
measure_entries = ima_use_tcb ? ARRAY_SIZE(default_rules) : 0;
|
||||
/* if !ima_policy set entries = 0 so we load NO default rules */
|
||||
measure_entries = ima_policy ? ARRAY_SIZE(dont_measure_rules) : 0;
|
||||
appraise_entries = ima_use_appraise_tcb ?
|
||||
ARRAY_SIZE(default_appraise_rules) : 0;
|
||||
|
||||
for (i = 0; i < measure_entries; i++)
|
||||
list_add_tail(&default_rules[i].list, &ima_default_rules);
|
||||
list_add_tail(&dont_measure_rules[i].list, &ima_default_rules);
|
||||
|
||||
switch (ima_policy) {
|
||||
case ORIGINAL_TCB:
|
||||
for (i = 0; i < ARRAY_SIZE(original_measurement_rules); i++)
|
||||
list_add_tail(&original_measurement_rules[i].list,
|
||||
&ima_default_rules);
|
||||
break;
|
||||
case DEFAULT_TCB:
|
||||
for (i = 0; i < ARRAY_SIZE(default_measurement_rules); i++)
|
||||
list_add_tail(&default_measurement_rules[i].list,
|
||||
&ima_default_rules);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 0; i < appraise_entries; i++) {
|
||||
list_add_tail(&default_appraise_rules[i].list,
|
||||
@ -373,7 +435,8 @@ enum {
|
||||
Opt_audit,
|
||||
Opt_obj_user, Opt_obj_role, Opt_obj_type,
|
||||
Opt_subj_user, Opt_subj_role, Opt_subj_type,
|
||||
Opt_func, Opt_mask, Opt_fsmagic, Opt_uid, Opt_fowner,
|
||||
Opt_func, Opt_mask, Opt_fsmagic,
|
||||
Opt_uid, Opt_euid, Opt_fowner,
|
||||
Opt_appraise_type, Opt_fsuuid, Opt_permit_directio
|
||||
};
|
||||
|
||||
@ -394,6 +457,7 @@ static match_table_t policy_tokens = {
|
||||
{Opt_fsmagic, "fsmagic=%s"},
|
||||
{Opt_fsuuid, "fsuuid=%s"},
|
||||
{Opt_uid, "uid=%s"},
|
||||
{Opt_euid, "euid=%s"},
|
||||
{Opt_fowner, "fowner=%s"},
|
||||
{Opt_appraise_type, "appraise_type=%s"},
|
||||
{Opt_permit_directio, "permit_directio"},
|
||||
@ -435,6 +499,7 @@ static void ima_log_string(struct audit_buffer *ab, char *key, char *value)
|
||||
static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
|
||||
{
|
||||
struct audit_buffer *ab;
|
||||
char *from;
|
||||
char *p;
|
||||
int result = 0;
|
||||
|
||||
@ -525,18 +590,23 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
|
||||
if (entry->mask)
|
||||
result = -EINVAL;
|
||||
|
||||
if ((strcmp(args[0].from, "MAY_EXEC")) == 0)
|
||||
from = args[0].from;
|
||||
if (*from == '^')
|
||||
from++;
|
||||
|
||||
if ((strcmp(from, "MAY_EXEC")) == 0)
|
||||
entry->mask = MAY_EXEC;
|
||||
else if (strcmp(args[0].from, "MAY_WRITE") == 0)
|
||||
else if (strcmp(from, "MAY_WRITE") == 0)
|
||||
entry->mask = MAY_WRITE;
|
||||
else if (strcmp(args[0].from, "MAY_READ") == 0)
|
||||
else if (strcmp(from, "MAY_READ") == 0)
|
||||
entry->mask = MAY_READ;
|
||||
else if (strcmp(args[0].from, "MAY_APPEND") == 0)
|
||||
else if (strcmp(from, "MAY_APPEND") == 0)
|
||||
entry->mask = MAY_APPEND;
|
||||
else
|
||||
result = -EINVAL;
|
||||
if (!result)
|
||||
entry->flags |= IMA_MASK;
|
||||
entry->flags |= (*args[0].from == '^')
|
||||
? IMA_INMASK : IMA_MASK;
|
||||
break;
|
||||
case Opt_fsmagic:
|
||||
ima_log_string(ab, "fsmagic", args[0].from);
|
||||
@ -566,6 +636,9 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
|
||||
break;
|
||||
case Opt_uid:
|
||||
ima_log_string(ab, "uid", args[0].from);
|
||||
case Opt_euid:
|
||||
if (token == Opt_euid)
|
||||
ima_log_string(ab, "euid", args[0].from);
|
||||
|
||||
if (uid_valid(entry->uid)) {
|
||||
result = -EINVAL;
|
||||
@ -574,11 +647,14 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
|
||||
|
||||
result = kstrtoul(args[0].from, 10, &lnum);
|
||||
if (!result) {
|
||||
entry->uid = make_kuid(current_user_ns(), (uid_t)lnum);
|
||||
if (!uid_valid(entry->uid) || (((uid_t)lnum) != lnum))
|
||||
entry->uid = make_kuid(current_user_ns(),
|
||||
(uid_t) lnum);
|
||||
if (!uid_valid(entry->uid) ||
|
||||
(uid_t)lnum != lnum)
|
||||
result = -EINVAL;
|
||||
else
|
||||
entry->flags |= IMA_UID;
|
||||
entry->flags |= (token == Opt_uid)
|
||||
? IMA_UID : IMA_EUID;
|
||||
}
|
||||
break;
|
||||
case Opt_fowner:
|
||||
|
@ -70,7 +70,8 @@ static void ima_show_template_data_ascii(struct seq_file *m,
|
||||
enum data_formats datafmt,
|
||||
struct ima_field_data *field_data)
|
||||
{
|
||||
u8 *buf_ptr = field_data->data, buflen = field_data->len;
|
||||
u8 *buf_ptr = field_data->data;
|
||||
u32 buflen = field_data->len;
|
||||
|
||||
switch (datafmt) {
|
||||
case DATA_FMT_DIGEST_WITH_ALGO:
|
||||
|
Loading…
Reference in New Issue
Block a user