aboutsummaryrefslogtreecommitdiff
path: root/security/integrity/ima
diff options
context:
space:
mode:
Diffstat (limited to 'security/integrity/ima')
-rw-r--r--security/integrity/ima/ima.h2
-rw-r--r--security/integrity/ima/ima_fs.c4
-rw-r--r--security/integrity/ima/ima_policy.c47
-rw-r--r--security/integrity/ima/ima_template_lib.c3
4 files changed, 43 insertions, 13 deletions
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index 8ee997dff139..fc56d4dfa954 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -106,7 +106,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);
diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c
index da92fcc08d15..d30afe461070 100644
--- a/security/integrity/ima/ima_fs.c
+++ b/security/integrity/ima/ima_fs.c
@@ -186,9 +186,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));
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
index cdc620b2152f..7e4ad2943918 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -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 */
@@ -176,6 +178,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;
@@ -184,6 +189,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++) {
@@ -378,7 +393,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
};
@@ -399,6 +415,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"},
@@ -440,6 +457,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;
@@ -530,18 +548,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);
@@ -571,6 +594,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;
@@ -579,11 +605,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:
diff --git a/security/integrity/ima/ima_template_lib.c b/security/integrity/ima/ima_template_lib.c
index 1506f0248572..1eb173ddefd6 100644
--- a/security/integrity/ima/ima_template_lib.c
+++ b/security/integrity/ima/ima_template_lib.c
@@ -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: