ima_policy.c 31.6 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

37 38 39 40 41
#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 已提交
42
#define AUDIT		0x0040
M
Mimi Zohar 已提交
43

44 45 46
#define INVALID_PCR(a) (((a) < 0) || \
	(a) >= (FIELD_SIZEOF(struct integrity_iint_cache, measured_pcrs) * 8))

47
int ima_policy_flag;
48
static int temp_ima_appraise;
49

M
Mimi Zohar 已提交
50 51 52 53
#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
};
54

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

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

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

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

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

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

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

159 160 161 162 163 164 165 166 167 168 169
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},
};

170 171
static LIST_HEAD(ima_default_rules);
static LIST_HEAD(ima_policy_rules);
172
static LIST_HEAD(ima_temp_rules);
173
static struct list_head *ima_rules;
174

M
Mimi Zohar 已提交
175
static int ima_policy __initdata;
176

177
static int __init default_measure_policy_setup(char *str)
178
{
M
Mimi Zohar 已提交
179 180 181 182
	if (ima_policy)
		return 1;

	ima_policy = ORIGINAL_TCB;
183 184
	return 1;
}
185 186
__setup("ima_tcb", default_measure_policy_setup);

187
static bool ima_use_appraise_tcb __initdata;
188
static bool ima_use_secure_boot __initdata;
M
Mimi Zohar 已提交
189 190
static int __init policy_setup(char *str)
{
191
	char *p;
M
Mimi Zohar 已提交
192

193 194 195 196 197 198 199
	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)
			ima_use_appraise_tcb = 1;
200 201
		else if (strcmp(p, "secure_boot") == 0)
			ima_use_secure_boot = 1;
202
	}
M
Mimi Zohar 已提交
203 204 205 206 207

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

208 209 210 211 212 213
static int __init default_appraise_policy_setup(char *str)
{
	ima_use_appraise_tcb = 1;
	return 1;
}
__setup("ima_appraise_tcb", default_appraise_policy_setup);
214

215
/*
216 217 218 219
 * 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.
220 221 222
 */
static void ima_lsm_update_rules(void)
{
223
	struct ima_rule_entry *entry;
224 225 226
	int result;
	int i;

227
	list_for_each_entry(entry, &ima_policy_rules, list) {
228 229 230 231 232 233 234 235 236 237 238 239
		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);
		}
	}
}

240 241 242 243 244 245 246 247 248
/**
 * 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.
 */
249 250
static bool ima_match_rules(struct ima_rule_entry *rule, struct inode *inode,
			    enum ima_hooks func, int mask)
251 252
{
	struct task_struct *tsk = current;
M
Mimi Zohar 已提交
253
	const struct cred *cred = current_cred();
M
Mimi Zohar 已提交
254
	int i;
255

256 257
	if ((rule->flags & IMA_FUNC) &&
	    (rule->func != func && func != POST_SETATTR))
258
		return false;
259 260
	if ((rule->flags & IMA_MASK) &&
	    (rule->mask != mask && func != POST_SETATTR))
261
		return false;
262 263 264
	if ((rule->flags & IMA_INMASK) &&
	    (!(rule->mask & mask) && func != POST_SETATTR))
		return false;
265 266 267
	if ((rule->flags & IMA_FSMAGIC)
	    && rule->fsmagic != inode->i_sb->s_magic)
		return false;
268
	if ((rule->flags & IMA_FSUUID) &&
269
	    memcmp(rule->fsuuid, inode->i_sb->s_uuid, sizeof(rule->fsuuid)))
270
		return false;
271
	if ((rule->flags & IMA_UID) && !rule->uid_op(cred->uid, rule->uid))
272
		return false;
273 274
	if (rule->flags & IMA_EUID) {
		if (has_capability_noaudit(current, CAP_SETUID)) {
275 276 277
			if (!rule->uid_op(cred->euid, rule->uid)
			    && !rule->uid_op(cred->suid, rule->uid)
			    && !rule->uid_op(cred->uid, rule->uid))
278
				return false;
279
		} else if (!rule->uid_op(cred->euid, rule->uid))
280 281 282
			return false;
	}

283 284
	if ((rule->flags & IMA_FOWNER) &&
	    !rule->fowner_op(inode->i_uid, rule->fowner))
285
		return false;
M
Mimi Zohar 已提交
286
	for (i = 0; i < MAX_LSM_RULES; i++) {
287
		int rc = 0;
M
Mimi Zohar 已提交
288
		u32 osid, sid;
289
		int retried = 0;
M
Mimi Zohar 已提交
290 291 292

		if (!rule->lsm[i].rule)
			continue;
293
retry:
M
Mimi Zohar 已提交
294 295 296 297 298 299 300
		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,
301
							Audit_equal,
M
Mimi Zohar 已提交
302 303 304 305 306 307 308 309 310
							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,
311
							Audit_equal,
M
Mimi Zohar 已提交
312 313 314 315 316
							rule->lsm[i].rule,
							NULL);
		default:
			break;
		}
317 318 319 320
		if ((rc < 0) && (!retried)) {
			retried = 1;
			ima_lsm_update_rules();
			goto retry;
321
		}
M
Mimi Zohar 已提交
322 323 324
		if (!rc)
			return false;
	}
325 326 327
	return true;
}

328 329
/*
 * In addition to knowing that we need to appraise the file in general,
330
 * we need to differentiate between calling hooks, for hook specific rules.
331
 */
332
static int get_subaction(struct ima_rule_entry *rule, enum ima_hooks func)
333
{
334 335 336
	if (!(rule->flags & IMA_FUNC))
		return IMA_FILE_APPRAISE;

337
	switch (func) {
338 339 340 341 342
	case MMAP_CHECK:
		return IMA_MMAP_APPRAISE;
	case BPRM_CHECK:
		return IMA_BPRM_APPRAISE;
	case FILE_CHECK:
343
	case POST_SETATTR:
344
		return IMA_FILE_APPRAISE;
345 346 347
	case MODULE_CHECK ... MAX_CHECK - 1:
	default:
		return IMA_READ_APPRAISE;
348 349 350
	}
}

351 352 353 354 355
/**
 * 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)
356
 * @pcr: set the pcr to extend
357 358 359 360
 *
 * Measure decision based on func/mask/fsmagic and LSM(subj/obj/type)
 * conditions.
 *
361 362 363
 * 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.
364
 */
M
Mimi Zohar 已提交
365
int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask,
366
		     int flags, int *pcr)
367
{
368
	struct ima_rule_entry *entry;
M
Mimi Zohar 已提交
369
	int action = 0, actmask = flags | (flags << 1);
370

371 372
	rcu_read_lock();
	list_for_each_entry_rcu(entry, ima_rules, list) {
373

M
Mimi Zohar 已提交
374 375 376 377 378
		if (!(entry->action & actmask))
			continue;

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

380 381
		action |= entry->flags & IMA_ACTION_FLAGS;

382
		action |= entry->action & IMA_DO_MASK;
383
		if (entry->action & IMA_APPRAISE)
384
			action |= get_subaction(entry, func);
385

386 387 388 389
		if (entry->action & IMA_DO_MASK)
			actmask &= ~(entry->action | entry->action << 1);
		else
			actmask &= ~(entry->action | entry->action >> 1);
390

391 392 393
		if ((pcr) && (entry->flags & IMA_PCR))
			*pcr = entry->pcr;

M
Mimi Zohar 已提交
394 395
		if (!actmask)
			break;
396
	}
397
	rcu_read_unlock();
M
Mimi Zohar 已提交
398 399

	return action;
400 401
}

402 403 404 405 406 407 408 409 410 411 412 413 414 415 416
/*
 * 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;
	}

417
	ima_appraise |= temp_ima_appraise;
418 419 420 421
	if (!ima_appraise)
		ima_policy_flag &= ~IMA_APPRAISE;
}

422 423 424
/**
 * ima_init_policy - initialize the default measure rules.
 *
425 426
 * ima_rules points to either the ima_default_rules or the
 * the new ima_policy_rules.
427
 */
428
void __init ima_init_policy(void)
429
{
430
	int i, measure_entries, appraise_entries, secure_boot_entries;
431

M
Mimi Zohar 已提交
432 433
	/* if !ima_policy set entries = 0 so we load NO default rules */
	measure_entries = ima_policy ? ARRAY_SIZE(dont_measure_rules) : 0;
434 435
	appraise_entries = ima_use_appraise_tcb ?
			 ARRAY_SIZE(default_appraise_rules) : 0;
436 437
	secure_boot_entries = ima_use_secure_boot ?
			ARRAY_SIZE(secure_boot_rules) : 0;
438

439
	for (i = 0; i < measure_entries; i++)
M
Mimi Zohar 已提交
440 441 442 443 444 445 446 447 448 449 450 451 452 453 454
		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;
	}
455

456 457 458 459 460 461 462 463
	/*
	 * 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);

464 465 466
	for (i = 0; i < appraise_entries; i++) {
		list_add_tail(&default_appraise_rules[i].list,
			      &ima_default_rules);
M
Mimi Zohar 已提交
467 468
		if (default_appraise_rules[i].func == POLICY_CHECK)
			temp_ima_appraise |= IMA_APPRAISE_POLICY;
469 470 471
	}

	ima_rules = &ima_default_rules;
M
Mimi Zohar 已提交
472
	ima_update_policy_flag();
473
}
M
Mimi Zohar 已提交
474

475
/* Make sure we have a valid policy, at least containing some rules. */
476
int ima_check_policy(void)
477 478 479 480 481 482
{
	if (list_empty(&ima_temp_rules))
		return -EINVAL;
	return 0;
}

M
Mimi Zohar 已提交
483 484 485 486
/**
 * ima_update_policy - update default_rules with new measure rules
 *
 * Called on file .release to update the default rules with a complete new
487 488 489 490 491 492
 * 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 已提交
493 494 495
 */
void ima_update_policy(void)
{
496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516
	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;
	}
517
	ima_update_policy_flag();
M
Mimi Zohar 已提交
518 519 520 521 522
}

enum {
	Opt_err = -1,
	Opt_measure = 1, Opt_dont_measure,
523
	Opt_appraise, Opt_dont_appraise,
P
Peter Moody 已提交
524
	Opt_audit,
M
Mimi Zohar 已提交
525 526
	Opt_obj_user, Opt_obj_role, Opt_obj_type,
	Opt_subj_user, Opt_subj_role, Opt_subj_type,
527
	Opt_func, Opt_mask, Opt_fsmagic,
528 529 530
	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,
531 532
	Opt_appraise_type, Opt_permit_directio,
	Opt_pcr
M
Mimi Zohar 已提交
533 534 535 536 537
};

static match_table_t policy_tokens = {
	{Opt_measure, "measure"},
	{Opt_dont_measure, "dont_measure"},
538 539
	{Opt_appraise, "appraise"},
	{Opt_dont_appraise, "dont_appraise"},
P
Peter Moody 已提交
540
	{Opt_audit, "audit"},
M
Mimi Zohar 已提交
541 542 543 544 545 546 547 548 549
	{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"},
550
	{Opt_fsuuid, "fsuuid=%s"},
551 552 553 554 555 556 557 558 559
	{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"},
560
	{Opt_appraise_type, "appraise_type=%s"},
561
	{Opt_permit_directio, "permit_directio"},
562
	{Opt_pcr, "pcr=%s"},
M
Mimi Zohar 已提交
563 564 565
	{Opt_err, NULL}
};

566
static int ima_lsm_rule_init(struct ima_rule_entry *entry,
567
			     substring_t *args, int lsm_rule, int audit_type)
M
Mimi Zohar 已提交
568 569 570
{
	int result;

571 572 573
	if (entry->lsm[lsm_rule].rule)
		return -EINVAL;

574 575 576 577
	entry->lsm[lsm_rule].args_p = match_strdup(args);
	if (!entry->lsm[lsm_rule].args_p)
		return -ENOMEM;

M
Mimi Zohar 已提交
578 579
	entry->lsm[lsm_rule].type = audit_type;
	result = security_filter_rule_init(entry->lsm[lsm_rule].type,
580 581
					   Audit_equal,
					   entry->lsm[lsm_rule].args_p,
M
Mimi Zohar 已提交
582
					   &entry->lsm[lsm_rule].rule);
583 584
	if (!entry->lsm[lsm_rule].rule) {
		kfree(entry->lsm[lsm_rule].args_p);
M
Mimi Zohar 已提交
585
		return -EINVAL;
586 587
	}

M
Mimi Zohar 已提交
588 589 590
	return result;
}

591 592
static void ima_log_string_op(struct audit_buffer *ab, char *key, char *value,
			      bool (*rule_operator)(kuid_t, kuid_t))
593
{
594 595 596 597 598 599
	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);
600 601 602
	audit_log_untrustedstring(ab, value);
	audit_log_format(ab, " ");
}
603 604 605 606
static void ima_log_string(struct audit_buffer *ab, char *key, char *value)
{
	ima_log_string_op(ab, key, value, NULL);
}
607

608
static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
M
Mimi Zohar 已提交
609 610
{
	struct audit_buffer *ab;
611
	char *from;
M
Mimi Zohar 已提交
612
	char *p;
613
	bool uid_token;
M
Mimi Zohar 已提交
614 615
	int result = 0;

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

618
	entry->uid = INVALID_UID;
619
	entry->fowner = INVALID_UID;
620 621
	entry->uid_op = &uid_eq;
	entry->fowner_op = &uid_eq;
622
	entry->action = UNKNOWN;
E
Eric Paris 已提交
623
	while ((p = strsep(&rule, " \t")) != NULL) {
M
Mimi Zohar 已提交
624 625 626 627 628 629
		substring_t args[MAX_OPT_ARGS];
		int token;
		unsigned long lnum;

		if (result < 0)
			break;
E
Eric Paris 已提交
630 631
		if ((*p == '\0') || (*p == ' ') || (*p == '\t'))
			continue;
M
Mimi Zohar 已提交
632 633 634
		token = match_token(p, policy_tokens, args);
		switch (token) {
		case Opt_measure:
635
			ima_log_string(ab, "action", "measure");
636 637 638 639

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

M
Mimi Zohar 已提交
640 641 642
			entry->action = MEASURE;
			break;
		case Opt_dont_measure:
643
			ima_log_string(ab, "action", "dont_measure");
644 645 646 647

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

M
Mimi Zohar 已提交
648 649
			entry->action = DONT_MEASURE;
			break;
650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665
		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 已提交
666 667 668 669 670 671 672 673
		case Opt_audit:
			ima_log_string(ab, "action", "audit");

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

			entry->action = AUDIT;
			break;
M
Mimi Zohar 已提交
674
		case Opt_func:
675
			ima_log_string(ab, "func", args[0].from);
676 677

			if (entry->func)
678
				result = -EINVAL;
679

680 681 682 683 684
			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;
685 686
			else if (strcmp(args[0].from, "MODULE_CHECK") == 0)
				entry->func = MODULE_CHECK;
687 688
			else if (strcmp(args[0].from, "FIRMWARE_CHECK") == 0)
				entry->func = FIRMWARE_CHECK;
M
Mimi Zohar 已提交
689 690 691
			else if ((strcmp(args[0].from, "FILE_MMAP") == 0)
				|| (strcmp(args[0].from, "MMAP_CHECK") == 0))
				entry->func = MMAP_CHECK;
M
Mimi Zohar 已提交
692 693
			else if (strcmp(args[0].from, "BPRM_CHECK") == 0)
				entry->func = BPRM_CHECK;
694 695 696 697 698 699
			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;
700 701
			else if (strcmp(args[0].from, "POLICY_CHECK") == 0)
				entry->func = POLICY_CHECK;
M
Mimi Zohar 已提交
702 703 704 705 706 707
			else
				result = -EINVAL;
			if (!result)
				entry->flags |= IMA_FUNC;
			break;
		case Opt_mask:
708
			ima_log_string(ab, "mask", args[0].from);
709 710 711 712

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

713 714 715 716 717
			from = args[0].from;
			if (*from == '^')
				from++;

			if ((strcmp(from, "MAY_EXEC")) == 0)
M
Mimi Zohar 已提交
718
				entry->mask = MAY_EXEC;
719
			else if (strcmp(from, "MAY_WRITE") == 0)
M
Mimi Zohar 已提交
720
				entry->mask = MAY_WRITE;
721
			else if (strcmp(from, "MAY_READ") == 0)
M
Mimi Zohar 已提交
722
				entry->mask = MAY_READ;
723
			else if (strcmp(from, "MAY_APPEND") == 0)
M
Mimi Zohar 已提交
724 725 726 727
				entry->mask = MAY_APPEND;
			else
				result = -EINVAL;
			if (!result)
728 729
				entry->flags |= (*args[0].from == '^')
				     ? IMA_INMASK : IMA_MASK;
M
Mimi Zohar 已提交
730 731
			break;
		case Opt_fsmagic:
732
			ima_log_string(ab, "fsmagic", args[0].from);
733 734 735 736 737 738

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

739
			result = kstrtoul(args[0].from, 16, &entry->fsmagic);
M
Mimi Zohar 已提交
740 741 742
			if (!result)
				entry->flags |= IMA_FSMAGIC;
			break;
743 744 745 746
		case Opt_fsuuid:
			ima_log_string(ab, "fsuuid", args[0].from);

			if (memchr_inv(entry->fsuuid, 0x00,
747
				       sizeof(entry->fsuuid))) {
748 749 750 751
				result = -EINVAL;
				break;
			}

752 753 754 755
			result = blk_part_pack_uuid(args[0].from,
						    entry->fsuuid);
			if (!result)
				entry->flags |= IMA_FSUUID;
756
			break;
757 758 759 760 761 762 763 764 765 766 767 768 769 770 771
		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);
772

773
			if (uid_valid(entry->uid)) {
774 775 776 777
				result = -EINVAL;
				break;
			}

778
			result = kstrtoul(args[0].from, 10, &lnum);
M
Mimi Zohar 已提交
779
			if (!result) {
780 781 782 783
				entry->uid = make_kuid(current_user_ns(),
						       (uid_t) lnum);
				if (!uid_valid(entry->uid) ||
				    (uid_t)lnum != lnum)
M
Mimi Zohar 已提交
784 785
					result = -EINVAL;
				else
786
					entry->flags |= uid_token
787
					    ? IMA_UID : IMA_EUID;
M
Mimi Zohar 已提交
788 789
			}
			break;
790 791 792 793 794 795 796 797
		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);
798

799
			if (uid_valid(entry->fowner)) {
800 801 802 803
				result = -EINVAL;
				break;
			}

804
			result = kstrtoul(args[0].from, 10, &lnum);
805
			if (!result) {
806 807
				entry->fowner = make_kuid(current_user_ns(), (uid_t)lnum);
				if (!uid_valid(entry->fowner) || (((uid_t)lnum) != lnum))
808 809 810 811 812
					result = -EINVAL;
				else
					entry->flags |= IMA_FOWNER;
			}
			break;
M
Mimi Zohar 已提交
813
		case Opt_obj_user:
814
			ima_log_string(ab, "obj_user", args[0].from);
815
			result = ima_lsm_rule_init(entry, args,
M
Mimi Zohar 已提交
816 817 818 819
						   LSM_OBJ_USER,
						   AUDIT_OBJ_USER);
			break;
		case Opt_obj_role:
820
			ima_log_string(ab, "obj_role", args[0].from);
821
			result = ima_lsm_rule_init(entry, args,
M
Mimi Zohar 已提交
822 823 824 825
						   LSM_OBJ_ROLE,
						   AUDIT_OBJ_ROLE);
			break;
		case Opt_obj_type:
826
			ima_log_string(ab, "obj_type", args[0].from);
827
			result = ima_lsm_rule_init(entry, args,
M
Mimi Zohar 已提交
828 829 830 831
						   LSM_OBJ_TYPE,
						   AUDIT_OBJ_TYPE);
			break;
		case Opt_subj_user:
832
			ima_log_string(ab, "subj_user", args[0].from);
833
			result = ima_lsm_rule_init(entry, args,
M
Mimi Zohar 已提交
834 835 836 837
						   LSM_SUBJ_USER,
						   AUDIT_SUBJ_USER);
			break;
		case Opt_subj_role:
838
			ima_log_string(ab, "subj_role", args[0].from);
839
			result = ima_lsm_rule_init(entry, args,
M
Mimi Zohar 已提交
840 841 842 843
						   LSM_SUBJ_ROLE,
						   AUDIT_SUBJ_ROLE);
			break;
		case Opt_subj_type:
844
			ima_log_string(ab, "subj_type", args[0].from);
845
			result = ima_lsm_rule_init(entry, args,
M
Mimi Zohar 已提交
846 847 848
						   LSM_SUBJ_TYPE,
						   AUDIT_SUBJ_TYPE);
			break;
849 850 851 852 853 854 855 856 857 858 859 860
		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;
861 862
		case Opt_permit_directio:
			entry->flags |= IMA_PERMIT_DIRECTIO;
863 864 865 866 867 868 869 870 871 872 873 874 875 876
			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;

877
			break;
M
Mimi Zohar 已提交
878
		case Opt_err:
879
			ima_log_string(ab, "UNKNOWN", p);
880
			result = -EINVAL;
M
Mimi Zohar 已提交
881 882 883
			break;
		}
	}
884
	if (!result && (entry->action == UNKNOWN))
M
Mimi Zohar 已提交
885
		result = -EINVAL;
886
	else if (entry->func == MODULE_CHECK)
887
		temp_ima_appraise |= IMA_APPRAISE_MODULES;
888
	else if (entry->func == FIRMWARE_CHECK)
889
		temp_ima_appraise |= IMA_APPRAISE_FIRMWARE;
890 891
	else if (entry->func == POLICY_CHECK)
		temp_ima_appraise |= IMA_APPRAISE_POLICY;
892
	audit_log_format(ab, "res=%d", !result);
M
Mimi Zohar 已提交
893 894 895 896 897
	audit_log_end(ab);
	return result;
}

/**
898
 * ima_parse_add_rule - add a rule to ima_policy_rules
M
Mimi Zohar 已提交
899 900
 * @rule - ima measurement policy rule
 *
901
 * Avoid locking by allowing just one writer at a time in ima_write_policy()
902
 * Returns the length of the rule parsed, an error code on failure
M
Mimi Zohar 已提交
903
 */
904
ssize_t ima_parse_add_rule(char *rule)
M
Mimi Zohar 已提交
905
{
906
	static const char op[] = "update_policy";
907
	char *p;
908
	struct ima_rule_entry *entry;
909
	ssize_t result, len;
M
Mimi Zohar 已提交
910 911
	int audit_info = 0;

912 913
	p = strsep(&rule, "\n");
	len = strlen(p) + 1;
914
	p += strspn(p, " \t");
915

916
	if (*p == '#' || *p == '\0')
917 918
		return len;

M
Mimi Zohar 已提交
919 920 921 922 923 924 925 926 927
	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);

928
	result = ima_parse_rule(p, entry);
E
Eric Paris 已提交
929
	if (result) {
M
Mimi Zohar 已提交
930
		kfree(entry);
M
Mimi Zohar 已提交
931
		integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL,
932
				    NULL, op, "invalid-policy", result,
M
Mimi Zohar 已提交
933
				    audit_info);
E
Eric Paris 已提交
934
		return result;
M
Mimi Zohar 已提交
935
	}
E
Eric Paris 已提交
936

937
	list_add_tail(&entry->list, &ima_temp_rules);
E
Eric Paris 已提交
938 939

	return len;
M
Mimi Zohar 已提交
940 941
}

942 943 944 945 946 947
/**
 * 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.
 */
948
void ima_delete_rules(void)
M
Mimi Zohar 已提交
949
{
950
	struct ima_rule_entry *entry, *tmp;
951
	int i;
M
Mimi Zohar 已提交
952

953
	temp_ima_appraise = 0;
954
	list_for_each_entry_safe(entry, tmp, &ima_temp_rules, list) {
955 956 957
		for (i = 0; i < MAX_LSM_RULES; i++)
			kfree(entry->lsm[i].args_p);

M
Mimi Zohar 已提交
958 959 960 961
		list_del(&entry->list);
		kfree(entry);
	}
}
962 963 964 965 966 967 968 969 970 971 972 973 974 975 976

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

static char *mask_tokens[] = {
	"MAY_EXEC",
	"MAY_WRITE",
	"MAY_READ",
	"MAY_APPEND"
};

enum {
	func_file = 0, func_mmap, func_bprm,
977
	func_module, func_firmware, func_post,
978 979
	func_kexec_kernel, func_kexec_initramfs,
	func_policy
980 981 982 983 984 985 986 987
};

static char *func_tokens[] = {
	"FILE_CHECK",
	"MMAP_CHECK",
	"BPRM_CHECK",
	"MODULE_CHECK",
	"FIRMWARE_CHECK",
988
	"POST_SETATTR",
989 990
	"KEXEC_KERNEL_CHECK",
	"KEXEC_INITRAMFS_CHECK",
991
	"POLICY_CHECK"
992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029
};

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]
#define ft(token)	func_tokens[token]

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
/*
 * policy_func_show - display the ima_hooks policy rule
 */
static void policy_func_show(struct seq_file *m, enum ima_hooks func)
{
	char tbuf[64] = {0,};

	switch (func) {
	case FILE_CHECK:
		seq_printf(m, pt(Opt_func), ft(func_file));
		break;
	case MMAP_CHECK:
		seq_printf(m, pt(Opt_func), ft(func_mmap));
		break;
	case BPRM_CHECK:
		seq_printf(m, pt(Opt_func), ft(func_bprm));
		break;
	case MODULE_CHECK:
		seq_printf(m, pt(Opt_func), ft(func_module));
		break;
	case FIRMWARE_CHECK:
		seq_printf(m, pt(Opt_func), ft(func_firmware));
		break;
	case POST_SETATTR:
		seq_printf(m, pt(Opt_func), ft(func_post));
		break;
1056 1057 1058 1059 1060 1061
	case KEXEC_KERNEL_CHECK:
		seq_printf(m, pt(Opt_func), ft(func_kexec_kernel));
		break;
	case KEXEC_INITRAMFS_CHECK:
		seq_printf(m, pt(Opt_func), ft(func_kexec_initramfs));
		break;
1062 1063 1064
	case POLICY_CHECK:
		seq_printf(m, pt(Opt_func), ft(func_policy));
		break;
1065 1066 1067 1068 1069 1070 1071 1072
	default:
		snprintf(tbuf, sizeof(tbuf), "%d", func);
		seq_printf(m, pt(Opt_func), tbuf);
		break;
	}
	seq_puts(m, " ");
}

1073 1074 1075
int ima_policy_show(struct seq_file *m, void *v)
{
	struct ima_rule_entry *entry = v;
1076
	int i;
1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093
	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));

	seq_puts(m, " ");

1094 1095
	if (entry->flags & IMA_FUNC)
		policy_func_show(m, entry->func);
1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114

	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, " ");
	}

1115 1116 1117 1118 1119 1120
	if (entry->flags & IMA_PCR) {
		snprintf(tbuf, sizeof(tbuf), "%d", entry->pcr);
		seq_printf(m, pt(Opt_pcr), tbuf);
		seq_puts(m, " ");
	}

1121
	if (entry->flags & IMA_FSUUID) {
1122
		seq_printf(m, "fsuuid=%pU", entry->fsuuid);
1123 1124 1125 1126 1127
		seq_puts(m, " ");
	}

	if (entry->flags & IMA_UID) {
		snprintf(tbuf, sizeof(tbuf), "%d", __kuid_val(entry->uid));
1128 1129 1130 1131 1132 1133
		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);
1134 1135 1136 1137 1138
		seq_puts(m, " ");
	}

	if (entry->flags & IMA_EUID) {
		snprintf(tbuf, sizeof(tbuf), "%d", __kuid_val(entry->uid));
1139 1140 1141 1142 1143 1144
		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);
1145 1146 1147 1148 1149
		seq_puts(m, " ");
	}

	if (entry->flags & IMA_FOWNER) {
		snprintf(tbuf, sizeof(tbuf), "%d", __kuid_val(entry->fowner));
1150 1151 1152 1153 1154 1155
		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);
1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 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
		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 */