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

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},
M
Mimi Zohar 已提交
99 100 101
	{.action = DONT_MEASURE, .fsmagic = NSFS_MAGIC, .flags = IMA_FSMAGIC}
};

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

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

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

156 157 158 159 160 161 162 163 164 165 166
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},
};

167 168
static LIST_HEAD(ima_default_rules);
static LIST_HEAD(ima_policy_rules);
169
static LIST_HEAD(ima_temp_rules);
170
static struct list_head *ima_rules;
171

M
Mimi Zohar 已提交
172
static int ima_policy __initdata;
173

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

	ima_policy = ORIGINAL_TCB;
180 181
	return 1;
}
182 183
__setup("ima_tcb", default_measure_policy_setup);

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

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

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

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

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

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

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

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

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

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

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

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

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

368 369
	rcu_read_lock();
	list_for_each_entry_rcu(entry, ima_rules, list) {
370

M
Mimi Zohar 已提交
371 372 373 374 375
		if (!(entry->action & actmask))
			continue;

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

377 378
		action |= entry->flags & IMA_ACTION_FLAGS;

379
		action |= entry->action & IMA_DO_MASK;
380
		if (entry->action & IMA_APPRAISE)
381
			action |= get_subaction(entry, func);
382

383 384 385 386
		if (entry->action & IMA_DO_MASK)
			actmask &= ~(entry->action | entry->action << 1);
		else
			actmask &= ~(entry->action | entry->action >> 1);
387

388 389 390
		if ((pcr) && (entry->flags & IMA_PCR))
			*pcr = entry->pcr;

M
Mimi Zohar 已提交
391 392
		if (!actmask)
			break;
393
	}
394
	rcu_read_unlock();
M
Mimi Zohar 已提交
395 396

	return action;
397 398
}

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

414
	ima_appraise |= temp_ima_appraise;
415 416 417 418
	if (!ima_appraise)
		ima_policy_flag &= ~IMA_APPRAISE;
}

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

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

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

453 454 455 456 457 458 459 460
	/*
	 * 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);

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

	ima_rules = &ima_default_rules;
M
Mimi Zohar 已提交
469
	ima_update_policy_flag();
470
}
M
Mimi Zohar 已提交
471

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

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

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

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

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

568 569 570
	if (entry->lsm[lsm_rule].rule)
		return -EINVAL;

571 572 573 574
	entry->lsm[lsm_rule].args_p = match_strdup(args);
	if (!entry->lsm[lsm_rule].args_p)
		return -ENOMEM;

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

M
Mimi Zohar 已提交
585 586 587
	return result;
}

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

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

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

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

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

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

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

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

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

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

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

			if (entry->func)
675
				result = -EINVAL;
676

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

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

710 711 712 713 714
			from = args[0].from;
			if (*from == '^')
				from++;

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

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

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

			if (memchr_inv(entry->fsuuid, 0x00,
744
				       sizeof(entry->fsuuid))) {
745 746 747 748
				result = -EINVAL;
				break;
			}

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

770
			if (uid_valid(entry->uid)) {
771 772 773 774
				result = -EINVAL;
				break;
			}

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

796
			if (uid_valid(entry->fowner)) {
797 798 799 800
				result = -EINVAL;
				break;
			}

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

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

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

909 910
	p = strsep(&rule, "\n");
	len = strlen(p) + 1;
911
	p += strspn(p, " \t");
912

913
	if (*p == '#' || *p == '\0')
914 915
		return len;

M
Mimi Zohar 已提交
916 917 918 919 920 921 922 923 924
	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);

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

934
	list_add_tail(&entry->list, &ima_temp_rules);
E
Eric Paris 已提交
935 936

	return len;
M
Mimi Zohar 已提交
937 938
}

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

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

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

#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,
974
	func_module, func_firmware, func_post,
975 976
	func_kexec_kernel, func_kexec_initramfs,
	func_policy
977 978 979 980 981 982 983 984
};

static char *func_tokens[] = {
	"FILE_CHECK",
	"MMAP_CHECK",
	"BPRM_CHECK",
	"MODULE_CHECK",
	"FIRMWARE_CHECK",
985
	"POST_SETATTR",
986 987
	"KEXEC_KERNEL_CHECK",
	"KEXEC_INITRAMFS_CHECK",
988
	"POLICY_CHECK"
989 990 991 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
};

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]

1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052
/*
 * 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;
1053 1054 1055 1056 1057 1058
	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;
1059 1060 1061
	case POLICY_CHECK:
		seq_printf(m, pt(Opt_func), ft(func_policy));
		break;
1062 1063 1064 1065 1066 1067 1068 1069
	default:
		snprintf(tbuf, sizeof(tbuf), "%d", func);
		seq_printf(m, pt(Opt_func), tbuf);
		break;
	}
	seq_puts(m, " ");
}

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

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

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

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

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

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

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

	if (entry->flags & IMA_FOWNER) {
		snprintf(tbuf, sizeof(tbuf), "%d", __kuid_val(entry->fowner));
1147 1148 1149 1150 1151 1152
		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);
1153 1154 1155 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
		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 */