ima_policy.c 19.3 KB
Newer Older
1 2 3 4 5 6 7 8 9
/*
 * Copyright (C) 2008 IBM Corporation
 * Author: Mimi Zohar <zohar@us.ibm.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, version 2 of the License.
 *
 * ima_policy.c
10
 *	- initialize default measure policy rules
11 12 13 14 15 16
 *
 */
#include <linux/module.h>
#include <linux/list.h>
#include <linux/security.h>
#include <linux/magic.h>
M
Mimi Zohar 已提交
17
#include <linux/parser.h>
18
#include <linux/slab.h>
19
#include <linux/genhd.h>
20 21 22 23

#include "ima.h"

/* flags definitions */
24 25
#define IMA_FUNC	0x0001
#define IMA_MASK	0x0002
26 27
#define IMA_FSMAGIC	0x0004
#define IMA_UID		0x0008
28
#define IMA_FOWNER	0x0010
29
#define IMA_FSUUID	0x0020
30

31 32 33 34 35
#define UNKNOWN		0
#define MEASURE		0x0001	/* same as IMA_MEASURE */
#define DONT_MEASURE	0x0002
#define APPRAISE	0x0004	/* same as IMA_APPRAISE */
#define DONT_APPRAISE	0x0008
P
Peter Moody 已提交
36
#define AUDIT		0x0040
M
Mimi Zohar 已提交
37

38 39
int ima_policy_flag;

M
Mimi Zohar 已提交
40 41 42 43
#define MAX_LSM_RULES 6
enum lsm_rule_types { LSM_OBJ_USER, LSM_OBJ_ROLE, LSM_OBJ_TYPE,
	LSM_SUBJ_USER, LSM_SUBJ_ROLE, LSM_SUBJ_TYPE
};
44

45
struct ima_rule_entry {
46
	struct list_head list;
M
Mimi Zohar 已提交
47
	int action;
48 49 50 51
	unsigned int flags;
	enum ima_hooks func;
	int mask;
	unsigned long fsmagic;
52
	u8 fsuuid[16];
53
	kuid_t uid;
54
	kuid_t fowner;
M
Mimi Zohar 已提交
55 56
	struct {
		void *rule;	/* LSM file metadata specific */
57
		void *args_p;	/* audit value */
M
Mimi Zohar 已提交
58 59
		int type;	/* audit type */
	} lsm[MAX_LSM_RULES];
60 61
};

62 63
/*
 * Without LSM specific knowledge, the default policy can only be
64
 * written in terms of .action, .func, .mask, .fsmagic, .uid, and .fowner
M
Mimi Zohar 已提交
65
 */
66 67 68 69 70 71 72

/*
 * 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.
 */
73
static struct ima_rule_entry default_rules[] = {
74 75 76 77 78 79 80 81
	{.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 = DEVPTS_SUPER_MAGIC, .flags = IMA_FSMAGIC},
	{.action = DONT_MEASURE, .fsmagic = BINFMTFS_MAGIC, .flags = IMA_FSMAGIC},
	{.action = DONT_MEASURE, .fsmagic = SECURITYFS_MAGIC, .flags = IMA_FSMAGIC},
	{.action = DONT_MEASURE, .fsmagic = SELINUX_MAGIC, .flags = IMA_FSMAGIC},
82 83
	{.action = DONT_MEASURE, .fsmagic = CGROUP_SUPER_MAGIC,
	 .flags = IMA_FSMAGIC},
84
	{.action = DONT_MEASURE, .fsmagic = NSFS_MAGIC, .flags = IMA_FSMAGIC},
85
	{.action = MEASURE, .func = MMAP_CHECK, .mask = MAY_EXEC,
86
	 .flags = IMA_FUNC | IMA_MASK},
87
	{.action = MEASURE, .func = BPRM_CHECK, .mask = MAY_EXEC,
88
	 .flags = IMA_FUNC | IMA_MASK},
89
	{.action = MEASURE, .func = FILE_CHECK, .mask = MAY_READ, .uid = GLOBAL_ROOT_UID,
90
	 .flags = IMA_FUNC | IMA_MASK | IMA_UID},
91
	{.action = MEASURE, .func = MODULE_CHECK, .flags = IMA_FUNC},
92
	{.action = MEASURE, .func = FIRMWARE_CHECK, .flags = IMA_FUNC},
93 94
};

95
static struct ima_rule_entry default_appraise_rules[] = {
96 97 98 99 100 101 102 103 104
	{.action = DONT_APPRAISE, .fsmagic = PROC_SUPER_MAGIC, .flags = IMA_FSMAGIC},
	{.action = DONT_APPRAISE, .fsmagic = SYSFS_MAGIC, .flags = IMA_FSMAGIC},
	{.action = DONT_APPRAISE, .fsmagic = DEBUGFS_MAGIC, .flags = IMA_FSMAGIC},
	{.action = DONT_APPRAISE, .fsmagic = TMPFS_MAGIC, .flags = IMA_FSMAGIC},
	{.action = DONT_APPRAISE, .fsmagic = RAMFS_MAGIC, .flags = IMA_FSMAGIC},
	{.action = DONT_APPRAISE, .fsmagic = DEVPTS_SUPER_MAGIC, .flags = IMA_FSMAGIC},
	{.action = DONT_APPRAISE, .fsmagic = BINFMTFS_MAGIC, .flags = IMA_FSMAGIC},
	{.action = DONT_APPRAISE, .fsmagic = SECURITYFS_MAGIC, .flags = IMA_FSMAGIC},
	{.action = DONT_APPRAISE, .fsmagic = SELINUX_MAGIC, .flags = IMA_FSMAGIC},
105
	{.action = DONT_APPRAISE, .fsmagic = NSFS_MAGIC, .flags = IMA_FSMAGIC},
106
	{.action = DONT_APPRAISE, .fsmagic = CGROUP_SUPER_MAGIC, .flags = IMA_FSMAGIC},
107
#ifndef CONFIG_IMA_APPRAISE_SIGNED_INIT
108
	{.action = APPRAISE, .fowner = GLOBAL_ROOT_UID, .flags = IMA_FOWNER},
109 110 111 112 113
#else
	/* force signature */
	{.action = APPRAISE, .fowner = GLOBAL_ROOT_UID,
	 .flags = IMA_FOWNER | IMA_DIGSIG_REQUIRED},
#endif
114 115 116 117 118
};

static LIST_HEAD(ima_default_rules);
static LIST_HEAD(ima_policy_rules);
static struct list_head *ima_rules;
119

120
static DEFINE_MUTEX(ima_rules_mutex);
M
Mimi Zohar 已提交
121

122
static bool ima_use_tcb __initdata;
123
static int __init default_measure_policy_setup(char *str)
124 125 126 127
{
	ima_use_tcb = 1;
	return 1;
}
128 129 130 131 132 133 134 135 136
__setup("ima_tcb", default_measure_policy_setup);

static bool ima_use_appraise_tcb __initdata;
static int __init default_appraise_policy_setup(char *str)
{
	ima_use_appraise_tcb = 1;
	return 1;
}
__setup("ima_appraise_tcb", default_appraise_policy_setup);
137

138
/*
139 140 141 142
 * Although the IMA policy does not change, the LSM policy can be
 * reloaded, leaving the IMA LSM based rules referring to the old,
 * stale LSM policy.
 *
143
 * Update the IMA LSM based rules to reflect the reloaded LSM policy.
144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
 * We assume the rules still exist; and BUG_ON() if they don't.
 */
static void ima_lsm_update_rules(void)
{
	struct ima_rule_entry *entry, *tmp;
	int result;
	int i;

	mutex_lock(&ima_rules_mutex);
	list_for_each_entry_safe(entry, tmp, &ima_policy_rules, list) {
		for (i = 0; i < MAX_LSM_RULES; i++) {
			if (!entry->lsm[i].rule)
				continue;
			result = security_filter_rule_init(entry->lsm[i].type,
							   Audit_equal,
							   entry->lsm[i].args_p,
							   &entry->lsm[i].rule);
			BUG_ON(!entry->lsm[i].rule);
		}
	}
	mutex_unlock(&ima_rules_mutex);
}

167 168 169 170 171 172 173 174 175
/**
 * ima_match_rules - determine whether an inode matches the measure rule.
 * @rule: a pointer to a rule
 * @inode: a pointer to an inode
 * @func: LIM hook identifier
 * @mask: requested action (MAY_READ | MAY_WRITE | MAY_APPEND | MAY_EXEC)
 *
 * Returns true on rule match, false on failure.
 */
176
static bool ima_match_rules(struct ima_rule_entry *rule,
177 178 179
			    struct inode *inode, enum ima_hooks func, int mask)
{
	struct task_struct *tsk = current;
M
Mimi Zohar 已提交
180
	const struct cred *cred = current_cred();
M
Mimi Zohar 已提交
181
	int i;
182

183 184
	if ((rule->flags & IMA_FUNC) &&
	    (rule->func != func && func != POST_SETATTR))
185
		return false;
186 187
	if ((rule->flags & IMA_MASK) &&
	    (rule->mask != mask && func != POST_SETATTR))
188 189 190 191
		return false;
	if ((rule->flags & IMA_FSMAGIC)
	    && rule->fsmagic != inode->i_sb->s_magic)
		return false;
192
	if ((rule->flags & IMA_FSUUID) &&
193
	    memcmp(rule->fsuuid, inode->i_sb->s_uuid, sizeof(rule->fsuuid)))
194
		return false;
195
	if ((rule->flags & IMA_UID) && !uid_eq(rule->uid, cred->uid))
196
		return false;
197
	if ((rule->flags & IMA_FOWNER) && !uid_eq(rule->fowner, inode->i_uid))
198
		return false;
M
Mimi Zohar 已提交
199
	for (i = 0; i < MAX_LSM_RULES; i++) {
200
		int rc = 0;
M
Mimi Zohar 已提交
201
		u32 osid, sid;
202
		int retried = 0;
M
Mimi Zohar 已提交
203 204 205

		if (!rule->lsm[i].rule)
			continue;
206
retry:
M
Mimi Zohar 已提交
207 208 209 210 211 212 213
		switch (i) {
		case LSM_OBJ_USER:
		case LSM_OBJ_ROLE:
		case LSM_OBJ_TYPE:
			security_inode_getsecid(inode, &osid);
			rc = security_filter_rule_match(osid,
							rule->lsm[i].type,
214
							Audit_equal,
M
Mimi Zohar 已提交
215 216 217 218 219 220 221 222 223
							rule->lsm[i].rule,
							NULL);
			break;
		case LSM_SUBJ_USER:
		case LSM_SUBJ_ROLE:
		case LSM_SUBJ_TYPE:
			security_task_getsecid(tsk, &sid);
			rc = security_filter_rule_match(sid,
							rule->lsm[i].type,
224
							Audit_equal,
M
Mimi Zohar 已提交
225 226 227 228 229
							rule->lsm[i].rule,
							NULL);
		default:
			break;
		}
230 231 232 233
		if ((rc < 0) && (!retried)) {
			retried = 1;
			ima_lsm_update_rules();
			goto retry;
234
		}
M
Mimi Zohar 已提交
235 236 237
		if (!rc)
			return false;
	}
238 239 240
	return true;
}

241 242
/*
 * In addition to knowing that we need to appraise the file in general,
243
 * we need to differentiate between calling hooks, for hook specific rules.
244
 */
245
static int get_subaction(struct ima_rule_entry *rule, int func)
246
{
247 248 249
	if (!(rule->flags & IMA_FUNC))
		return IMA_FILE_APPRAISE;

250
	switch (func) {
251 252 253 254 255 256
	case MMAP_CHECK:
		return IMA_MMAP_APPRAISE;
	case BPRM_CHECK:
		return IMA_BPRM_APPRAISE;
	case MODULE_CHECK:
		return IMA_MODULE_APPRAISE;
257 258
	case FIRMWARE_CHECK:
		return IMA_FIRMWARE_APPRAISE;
259 260 261 262 263 264
	case FILE_CHECK:
	default:
		return IMA_FILE_APPRAISE;
	}
}

265 266 267 268 269 270 271 272 273 274 275 276 277
/**
 * ima_match_policy - decision based on LSM and other conditions
 * @inode: pointer to an inode for which the policy decision is being made
 * @func: IMA hook identifier
 * @mask: requested action (MAY_READ | MAY_WRITE | MAY_APPEND | MAY_EXEC)
 *
 * Measure decision based on func/mask/fsmagic and LSM(subj/obj/type)
 * conditions.
 *
 * (There is no need for locking when walking the policy list,
 * as elements in the list are never deleted, nor does the list
 * change.)
 */
M
Mimi Zohar 已提交
278 279
int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask,
		     int flags)
280
{
281
	struct ima_rule_entry *entry;
M
Mimi Zohar 已提交
282
	int action = 0, actmask = flags | (flags << 1);
283

284
	list_for_each_entry(entry, ima_rules, list) {
285

M
Mimi Zohar 已提交
286 287 288 289 290
		if (!(entry->action & actmask))
			continue;

		if (!ima_match_rules(entry, inode, func, mask))
			continue;
291

292 293
		action |= entry->flags & IMA_ACTION_FLAGS;

294
		action |= entry->action & IMA_DO_MASK;
295
		if (entry->action & IMA_APPRAISE)
296
			action |= get_subaction(entry, func);
297

298 299 300 301
		if (entry->action & IMA_DO_MASK)
			actmask &= ~(entry->action | entry->action << 1);
		else
			actmask &= ~(entry->action | entry->action >> 1);
302

M
Mimi Zohar 已提交
303 304
		if (!actmask)
			break;
305
	}
M
Mimi Zohar 已提交
306 307

	return action;
308 309
}

310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329
/*
 * Initialize the ima_policy_flag variable based on the currently
 * loaded policy.  Based on this flag, the decision to short circuit
 * out of a function or not call the function in the first place
 * can be made earlier.
 */
void ima_update_policy_flag(void)
{
	struct ima_rule_entry *entry;

	ima_policy_flag = 0;
	list_for_each_entry(entry, ima_rules, list) {
		if (entry->action & IMA_DO_MASK)
			ima_policy_flag |= entry->action;
	}

	if (!ima_appraise)
		ima_policy_flag &= ~IMA_APPRAISE;
}

330 331 332
/**
 * ima_init_policy - initialize the default measure rules.
 *
333 334
 * ima_rules points to either the ima_default_rules or the
 * the new ima_policy_rules.
335
 */
336
void __init ima_init_policy(void)
337
{
338
	int i, measure_entries, appraise_entries;
339 340

	/* if !ima_use_tcb set entries = 0 so we load NO default rules */
341 342 343
	measure_entries = ima_use_tcb ? ARRAY_SIZE(default_rules) : 0;
	appraise_entries = ima_use_appraise_tcb ?
			 ARRAY_SIZE(default_appraise_rules) : 0;
344

345 346 347 348 349 350
	for (i = 0; i < measure_entries; i++)
		list_add_tail(&default_rules[i].list, &ima_default_rules);

	for (i = 0; i < appraise_entries; i++) {
		list_add_tail(&default_appraise_rules[i].list,
			      &ima_default_rules);
351 352 353
	}

	ima_rules = &ima_default_rules;
354
}
M
Mimi Zohar 已提交
355 356 357 358 359 360 361 362 363 364

/**
 * ima_update_policy - update default_rules with new measure rules
 *
 * Called on file .release to update the default rules with a complete new
 * policy.  Once updated, the policy is locked, no additional rules can be
 * added to the policy.
 */
void ima_update_policy(void)
{
365 366
	ima_rules = &ima_policy_rules;
	ima_update_policy_flag();
M
Mimi Zohar 已提交
367 368 369 370 371
}

enum {
	Opt_err = -1,
	Opt_measure = 1, Opt_dont_measure,
372
	Opt_appraise, Opt_dont_appraise,
P
Peter Moody 已提交
373
	Opt_audit,
M
Mimi Zohar 已提交
374 375
	Opt_obj_user, Opt_obj_role, Opt_obj_type,
	Opt_subj_user, Opt_subj_role, Opt_subj_type,
376
	Opt_func, Opt_mask, Opt_fsmagic, Opt_uid, Opt_fowner,
377
	Opt_appraise_type, Opt_fsuuid, Opt_permit_directio
M
Mimi Zohar 已提交
378 379 380 381 382
};

static match_table_t policy_tokens = {
	{Opt_measure, "measure"},
	{Opt_dont_measure, "dont_measure"},
383 384
	{Opt_appraise, "appraise"},
	{Opt_dont_appraise, "dont_appraise"},
P
Peter Moody 已提交
385
	{Opt_audit, "audit"},
M
Mimi Zohar 已提交
386 387 388 389 390 391 392 393 394
	{Opt_obj_user, "obj_user=%s"},
	{Opt_obj_role, "obj_role=%s"},
	{Opt_obj_type, "obj_type=%s"},
	{Opt_subj_user, "subj_user=%s"},
	{Opt_subj_role, "subj_role=%s"},
	{Opt_subj_type, "subj_type=%s"},
	{Opt_func, "func=%s"},
	{Opt_mask, "mask=%s"},
	{Opt_fsmagic, "fsmagic=%s"},
395
	{Opt_fsuuid, "fsuuid=%s"},
M
Mimi Zohar 已提交
396
	{Opt_uid, "uid=%s"},
397
	{Opt_fowner, "fowner=%s"},
398
	{Opt_appraise_type, "appraise_type=%s"},
399
	{Opt_permit_directio, "permit_directio"},
M
Mimi Zohar 已提交
400 401 402
	{Opt_err, NULL}
};

403
static int ima_lsm_rule_init(struct ima_rule_entry *entry,
404
			     substring_t *args, int lsm_rule, int audit_type)
M
Mimi Zohar 已提交
405 406 407
{
	int result;

408 409 410
	if (entry->lsm[lsm_rule].rule)
		return -EINVAL;

411 412 413 414
	entry->lsm[lsm_rule].args_p = match_strdup(args);
	if (!entry->lsm[lsm_rule].args_p)
		return -ENOMEM;

M
Mimi Zohar 已提交
415 416
	entry->lsm[lsm_rule].type = audit_type;
	result = security_filter_rule_init(entry->lsm[lsm_rule].type,
417 418
					   Audit_equal,
					   entry->lsm[lsm_rule].args_p,
M
Mimi Zohar 已提交
419
					   &entry->lsm[lsm_rule].rule);
420 421
	if (!entry->lsm[lsm_rule].rule) {
		kfree(entry->lsm[lsm_rule].args_p);
M
Mimi Zohar 已提交
422
		return -EINVAL;
423 424
	}

M
Mimi Zohar 已提交
425 426 427
	return result;
}

428 429 430 431 432 433 434
static void ima_log_string(struct audit_buffer *ab, char *key, char *value)
{
	audit_log_format(ab, "%s=", key);
	audit_log_untrustedstring(ab, value);
	audit_log_format(ab, " ");
}

435
static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
M
Mimi Zohar 已提交
436 437 438 439 440
{
	struct audit_buffer *ab;
	char *p;
	int result = 0;

M
Mimi Zohar 已提交
441
	ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_INTEGRITY_RULE);
M
Mimi Zohar 已提交
442

443
	entry->uid = INVALID_UID;
444
	entry->fowner = INVALID_UID;
445
	entry->action = UNKNOWN;
E
Eric Paris 已提交
446
	while ((p = strsep(&rule, " \t")) != NULL) {
M
Mimi Zohar 已提交
447 448 449 450 451 452
		substring_t args[MAX_OPT_ARGS];
		int token;
		unsigned long lnum;

		if (result < 0)
			break;
E
Eric Paris 已提交
453 454
		if ((*p == '\0') || (*p == ' ') || (*p == '\t'))
			continue;
M
Mimi Zohar 已提交
455 456 457
		token = match_token(p, policy_tokens, args);
		switch (token) {
		case Opt_measure:
458
			ima_log_string(ab, "action", "measure");
459 460 461 462

			if (entry->action != UNKNOWN)
				result = -EINVAL;

M
Mimi Zohar 已提交
463 464 465
			entry->action = MEASURE;
			break;
		case Opt_dont_measure:
466
			ima_log_string(ab, "action", "dont_measure");
467 468 469 470

			if (entry->action != UNKNOWN)
				result = -EINVAL;

M
Mimi Zohar 已提交
471 472
			entry->action = DONT_MEASURE;
			break;
473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488
		case Opt_appraise:
			ima_log_string(ab, "action", "appraise");

			if (entry->action != UNKNOWN)
				result = -EINVAL;

			entry->action = APPRAISE;
			break;
		case Opt_dont_appraise:
			ima_log_string(ab, "action", "dont_appraise");

			if (entry->action != UNKNOWN)
				result = -EINVAL;

			entry->action = DONT_APPRAISE;
			break;
P
Peter Moody 已提交
489 490 491 492 493 494 495 496
		case Opt_audit:
			ima_log_string(ab, "action", "audit");

			if (entry->action != UNKNOWN)
				result = -EINVAL;

			entry->action = AUDIT;
			break;
M
Mimi Zohar 已提交
497
		case Opt_func:
498
			ima_log_string(ab, "func", args[0].from);
499 500

			if (entry->func)
501
				result = -EINVAL;
502

503 504 505 506 507
			if (strcmp(args[0].from, "FILE_CHECK") == 0)
				entry->func = FILE_CHECK;
			/* PATH_CHECK is for backwards compat */
			else if (strcmp(args[0].from, "PATH_CHECK") == 0)
				entry->func = FILE_CHECK;
508 509
			else if (strcmp(args[0].from, "MODULE_CHECK") == 0)
				entry->func = MODULE_CHECK;
510 511
			else if (strcmp(args[0].from, "FIRMWARE_CHECK") == 0)
				entry->func = FIRMWARE_CHECK;
M
Mimi Zohar 已提交
512 513 514
			else if ((strcmp(args[0].from, "FILE_MMAP") == 0)
				|| (strcmp(args[0].from, "MMAP_CHECK") == 0))
				entry->func = MMAP_CHECK;
M
Mimi Zohar 已提交
515 516 517 518 519 520 521 522
			else if (strcmp(args[0].from, "BPRM_CHECK") == 0)
				entry->func = BPRM_CHECK;
			else
				result = -EINVAL;
			if (!result)
				entry->flags |= IMA_FUNC;
			break;
		case Opt_mask:
523
			ima_log_string(ab, "mask", args[0].from);
524 525 526 527

			if (entry->mask)
				result = -EINVAL;

M
Mimi Zohar 已提交
528 529 530 531 532 533 534 535 536 537 538 539 540 541
			if ((strcmp(args[0].from, "MAY_EXEC")) == 0)
				entry->mask = MAY_EXEC;
			else if (strcmp(args[0].from, "MAY_WRITE") == 0)
				entry->mask = MAY_WRITE;
			else if (strcmp(args[0].from, "MAY_READ") == 0)
				entry->mask = MAY_READ;
			else if (strcmp(args[0].from, "MAY_APPEND") == 0)
				entry->mask = MAY_APPEND;
			else
				result = -EINVAL;
			if (!result)
				entry->flags |= IMA_MASK;
			break;
		case Opt_fsmagic:
542
			ima_log_string(ab, "fsmagic", args[0].from);
543 544 545 546 547 548

			if (entry->fsmagic) {
				result = -EINVAL;
				break;
			}

549
			result = kstrtoul(args[0].from, 16, &entry->fsmagic);
M
Mimi Zohar 已提交
550 551 552
			if (!result)
				entry->flags |= IMA_FSMAGIC;
			break;
553 554 555 556
		case Opt_fsuuid:
			ima_log_string(ab, "fsuuid", args[0].from);

			if (memchr_inv(entry->fsuuid, 0x00,
557
				       sizeof(entry->fsuuid))) {
558 559 560 561
				result = -EINVAL;
				break;
			}

562 563 564 565
			result = blk_part_pack_uuid(args[0].from,
						    entry->fsuuid);
			if (!result)
				entry->flags |= IMA_FSUUID;
566
			break;
M
Mimi Zohar 已提交
567
		case Opt_uid:
568
			ima_log_string(ab, "uid", args[0].from);
569

570
			if (uid_valid(entry->uid)) {
571 572 573 574
				result = -EINVAL;
				break;
			}

575
			result = kstrtoul(args[0].from, 10, &lnum);
M
Mimi Zohar 已提交
576
			if (!result) {
577 578
				entry->uid = make_kuid(current_user_ns(), (uid_t)lnum);
				if (!uid_valid(entry->uid) || (((uid_t)lnum) != lnum))
M
Mimi Zohar 已提交
579 580 581 582 583
					result = -EINVAL;
				else
					entry->flags |= IMA_UID;
			}
			break;
584 585 586
		case Opt_fowner:
			ima_log_string(ab, "fowner", args[0].from);

587
			if (uid_valid(entry->fowner)) {
588 589 590 591
				result = -EINVAL;
				break;
			}

592
			result = kstrtoul(args[0].from, 10, &lnum);
593
			if (!result) {
594 595
				entry->fowner = make_kuid(current_user_ns(), (uid_t)lnum);
				if (!uid_valid(entry->fowner) || (((uid_t)lnum) != lnum))
596 597 598 599 600
					result = -EINVAL;
				else
					entry->flags |= IMA_FOWNER;
			}
			break;
M
Mimi Zohar 已提交
601
		case Opt_obj_user:
602
			ima_log_string(ab, "obj_user", args[0].from);
603
			result = ima_lsm_rule_init(entry, args,
M
Mimi Zohar 已提交
604 605 606 607
						   LSM_OBJ_USER,
						   AUDIT_OBJ_USER);
			break;
		case Opt_obj_role:
608
			ima_log_string(ab, "obj_role", args[0].from);
609
			result = ima_lsm_rule_init(entry, args,
M
Mimi Zohar 已提交
610 611 612 613
						   LSM_OBJ_ROLE,
						   AUDIT_OBJ_ROLE);
			break;
		case Opt_obj_type:
614
			ima_log_string(ab, "obj_type", args[0].from);
615
			result = ima_lsm_rule_init(entry, args,
M
Mimi Zohar 已提交
616 617 618 619
						   LSM_OBJ_TYPE,
						   AUDIT_OBJ_TYPE);
			break;
		case Opt_subj_user:
620
			ima_log_string(ab, "subj_user", args[0].from);
621
			result = ima_lsm_rule_init(entry, args,
M
Mimi Zohar 已提交
622 623 624 625
						   LSM_SUBJ_USER,
						   AUDIT_SUBJ_USER);
			break;
		case Opt_subj_role:
626
			ima_log_string(ab, "subj_role", args[0].from);
627
			result = ima_lsm_rule_init(entry, args,
M
Mimi Zohar 已提交
628 629 630 631
						   LSM_SUBJ_ROLE,
						   AUDIT_SUBJ_ROLE);
			break;
		case Opt_subj_type:
632
			ima_log_string(ab, "subj_type", args[0].from);
633
			result = ima_lsm_rule_init(entry, args,
M
Mimi Zohar 已提交
634 635 636
						   LSM_SUBJ_TYPE,
						   AUDIT_SUBJ_TYPE);
			break;
637 638 639 640 641 642 643 644 645 646 647 648
		case Opt_appraise_type:
			if (entry->action != APPRAISE) {
				result = -EINVAL;
				break;
			}

			ima_log_string(ab, "appraise_type", args[0].from);
			if ((strcmp(args[0].from, "imasig")) == 0)
				entry->flags |= IMA_DIGSIG_REQUIRED;
			else
				result = -EINVAL;
			break;
649 650 651
		case Opt_permit_directio:
			entry->flags |= IMA_PERMIT_DIRECTIO;
			break;
M
Mimi Zohar 已提交
652
		case Opt_err:
653
			ima_log_string(ab, "UNKNOWN", p);
654
			result = -EINVAL;
M
Mimi Zohar 已提交
655 656 657
			break;
		}
	}
658
	if (!result && (entry->action == UNKNOWN))
M
Mimi Zohar 已提交
659
		result = -EINVAL;
660 661
	else if (entry->func == MODULE_CHECK)
		ima_appraise |= IMA_APPRAISE_MODULES;
662 663
	else if (entry->func == FIRMWARE_CHECK)
		ima_appraise |= IMA_APPRAISE_FIRMWARE;
664
	audit_log_format(ab, "res=%d", !result);
M
Mimi Zohar 已提交
665 666 667 668 669
	audit_log_end(ab);
	return result;
}

/**
670
 * ima_parse_add_rule - add a rule to ima_policy_rules
M
Mimi Zohar 已提交
671 672 673
 * @rule - ima measurement policy rule
 *
 * Uses a mutex to protect the policy list from multiple concurrent writers.
674
 * Returns the length of the rule parsed, an error code on failure
M
Mimi Zohar 已提交
675
 */
676
ssize_t ima_parse_add_rule(char *rule)
M
Mimi Zohar 已提交
677
{
678
	static const char op[] = "update_policy";
679
	char *p;
680
	struct ima_rule_entry *entry;
681
	ssize_t result, len;
M
Mimi Zohar 已提交
682 683
	int audit_info = 0;

684 685
	p = strsep(&rule, "\n");
	len = strlen(p) + 1;
686
	p += strspn(p, " \t");
687

688
	if (*p == '#' || *p == '\0')
689 690
		return len;

M
Mimi Zohar 已提交
691 692 693 694 695 696 697 698 699
	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
	if (!entry) {
		integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL,
				    NULL, op, "-ENOMEM", -ENOMEM, audit_info);
		return -ENOMEM;
	}

	INIT_LIST_HEAD(&entry->list);

700
	result = ima_parse_rule(p, entry);
E
Eric Paris 已提交
701
	if (result) {
M
Mimi Zohar 已提交
702
		kfree(entry);
M
Mimi Zohar 已提交
703
		integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL,
704
				    NULL, op, "invalid-policy", result,
M
Mimi Zohar 已提交
705
				    audit_info);
E
Eric Paris 已提交
706
		return result;
M
Mimi Zohar 已提交
707
	}
E
Eric Paris 已提交
708

709 710 711
	mutex_lock(&ima_rules_mutex);
	list_add_tail(&entry->list, &ima_policy_rules);
	mutex_unlock(&ima_rules_mutex);
E
Eric Paris 已提交
712 713

	return len;
M
Mimi Zohar 已提交
714 715 716
}

/* ima_delete_rules called to cleanup invalid policy */
717
void ima_delete_rules(void)
M
Mimi Zohar 已提交
718
{
719
	struct ima_rule_entry *entry, *tmp;
720
	int i;
M
Mimi Zohar 已提交
721

722 723
	mutex_lock(&ima_rules_mutex);
	list_for_each_entry_safe(entry, tmp, &ima_policy_rules, list) {
724 725 726
		for (i = 0; i < MAX_LSM_RULES; i++)
			kfree(entry->lsm[i].args_p);

M
Mimi Zohar 已提交
727 728 729
		list_del(&entry->list);
		kfree(entry);
	}
730
	mutex_unlock(&ima_rules_mutex);
M
Mimi Zohar 已提交
731
}