ima_policy.c 19.1 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 82
	{.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},
	{.action = MEASURE, .func = MMAP_CHECK, .mask = MAY_EXEC,
83
	 .flags = IMA_FUNC | IMA_MASK},
84
	{.action = MEASURE, .func = BPRM_CHECK, .mask = MAY_EXEC,
85
	 .flags = IMA_FUNC | IMA_MASK},
86
	{.action = MEASURE, .func = FILE_CHECK, .mask = MAY_READ, .uid = GLOBAL_ROOT_UID,
87
	 .flags = IMA_FUNC | IMA_MASK | IMA_UID},
88
	{.action = MEASURE, .func = MODULE_CHECK, .flags = IMA_FUNC},
89
	{.action = MEASURE, .func = FIRMWARE_CHECK, .flags = IMA_FUNC},
90 91
};

92
static struct ima_rule_entry default_appraise_rules[] = {
93 94 95 96 97 98 99 100 101 102
	{.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},
	{.action = DONT_APPRAISE, .fsmagic = CGROUP_SUPER_MAGIC, .flags = IMA_FSMAGIC},
103
#ifndef CONFIG_IMA_APPRAISE_SIGNED_INIT
104
	{.action = APPRAISE, .fowner = GLOBAL_ROOT_UID, .flags = IMA_FOWNER},
105 106 107 108 109
#else
	/* force signature */
	{.action = APPRAISE, .fowner = GLOBAL_ROOT_UID,
	 .flags = IMA_FOWNER | IMA_DIGSIG_REQUIRED},
#endif
110 111 112 113 114
};

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

116
static DEFINE_MUTEX(ima_rules_mutex);
M
Mimi Zohar 已提交
117

118
static bool ima_use_tcb __initdata;
119
static int __init default_measure_policy_setup(char *str)
120 121 122 123
{
	ima_use_tcb = 1;
	return 1;
}
124 125 126 127 128 129 130 131 132
__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);
133

134
/*
135 136 137 138
 * 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.
 *
139
 * Update the IMA LSM based rules to reflect the reloaded LSM policy.
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
 * 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);
}

163 164 165 166 167 168 169 170 171
/**
 * 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.
 */
172
static bool ima_match_rules(struct ima_rule_entry *rule,
173 174 175
			    struct inode *inode, enum ima_hooks func, int mask)
{
	struct task_struct *tsk = current;
M
Mimi Zohar 已提交
176
	const struct cred *cred = current_cred();
M
Mimi Zohar 已提交
177
	int i;
178

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

		if (!rule->lsm[i].rule)
			continue;
202
retry:
M
Mimi Zohar 已提交
203 204 205 206 207 208 209
		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,
210
							Audit_equal,
M
Mimi Zohar 已提交
211 212 213 214 215 216 217 218 219
							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,
220
							Audit_equal,
M
Mimi Zohar 已提交
221 222 223 224 225
							rule->lsm[i].rule,
							NULL);
		default:
			break;
		}
226 227 228 229
		if ((rc < 0) && (!retried)) {
			retried = 1;
			ima_lsm_update_rules();
			goto retry;
230
		}
M
Mimi Zohar 已提交
231 232 233
		if (!rc)
			return false;
	}
234 235 236
	return true;
}

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

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

261 262 263 264 265 266 267 268 269 270 271 272 273
/**
 * 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 已提交
274 275
int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask,
		     int flags)
276
{
277
	struct ima_rule_entry *entry;
M
Mimi Zohar 已提交
278
	int action = 0, actmask = flags | (flags << 1);
279

280
	list_for_each_entry(entry, ima_rules, list) {
281

M
Mimi Zohar 已提交
282 283 284 285 286
		if (!(entry->action & actmask))
			continue;

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

288 289
		action |= entry->flags & IMA_ACTION_FLAGS;

290
		action |= entry->action & IMA_DO_MASK;
291
		if (entry->action & IMA_APPRAISE)
292
			action |= get_subaction(entry, func);
293

294 295 296 297
		if (entry->action & IMA_DO_MASK)
			actmask &= ~(entry->action | entry->action << 1);
		else
			actmask &= ~(entry->action | entry->action >> 1);
298

M
Mimi Zohar 已提交
299 300
		if (!actmask)
			break;
301
	}
M
Mimi Zohar 已提交
302 303

	return action;
304 305
}

306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325
/*
 * 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;
}

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

	/* if !ima_use_tcb set entries = 0 so we load NO default rules */
337 338 339
	measure_entries = ima_use_tcb ? ARRAY_SIZE(default_rules) : 0;
	appraise_entries = ima_use_appraise_tcb ?
			 ARRAY_SIZE(default_appraise_rules) : 0;
340

341 342 343 344 345 346
	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);
347 348 349
	}

	ima_rules = &ima_default_rules;
350
}
M
Mimi Zohar 已提交
351 352 353 354 355 356 357 358 359 360

/**
 * 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)
{
361 362
	ima_rules = &ima_policy_rules;
	ima_update_policy_flag();
M
Mimi Zohar 已提交
363 364 365 366 367
}

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

static match_table_t policy_tokens = {
	{Opt_measure, "measure"},
	{Opt_dont_measure, "dont_measure"},
379 380
	{Opt_appraise, "appraise"},
	{Opt_dont_appraise, "dont_appraise"},
P
Peter Moody 已提交
381
	{Opt_audit, "audit"},
M
Mimi Zohar 已提交
382 383 384 385 386 387 388 389 390
	{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"},
391
	{Opt_fsuuid, "fsuuid=%s"},
M
Mimi Zohar 已提交
392
	{Opt_uid, "uid=%s"},
393
	{Opt_fowner, "fowner=%s"},
394
	{Opt_appraise_type, "appraise_type=%s"},
395
	{Opt_permit_directio, "permit_directio"},
M
Mimi Zohar 已提交
396 397 398
	{Opt_err, NULL}
};

399
static int ima_lsm_rule_init(struct ima_rule_entry *entry,
400
			     substring_t *args, int lsm_rule, int audit_type)
M
Mimi Zohar 已提交
401 402 403
{
	int result;

404 405 406
	if (entry->lsm[lsm_rule].rule)
		return -EINVAL;

407 408 409 410
	entry->lsm[lsm_rule].args_p = match_strdup(args);
	if (!entry->lsm[lsm_rule].args_p)
		return -ENOMEM;

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

M
Mimi Zohar 已提交
421 422 423
	return result;
}

424 425 426 427 428 429 430
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, " ");
}

431
static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
M
Mimi Zohar 已提交
432 433 434 435 436
{
	struct audit_buffer *ab;
	char *p;
	int result = 0;

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

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

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

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

M
Mimi Zohar 已提交
459 460 461
			entry->action = MEASURE;
			break;
		case Opt_dont_measure:
462
			ima_log_string(ab, "action", "dont_measure");
463 464 465 466

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

M
Mimi Zohar 已提交
467 468
			entry->action = DONT_MEASURE;
			break;
469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484
		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 已提交
485 486 487 488 489 490 491 492
		case Opt_audit:
			ima_log_string(ab, "action", "audit");

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

			entry->action = AUDIT;
			break;
M
Mimi Zohar 已提交
493
		case Opt_func:
494
			ima_log_string(ab, "func", args[0].from);
495 496

			if (entry->func)
497
				result = -EINVAL;
498

499 500 501 502 503
			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;
504 505
			else if (strcmp(args[0].from, "MODULE_CHECK") == 0)
				entry->func = MODULE_CHECK;
506 507
			else if (strcmp(args[0].from, "FIRMWARE_CHECK") == 0)
				entry->func = FIRMWARE_CHECK;
M
Mimi Zohar 已提交
508 509 510
			else if ((strcmp(args[0].from, "FILE_MMAP") == 0)
				|| (strcmp(args[0].from, "MMAP_CHECK") == 0))
				entry->func = MMAP_CHECK;
M
Mimi Zohar 已提交
511 512 513 514 515 516 517 518
			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:
519
			ima_log_string(ab, "mask", args[0].from);
520 521 522 523

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

M
Mimi Zohar 已提交
524 525 526 527 528 529 530 531 532 533 534 535 536 537
			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:
538
			ima_log_string(ab, "fsmagic", args[0].from);
539 540 541 542 543 544

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

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

			if (memchr_inv(entry->fsuuid, 0x00,
553
				       sizeof(entry->fsuuid))) {
554 555 556 557
				result = -EINVAL;
				break;
			}

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

566
			if (uid_valid(entry->uid)) {
567 568 569 570
				result = -EINVAL;
				break;
			}

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

583
			if (uid_valid(entry->fowner)) {
584 585 586 587
				result = -EINVAL;
				break;
			}

588
			result = kstrtoul(args[0].from, 10, &lnum);
589
			if (!result) {
590 591
				entry->fowner = make_kuid(current_user_ns(), (uid_t)lnum);
				if (!uid_valid(entry->fowner) || (((uid_t)lnum) != lnum))
592 593 594 595 596
					result = -EINVAL;
				else
					entry->flags |= IMA_FOWNER;
			}
			break;
M
Mimi Zohar 已提交
597
		case Opt_obj_user:
598
			ima_log_string(ab, "obj_user", args[0].from);
599
			result = ima_lsm_rule_init(entry, args,
M
Mimi Zohar 已提交
600 601 602 603
						   LSM_OBJ_USER,
						   AUDIT_OBJ_USER);
			break;
		case Opt_obj_role:
604
			ima_log_string(ab, "obj_role", args[0].from);
605
			result = ima_lsm_rule_init(entry, args,
M
Mimi Zohar 已提交
606 607 608 609
						   LSM_OBJ_ROLE,
						   AUDIT_OBJ_ROLE);
			break;
		case Opt_obj_type:
610
			ima_log_string(ab, "obj_type", args[0].from);
611
			result = ima_lsm_rule_init(entry, args,
M
Mimi Zohar 已提交
612 613 614 615
						   LSM_OBJ_TYPE,
						   AUDIT_OBJ_TYPE);
			break;
		case Opt_subj_user:
616
			ima_log_string(ab, "subj_user", args[0].from);
617
			result = ima_lsm_rule_init(entry, args,
M
Mimi Zohar 已提交
618 619 620 621
						   LSM_SUBJ_USER,
						   AUDIT_SUBJ_USER);
			break;
		case Opt_subj_role:
622
			ima_log_string(ab, "subj_role", args[0].from);
623
			result = ima_lsm_rule_init(entry, args,
M
Mimi Zohar 已提交
624 625 626 627
						   LSM_SUBJ_ROLE,
						   AUDIT_SUBJ_ROLE);
			break;
		case Opt_subj_type:
628
			ima_log_string(ab, "subj_type", args[0].from);
629
			result = ima_lsm_rule_init(entry, args,
M
Mimi Zohar 已提交
630 631 632
						   LSM_SUBJ_TYPE,
						   AUDIT_SUBJ_TYPE);
			break;
633 634 635 636 637 638 639 640 641 642 643 644
		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;
645 646 647
		case Opt_permit_directio:
			entry->flags |= IMA_PERMIT_DIRECTIO;
			break;
M
Mimi Zohar 已提交
648
		case Opt_err:
649
			ima_log_string(ab, "UNKNOWN", p);
650
			result = -EINVAL;
M
Mimi Zohar 已提交
651 652 653
			break;
		}
	}
654
	if (!result && (entry->action == UNKNOWN))
M
Mimi Zohar 已提交
655
		result = -EINVAL;
656 657
	else if (entry->func == MODULE_CHECK)
		ima_appraise |= IMA_APPRAISE_MODULES;
658 659
	else if (entry->func == FIRMWARE_CHECK)
		ima_appraise |= IMA_APPRAISE_FIRMWARE;
660
	audit_log_format(ab, "res=%d", !result);
M
Mimi Zohar 已提交
661 662 663 664 665
	audit_log_end(ab);
	return result;
}

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

680 681
	p = strsep(&rule, "\n");
	len = strlen(p) + 1;
682
	p += strspn(p, " \t");
683

684
	if (*p == '#' || *p == '\0')
685 686
		return len;

M
Mimi Zohar 已提交
687 688 689 690 691 692 693 694 695
	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);

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

705 706 707
	mutex_lock(&ima_rules_mutex);
	list_add_tail(&entry->list, &ima_policy_rules);
	mutex_unlock(&ima_rules_mutex);
E
Eric Paris 已提交
708 709

	return len;
M
Mimi Zohar 已提交
710 711 712
}

/* ima_delete_rules called to cleanup invalid policy */
713
void ima_delete_rules(void)
M
Mimi Zohar 已提交
714
{
715
	struct ima_rule_entry *entry, *tmp;
716
	int i;
M
Mimi Zohar 已提交
717

718 719
	mutex_lock(&ima_rules_mutex);
	list_for_each_entry_safe(entry, tmp, &ima_policy_rules, list) {
720 721 722
		for (i = 0; i < MAX_LSM_RULES; i++)
			kfree(entry->lsm[i].args_p);

M
Mimi Zohar 已提交
723 724 725
		list_del(&entry->list);
		kfree(entry);
	}
726
	mutex_unlock(&ima_rules_mutex);
M
Mimi Zohar 已提交
727
}