ima_policy.c 32.5 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
 *
 */
#include <linux/module.h>
#include <linux/list.h>
15
#include <linux/fs.h>
16 17
#include <linux/security.h>
#include <linux/magic.h>
M
Mimi Zohar 已提交
18
#include <linux/parser.h>
19
#include <linux/slab.h>
20
#include <linux/rculist.h>
21
#include <linux/genhd.h>
22
#include <linux/seq_file.h>
23 24 25 26

#include "ima.h"

/* flags definitions */
27 28
#define IMA_FUNC	0x0001
#define IMA_MASK	0x0002
29 30
#define IMA_FSMAGIC	0x0004
#define IMA_UID		0x0008
31
#define IMA_FOWNER	0x0010
32
#define IMA_FSUUID	0x0020
33
#define IMA_INMASK	0x0040
34
#define IMA_EUID	0x0080
35
#define IMA_PCR		0x0100
36
#define IMA_FSNAME	0x0200
37

38 39 40 41 42
#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 已提交
43
#define AUDIT		0x0040
44 45
#define HASH		0x0100
#define DONT_HASH	0x0200
M
Mimi Zohar 已提交
46

47 48 49
#define INVALID_PCR(a) (((a) < 0) || \
	(a) >= (FIELD_SIZEOF(struct integrity_iint_cache, measured_pcrs) * 8))

50
int ima_policy_flag;
51
static int temp_ima_appraise;
52

M
Mimi Zohar 已提交
53 54 55 56
#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
};
57

M
Mimi Zohar 已提交
58 59
enum policy_types { ORIGINAL_TCB = 1, DEFAULT_TCB };

60
struct ima_rule_entry {
61
	struct list_head list;
M
Mimi Zohar 已提交
62
	int action;
63 64 65 66
	unsigned int flags;
	enum ima_hooks func;
	int mask;
	unsigned long fsmagic;
67
	uuid_t fsuuid;
68
	kuid_t uid;
69
	kuid_t fowner;
70 71
	bool (*uid_op)(kuid_t, kuid_t);    /* Handlers for operators       */
	bool (*fowner_op)(kuid_t, kuid_t); /* uid_eq(), uid_gt(), uid_lt() */
72
	int pcr;
M
Mimi Zohar 已提交
73 74
	struct {
		void *rule;	/* LSM file metadata specific */
75
		void *args_p;	/* audit value */
M
Mimi Zohar 已提交
76 77
		int type;	/* audit type */
	} lsm[MAX_LSM_RULES];
78
	char *fsname;
79 80
};

81 82
/*
 * Without LSM specific knowledge, the default policy can only be
83
 * written in terms of .action, .func, .mask, .fsmagic, .uid, and .fowner
M
Mimi Zohar 已提交
84
 */
85 86 87 88 89 90 91

/*
 * 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.
 */
92
static struct ima_rule_entry dont_measure_rules[] __ro_after_init = {
93 94 95 96 97 98 99 100
	{.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},
101
	{.action = DONT_MEASURE, .fsmagic = SMACK_MAGIC, .flags = IMA_FSMAGIC},
102 103
	{.action = DONT_MEASURE, .fsmagic = CGROUP_SUPER_MAGIC,
	 .flags = IMA_FSMAGIC},
104 105
	{.action = DONT_MEASURE, .fsmagic = CGROUP2_SUPER_MAGIC,
	 .flags = IMA_FSMAGIC},
M
Mimi Zohar 已提交
106 107 108
	{.action = DONT_MEASURE, .fsmagic = NSFS_MAGIC, .flags = IMA_FSMAGIC}
};

109
static struct ima_rule_entry original_measurement_rules[] __ro_after_init = {
M
Mimi Zohar 已提交
110 111 112 113 114
	{.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,
115 116
	 .uid = GLOBAL_ROOT_UID, .uid_op = &uid_eq,
	 .flags = IMA_FUNC | IMA_MASK | IMA_UID},
M
Mimi Zohar 已提交
117 118 119 120
	{.action = MEASURE, .func = MODULE_CHECK, .flags = IMA_FUNC},
	{.action = MEASURE, .func = FIRMWARE_CHECK, .flags = IMA_FUNC},
};

121
static struct ima_rule_entry default_measurement_rules[] __ro_after_init = {
122
	{.action = MEASURE, .func = MMAP_CHECK, .mask = MAY_EXEC,
123
	 .flags = IMA_FUNC | IMA_MASK},
124
	{.action = MEASURE, .func = BPRM_CHECK, .mask = MAY_EXEC,
125
	 .flags = IMA_FUNC | IMA_MASK},
M
Mimi Zohar 已提交
126
	{.action = MEASURE, .func = FILE_CHECK, .mask = MAY_READ,
127 128
	 .uid = GLOBAL_ROOT_UID, .uid_op = &uid_eq,
	 .flags = IMA_FUNC | IMA_INMASK | IMA_EUID},
M
Mimi Zohar 已提交
129
	{.action = MEASURE, .func = FILE_CHECK, .mask = MAY_READ,
130 131
	 .uid = GLOBAL_ROOT_UID, .uid_op = &uid_eq,
	 .flags = IMA_FUNC | IMA_INMASK | IMA_UID},
132
	{.action = MEASURE, .func = MODULE_CHECK, .flags = IMA_FUNC},
133
	{.action = MEASURE, .func = FIRMWARE_CHECK, .flags = IMA_FUNC},
134
	{.action = MEASURE, .func = POLICY_CHECK, .flags = IMA_FUNC},
135 136
};

137
static struct ima_rule_entry default_appraise_rules[] __ro_after_init = {
138 139 140 141 142 143 144 145 146
	{.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},
147
	{.action = DONT_APPRAISE, .fsmagic = SMACK_MAGIC, .flags = IMA_FSMAGIC},
148
	{.action = DONT_APPRAISE, .fsmagic = NSFS_MAGIC, .flags = IMA_FSMAGIC},
149
	{.action = DONT_APPRAISE, .fsmagic = CGROUP_SUPER_MAGIC, .flags = IMA_FSMAGIC},
150
	{.action = DONT_APPRAISE, .fsmagic = CGROUP2_SUPER_MAGIC, .flags = IMA_FSMAGIC},
M
Mimi Zohar 已提交
151 152 153 154
#ifdef CONFIG_IMA_WRITE_POLICY
	{.action = APPRAISE, .func = POLICY_CHECK,
	.flags = IMA_FUNC | IMA_DIGSIG_REQUIRED},
#endif
155
#ifndef CONFIG_IMA_APPRAISE_SIGNED_INIT
156 157
	{.action = APPRAISE, .fowner = GLOBAL_ROOT_UID, .fowner_op = &uid_eq,
	 .flags = IMA_FOWNER},
158 159
#else
	/* force signature */
160
	{.action = APPRAISE, .fowner = GLOBAL_ROOT_UID, .fowner_op = &uid_eq,
161 162
	 .flags = IMA_FOWNER | IMA_DIGSIG_REQUIRED},
#endif
163 164
};

165 166 167 168 169 170 171 172 173 174 175
static struct ima_rule_entry secure_boot_rules[] __ro_after_init = {
	{.action = APPRAISE, .func = MODULE_CHECK,
	 .flags = IMA_FUNC | IMA_DIGSIG_REQUIRED},
	{.action = APPRAISE, .func = FIRMWARE_CHECK,
	 .flags = IMA_FUNC | IMA_DIGSIG_REQUIRED},
	{.action = APPRAISE, .func = KEXEC_KERNEL_CHECK,
	 .flags = IMA_FUNC | IMA_DIGSIG_REQUIRED},
	{.action = APPRAISE, .func = POLICY_CHECK,
	 .flags = IMA_FUNC | IMA_DIGSIG_REQUIRED},
};

176 177
static LIST_HEAD(ima_default_rules);
static LIST_HEAD(ima_policy_rules);
178
static LIST_HEAD(ima_temp_rules);
179
static struct list_head *ima_rules;
180

M
Mimi Zohar 已提交
181
static int ima_policy __initdata;
182

183
static int __init default_measure_policy_setup(char *str)
184
{
M
Mimi Zohar 已提交
185 186 187 188
	if (ima_policy)
		return 1;

	ima_policy = ORIGINAL_TCB;
189 190
	return 1;
}
191 192
__setup("ima_tcb", default_measure_policy_setup);

193
static bool ima_use_appraise_tcb __initdata;
194
static bool ima_use_secure_boot __initdata;
195
static bool ima_fail_unverifiable_sigs __ro_after_init;
M
Mimi Zohar 已提交
196 197
static int __init policy_setup(char *str)
{
198
	char *p;
M
Mimi Zohar 已提交
199

200 201 202 203 204 205
	while ((p = strsep(&str, " |\n")) != NULL) {
		if (*p == ' ')
			continue;
		if ((strcmp(p, "tcb") == 0) && !ima_policy)
			ima_policy = DEFAULT_TCB;
		else if (strcmp(p, "appraise_tcb") == 0)
206
			ima_use_appraise_tcb = true;
207
		else if (strcmp(p, "secure_boot") == 0)
208
			ima_use_secure_boot = true;
209 210
		else if (strcmp(p, "fail_securely") == 0)
			ima_fail_unverifiable_sigs = true;
211
	}
M
Mimi Zohar 已提交
212 213 214 215 216

	return 1;
}
__setup("ima_policy=", policy_setup);

217 218
static int __init default_appraise_policy_setup(char *str)
{
219
	ima_use_appraise_tcb = true;
220 221 222
	return 1;
}
__setup("ima_appraise_tcb", default_appraise_policy_setup);
223

224
/*
225 226 227 228
 * The LSM policy can be reloaded, leaving the IMA LSM based rules referring
 * to the old, stale LSM policy.  Update the IMA LSM based rules to reflect
 * the reloaded LSM policy.  We assume the rules still exist; and BUG_ON() if
 * they don't.
229 230 231
 */
static void ima_lsm_update_rules(void)
{
232
	struct ima_rule_entry *entry;
233 234 235
	int result;
	int i;

236
	list_for_each_entry(entry, &ima_policy_rules, list) {
237 238 239 240 241 242 243 244 245 246 247 248
		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);
		}
	}
}

249 250 251 252
/**
 * ima_match_rules - determine whether an inode matches the measure rule.
 * @rule: a pointer to a rule
 * @inode: a pointer to an inode
253 254
 * @cred: a pointer to a credentials structure for user validation
 * @secid: the secid of the task to be validated
255 256 257 258 259
 * @func: LIM hook identifier
 * @mask: requested action (MAY_READ | MAY_WRITE | MAY_APPEND | MAY_EXEC)
 *
 * Returns true on rule match, false on failure.
 */
260
static bool ima_match_rules(struct ima_rule_entry *rule, struct inode *inode,
261
			    const struct cred *cred, u32 secid,
262
			    enum ima_hooks func, int mask)
263
{
M
Mimi Zohar 已提交
264
	int i;
265

266 267
	if ((rule->flags & IMA_FUNC) &&
	    (rule->func != func && func != POST_SETATTR))
268
		return false;
269 270
	if ((rule->flags & IMA_MASK) &&
	    (rule->mask != mask && func != POST_SETATTR))
271
		return false;
272 273 274
	if ((rule->flags & IMA_INMASK) &&
	    (!(rule->mask & mask) && func != POST_SETATTR))
		return false;
275 276 277
	if ((rule->flags & IMA_FSMAGIC)
	    && rule->fsmagic != inode->i_sb->s_magic)
		return false;
278 279 280
	if ((rule->flags & IMA_FSNAME)
	    && strcmp(rule->fsname, inode->i_sb->s_type->name))
		return false;
281
	if ((rule->flags & IMA_FSUUID) &&
282
	    !uuid_equal(&rule->fsuuid, &inode->i_sb->s_uuid))
283
		return false;
284
	if ((rule->flags & IMA_UID) && !rule->uid_op(cred->uid, rule->uid))
285
		return false;
286 287
	if (rule->flags & IMA_EUID) {
		if (has_capability_noaudit(current, CAP_SETUID)) {
288 289 290
			if (!rule->uid_op(cred->euid, rule->uid)
			    && !rule->uid_op(cred->suid, rule->uid)
			    && !rule->uid_op(cred->uid, rule->uid))
291
				return false;
292
		} else if (!rule->uid_op(cred->euid, rule->uid))
293 294 295
			return false;
	}

296 297
	if ((rule->flags & IMA_FOWNER) &&
	    !rule->fowner_op(inode->i_uid, rule->fowner))
298
		return false;
M
Mimi Zohar 已提交
299
	for (i = 0; i < MAX_LSM_RULES; i++) {
300
		int rc = 0;
301
		u32 osid;
302
		int retried = 0;
M
Mimi Zohar 已提交
303 304 305

		if (!rule->lsm[i].rule)
			continue;
306
retry:
M
Mimi Zohar 已提交
307 308 309 310 311 312 313
		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,
314
							Audit_equal,
M
Mimi Zohar 已提交
315 316 317 318 319 320
							rule->lsm[i].rule,
							NULL);
			break;
		case LSM_SUBJ_USER:
		case LSM_SUBJ_ROLE:
		case LSM_SUBJ_TYPE:
321
			rc = security_filter_rule_match(secid,
M
Mimi Zohar 已提交
322
							rule->lsm[i].type,
323
							Audit_equal,
M
Mimi Zohar 已提交
324 325 326 327 328
							rule->lsm[i].rule,
							NULL);
		default:
			break;
		}
329 330 331 332
		if ((rc < 0) && (!retried)) {
			retried = 1;
			ima_lsm_update_rules();
			goto retry;
333
		}
M
Mimi Zohar 已提交
334 335 336
		if (!rc)
			return false;
	}
337 338 339
	return true;
}

340 341
/*
 * In addition to knowing that we need to appraise the file in general,
342
 * we need to differentiate between calling hooks, for hook specific rules.
343
 */
344
static int get_subaction(struct ima_rule_entry *rule, enum ima_hooks func)
345
{
346 347 348
	if (!(rule->flags & IMA_FUNC))
		return IMA_FILE_APPRAISE;

349
	switch (func) {
350 351 352 353
	case MMAP_CHECK:
		return IMA_MMAP_APPRAISE;
	case BPRM_CHECK:
		return IMA_BPRM_APPRAISE;
354 355
	case CREDS_CHECK:
		return IMA_CREDS_APPRAISE;
356
	case FILE_CHECK:
357
	case POST_SETATTR:
358
		return IMA_FILE_APPRAISE;
359 360 361
	case MODULE_CHECK ... MAX_CHECK - 1:
	default:
		return IMA_READ_APPRAISE;
362 363 364
	}
}

365 366 367
/**
 * ima_match_policy - decision based on LSM and other conditions
 * @inode: pointer to an inode for which the policy decision is being made
368 369 370
 * @cred: pointer to a credentials structure for which the policy decision is
 *        being made
 * @secid: LSM secid of the task to be validated
371 372
 * @func: IMA hook identifier
 * @mask: requested action (MAY_READ | MAY_WRITE | MAY_APPEND | MAY_EXEC)
373
 * @pcr: set the pcr to extend
374 375 376 377
 *
 * Measure decision based on func/mask/fsmagic and LSM(subj/obj/type)
 * conditions.
 *
378 379 380
 * Since the IMA policy may be updated multiple times we need to lock the
 * list when walking it.  Reads are many orders of magnitude more numerous
 * than writes so ima_match_policy() is classical RCU candidate.
381
 */
382 383
int ima_match_policy(struct inode *inode, const struct cred *cred, u32 secid,
		     enum ima_hooks func, int mask, int flags, int *pcr)
384
{
385
	struct ima_rule_entry *entry;
M
Mimi Zohar 已提交
386
	int action = 0, actmask = flags | (flags << 1);
387

388 389
	rcu_read_lock();
	list_for_each_entry_rcu(entry, ima_rules, list) {
390

M
Mimi Zohar 已提交
391 392 393
		if (!(entry->action & actmask))
			continue;

394
		if (!ima_match_rules(entry, inode, cred, secid, func, mask))
M
Mimi Zohar 已提交
395
			continue;
396

397 398
		action |= entry->flags & IMA_ACTION_FLAGS;

399
		action |= entry->action & IMA_DO_MASK;
400
		if (entry->action & IMA_APPRAISE) {
401
			action |= get_subaction(entry, func);
M
Mimi Zohar 已提交
402
			action &= ~IMA_HASH;
403 404
			if (ima_fail_unverifiable_sigs)
				action |= IMA_FAIL_UNVERIFIABLE_SIGS;
405
		}
406

407 408 409 410
		if (entry->action & IMA_DO_MASK)
			actmask &= ~(entry->action | entry->action << 1);
		else
			actmask &= ~(entry->action | entry->action >> 1);
411

412 413 414
		if ((pcr) && (entry->flags & IMA_PCR))
			*pcr = entry->pcr;

M
Mimi Zohar 已提交
415 416
		if (!actmask)
			break;
417
	}
418
	rcu_read_unlock();
M
Mimi Zohar 已提交
419 420

	return action;
421 422
}

423 424 425 426 427 428 429 430 431 432 433 434 435 436 437
/*
 * 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;

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

438
	ima_appraise |= temp_ima_appraise;
439 440 441 442
	if (!ima_appraise)
		ima_policy_flag &= ~IMA_APPRAISE;
}

443 444 445
/**
 * ima_init_policy - initialize the default measure rules.
 *
446 447
 * ima_rules points to either the ima_default_rules or the
 * the new ima_policy_rules.
448
 */
449
void __init ima_init_policy(void)
450
{
451
	int i, measure_entries, appraise_entries, secure_boot_entries;
452

M
Mimi Zohar 已提交
453 454
	/* if !ima_policy set entries = 0 so we load NO default rules */
	measure_entries = ima_policy ? ARRAY_SIZE(dont_measure_rules) : 0;
455 456
	appraise_entries = ima_use_appraise_tcb ?
			 ARRAY_SIZE(default_appraise_rules) : 0;
457 458
	secure_boot_entries = ima_use_secure_boot ?
			ARRAY_SIZE(secure_boot_rules) : 0;
459

460
	for (i = 0; i < measure_entries; i++)
M
Mimi Zohar 已提交
461 462 463 464 465 466 467 468 469 470 471 472 473 474 475
		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;
	}
476

477 478 479 480 481 482 483 484
	/*
	 * Insert the appraise rules requiring file signatures, prior to
	 * any other appraise rules.
	 */
	for (i = 0; i < secure_boot_entries; i++)
		list_add_tail(&secure_boot_rules[i].list,
			      &ima_default_rules);

485 486 487
	for (i = 0; i < appraise_entries; i++) {
		list_add_tail(&default_appraise_rules[i].list,
			      &ima_default_rules);
M
Mimi Zohar 已提交
488 489
		if (default_appraise_rules[i].func == POLICY_CHECK)
			temp_ima_appraise |= IMA_APPRAISE_POLICY;
490 491 492
	}

	ima_rules = &ima_default_rules;
M
Mimi Zohar 已提交
493
	ima_update_policy_flag();
494
}
M
Mimi Zohar 已提交
495

496
/* Make sure we have a valid policy, at least containing some rules. */
497
int ima_check_policy(void)
498 499 500 501 502 503
{
	if (list_empty(&ima_temp_rules))
		return -EINVAL;
	return 0;
}

M
Mimi Zohar 已提交
504 505 506 507
/**
 * ima_update_policy - update default_rules with new measure rules
 *
 * Called on file .release to update the default rules with a complete new
508 509 510 511 512 513
 * policy.  What we do here is to splice ima_policy_rules and ima_temp_rules so
 * they make a queue.  The policy may be updated multiple times and this is the
 * RCU updater.
 *
 * Policy rules are never deleted so ima_policy_flag gets zeroed only once when
 * we switch from the default policy to user defined.
M
Mimi Zohar 已提交
514 515 516
 */
void ima_update_policy(void)
{
517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537
	struct list_head *first, *last, *policy;

	/* append current policy with the new rules */
	first = (&ima_temp_rules)->next;
	last = (&ima_temp_rules)->prev;
	policy = &ima_policy_rules;

	synchronize_rcu();

	last->next = policy;
	rcu_assign_pointer(list_next_rcu(policy->prev), first);
	first->prev = policy->prev;
	policy->prev = last;

	/* prepare for the next policy rules addition */
	INIT_LIST_HEAD(&ima_temp_rules);

	if (ima_rules != policy) {
		ima_policy_flag = 0;
		ima_rules = policy;
	}
538
	ima_update_policy_flag();
M
Mimi Zohar 已提交
539 540 541 542 543
}

enum {
	Opt_err = -1,
	Opt_measure = 1, Opt_dont_measure,
544
	Opt_appraise, Opt_dont_appraise,
545
	Opt_audit, Opt_hash, Opt_dont_hash,
M
Mimi Zohar 已提交
546 547
	Opt_obj_user, Opt_obj_role, Opt_obj_type,
	Opt_subj_user, Opt_subj_role, Opt_subj_type,
548
	Opt_func, Opt_mask, Opt_fsmagic, Opt_fsname,
549 550 551
	Opt_fsuuid, Opt_uid_eq, Opt_euid_eq, Opt_fowner_eq,
	Opt_uid_gt, Opt_euid_gt, Opt_fowner_gt,
	Opt_uid_lt, Opt_euid_lt, Opt_fowner_lt,
552 553
	Opt_appraise_type, Opt_permit_directio,
	Opt_pcr
M
Mimi Zohar 已提交
554 555 556 557 558
};

static match_table_t policy_tokens = {
	{Opt_measure, "measure"},
	{Opt_dont_measure, "dont_measure"},
559 560
	{Opt_appraise, "appraise"},
	{Opt_dont_appraise, "dont_appraise"},
P
Peter Moody 已提交
561
	{Opt_audit, "audit"},
562 563
	{Opt_hash, "hash"},
	{Opt_dont_hash, "dont_hash"},
M
Mimi Zohar 已提交
564 565 566 567 568 569 570 571 572
	{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"},
573
	{Opt_fsname, "fsname=%s"},
574
	{Opt_fsuuid, "fsuuid=%s"},
575 576 577 578 579 580 581 582 583
	{Opt_uid_eq, "uid=%s"},
	{Opt_euid_eq, "euid=%s"},
	{Opt_fowner_eq, "fowner=%s"},
	{Opt_uid_gt, "uid>%s"},
	{Opt_euid_gt, "euid>%s"},
	{Opt_fowner_gt, "fowner>%s"},
	{Opt_uid_lt, "uid<%s"},
	{Opt_euid_lt, "euid<%s"},
	{Opt_fowner_lt, "fowner<%s"},
584
	{Opt_appraise_type, "appraise_type=%s"},
585
	{Opt_permit_directio, "permit_directio"},
586
	{Opt_pcr, "pcr=%s"},
M
Mimi Zohar 已提交
587 588 589
	{Opt_err, NULL}
};

590
static int ima_lsm_rule_init(struct ima_rule_entry *entry,
591
			     substring_t *args, int lsm_rule, int audit_type)
M
Mimi Zohar 已提交
592 593 594
{
	int result;

595 596 597
	if (entry->lsm[lsm_rule].rule)
		return -EINVAL;

598 599 600 601
	entry->lsm[lsm_rule].args_p = match_strdup(args);
	if (!entry->lsm[lsm_rule].args_p)
		return -ENOMEM;

M
Mimi Zohar 已提交
602 603
	entry->lsm[lsm_rule].type = audit_type;
	result = security_filter_rule_init(entry->lsm[lsm_rule].type,
604 605
					   Audit_equal,
					   entry->lsm[lsm_rule].args_p,
M
Mimi Zohar 已提交
606
					   &entry->lsm[lsm_rule].rule);
607 608
	if (!entry->lsm[lsm_rule].rule) {
		kfree(entry->lsm[lsm_rule].args_p);
M
Mimi Zohar 已提交
609
		return -EINVAL;
610 611
	}

M
Mimi Zohar 已提交
612 613 614
	return result;
}

615 616
static void ima_log_string_op(struct audit_buffer *ab, char *key, char *value,
			      bool (*rule_operator)(kuid_t, kuid_t))
617
{
618 619 620 621 622 623
	if (rule_operator == &uid_gt)
		audit_log_format(ab, "%s>", key);
	else if (rule_operator == &uid_lt)
		audit_log_format(ab, "%s<", key);
	else
		audit_log_format(ab, "%s=", key);
624 625 626
	audit_log_untrustedstring(ab, value);
	audit_log_format(ab, " ");
}
627 628 629 630
static void ima_log_string(struct audit_buffer *ab, char *key, char *value)
{
	ima_log_string_op(ab, key, value, NULL);
}
631

632
static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
M
Mimi Zohar 已提交
633 634
{
	struct audit_buffer *ab;
635
	char *from;
M
Mimi Zohar 已提交
636
	char *p;
637
	bool uid_token;
M
Mimi Zohar 已提交
638 639
	int result = 0;

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

642
	entry->uid = INVALID_UID;
643
	entry->fowner = INVALID_UID;
644 645
	entry->uid_op = &uid_eq;
	entry->fowner_op = &uid_eq;
646
	entry->action = UNKNOWN;
E
Eric Paris 已提交
647
	while ((p = strsep(&rule, " \t")) != NULL) {
M
Mimi Zohar 已提交
648 649 650 651 652 653
		substring_t args[MAX_OPT_ARGS];
		int token;
		unsigned long lnum;

		if (result < 0)
			break;
E
Eric Paris 已提交
654 655
		if ((*p == '\0') || (*p == ' ') || (*p == '\t'))
			continue;
M
Mimi Zohar 已提交
656 657 658
		token = match_token(p, policy_tokens, args);
		switch (token) {
		case Opt_measure:
659
			ima_log_string(ab, "action", "measure");
660 661 662 663

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

M
Mimi Zohar 已提交
664 665 666
			entry->action = MEASURE;
			break;
		case Opt_dont_measure:
667
			ima_log_string(ab, "action", "dont_measure");
668 669 670 671

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

M
Mimi Zohar 已提交
672 673
			entry->action = DONT_MEASURE;
			break;
674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689
		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 已提交
690 691 692 693 694 695 696 697
		case Opt_audit:
			ima_log_string(ab, "action", "audit");

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

			entry->action = AUDIT;
			break;
698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713
		case Opt_hash:
			ima_log_string(ab, "action", "hash");

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

			entry->action = HASH;
			break;
		case Opt_dont_hash:
			ima_log_string(ab, "action", "dont_hash");

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

			entry->action = DONT_HASH;
			break;
M
Mimi Zohar 已提交
714
		case Opt_func:
715
			ima_log_string(ab, "func", args[0].from);
716 717

			if (entry->func)
718
				result = -EINVAL;
719

720 721 722 723 724
			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;
725 726
			else if (strcmp(args[0].from, "MODULE_CHECK") == 0)
				entry->func = MODULE_CHECK;
727 728
			else if (strcmp(args[0].from, "FIRMWARE_CHECK") == 0)
				entry->func = FIRMWARE_CHECK;
M
Mimi Zohar 已提交
729 730 731
			else if ((strcmp(args[0].from, "FILE_MMAP") == 0)
				|| (strcmp(args[0].from, "MMAP_CHECK") == 0))
				entry->func = MMAP_CHECK;
M
Mimi Zohar 已提交
732 733
			else if (strcmp(args[0].from, "BPRM_CHECK") == 0)
				entry->func = BPRM_CHECK;
734 735
			else if (strcmp(args[0].from, "CREDS_CHECK") == 0)
				entry->func = CREDS_CHECK;
736 737 738 739 740 741
			else if (strcmp(args[0].from, "KEXEC_KERNEL_CHECK") ==
				 0)
				entry->func = KEXEC_KERNEL_CHECK;
			else if (strcmp(args[0].from, "KEXEC_INITRAMFS_CHECK")
				 == 0)
				entry->func = KEXEC_INITRAMFS_CHECK;
742 743
			else if (strcmp(args[0].from, "POLICY_CHECK") == 0)
				entry->func = POLICY_CHECK;
M
Mimi Zohar 已提交
744 745 746 747 748 749
			else
				result = -EINVAL;
			if (!result)
				entry->flags |= IMA_FUNC;
			break;
		case Opt_mask:
750
			ima_log_string(ab, "mask", args[0].from);
751 752 753 754

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

755 756 757 758 759
			from = args[0].from;
			if (*from == '^')
				from++;

			if ((strcmp(from, "MAY_EXEC")) == 0)
M
Mimi Zohar 已提交
760
				entry->mask = MAY_EXEC;
761
			else if (strcmp(from, "MAY_WRITE") == 0)
M
Mimi Zohar 已提交
762
				entry->mask = MAY_WRITE;
763
			else if (strcmp(from, "MAY_READ") == 0)
M
Mimi Zohar 已提交
764
				entry->mask = MAY_READ;
765
			else if (strcmp(from, "MAY_APPEND") == 0)
M
Mimi Zohar 已提交
766 767 768 769
				entry->mask = MAY_APPEND;
			else
				result = -EINVAL;
			if (!result)
770 771
				entry->flags |= (*args[0].from == '^')
				     ? IMA_INMASK : IMA_MASK;
M
Mimi Zohar 已提交
772 773
			break;
		case Opt_fsmagic:
774
			ima_log_string(ab, "fsmagic", args[0].from);
775 776 777 778 779 780

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

781
			result = kstrtoul(args[0].from, 16, &entry->fsmagic);
M
Mimi Zohar 已提交
782 783 784
			if (!result)
				entry->flags |= IMA_FSMAGIC;
			break;
785 786 787 788 789 790 791 792 793 794 795
		case Opt_fsname:
			ima_log_string(ab, "fsname", args[0].from);

			entry->fsname = kstrdup(args[0].from, GFP_KERNEL);
			if (!entry->fsname) {
				result = -ENOMEM;
				break;
			}
			result = 0;
			entry->flags |= IMA_FSNAME;
			break;
796 797 798
		case Opt_fsuuid:
			ima_log_string(ab, "fsuuid", args[0].from);

799
			if (!uuid_is_null(&entry->fsuuid)) {
800 801 802 803
				result = -EINVAL;
				break;
			}

804
			result = uuid_parse(args[0].from, &entry->fsuuid);
805 806
			if (!result)
				entry->flags |= IMA_FSUUID;
807
			break;
808 809 810 811 812 813 814 815 816 817 818 819 820 821 822
		case Opt_uid_gt:
		case Opt_euid_gt:
			entry->uid_op = &uid_gt;
		case Opt_uid_lt:
		case Opt_euid_lt:
			if ((token == Opt_uid_lt) || (token == Opt_euid_lt))
				entry->uid_op = &uid_lt;
		case Opt_uid_eq:
		case Opt_euid_eq:
			uid_token = (token == Opt_uid_eq) ||
				    (token == Opt_uid_gt) ||
				    (token == Opt_uid_lt);

			ima_log_string_op(ab, uid_token ? "uid" : "euid",
					  args[0].from, entry->uid_op);
823

824
			if (uid_valid(entry->uid)) {
825 826 827 828
				result = -EINVAL;
				break;
			}

829
			result = kstrtoul(args[0].from, 10, &lnum);
M
Mimi Zohar 已提交
830
			if (!result) {
831 832 833 834
				entry->uid = make_kuid(current_user_ns(),
						       (uid_t) lnum);
				if (!uid_valid(entry->uid) ||
				    (uid_t)lnum != lnum)
M
Mimi Zohar 已提交
835 836
					result = -EINVAL;
				else
837
					entry->flags |= uid_token
838
					    ? IMA_UID : IMA_EUID;
M
Mimi Zohar 已提交
839 840
			}
			break;
841 842 843 844 845 846 847 848
		case Opt_fowner_gt:
			entry->fowner_op = &uid_gt;
		case Opt_fowner_lt:
			if (token == Opt_fowner_lt)
				entry->fowner_op = &uid_lt;
		case Opt_fowner_eq:
			ima_log_string_op(ab, "fowner", args[0].from,
					  entry->fowner_op);
849

850
			if (uid_valid(entry->fowner)) {
851 852 853 854
				result = -EINVAL;
				break;
			}

855
			result = kstrtoul(args[0].from, 10, &lnum);
856
			if (!result) {
857 858
				entry->fowner = make_kuid(current_user_ns(), (uid_t)lnum);
				if (!uid_valid(entry->fowner) || (((uid_t)lnum) != lnum))
859 860 861 862 863
					result = -EINVAL;
				else
					entry->flags |= IMA_FOWNER;
			}
			break;
M
Mimi Zohar 已提交
864
		case Opt_obj_user:
865
			ima_log_string(ab, "obj_user", args[0].from);
866
			result = ima_lsm_rule_init(entry, args,
M
Mimi Zohar 已提交
867 868 869 870
						   LSM_OBJ_USER,
						   AUDIT_OBJ_USER);
			break;
		case Opt_obj_role:
871
			ima_log_string(ab, "obj_role", args[0].from);
872
			result = ima_lsm_rule_init(entry, args,
M
Mimi Zohar 已提交
873 874 875 876
						   LSM_OBJ_ROLE,
						   AUDIT_OBJ_ROLE);
			break;
		case Opt_obj_type:
877
			ima_log_string(ab, "obj_type", args[0].from);
878
			result = ima_lsm_rule_init(entry, args,
M
Mimi Zohar 已提交
879 880 881 882
						   LSM_OBJ_TYPE,
						   AUDIT_OBJ_TYPE);
			break;
		case Opt_subj_user:
883
			ima_log_string(ab, "subj_user", args[0].from);
884
			result = ima_lsm_rule_init(entry, args,
M
Mimi Zohar 已提交
885 886 887 888
						   LSM_SUBJ_USER,
						   AUDIT_SUBJ_USER);
			break;
		case Opt_subj_role:
889
			ima_log_string(ab, "subj_role", args[0].from);
890
			result = ima_lsm_rule_init(entry, args,
M
Mimi Zohar 已提交
891 892 893 894
						   LSM_SUBJ_ROLE,
						   AUDIT_SUBJ_ROLE);
			break;
		case Opt_subj_type:
895
			ima_log_string(ab, "subj_type", args[0].from);
896
			result = ima_lsm_rule_init(entry, args,
M
Mimi Zohar 已提交
897 898 899
						   LSM_SUBJ_TYPE,
						   AUDIT_SUBJ_TYPE);
			break;
900 901 902 903 904 905 906 907 908 909 910 911
		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;
912 913
		case Opt_permit_directio:
			entry->flags |= IMA_PERMIT_DIRECTIO;
914 915 916 917 918 919 920 921 922 923 924 925 926 927
			break;
		case Opt_pcr:
			if (entry->action != MEASURE) {
				result = -EINVAL;
				break;
			}
			ima_log_string(ab, "pcr", args[0].from);

			result = kstrtoint(args[0].from, 10, &entry->pcr);
			if (result || INVALID_PCR(entry->pcr))
				result = -EINVAL;
			else
				entry->flags |= IMA_PCR;

928
			break;
M
Mimi Zohar 已提交
929
		case Opt_err:
930
			ima_log_string(ab, "UNKNOWN", p);
931
			result = -EINVAL;
M
Mimi Zohar 已提交
932 933 934
			break;
		}
	}
935
	if (!result && (entry->action == UNKNOWN))
M
Mimi Zohar 已提交
936
		result = -EINVAL;
937
	else if (entry->func == MODULE_CHECK)
938
		temp_ima_appraise |= IMA_APPRAISE_MODULES;
939
	else if (entry->func == FIRMWARE_CHECK)
940
		temp_ima_appraise |= IMA_APPRAISE_FIRMWARE;
941 942
	else if (entry->func == POLICY_CHECK)
		temp_ima_appraise |= IMA_APPRAISE_POLICY;
943
	audit_log_format(ab, "res=%d", !result);
M
Mimi Zohar 已提交
944 945 946 947 948
	audit_log_end(ab);
	return result;
}

/**
949
 * ima_parse_add_rule - add a rule to ima_policy_rules
M
Mimi Zohar 已提交
950 951
 * @rule - ima measurement policy rule
 *
952
 * Avoid locking by allowing just one writer at a time in ima_write_policy()
953
 * Returns the length of the rule parsed, an error code on failure
M
Mimi Zohar 已提交
954
 */
955
ssize_t ima_parse_add_rule(char *rule)
M
Mimi Zohar 已提交
956
{
957
	static const char op[] = "update_policy";
958
	char *p;
959
	struct ima_rule_entry *entry;
960
	ssize_t result, len;
M
Mimi Zohar 已提交
961 962
	int audit_info = 0;

963 964
	p = strsep(&rule, "\n");
	len = strlen(p) + 1;
965
	p += strspn(p, " \t");
966

967
	if (*p == '#' || *p == '\0')
968 969
		return len;

M
Mimi Zohar 已提交
970 971 972 973 974 975 976 977 978
	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);

979
	result = ima_parse_rule(p, entry);
E
Eric Paris 已提交
980
	if (result) {
M
Mimi Zohar 已提交
981
		kfree(entry);
M
Mimi Zohar 已提交
982
		integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL,
983
				    NULL, op, "invalid-policy", result,
M
Mimi Zohar 已提交
984
				    audit_info);
E
Eric Paris 已提交
985
		return result;
M
Mimi Zohar 已提交
986
	}
E
Eric Paris 已提交
987

988
	list_add_tail(&entry->list, &ima_temp_rules);
E
Eric Paris 已提交
989 990

	return len;
M
Mimi Zohar 已提交
991 992
}

993 994 995 996 997 998
/**
 * ima_delete_rules() called to cleanup invalid in-flight policy.
 * We don't need locking as we operate on the temp list, which is
 * different from the active one.  There is also only one user of
 * ima_delete_rules() at a time.
 */
999
void ima_delete_rules(void)
M
Mimi Zohar 已提交
1000
{
1001
	struct ima_rule_entry *entry, *tmp;
1002
	int i;
M
Mimi Zohar 已提交
1003

1004
	temp_ima_appraise = 0;
1005
	list_for_each_entry_safe(entry, tmp, &ima_temp_rules, list) {
1006 1007 1008
		for (i = 0; i < MAX_LSM_RULES; i++)
			kfree(entry->lsm[i].args_p);

M
Mimi Zohar 已提交
1009 1010 1011 1012
		list_del(&entry->list);
		kfree(entry);
	}
}
1013 1014 1015 1016 1017 1018

#ifdef	CONFIG_IMA_READ_POLICY
enum {
	mask_exec = 0, mask_write, mask_read, mask_append
};

1019
static const char *const mask_tokens[] = {
1020 1021 1022 1023 1024 1025
	"MAY_EXEC",
	"MAY_WRITE",
	"MAY_READ",
	"MAY_APPEND"
};

1026
#define __ima_hook_stringify(str)	(#str),
1027

1028
static const char *const func_tokens[] = {
1029
	__ima_hooks(__ima_hook_stringify)
1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066
};

void *ima_policy_start(struct seq_file *m, loff_t *pos)
{
	loff_t l = *pos;
	struct ima_rule_entry *entry;

	rcu_read_lock();
	list_for_each_entry_rcu(entry, ima_rules, list) {
		if (!l--) {
			rcu_read_unlock();
			return entry;
		}
	}
	rcu_read_unlock();
	return NULL;
}

void *ima_policy_next(struct seq_file *m, void *v, loff_t *pos)
{
	struct ima_rule_entry *entry = v;

	rcu_read_lock();
	entry = list_entry_rcu(entry->list.next, struct ima_rule_entry, list);
	rcu_read_unlock();
	(*pos)++;

	return (&entry->list == ima_rules) ? NULL : entry;
}

void ima_policy_stop(struct seq_file *m, void *v)
{
}

#define pt(token)	policy_tokens[token + Opt_err].pattern
#define mt(token)	mask_tokens[token]

1067 1068 1069 1070 1071
/*
 * policy_func_show - display the ima_hooks policy rule
 */
static void policy_func_show(struct seq_file *m, enum ima_hooks func)
{
1072 1073 1074 1075
	if (func > 0 && func < MAX_CHECK)
		seq_printf(m, "func=%s ", func_tokens[func]);
	else
		seq_printf(m, "func=%d ", func);
1076 1077
}

1078 1079 1080
int ima_policy_show(struct seq_file *m, void *v)
{
	struct ima_rule_entry *entry = v;
1081
	int i;
1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095
	char tbuf[64] = {0,};

	rcu_read_lock();

	if (entry->action & MEASURE)
		seq_puts(m, pt(Opt_measure));
	if (entry->action & DONT_MEASURE)
		seq_puts(m, pt(Opt_dont_measure));
	if (entry->action & APPRAISE)
		seq_puts(m, pt(Opt_appraise));
	if (entry->action & DONT_APPRAISE)
		seq_puts(m, pt(Opt_dont_appraise));
	if (entry->action & AUDIT)
		seq_puts(m, pt(Opt_audit));
1096 1097 1098 1099
	if (entry->action & HASH)
		seq_puts(m, pt(Opt_hash));
	if (entry->action & DONT_HASH)
		seq_puts(m, pt(Opt_dont_hash));
1100 1101 1102

	seq_puts(m, " ");

1103 1104
	if (entry->flags & IMA_FUNC)
		policy_func_show(m, entry->func);
1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123

	if (entry->flags & IMA_MASK) {
		if (entry->mask & MAY_EXEC)
			seq_printf(m, pt(Opt_mask), mt(mask_exec));
		if (entry->mask & MAY_WRITE)
			seq_printf(m, pt(Opt_mask), mt(mask_write));
		if (entry->mask & MAY_READ)
			seq_printf(m, pt(Opt_mask), mt(mask_read));
		if (entry->mask & MAY_APPEND)
			seq_printf(m, pt(Opt_mask), mt(mask_append));
		seq_puts(m, " ");
	}

	if (entry->flags & IMA_FSMAGIC) {
		snprintf(tbuf, sizeof(tbuf), "0x%lx", entry->fsmagic);
		seq_printf(m, pt(Opt_fsmagic), tbuf);
		seq_puts(m, " ");
	}

1124 1125 1126 1127 1128 1129
	if (entry->flags & IMA_FSNAME) {
		snprintf(tbuf, sizeof(tbuf), "%s", entry->fsname);
		seq_printf(m, pt(Opt_fsname), tbuf);
		seq_puts(m, " ");
	}

1130 1131 1132 1133 1134 1135
	if (entry->flags & IMA_PCR) {
		snprintf(tbuf, sizeof(tbuf), "%d", entry->pcr);
		seq_printf(m, pt(Opt_pcr), tbuf);
		seq_puts(m, " ");
	}

1136
	if (entry->flags & IMA_FSUUID) {
1137
		seq_printf(m, "fsuuid=%pU", &entry->fsuuid);
1138 1139 1140 1141 1142
		seq_puts(m, " ");
	}

	if (entry->flags & IMA_UID) {
		snprintf(tbuf, sizeof(tbuf), "%d", __kuid_val(entry->uid));
1143 1144 1145 1146 1147 1148
		if (entry->uid_op == &uid_gt)
			seq_printf(m, pt(Opt_uid_gt), tbuf);
		else if (entry->uid_op == &uid_lt)
			seq_printf(m, pt(Opt_uid_lt), tbuf);
		else
			seq_printf(m, pt(Opt_uid_eq), tbuf);
1149 1150 1151 1152 1153
		seq_puts(m, " ");
	}

	if (entry->flags & IMA_EUID) {
		snprintf(tbuf, sizeof(tbuf), "%d", __kuid_val(entry->uid));
1154 1155 1156 1157 1158 1159
		if (entry->uid_op == &uid_gt)
			seq_printf(m, pt(Opt_euid_gt), tbuf);
		else if (entry->uid_op == &uid_lt)
			seq_printf(m, pt(Opt_euid_lt), tbuf);
		else
			seq_printf(m, pt(Opt_euid_eq), tbuf);
1160 1161 1162 1163 1164
		seq_puts(m, " ");
	}

	if (entry->flags & IMA_FOWNER) {
		snprintf(tbuf, sizeof(tbuf), "%d", __kuid_val(entry->fowner));
1165 1166 1167 1168 1169 1170
		if (entry->fowner_op == &uid_gt)
			seq_printf(m, pt(Opt_fowner_gt), tbuf);
		else if (entry->fowner_op == &uid_lt)
			seq_printf(m, pt(Opt_fowner_lt), tbuf);
		else
			seq_printf(m, pt(Opt_fowner_eq), tbuf);
1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212
		seq_puts(m, " ");
	}

	for (i = 0; i < MAX_LSM_RULES; i++) {
		if (entry->lsm[i].rule) {
			switch (i) {
			case LSM_OBJ_USER:
				seq_printf(m, pt(Opt_obj_user),
					   (char *)entry->lsm[i].args_p);
				break;
			case LSM_OBJ_ROLE:
				seq_printf(m, pt(Opt_obj_role),
					   (char *)entry->lsm[i].args_p);
				break;
			case LSM_OBJ_TYPE:
				seq_printf(m, pt(Opt_obj_type),
					   (char *)entry->lsm[i].args_p);
				break;
			case LSM_SUBJ_USER:
				seq_printf(m, pt(Opt_subj_user),
					   (char *)entry->lsm[i].args_p);
				break;
			case LSM_SUBJ_ROLE:
				seq_printf(m, pt(Opt_subj_role),
					   (char *)entry->lsm[i].args_p);
				break;
			case LSM_SUBJ_TYPE:
				seq_printf(m, pt(Opt_subj_type),
					   (char *)entry->lsm[i].args_p);
				break;
			}
		}
	}
	if (entry->flags & IMA_DIGSIG_REQUIRED)
		seq_puts(m, "appraise_type=imasig ");
	if (entry->flags & IMA_PERMIT_DIRECTIO)
		seq_puts(m, "permit_directio ");
	rcu_read_unlock();
	seq_puts(m, "\n");
	return 0;
}
#endif	/* CONFIG_IMA_READ_POLICY */