Browse Source

Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity into next

James Morris 10 years ago
parent
commit
b3bddffd35

+ 4 - 2
Documentation/ABI/testing/ima_policy

@@ -20,17 +20,19 @@ Description:
 		action: measure | dont_measure | appraise | dont_appraise | audit
 		action: measure | dont_measure | appraise | dont_appraise | audit
 		condition:= base | lsm  [option]
 		condition:= base | lsm  [option]
 			base:	[[func=] [mask=] [fsmagic=] [fsuuid=] [uid=]
 			base:	[[func=] [mask=] [fsmagic=] [fsuuid=] [uid=]
-				 [fowner]]
+				[euid=] [fowner=]]
 			lsm:	[[subj_user=] [subj_role=] [subj_type=]
 			lsm:	[[subj_user=] [subj_role=] [subj_type=]
 				 [obj_user=] [obj_role=] [obj_type=]]
 				 [obj_user=] [obj_role=] [obj_type=]]
 			option:	[[appraise_type=]] [permit_directio]
 			option:	[[appraise_type=]] [permit_directio]
 
 
 		base: 	func:= [BPRM_CHECK][MMAP_CHECK][FILE_CHECK][MODULE_CHECK]
 		base: 	func:= [BPRM_CHECK][MMAP_CHECK][FILE_CHECK][MODULE_CHECK]
 				[FIRMWARE_CHECK]
 				[FIRMWARE_CHECK]
-			mask:= [MAY_READ] [MAY_WRITE] [MAY_APPEND] [MAY_EXEC]
+			mask:= [[^]MAY_READ] [[^]MAY_WRITE] [[^]MAY_APPEND]
+			       [[^]MAY_EXEC]
 			fsmagic:= hex value
 			fsmagic:= hex value
 			fsuuid:= file system UUID (e.g 8bcbe394-4f13-4144-be8e-5aa9ea2ce2f6)
 			fsuuid:= file system UUID (e.g 8bcbe394-4f13-4144-be8e-5aa9ea2ce2f6)
 			uid:= decimal value
 			uid:= decimal value
+			euid:= decimal value
 			fowner:=decimal value
 			fowner:=decimal value
 		lsm:  	are LSM specific
 		lsm:  	are LSM specific
 		option:	appraise_type:= [imasig]
 		option:	appraise_type:= [imasig]

+ 9 - 1
Documentation/kernel-parameters.txt

@@ -1398,7 +1398,15 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 			The list of supported hash algorithms is defined
 			The list of supported hash algorithms is defined
 			in crypto/hash_info.h.
 			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
 			Load a policy which meets the needs of the Trusted
 			Computing Base.  This means IMA will measure all
 			Computing Base.  This means IMA will measure all
 			programs exec'd, files mmap'd for exec, and all files
 			programs exec'd, files mmap'd for exec, and all files

+ 1 - 1
security/integrity/ima/ima.h

@@ -115,7 +115,7 @@ void ima_add_violation(struct file *file, const unsigned char *filename,
 		       const char *op, const char *cause);
 		       const char *op, const char *cause);
 int ima_init_crypto(void);
 int ima_init_crypto(void);
 void ima_putc(struct seq_file *m, void *data, int datalen);
 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);
 struct ima_template_desc *ima_template_desc_current(void);
 int ima_init_template(void);
 int ima_init_template(void);
 
 

+ 2 - 2
security/integrity/ima/ima_fs.c

@@ -190,9 +190,9 @@ static const struct file_operations ima_measurements_ops = {
 	.release = seq_release,
 	.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++)
 	for (i = 0; i < size; i++)
 		seq_printf(m, "%02x", *(digest + i));
 		seq_printf(m, "%02x", *(digest + i));

+ 94 - 18
security/integrity/ima/ima_policy.c

@@ -27,6 +27,8 @@
 #define IMA_UID		0x0008
 #define IMA_UID		0x0008
 #define IMA_FOWNER	0x0010
 #define IMA_FOWNER	0x0010
 #define IMA_FSUUID	0x0020
 #define IMA_FSUUID	0x0020
+#define IMA_INMASK	0x0040
+#define IMA_EUID	0x0080
 
 
 #define UNKNOWN		0
 #define UNKNOWN		0
 #define MEASURE		0x0001	/* same as IMA_MEASURE */
 #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
 	LSM_SUBJ_USER, LSM_SUBJ_ROLE, LSM_SUBJ_TYPE
 };
 };
 
 
+enum policy_types { ORIGINAL_TCB = 1, DEFAULT_TCB };
+
 struct ima_rule_entry {
 struct ima_rule_entry {
 	struct list_head list;
 	struct list_head list;
 	int action;
 	int action;
@@ -70,7 +74,7 @@ struct ima_rule_entry {
  * normal users can easily run the machine out of memory simply building
  * normal users can easily run the machine out of memory simply building
  * and running executables.
  * 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 = PROC_SUPER_MAGIC, .flags = IMA_FSMAGIC},
 	{.action = DONT_MEASURE, .fsmagic = SYSFS_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 = 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 = SELINUX_MAGIC, .flags = IMA_FSMAGIC},
 	{.action = DONT_MEASURE, .fsmagic = CGROUP_SUPER_MAGIC,
 	{.action = DONT_MEASURE, .fsmagic = CGROUP_SUPER_MAGIC,
 	 .flags = IMA_FSMAGIC},
 	 .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,
 	{.action = MEASURE, .func = MMAP_CHECK, .mask = MAY_EXEC,
 	 .flags = IMA_FUNC | IMA_MASK},
 	 .flags = IMA_FUNC | IMA_MASK},
 	{.action = MEASURE, .func = BPRM_CHECK, .mask = MAY_EXEC,
 	{.action = MEASURE, .func = BPRM_CHECK, .mask = MAY_EXEC,
 	 .flags = IMA_FUNC | IMA_MASK},
 	 .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 = MODULE_CHECK, .flags = IMA_FUNC},
 	{.action = MEASURE, .func = FIRMWARE_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 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)
 static int __init default_measure_policy_setup(char *str)
 {
 {
-	ima_use_tcb = 1;
+	if (ima_policy)
+		return 1;
+
+	ima_policy = ORIGINAL_TCB;
 	return 1;
 	return 1;
 }
 }
 __setup("ima_tcb", default_measure_policy_setup);
 __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 bool ima_use_appraise_tcb __initdata;
 static int __init default_appraise_policy_setup(char *str)
 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) &&
 	if ((rule->flags & IMA_MASK) &&
 	    (rule->mask != mask && func != POST_SETATTR))
 	    (rule->mask != mask && func != POST_SETATTR))
 		return false;
 		return false;
+	if ((rule->flags & IMA_INMASK) &&
+	    (!(rule->mask & mask) && func != POST_SETATTR))
+		return false;
 	if ((rule->flags & IMA_FSMAGIC)
 	if ((rule->flags & IMA_FSMAGIC)
 	    && rule->fsmagic != inode->i_sb->s_magic)
 	    && rule->fsmagic != inode->i_sb->s_magic)
 		return false;
 		return false;
@@ -194,6 +232,16 @@ static bool ima_match_rules(struct ima_rule_entry *rule,
 		return false;
 		return false;
 	if ((rule->flags & IMA_UID) && !uid_eq(rule->uid, cred->uid))
 	if ((rule->flags & IMA_UID) && !uid_eq(rule->uid, cred->uid))
 		return false;
 		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))
 	if ((rule->flags & IMA_FOWNER) && !uid_eq(rule->fowner, inode->i_uid))
 		return false;
 		return false;
 	for (i = 0; i < MAX_LSM_RULES; i++) {
 	for (i = 0; i < MAX_LSM_RULES; i++) {
@@ -337,13 +385,27 @@ void __init ima_init_policy(void)
 {
 {
 	int i, measure_entries, appraise_entries;
 	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 ?
 	appraise_entries = ima_use_appraise_tcb ?
 			 ARRAY_SIZE(default_appraise_rules) : 0;
 			 ARRAY_SIZE(default_appraise_rules) : 0;
 
 
 	for (i = 0; i < measure_entries; i++)
 	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++) {
 	for (i = 0; i < appraise_entries; i++) {
 		list_add_tail(&default_appraise_rules[i].list,
 		list_add_tail(&default_appraise_rules[i].list,
@@ -373,7 +435,8 @@ enum {
 	Opt_audit,
 	Opt_audit,
 	Opt_obj_user, Opt_obj_role, Opt_obj_type,
 	Opt_obj_user, Opt_obj_role, Opt_obj_type,
 	Opt_subj_user, Opt_subj_role, Opt_subj_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
 	Opt_appraise_type, Opt_fsuuid, Opt_permit_directio
 };
 };
 
 
@@ -394,6 +457,7 @@ static match_table_t policy_tokens = {
 	{Opt_fsmagic, "fsmagic=%s"},
 	{Opt_fsmagic, "fsmagic=%s"},
 	{Opt_fsuuid, "fsuuid=%s"},
 	{Opt_fsuuid, "fsuuid=%s"},
 	{Opt_uid, "uid=%s"},
 	{Opt_uid, "uid=%s"},
+	{Opt_euid, "euid=%s"},
 	{Opt_fowner, "fowner=%s"},
 	{Opt_fowner, "fowner=%s"},
 	{Opt_appraise_type, "appraise_type=%s"},
 	{Opt_appraise_type, "appraise_type=%s"},
 	{Opt_permit_directio, "permit_directio"},
 	{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)
 static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
 {
 {
 	struct audit_buffer *ab;
 	struct audit_buffer *ab;
+	char *from;
 	char *p;
 	char *p;
 	int result = 0;
 	int result = 0;
 
 
@@ -525,18 +590,23 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
 			if (entry->mask)
 			if (entry->mask)
 				result = -EINVAL;
 				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;
 				entry->mask = MAY_EXEC;
-			else if (strcmp(args[0].from, "MAY_WRITE") == 0)
+			else if (strcmp(from, "MAY_WRITE") == 0)
 				entry->mask = MAY_WRITE;
 				entry->mask = MAY_WRITE;
-			else if (strcmp(args[0].from, "MAY_READ") == 0)
+			else if (strcmp(from, "MAY_READ") == 0)
 				entry->mask = MAY_READ;
 				entry->mask = MAY_READ;
-			else if (strcmp(args[0].from, "MAY_APPEND") == 0)
+			else if (strcmp(from, "MAY_APPEND") == 0)
 				entry->mask = MAY_APPEND;
 				entry->mask = MAY_APPEND;
 			else
 			else
 				result = -EINVAL;
 				result = -EINVAL;
 			if (!result)
 			if (!result)
-				entry->flags |= IMA_MASK;
+				entry->flags |= (*args[0].from == '^')
+				     ? IMA_INMASK : IMA_MASK;
 			break;
 			break;
 		case Opt_fsmagic:
 		case Opt_fsmagic:
 			ima_log_string(ab, "fsmagic", args[0].from);
 			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;
 			break;
 		case Opt_uid:
 		case Opt_uid:
 			ima_log_string(ab, "uid", args[0].from);
 			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)) {
 			if (uid_valid(entry->uid)) {
 				result = -EINVAL;
 				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);
 			result = kstrtoul(args[0].from, 10, &lnum);
 			if (!result) {
 			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;
 					result = -EINVAL;
 				else
 				else
-					entry->flags |= IMA_UID;
+					entry->flags |= (token == Opt_uid)
+					    ? IMA_UID : IMA_EUID;
 			}
 			}
 			break;
 			break;
 		case Opt_fowner:
 		case Opt_fowner:

+ 2 - 1
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,
 					 enum data_formats datafmt,
 					 struct ima_field_data *field_data)
 					 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) {
 	switch (datafmt) {
 	case DATA_FMT_DIGEST_WITH_ALGO:
 	case DATA_FMT_DIGEST_WITH_ALGO: