blob: b560a3ffeabb1ceaf45fd9cb74a46f62141f8dbc [file] [log] [blame]
Thomas Gleixnerb886d83c2019-06-01 10:08:55 +02001// SPDX-License-Identifier: GPL-2.0-only
Mimi Zohar3323eec2009-02-04 09:06:58 -05002/*
3 * Copyright (C) 2008 IBM Corporation
4 * Author: Mimi Zohar <zohar@us.ibm.com>
5 *
Mimi Zohar3323eec2009-02-04 09:06:58 -05006 * ima_policy.c
Dmitry Kasatkin2bb930a2014-03-04 18:04:20 +02007 * - initialize default measure policy rules
Mimi Zohar3323eec2009-02-04 09:06:58 -05008 */
Thiago Jung Bauermann3878d502019-06-27 23:19:32 -03009
10#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
11
Paul Gortmaker876979c2018-12-09 15:36:29 -050012#include <linux/init.h>
Mimi Zohar3323eec2009-02-04 09:06:58 -050013#include <linux/list.h>
Mimi Zoharcf222212016-01-14 17:57:47 -050014#include <linux/fs.h>
Mimi Zohar3323eec2009-02-04 09:06:58 -050015#include <linux/security.h>
16#include <linux/magic.h>
Mimi Zohar4af46622009-02-04 09:07:00 -050017#include <linux/parser.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090018#include <linux/slab.h>
Petko Manolov38d859f2015-12-02 17:47:54 +020019#include <linux/rculist.h>
Dmitry Kasatkin85865c12012-09-03 23:23:13 +030020#include <linux/genhd.h>
Petko Manolov80eae202015-12-02 17:47:56 +020021#include <linux/seq_file.h>
Nayna Jain61917062018-10-09 23:00:36 +053022#include <linux/ima.h>
Mimi Zohar3323eec2009-02-04 09:06:58 -050023
24#include "ima.h"
25
26/* flags definitions */
Dmitry Kasatkin2bb930a2014-03-04 18:04:20 +020027#define IMA_FUNC 0x0001
28#define IMA_MASK 0x0002
Mimi Zohar3323eec2009-02-04 09:06:58 -050029#define IMA_FSMAGIC 0x0004
30#define IMA_UID 0x0008
Mimi Zohar07f6a792011-03-09 22:25:48 -050031#define IMA_FOWNER 0x0010
Dmitry Kasatkin85865c12012-09-03 23:23:13 +030032#define IMA_FSUUID 0x0020
Mimi Zohar4351c292014-11-05 07:53:55 -050033#define IMA_INMASK 0x0040
Mimi Zohar139069e2014-11-05 07:48:36 -050034#define IMA_EUID 0x0080
Eric Richter02606432016-06-01 13:14:01 -050035#define IMA_PCR 0x0100
Mimi Zoharf1b08bb2018-01-15 11:20:36 -050036#define IMA_FSNAME 0x0200
Lakshmi Ramasubramanian2b60c0e2019-12-11 08:47:07 -080037#define IMA_KEYRINGS 0x0400
Mimi Zohar3323eec2009-02-04 09:06:58 -050038
Dmitry Kasatkin45e24722012-09-12 20:51:32 +030039#define UNKNOWN 0
40#define MEASURE 0x0001 /* same as IMA_MEASURE */
41#define DONT_MEASURE 0x0002
42#define APPRAISE 0x0004 /* same as IMA_APPRAISE */
43#define DONT_APPRAISE 0x0008
Peter Moodye7c568e2012-06-14 10:04:36 -070044#define AUDIT 0x0040
Mimi Zoharda1b0022016-09-29 10:04:52 -040045#define HASH 0x0100
46#define DONT_HASH 0x0200
Mimi Zohar4af46622009-02-04 09:07:00 -050047
Eric Richter02606432016-06-01 13:14:01 -050048#define INVALID_PCR(a) (((a) < 0) || \
49 (a) >= (FIELD_SIZEOF(struct integrity_iint_cache, measured_pcrs) * 8))
50
Roberto Sassua7560242014-09-12 19:35:54 +020051int ima_policy_flag;
Mimi Zohar6ad6afa2015-12-07 14:35:47 -050052static int temp_ima_appraise;
Mimi Zoharef968372018-07-13 14:06:01 -040053static int build_ima_appraise __ro_after_init;
Roberto Sassua7560242014-09-12 19:35:54 +020054
Mimi Zohar4af46622009-02-04 09:07:00 -050055#define MAX_LSM_RULES 6
56enum lsm_rule_types { LSM_OBJ_USER, LSM_OBJ_ROLE, LSM_OBJ_TYPE,
57 LSM_SUBJ_USER, LSM_SUBJ_ROLE, LSM_SUBJ_TYPE
58};
Mimi Zohar3323eec2009-02-04 09:06:58 -050059
Mimi Zohar24fd03c2015-06-11 20:48:33 -040060enum policy_types { ORIGINAL_TCB = 1, DEFAULT_TCB };
61
Nayna Jainc52657d2018-10-09 23:00:35 +053062enum policy_rule_list { IMA_DEFAULT_POLICY = 1, IMA_CUSTOM_POLICY };
63
Mimi Zohar07f6a792011-03-09 22:25:48 -050064struct ima_rule_entry {
Mimi Zohar3323eec2009-02-04 09:06:58 -050065 struct list_head list;
Mimi Zohar2fe5d6d2012-02-13 10:15:05 -050066 int action;
Mimi Zohar3323eec2009-02-04 09:06:58 -050067 unsigned int flags;
68 enum ima_hooks func;
69 int mask;
70 unsigned long fsmagic;
Christoph Hellwig787d8c52017-06-01 07:00:26 +020071 uuid_t fsuuid;
Eric W. Biederman8b94eea2012-05-25 18:24:12 -060072 kuid_t uid;
Linus Torvalds882653222012-10-02 21:38:48 -070073 kuid_t fowner;
Mikhail Kurinnoi3dd0c8d2017-01-27 19:23:01 +030074 bool (*uid_op)(kuid_t, kuid_t); /* Handlers for operators */
75 bool (*fowner_op)(kuid_t, kuid_t); /* uid_eq(), uid_gt(), uid_lt() */
Eric Richter02606432016-06-01 13:14:01 -050076 int pcr;
Mimi Zohar4af46622009-02-04 09:07:00 -050077 struct {
78 void *rule; /* LSM file metadata specific */
Mimi Zohar7163a992013-01-03 14:19:09 -050079 void *args_p; /* audit value */
Mimi Zohar4af46622009-02-04 09:07:00 -050080 int type; /* audit type */
81 } lsm[MAX_LSM_RULES];
Mimi Zoharf1b08bb2018-01-15 11:20:36 -050082 char *fsname;
Lakshmi Ramasubramaniane9085e02019-12-11 08:47:06 -080083 char *keyrings; /* Measure keys added to these keyrings */
Matthew Garrett19453ce02019-06-19 15:46:11 -070084 struct ima_template_desc *template;
Mimi Zohar3323eec2009-02-04 09:06:58 -050085};
86
Eric Paris5789ba32009-05-21 15:47:06 -040087/*
88 * Without LSM specific knowledge, the default policy can only be
Mimi Zohar07f6a792011-03-09 22:25:48 -050089 * written in terms of .action, .func, .mask, .fsmagic, .uid, and .fowner
Mimi Zohar4af46622009-02-04 09:07:00 -050090 */
Eric Paris5789ba32009-05-21 15:47:06 -040091
92/*
93 * The minimum rule set to allow for full TCB coverage. Measures all files
94 * opened or mmap for exec and everything read by root. Dangerous because
95 * normal users can easily run the machine out of memory simply building
96 * and running executables.
97 */
James Morrisbad44172017-02-13 16:34:35 +110098static struct ima_rule_entry dont_measure_rules[] __ro_after_init = {
Dmitry Kasatkin2bb930a2014-03-04 18:04:20 +020099 {.action = DONT_MEASURE, .fsmagic = PROC_SUPER_MAGIC, .flags = IMA_FSMAGIC},
100 {.action = DONT_MEASURE, .fsmagic = SYSFS_MAGIC, .flags = IMA_FSMAGIC},
101 {.action = DONT_MEASURE, .fsmagic = DEBUGFS_MAGIC, .flags = IMA_FSMAGIC},
102 {.action = DONT_MEASURE, .fsmagic = TMPFS_MAGIC, .flags = IMA_FSMAGIC},
103 {.action = DONT_MEASURE, .fsmagic = DEVPTS_SUPER_MAGIC, .flags = IMA_FSMAGIC},
104 {.action = DONT_MEASURE, .fsmagic = BINFMTFS_MAGIC, .flags = IMA_FSMAGIC},
105 {.action = DONT_MEASURE, .fsmagic = SECURITYFS_MAGIC, .flags = IMA_FSMAGIC},
106 {.action = DONT_MEASURE, .fsmagic = SELINUX_MAGIC, .flags = IMA_FSMAGIC},
Martin Townsend1c070b12018-03-22 13:46:01 +0000107 {.action = DONT_MEASURE, .fsmagic = SMACK_MAGIC, .flags = IMA_FSMAGIC},
Roberto Sassu6438de92015-04-11 17:13:06 +0200108 {.action = DONT_MEASURE, .fsmagic = CGROUP_SUPER_MAGIC,
109 .flags = IMA_FSMAGIC},
Laura Abbott82e3bb42017-05-09 11:25:27 -0700110 {.action = DONT_MEASURE, .fsmagic = CGROUP2_SUPER_MAGIC,
111 .flags = IMA_FSMAGIC},
Mimi Zohar060190f2018-11-14 17:24:13 -0500112 {.action = DONT_MEASURE, .fsmagic = NSFS_MAGIC, .flags = IMA_FSMAGIC},
113 {.action = DONT_MEASURE, .fsmagic = EFIVARFS_MAGIC, .flags = IMA_FSMAGIC}
Mimi Zohar24fd03c2015-06-11 20:48:33 -0400114};
115
James Morrisbad44172017-02-13 16:34:35 +1100116static struct ima_rule_entry original_measurement_rules[] __ro_after_init = {
Dmitry Kasatkin2bb930a2014-03-04 18:04:20 +0200117 {.action = MEASURE, .func = MMAP_CHECK, .mask = MAY_EXEC,
Mimi Zohar3323eec2009-02-04 09:06:58 -0500118 .flags = IMA_FUNC | IMA_MASK},
Dmitry Kasatkin2bb930a2014-03-04 18:04:20 +0200119 {.action = MEASURE, .func = BPRM_CHECK, .mask = MAY_EXEC,
Mimi Zohar3323eec2009-02-04 09:06:58 -0500120 .flags = IMA_FUNC | IMA_MASK},
Mimi Zohar24fd03c2015-06-11 20:48:33 -0400121 {.action = MEASURE, .func = FILE_CHECK, .mask = MAY_READ,
Mikhail Kurinnoi3dd0c8d2017-01-27 19:23:01 +0300122 .uid = GLOBAL_ROOT_UID, .uid_op = &uid_eq,
123 .flags = IMA_FUNC | IMA_MASK | IMA_UID},
Mimi Zohar24fd03c2015-06-11 20:48:33 -0400124 {.action = MEASURE, .func = MODULE_CHECK, .flags = IMA_FUNC},
125 {.action = MEASURE, .func = FIRMWARE_CHECK, .flags = IMA_FUNC},
126};
127
James Morrisbad44172017-02-13 16:34:35 +1100128static struct ima_rule_entry default_measurement_rules[] __ro_after_init = {
Mimi Zohar24fd03c2015-06-11 20:48:33 -0400129 {.action = MEASURE, .func = MMAP_CHECK, .mask = MAY_EXEC,
130 .flags = IMA_FUNC | IMA_MASK},
131 {.action = MEASURE, .func = BPRM_CHECK, .mask = MAY_EXEC,
132 .flags = IMA_FUNC | IMA_MASK},
133 {.action = MEASURE, .func = FILE_CHECK, .mask = MAY_READ,
Mikhail Kurinnoi3dd0c8d2017-01-27 19:23:01 +0300134 .uid = GLOBAL_ROOT_UID, .uid_op = &uid_eq,
135 .flags = IMA_FUNC | IMA_INMASK | IMA_EUID},
Mimi Zohar24fd03c2015-06-11 20:48:33 -0400136 {.action = MEASURE, .func = FILE_CHECK, .mask = MAY_READ,
Mikhail Kurinnoi3dd0c8d2017-01-27 19:23:01 +0300137 .uid = GLOBAL_ROOT_UID, .uid_op = &uid_eq,
138 .flags = IMA_FUNC | IMA_INMASK | IMA_UID},
Dmitry Kasatkin2bb930a2014-03-04 18:04:20 +0200139 {.action = MEASURE, .func = MODULE_CHECK, .flags = IMA_FUNC},
Mimi Zohar5a9196d2014-07-22 10:39:48 -0400140 {.action = MEASURE, .func = FIRMWARE_CHECK, .flags = IMA_FUNC},
Mimi Zohar19f8a842016-01-15 10:17:12 -0500141 {.action = MEASURE, .func = POLICY_CHECK, .flags = IMA_FUNC},
Mimi Zohar3323eec2009-02-04 09:06:58 -0500142};
143
James Morrisbad44172017-02-13 16:34:35 +1100144static struct ima_rule_entry default_appraise_rules[] __ro_after_init = {
Dmitry Kasatkin2bb930a2014-03-04 18:04:20 +0200145 {.action = DONT_APPRAISE, .fsmagic = PROC_SUPER_MAGIC, .flags = IMA_FSMAGIC},
146 {.action = DONT_APPRAISE, .fsmagic = SYSFS_MAGIC, .flags = IMA_FSMAGIC},
147 {.action = DONT_APPRAISE, .fsmagic = DEBUGFS_MAGIC, .flags = IMA_FSMAGIC},
148 {.action = DONT_APPRAISE, .fsmagic = TMPFS_MAGIC, .flags = IMA_FSMAGIC},
149 {.action = DONT_APPRAISE, .fsmagic = RAMFS_MAGIC, .flags = IMA_FSMAGIC},
150 {.action = DONT_APPRAISE, .fsmagic = DEVPTS_SUPER_MAGIC, .flags = IMA_FSMAGIC},
151 {.action = DONT_APPRAISE, .fsmagic = BINFMTFS_MAGIC, .flags = IMA_FSMAGIC},
152 {.action = DONT_APPRAISE, .fsmagic = SECURITYFS_MAGIC, .flags = IMA_FSMAGIC},
153 {.action = DONT_APPRAISE, .fsmagic = SELINUX_MAGIC, .flags = IMA_FSMAGIC},
Martin Townsend1c070b12018-03-22 13:46:01 +0000154 {.action = DONT_APPRAISE, .fsmagic = SMACK_MAGIC, .flags = IMA_FSMAGIC},
Mimi Zoharcd025f72015-04-21 16:54:24 -0400155 {.action = DONT_APPRAISE, .fsmagic = NSFS_MAGIC, .flags = IMA_FSMAGIC},
Mimi Zohar060190f2018-11-14 17:24:13 -0500156 {.action = DONT_APPRAISE, .fsmagic = EFIVARFS_MAGIC, .flags = IMA_FSMAGIC},
Dmitry Kasatkin2bb930a2014-03-04 18:04:20 +0200157 {.action = DONT_APPRAISE, .fsmagic = CGROUP_SUPER_MAGIC, .flags = IMA_FSMAGIC},
Laura Abbott82e3bb42017-05-09 11:25:27 -0700158 {.action = DONT_APPRAISE, .fsmagic = CGROUP2_SUPER_MAGIC, .flags = IMA_FSMAGIC},
Mimi Zohar95ee08f2015-12-07 15:08:01 -0500159#ifdef CONFIG_IMA_WRITE_POLICY
160 {.action = APPRAISE, .func = POLICY_CHECK,
161 .flags = IMA_FUNC | IMA_DIGSIG_REQUIRED},
162#endif
Dmitry Kasatkinc57782c2014-11-05 17:01:16 +0200163#ifndef CONFIG_IMA_APPRAISE_SIGNED_INIT
Mikhail Kurinnoi3dd0c8d2017-01-27 19:23:01 +0300164 {.action = APPRAISE, .fowner = GLOBAL_ROOT_UID, .fowner_op = &uid_eq,
165 .flags = IMA_FOWNER},
Dmitry Kasatkinc57782c2014-11-05 17:01:16 +0200166#else
167 /* force signature */
Mikhail Kurinnoi3dd0c8d2017-01-27 19:23:01 +0300168 {.action = APPRAISE, .fowner = GLOBAL_ROOT_UID, .fowner_op = &uid_eq,
Dmitry Kasatkinc57782c2014-11-05 17:01:16 +0200169 .flags = IMA_FOWNER | IMA_DIGSIG_REQUIRED},
170#endif
Mimi Zohar07f6a792011-03-09 22:25:48 -0500171};
Mimi Zohar3323eec2009-02-04 09:06:58 -0500172
Mimi Zoharef968372018-07-13 14:06:01 -0400173static struct ima_rule_entry build_appraise_rules[] __ro_after_init = {
174#ifdef CONFIG_IMA_APPRAISE_REQUIRE_MODULE_SIGS
175 {.action = APPRAISE, .func = MODULE_CHECK,
176 .flags = IMA_FUNC | IMA_DIGSIG_REQUIRED},
177#endif
178#ifdef CONFIG_IMA_APPRAISE_REQUIRE_FIRMWARE_SIGS
179 {.action = APPRAISE, .func = FIRMWARE_CHECK,
180 .flags = IMA_FUNC | IMA_DIGSIG_REQUIRED},
181#endif
182#ifdef CONFIG_IMA_APPRAISE_REQUIRE_KEXEC_SIGS
183 {.action = APPRAISE, .func = KEXEC_KERNEL_CHECK,
184 .flags = IMA_FUNC | IMA_DIGSIG_REQUIRED},
185#endif
186#ifdef CONFIG_IMA_APPRAISE_REQUIRE_POLICY_SIGS
187 {.action = APPRAISE, .func = POLICY_CHECK,
188 .flags = IMA_FUNC | IMA_DIGSIG_REQUIRED},
189#endif
190};
191
Mimi Zohar503ceae2017-04-21 18:58:27 -0400192static struct ima_rule_entry secure_boot_rules[] __ro_after_init = {
193 {.action = APPRAISE, .func = MODULE_CHECK,
194 .flags = IMA_FUNC | IMA_DIGSIG_REQUIRED},
195 {.action = APPRAISE, .func = FIRMWARE_CHECK,
196 .flags = IMA_FUNC | IMA_DIGSIG_REQUIRED},
197 {.action = APPRAISE, .func = KEXEC_KERNEL_CHECK,
198 .flags = IMA_FUNC | IMA_DIGSIG_REQUIRED},
199 {.action = APPRAISE, .func = POLICY_CHECK,
200 .flags = IMA_FUNC | IMA_DIGSIG_REQUIRED},
201};
202
Nayna Jain61917062018-10-09 23:00:36 +0530203/* An array of architecture specific rules */
YueHaibing68f25292019-06-11 21:40:32 +0800204static struct ima_rule_entry *arch_policy_entry __ro_after_init;
Nayna Jain61917062018-10-09 23:00:36 +0530205
Mimi Zohar07f6a792011-03-09 22:25:48 -0500206static LIST_HEAD(ima_default_rules);
207static LIST_HEAD(ima_policy_rules);
Petko Manolov38d859f2015-12-02 17:47:54 +0200208static LIST_HEAD(ima_temp_rules);
Mimi Zohar07f6a792011-03-09 22:25:48 -0500209static struct list_head *ima_rules;
210
Lakshmi Ramasubramanian5c7bac92020-01-16 18:18:21 -0800211/* Pre-allocated buffer used for matching keyrings. */
212static char *ima_keyrings;
213static size_t ima_keyrings_len;
214
Mimi Zohar24fd03c2015-06-11 20:48:33 -0400215static int ima_policy __initdata;
Petko Manolov38d859f2015-12-02 17:47:54 +0200216
Mimi Zohar07f6a792011-03-09 22:25:48 -0500217static int __init default_measure_policy_setup(char *str)
Eric Paris5789ba32009-05-21 15:47:06 -0400218{
Mimi Zohar24fd03c2015-06-11 20:48:33 -0400219 if (ima_policy)
220 return 1;
221
222 ima_policy = ORIGINAL_TCB;
Eric Paris5789ba32009-05-21 15:47:06 -0400223 return 1;
224}
Mimi Zohar07f6a792011-03-09 22:25:48 -0500225__setup("ima_tcb", default_measure_policy_setup);
226
Mimi Zohar33ce9542017-04-24 12:04:09 -0400227static bool ima_use_appraise_tcb __initdata;
Mimi Zohar503ceae2017-04-21 18:58:27 -0400228static bool ima_use_secure_boot __initdata;
Mimi Zohar9e670282018-02-21 11:36:32 -0500229static bool ima_fail_unverifiable_sigs __ro_after_init;
Mimi Zohar24fd03c2015-06-11 20:48:33 -0400230static int __init policy_setup(char *str)
231{
Mimi Zohar33ce9542017-04-24 12:04:09 -0400232 char *p;
Mimi Zohar24fd03c2015-06-11 20:48:33 -0400233
Mimi Zohar33ce9542017-04-24 12:04:09 -0400234 while ((p = strsep(&str, " |\n")) != NULL) {
235 if (*p == ' ')
236 continue;
237 if ((strcmp(p, "tcb") == 0) && !ima_policy)
238 ima_policy = DEFAULT_TCB;
239 else if (strcmp(p, "appraise_tcb") == 0)
Thomas Meyer39adb922017-10-07 16:02:21 +0200240 ima_use_appraise_tcb = true;
Mimi Zohar503ceae2017-04-21 18:58:27 -0400241 else if (strcmp(p, "secure_boot") == 0)
Thomas Meyer39adb922017-10-07 16:02:21 +0200242 ima_use_secure_boot = true;
Mimi Zohar9e670282018-02-21 11:36:32 -0500243 else if (strcmp(p, "fail_securely") == 0)
244 ima_fail_unverifiable_sigs = true;
Mimi Zohar33ce9542017-04-24 12:04:09 -0400245 }
Mimi Zohar24fd03c2015-06-11 20:48:33 -0400246
247 return 1;
248}
249__setup("ima_policy=", policy_setup);
250
Mimi Zohar07f6a792011-03-09 22:25:48 -0500251static int __init default_appraise_policy_setup(char *str)
252{
Thomas Meyer39adb922017-10-07 16:02:21 +0200253 ima_use_appraise_tcb = true;
Mimi Zohar07f6a792011-03-09 22:25:48 -0500254 return 1;
255}
256__setup("ima_appraise_tcb", default_appraise_policy_setup);
Eric Paris5789ba32009-05-21 15:47:06 -0400257
Janne Karhunenb1694242019-06-14 15:20:15 +0300258static void ima_lsm_free_rule(struct ima_rule_entry *entry)
259{
260 int i;
261
262 for (i = 0; i < MAX_LSM_RULES; i++) {
263 kfree(entry->lsm[i].rule);
264 kfree(entry->lsm[i].args_p);
265 }
266 kfree(entry);
267}
268
269static struct ima_rule_entry *ima_lsm_copy_rule(struct ima_rule_entry *entry)
270{
271 struct ima_rule_entry *nentry;
Janne Karhunen483ec262020-01-15 17:42:30 +0200272 int i;
Janne Karhunenb1694242019-06-14 15:20:15 +0300273
274 nentry = kmalloc(sizeof(*nentry), GFP_KERNEL);
275 if (!nentry)
276 return NULL;
277
278 /*
279 * Immutable elements are copied over as pointers and data; only
280 * lsm rules can change
281 */
282 memcpy(nentry, entry, sizeof(*nentry));
283 memset(nentry->lsm, 0, FIELD_SIZEOF(struct ima_rule_entry, lsm));
284
285 for (i = 0; i < MAX_LSM_RULES; i++) {
Janne Karhunen483ec262020-01-15 17:42:30 +0200286 if (!entry->lsm[i].args_p)
Janne Karhunenb1694242019-06-14 15:20:15 +0300287 continue;
288
289 nentry->lsm[i].type = entry->lsm[i].type;
290 nentry->lsm[i].args_p = kstrdup(entry->lsm[i].args_p,
291 GFP_KERNEL);
292 if (!nentry->lsm[i].args_p)
293 goto out_err;
294
Janne Karhunen483ec262020-01-15 17:42:30 +0200295 security_filter_rule_init(nentry->lsm[i].type,
296 Audit_equal,
297 nentry->lsm[i].args_p,
298 &nentry->lsm[i].rule);
299 if (!nentry->lsm[i].rule)
300 pr_warn("rule for LSM \'%s\' is undefined\n",
301 (char *)entry->lsm[i].args_p);
Janne Karhunenb1694242019-06-14 15:20:15 +0300302 }
303 return nentry;
304
305out_err:
306 ima_lsm_free_rule(nentry);
307 return NULL;
308}
309
310static int ima_lsm_update_rule(struct ima_rule_entry *entry)
311{
312 struct ima_rule_entry *nentry;
313
314 nentry = ima_lsm_copy_rule(entry);
315 if (!nentry)
316 return -ENOMEM;
317
318 list_replace_rcu(&entry->list, &nentry->list);
319 synchronize_rcu();
320 ima_lsm_free_rule(entry);
321
322 return 0;
323}
324
Dmitry Kasatkin2bb930a2014-03-04 18:04:20 +0200325/*
Petko Manolov38d859f2015-12-02 17:47:54 +0200326 * The LSM policy can be reloaded, leaving the IMA LSM based rules referring
327 * to the old, stale LSM policy. Update the IMA LSM based rules to reflect
Janne Karhunenb1694242019-06-14 15:20:15 +0300328 * the reloaded LSM policy.
Mimi Zohar7163a992013-01-03 14:19:09 -0500329 */
330static void ima_lsm_update_rules(void)
331{
Janne Karhunenb1694242019-06-14 15:20:15 +0300332 struct ima_rule_entry *entry, *e;
333 int i, result, needs_update;
Mimi Zohar7163a992013-01-03 14:19:09 -0500334
Janne Karhunenb1694242019-06-14 15:20:15 +0300335 list_for_each_entry_safe(entry, e, &ima_policy_rules, list) {
336 needs_update = 0;
Mimi Zohar7163a992013-01-03 14:19:09 -0500337 for (i = 0; i < MAX_LSM_RULES; i++) {
Janne Karhunen483ec262020-01-15 17:42:30 +0200338 if (entry->lsm[i].args_p) {
Janne Karhunenb1694242019-06-14 15:20:15 +0300339 needs_update = 1;
340 break;
341 }
342 }
343 if (!needs_update)
344 continue;
345
346 result = ima_lsm_update_rule(entry);
347 if (result) {
Janne Karhunen483ec262020-01-15 17:42:30 +0200348 pr_err("lsm rule update error %d\n", result);
Janne Karhunenb1694242019-06-14 15:20:15 +0300349 return;
Mimi Zohar7163a992013-01-03 14:19:09 -0500350 }
351 }
Mimi Zohar7163a992013-01-03 14:19:09 -0500352}
353
Janne Karhunenb1694242019-06-14 15:20:15 +0300354int ima_lsm_policy_change(struct notifier_block *nb, unsigned long event,
355 void *lsm_data)
356{
357 if (event != LSM_POLICY_CHANGE)
358 return NOTIFY_DONE;
359
360 ima_lsm_update_rules();
361 return NOTIFY_OK;
362}
363
Mimi Zohar3323eec2009-02-04 09:06:58 -0500364/**
Lakshmi Ramasubramaniane9085e02019-12-11 08:47:06 -0800365 * ima_match_keyring - determine whether the keyring matches the measure rule
366 * @rule: a pointer to a rule
367 * @keyring: name of the keyring to match against the measure rule
368 * @cred: a pointer to a credentials structure for user validation
369 *
370 * Returns true if keyring matches one in the rule, false otherwise.
371 */
372static bool ima_match_keyring(struct ima_rule_entry *rule,
373 const char *keyring, const struct cred *cred)
374{
Lakshmi Ramasubramanian5c7bac92020-01-16 18:18:21 -0800375 char *next_keyring, *keyrings_ptr;
Lakshmi Ramasubramaniane9085e02019-12-11 08:47:06 -0800376 bool matched = false;
377
378 if ((rule->flags & IMA_UID) && !rule->uid_op(cred->uid, rule->uid))
379 return false;
380
381 if (!rule->keyrings)
382 return true;
383
384 if (!keyring)
385 return false;
386
Lakshmi Ramasubramanian5c7bac92020-01-16 18:18:21 -0800387 strcpy(ima_keyrings, rule->keyrings);
Lakshmi Ramasubramaniane9085e02019-12-11 08:47:06 -0800388
389 /*
390 * "keyrings=" is specified in the policy in the format below:
391 * keyrings=.builtin_trusted_keys|.ima|.evm
392 */
Lakshmi Ramasubramanian5c7bac92020-01-16 18:18:21 -0800393 keyrings_ptr = ima_keyrings;
Lakshmi Ramasubramaniane9085e02019-12-11 08:47:06 -0800394 while ((next_keyring = strsep(&keyrings_ptr, "|")) != NULL) {
395 if (!strcmp(next_keyring, keyring)) {
396 matched = true;
397 break;
398 }
399 }
400
Lakshmi Ramasubramaniane9085e02019-12-11 08:47:06 -0800401 return matched;
402}
403
404/**
Janne Karhunen483ec262020-01-15 17:42:30 +0200405 * ima_match_rules - determine whether an inode matches the policy rule.
Mimi Zohar3323eec2009-02-04 09:06:58 -0500406 * @rule: a pointer to a rule
407 * @inode: a pointer to an inode
Matthew Garrettd906c102018-01-08 13:36:20 -0800408 * @cred: a pointer to a credentials structure for user validation
409 * @secid: the secid of the task to be validated
Mimi Zohar3323eec2009-02-04 09:06:58 -0500410 * @func: LIM hook identifier
411 * @mask: requested action (MAY_READ | MAY_WRITE | MAY_APPEND | MAY_EXEC)
Lakshmi Ramasubramaniane9085e02019-12-11 08:47:06 -0800412 * @keyring: keyring name to check in policy for KEY_CHECK func
Mimi Zohar3323eec2009-02-04 09:06:58 -0500413 *
414 * Returns true on rule match, false on failure.
415 */
Mimi Zohar4ad87a32016-01-14 20:59:14 -0500416static bool ima_match_rules(struct ima_rule_entry *rule, struct inode *inode,
Matthew Garrettd906c102018-01-08 13:36:20 -0800417 const struct cred *cred, u32 secid,
Lakshmi Ramasubramaniane9085e02019-12-11 08:47:06 -0800418 enum ima_hooks func, int mask,
419 const char *keyring)
Mimi Zohar3323eec2009-02-04 09:06:58 -0500420{
Mimi Zohar4af46622009-02-04 09:07:00 -0500421 int i;
Mimi Zohar3323eec2009-02-04 09:06:58 -0500422
Lakshmi Ramasubramanian58086112019-12-11 08:47:03 -0800423 if ((func == KEXEC_CMDLINE) || (func == KEY_CHECK)) {
Lakshmi Ramasubramaniane9085e02019-12-11 08:47:06 -0800424 if ((rule->flags & IMA_FUNC) && (rule->func == func)) {
425 if (func == KEY_CHECK)
426 return ima_match_keyring(rule, keyring, cred);
Prakhar Srivastavab0935122019-06-23 23:23:29 -0700427 return true;
Lakshmi Ramasubramaniane9085e02019-12-11 08:47:06 -0800428 }
Prakhar Srivastavab0935122019-06-23 23:23:29 -0700429 return false;
430 }
Dmitry Kasatkin09b11482013-11-13 23:42:39 +0200431 if ((rule->flags & IMA_FUNC) &&
432 (rule->func != func && func != POST_SETATTR))
Mimi Zohar3323eec2009-02-04 09:06:58 -0500433 return false;
Dmitry Kasatkin09b11482013-11-13 23:42:39 +0200434 if ((rule->flags & IMA_MASK) &&
435 (rule->mask != mask && func != POST_SETATTR))
Mimi Zohar3323eec2009-02-04 09:06:58 -0500436 return false;
Mimi Zohar4351c292014-11-05 07:53:55 -0500437 if ((rule->flags & IMA_INMASK) &&
438 (!(rule->mask & mask) && func != POST_SETATTR))
439 return false;
Mimi Zohar3323eec2009-02-04 09:06:58 -0500440 if ((rule->flags & IMA_FSMAGIC)
441 && rule->fsmagic != inode->i_sb->s_magic)
442 return false;
Mimi Zoharf1b08bb2018-01-15 11:20:36 -0500443 if ((rule->flags & IMA_FSNAME)
444 && strcmp(rule->fsname, inode->i_sb->s_type->name))
445 return false;
Dmitry Kasatkin85865c12012-09-03 23:23:13 +0300446 if ((rule->flags & IMA_FSUUID) &&
Christoph Hellwig85787092017-05-10 15:06:33 +0200447 !uuid_equal(&rule->fsuuid, &inode->i_sb->s_uuid))
Dmitry Kasatkin85865c12012-09-03 23:23:13 +0300448 return false;
Mikhail Kurinnoi3dd0c8d2017-01-27 19:23:01 +0300449 if ((rule->flags & IMA_UID) && !rule->uid_op(cred->uid, rule->uid))
Mimi Zohar3323eec2009-02-04 09:06:58 -0500450 return false;
Mimi Zohar139069e2014-11-05 07:48:36 -0500451 if (rule->flags & IMA_EUID) {
452 if (has_capability_noaudit(current, CAP_SETUID)) {
Mikhail Kurinnoi3dd0c8d2017-01-27 19:23:01 +0300453 if (!rule->uid_op(cred->euid, rule->uid)
454 && !rule->uid_op(cred->suid, rule->uid)
455 && !rule->uid_op(cred->uid, rule->uid))
Mimi Zohar139069e2014-11-05 07:48:36 -0500456 return false;
Mikhail Kurinnoi3dd0c8d2017-01-27 19:23:01 +0300457 } else if (!rule->uid_op(cred->euid, rule->uid))
Mimi Zohar139069e2014-11-05 07:48:36 -0500458 return false;
459 }
460
Mikhail Kurinnoi3dd0c8d2017-01-27 19:23:01 +0300461 if ((rule->flags & IMA_FOWNER) &&
462 !rule->fowner_op(inode->i_uid, rule->fowner))
Mimi Zohar07f6a792011-03-09 22:25:48 -0500463 return false;
Mimi Zohar4af46622009-02-04 09:07:00 -0500464 for (i = 0; i < MAX_LSM_RULES; i++) {
Mimi Zohar53fc0e22009-05-05 13:12:48 -0400465 int rc = 0;
Matthew Garrettd906c102018-01-08 13:36:20 -0800466 u32 osid;
Mimi Zohar4af46622009-02-04 09:07:00 -0500467
Janne Karhunen483ec262020-01-15 17:42:30 +0200468 if (!rule->lsm[i].rule) {
469 if (!rule->lsm[i].args_p)
470 continue;
471 else
472 return false;
473 }
Mimi Zohar4af46622009-02-04 09:07:00 -0500474 switch (i) {
475 case LSM_OBJ_USER:
476 case LSM_OBJ_ROLE:
477 case LSM_OBJ_TYPE:
478 security_inode_getsecid(inode, &osid);
479 rc = security_filter_rule_match(osid,
480 rule->lsm[i].type,
Mimi Zohar53fc0e22009-05-05 13:12:48 -0400481 Audit_equal,
Richard Guy Briggs90462a52019-01-31 11:52:11 -0500482 rule->lsm[i].rule);
Mimi Zohar4af46622009-02-04 09:07:00 -0500483 break;
484 case LSM_SUBJ_USER:
485 case LSM_SUBJ_ROLE:
486 case LSM_SUBJ_TYPE:
Matthew Garrettd906c102018-01-08 13:36:20 -0800487 rc = security_filter_rule_match(secid,
Mimi Zohar4af46622009-02-04 09:07:00 -0500488 rule->lsm[i].type,
Mimi Zohar53fc0e22009-05-05 13:12:48 -0400489 Audit_equal,
Richard Guy Briggs90462a52019-01-31 11:52:11 -0500490 rule->lsm[i].rule);
Mimi Zohar4af46622009-02-04 09:07:00 -0500491 default:
492 break;
493 }
494 if (!rc)
495 return false;
496 }
Mimi Zohar3323eec2009-02-04 09:06:58 -0500497 return true;
498}
499
Mimi Zohard79d72e2012-12-03 17:08:11 -0500500/*
501 * In addition to knowing that we need to appraise the file in general,
Mimi Zohar5a73fcf2012-12-05 15:14:38 -0500502 * we need to differentiate between calling hooks, for hook specific rules.
Mimi Zohard79d72e2012-12-03 17:08:11 -0500503 */
Mimi Zohar4ad87a32016-01-14 20:59:14 -0500504static int get_subaction(struct ima_rule_entry *rule, enum ima_hooks func)
Mimi Zohard79d72e2012-12-03 17:08:11 -0500505{
Mimi Zohar5a73fcf2012-12-05 15:14:38 -0500506 if (!(rule->flags & IMA_FUNC))
507 return IMA_FILE_APPRAISE;
508
Dmitry Kasatkin2bb930a2014-03-04 18:04:20 +0200509 switch (func) {
Mimi Zohard79d72e2012-12-03 17:08:11 -0500510 case MMAP_CHECK:
511 return IMA_MMAP_APPRAISE;
512 case BPRM_CHECK:
513 return IMA_BPRM_APPRAISE;
Matthew Garrettd906c102018-01-08 13:36:20 -0800514 case CREDS_CHECK:
515 return IMA_CREDS_APPRAISE;
Mimi Zohard79d72e2012-12-03 17:08:11 -0500516 case FILE_CHECK:
Mimi Zoharc6af8ef2015-11-19 12:39:22 -0500517 case POST_SETATTR:
Mimi Zohard79d72e2012-12-03 17:08:11 -0500518 return IMA_FILE_APPRAISE;
Mimi Zoharc6af8ef2015-11-19 12:39:22 -0500519 case MODULE_CHECK ... MAX_CHECK - 1:
520 default:
521 return IMA_READ_APPRAISE;
Mimi Zohard79d72e2012-12-03 17:08:11 -0500522 }
523}
524
Mimi Zohar3323eec2009-02-04 09:06:58 -0500525/**
526 * ima_match_policy - decision based on LSM and other conditions
527 * @inode: pointer to an inode for which the policy decision is being made
Matthew Garrettd906c102018-01-08 13:36:20 -0800528 * @cred: pointer to a credentials structure for which the policy decision is
529 * being made
530 * @secid: LSM secid of the task to be validated
Mimi Zohar3323eec2009-02-04 09:06:58 -0500531 * @func: IMA hook identifier
532 * @mask: requested action (MAY_READ | MAY_WRITE | MAY_APPEND | MAY_EXEC)
Eric Richter725de7f2016-06-01 13:14:02 -0500533 * @pcr: set the pcr to extend
Matthew Garrett19453ce02019-06-19 15:46:11 -0700534 * @template_desc: the template that should be used for this rule
Lakshmi Ramasubramaniane9085e02019-12-11 08:47:06 -0800535 * @keyring: the keyring name, if given, to be used to check in the policy.
536 * keyring can be NULL if func is anything other than KEY_CHECK.
Mimi Zohar3323eec2009-02-04 09:06:58 -0500537 *
538 * Measure decision based on func/mask/fsmagic and LSM(subj/obj/type)
539 * conditions.
540 *
Petko Manolov38d859f2015-12-02 17:47:54 +0200541 * Since the IMA policy may be updated multiple times we need to lock the
542 * list when walking it. Reads are many orders of magnitude more numerous
543 * than writes so ima_match_policy() is classical RCU candidate.
Mimi Zohar3323eec2009-02-04 09:06:58 -0500544 */
Matthew Garrettd906c102018-01-08 13:36:20 -0800545int ima_match_policy(struct inode *inode, const struct cred *cred, u32 secid,
Matthew Garrett19453ce02019-06-19 15:46:11 -0700546 enum ima_hooks func, int mask, int flags, int *pcr,
Lakshmi Ramasubramaniane9085e02019-12-11 08:47:06 -0800547 struct ima_template_desc **template_desc,
548 const char *keyring)
Mimi Zohar3323eec2009-02-04 09:06:58 -0500549{
Mimi Zohar07f6a792011-03-09 22:25:48 -0500550 struct ima_rule_entry *entry;
Mimi Zohar2fe5d6d2012-02-13 10:15:05 -0500551 int action = 0, actmask = flags | (flags << 1);
Mimi Zohar3323eec2009-02-04 09:06:58 -0500552
Mimi Zoharb36f2812019-07-19 07:16:57 -0400553 if (template_desc)
554 *template_desc = ima_template_desc_current();
555
Petko Manolov38d859f2015-12-02 17:47:54 +0200556 rcu_read_lock();
557 list_for_each_entry_rcu(entry, ima_rules, list) {
Mimi Zohar3323eec2009-02-04 09:06:58 -0500558
Mimi Zohar2fe5d6d2012-02-13 10:15:05 -0500559 if (!(entry->action & actmask))
560 continue;
561
Lakshmi Ramasubramaniane9085e02019-12-11 08:47:06 -0800562 if (!ima_match_rules(entry, inode, cred, secid, func, mask,
563 keyring))
Mimi Zohar2fe5d6d2012-02-13 10:15:05 -0500564 continue;
565
Dmitry Kasatkin0e5a2472012-06-08 13:58:49 +0300566 action |= entry->flags & IMA_ACTION_FLAGS;
567
Dmitry Kasatkin45e24722012-09-12 20:51:32 +0300568 action |= entry->action & IMA_DO_MASK;
Mimi Zoharda1b0022016-09-29 10:04:52 -0400569 if (entry->action & IMA_APPRAISE) {
Mimi Zohar5a73fcf2012-12-05 15:14:38 -0500570 action |= get_subaction(entry, func);
Mimi Zohara9a49352018-03-10 23:07:34 -0500571 action &= ~IMA_HASH;
Mimi Zohar9e670282018-02-21 11:36:32 -0500572 if (ima_fail_unverifiable_sigs)
573 action |= IMA_FAIL_UNVERIFIABLE_SIGS;
Mimi Zoharda1b0022016-09-29 10:04:52 -0400574 }
Mimi Zohard79d72e2012-12-03 17:08:11 -0500575
Mimi Zoharb36f2812019-07-19 07:16:57 -0400576
Dmitry Kasatkin45e24722012-09-12 20:51:32 +0300577 if (entry->action & IMA_DO_MASK)
578 actmask &= ~(entry->action | entry->action << 1);
579 else
580 actmask &= ~(entry->action | entry->action >> 1);
581
Eric Richter725de7f2016-06-01 13:14:02 -0500582 if ((pcr) && (entry->flags & IMA_PCR))
583 *pcr = entry->pcr;
584
Matthew Garrett19453ce02019-06-19 15:46:11 -0700585 if (template_desc && entry->template)
586 *template_desc = entry->template;
Matthew Garrett19453ce02019-06-19 15:46:11 -0700587
Mimi Zohar2fe5d6d2012-02-13 10:15:05 -0500588 if (!actmask)
589 break;
Mimi Zohar3323eec2009-02-04 09:06:58 -0500590 }
Petko Manolov38d859f2015-12-02 17:47:54 +0200591 rcu_read_unlock();
Mimi Zohar2fe5d6d2012-02-13 10:15:05 -0500592
593 return action;
Mimi Zohar3323eec2009-02-04 09:06:58 -0500594}
595
Roberto Sassua7560242014-09-12 19:35:54 +0200596/*
597 * Initialize the ima_policy_flag variable based on the currently
598 * loaded policy. Based on this flag, the decision to short circuit
599 * out of a function or not call the function in the first place
600 * can be made earlier.
601 */
602void ima_update_policy_flag(void)
603{
604 struct ima_rule_entry *entry;
605
Roberto Sassua7560242014-09-12 19:35:54 +0200606 list_for_each_entry(entry, ima_rules, list) {
607 if (entry->action & IMA_DO_MASK)
608 ima_policy_flag |= entry->action;
609 }
610
Mimi Zoharef968372018-07-13 14:06:01 -0400611 ima_appraise |= (build_ima_appraise | temp_ima_appraise);
Roberto Sassua7560242014-09-12 19:35:54 +0200612 if (!ima_appraise)
613 ima_policy_flag &= ~IMA_APPRAISE;
614}
615
Mimi Zohar6f0911a2018-04-12 00:15:22 -0400616static int ima_appraise_flag(enum ima_hooks func)
617{
618 if (func == MODULE_CHECK)
619 return IMA_APPRAISE_MODULES;
620 else if (func == FIRMWARE_CHECK)
621 return IMA_APPRAISE_FIRMWARE;
622 else if (func == POLICY_CHECK)
623 return IMA_APPRAISE_POLICY;
Mimi Zohar16c267a2018-07-13 14:05:58 -0400624 else if (func == KEXEC_KERNEL_CHECK)
625 return IMA_APPRAISE_KEXEC;
Mimi Zohar6f0911a2018-04-12 00:15:22 -0400626 return 0;
627}
628
Nayna Jainc52657d2018-10-09 23:00:35 +0530629static void add_rules(struct ima_rule_entry *entries, int count,
630 enum policy_rule_list policy_rule)
631{
632 int i = 0;
633
634 for (i = 0; i < count; i++) {
635 struct ima_rule_entry *entry;
636
637 if (policy_rule & IMA_DEFAULT_POLICY)
638 list_add_tail(&entries[i].list, &ima_default_rules);
639
640 if (policy_rule & IMA_CUSTOM_POLICY) {
641 entry = kmemdup(&entries[i], sizeof(*entry),
642 GFP_KERNEL);
643 if (!entry)
644 continue;
645
646 list_add_tail(&entry->list, &ima_policy_rules);
647 }
Petr Vorelf4001942019-05-15 08:18:07 +0200648 if (entries[i].action == APPRAISE) {
Nayna Jainc52657d2018-10-09 23:00:35 +0530649 temp_ima_appraise |= ima_appraise_flag(entries[i].func);
Petr Vorelf4001942019-05-15 08:18:07 +0200650 if (entries[i].func == POLICY_CHECK)
651 temp_ima_appraise |= IMA_APPRAISE_POLICY;
652 }
Nayna Jainc52657d2018-10-09 23:00:35 +0530653 }
654}
655
Nayna Jain61917062018-10-09 23:00:36 +0530656static int ima_parse_rule(char *rule, struct ima_rule_entry *entry);
657
658static int __init ima_init_arch_policy(void)
659{
660 const char * const *arch_rules;
661 const char * const *rules;
662 int arch_entries = 0;
663 int i = 0;
664
665 arch_rules = arch_get_ima_policy();
666 if (!arch_rules)
667 return arch_entries;
668
669 /* Get number of rules */
670 for (rules = arch_rules; *rules != NULL; rules++)
671 arch_entries++;
672
673 arch_policy_entry = kcalloc(arch_entries + 1,
674 sizeof(*arch_policy_entry), GFP_KERNEL);
675 if (!arch_policy_entry)
676 return 0;
677
678 /* Convert each policy string rules to struct ima_rule_entry format */
679 for (rules = arch_rules, i = 0; *rules != NULL; rules++) {
680 char rule[255];
681 int result;
682
683 result = strlcpy(rule, *rules, sizeof(rule));
684
685 INIT_LIST_HEAD(&arch_policy_entry[i].list);
686 result = ima_parse_rule(rule, &arch_policy_entry[i]);
687 if (result) {
688 pr_warn("Skipping unknown architecture policy rule: %s\n",
689 rule);
690 memset(&arch_policy_entry[i], 0,
691 sizeof(*arch_policy_entry));
692 continue;
693 }
694 i++;
695 }
696 return i;
697}
698
Mimi Zohar3323eec2009-02-04 09:06:58 -0500699/**
700 * ima_init_policy - initialize the default measure rules.
701 *
Mimi Zohar07f6a792011-03-09 22:25:48 -0500702 * ima_rules points to either the ima_default_rules or the
703 * the new ima_policy_rules.
Mimi Zohar3323eec2009-02-04 09:06:58 -0500704 */
Eric Paris932995f2009-05-21 15:43:32 -0400705void __init ima_init_policy(void)
Mimi Zohar3323eec2009-02-04 09:06:58 -0500706{
Nayna Jain61917062018-10-09 23:00:36 +0530707 int build_appraise_entries, arch_entries;
Mimi Zohar3323eec2009-02-04 09:06:58 -0500708
Nayna Jainc52657d2018-10-09 23:00:35 +0530709 /* if !ima_policy, we load NO default rules */
710 if (ima_policy)
711 add_rules(dont_measure_rules, ARRAY_SIZE(dont_measure_rules),
712 IMA_DEFAULT_POLICY);
Mimi Zohar24fd03c2015-06-11 20:48:33 -0400713
714 switch (ima_policy) {
715 case ORIGINAL_TCB:
Nayna Jainc52657d2018-10-09 23:00:35 +0530716 add_rules(original_measurement_rules,
717 ARRAY_SIZE(original_measurement_rules),
718 IMA_DEFAULT_POLICY);
Mimi Zohar24fd03c2015-06-11 20:48:33 -0400719 break;
720 case DEFAULT_TCB:
Nayna Jainc52657d2018-10-09 23:00:35 +0530721 add_rules(default_measurement_rules,
722 ARRAY_SIZE(default_measurement_rules),
723 IMA_DEFAULT_POLICY);
Mimi Zohar24fd03c2015-06-11 20:48:33 -0400724 default:
725 break;
726 }
Eric Paris5789ba32009-05-21 15:47:06 -0400727
Mimi Zohar503ceae2017-04-21 18:58:27 -0400728 /*
Nayna Jain61917062018-10-09 23:00:36 +0530729 * Based on runtime secure boot flags, insert arch specific measurement
730 * and appraise rules requiring file signatures for both the initial
731 * and custom policies, prior to other appraise rules.
732 * (Highest priority)
Mimi Zohar503ceae2017-04-21 18:58:27 -0400733 */
Nayna Jain61917062018-10-09 23:00:36 +0530734 arch_entries = ima_init_arch_policy();
735 if (!arch_entries)
736 pr_info("No architecture policies found\n");
737 else
738 add_rules(arch_policy_entry, arch_entries,
739 IMA_DEFAULT_POLICY | IMA_CUSTOM_POLICY);
740
741 /*
Mimi Zohar503ceae2017-04-21 18:58:27 -0400742 * Insert the builtin "secure_boot" policy rules requiring file
Nayna Jain61917062018-10-09 23:00:36 +0530743 * signatures, prior to other appraise rules.
Mimi Zohar503ceae2017-04-21 18:58:27 -0400744 */
Nayna Jainc52657d2018-10-09 23:00:35 +0530745 if (ima_use_secure_boot)
746 add_rules(secure_boot_rules, ARRAY_SIZE(secure_boot_rules),
747 IMA_DEFAULT_POLICY);
Mimi Zohar503ceae2017-04-21 18:58:27 -0400748
Mimi Zoharef968372018-07-13 14:06:01 -0400749 /*
750 * Insert the build time appraise rules requiring file signatures
751 * for both the initial and custom policies, prior to other appraise
Nayna Jainc52657d2018-10-09 23:00:35 +0530752 * rules. As the secure boot rules includes all of the build time
753 * rules, include either one or the other set of rules, but not both.
Mimi Zoharef968372018-07-13 14:06:01 -0400754 */
Nayna Jainc52657d2018-10-09 23:00:35 +0530755 build_appraise_entries = ARRAY_SIZE(build_appraise_rules);
756 if (build_appraise_entries) {
757 if (ima_use_secure_boot)
758 add_rules(build_appraise_rules, build_appraise_entries,
759 IMA_CUSTOM_POLICY);
760 else
761 add_rules(build_appraise_rules, build_appraise_entries,
762 IMA_DEFAULT_POLICY | IMA_CUSTOM_POLICY);
Mimi Zoharef968372018-07-13 14:06:01 -0400763 }
764
Nayna Jainc52657d2018-10-09 23:00:35 +0530765 if (ima_use_appraise_tcb)
766 add_rules(default_appraise_rules,
767 ARRAY_SIZE(default_appraise_rules),
768 IMA_DEFAULT_POLICY);
Mimi Zohar07f6a792011-03-09 22:25:48 -0500769
770 ima_rules = &ima_default_rules;
Mimi Zohar95ee08f2015-12-07 15:08:01 -0500771 ima_update_policy_flag();
Mimi Zohar3323eec2009-02-04 09:06:58 -0500772}
Mimi Zohar4af46622009-02-04 09:07:00 -0500773
Sasha Levin01127212015-12-22 08:51:23 -0500774/* Make sure we have a valid policy, at least containing some rules. */
Colin Ian Kingc75d8e92016-01-20 11:13:46 +0000775int ima_check_policy(void)
Sasha Levin01127212015-12-22 08:51:23 -0500776{
777 if (list_empty(&ima_temp_rules))
778 return -EINVAL;
779 return 0;
780}
781
Mimi Zohar4af46622009-02-04 09:07:00 -0500782/**
783 * ima_update_policy - update default_rules with new measure rules
784 *
785 * Called on file .release to update the default rules with a complete new
Petko Manolov38d859f2015-12-02 17:47:54 +0200786 * policy. What we do here is to splice ima_policy_rules and ima_temp_rules so
787 * they make a queue. The policy may be updated multiple times and this is the
788 * RCU updater.
789 *
790 * Policy rules are never deleted so ima_policy_flag gets zeroed only once when
791 * we switch from the default policy to user defined.
Mimi Zohar4af46622009-02-04 09:07:00 -0500792 */
793void ima_update_policy(void)
794{
Petko Manolov53b626f2018-05-22 17:06:55 +0300795 struct list_head *policy = &ima_policy_rules;
Petko Manolov38d859f2015-12-02 17:47:54 +0200796
Petko Manolov53b626f2018-05-22 17:06:55 +0300797 list_splice_tail_init_rcu(&ima_temp_rules, policy, synchronize_rcu);
Petko Manolov38d859f2015-12-02 17:47:54 +0200798
799 if (ima_rules != policy) {
800 ima_policy_flag = 0;
801 ima_rules = policy;
Nayna Jain61917062018-10-09 23:00:36 +0530802
803 /*
804 * IMA architecture specific policy rules are specified
805 * as strings and converted to an array of ima_entry_rules
806 * on boot. After loading a custom policy, free the
807 * architecture specific rules stored as an array.
808 */
809 kfree(arch_policy_entry);
Petko Manolov38d859f2015-12-02 17:47:54 +0200810 }
Dmitry Kasatkin0716abb2014-10-03 14:40:21 +0300811 ima_update_policy_flag();
Mimi Zohar4af46622009-02-04 09:07:00 -0500812}
813
Mimi Zohar1a9430d2018-12-17 19:14:49 -0500814/* Keep the enumeration in sync with the policy_tokens! */
Mimi Zohar4af46622009-02-04 09:07:00 -0500815enum {
Mimi Zohar1a9430d2018-12-17 19:14:49 -0500816 Opt_measure, Opt_dont_measure,
Mimi Zohar07f6a792011-03-09 22:25:48 -0500817 Opt_appraise, Opt_dont_appraise,
Mimi Zoharda1b0022016-09-29 10:04:52 -0400818 Opt_audit, Opt_hash, Opt_dont_hash,
Mimi Zohar4af46622009-02-04 09:07:00 -0500819 Opt_obj_user, Opt_obj_role, Opt_obj_type,
820 Opt_subj_user, Opt_subj_role, Opt_subj_type,
Mimi Zoharf1b08bb2018-01-15 11:20:36 -0500821 Opt_func, Opt_mask, Opt_fsmagic, Opt_fsname,
Mikhail Kurinnoi3dd0c8d2017-01-27 19:23:01 +0300822 Opt_fsuuid, Opt_uid_eq, Opt_euid_eq, Opt_fowner_eq,
823 Opt_uid_gt, Opt_euid_gt, Opt_fowner_gt,
824 Opt_uid_lt, Opt_euid_lt, Opt_fowner_lt,
Nayna Jain273df862019-10-30 23:31:32 -0400825 Opt_appraise_type, Opt_appraise_flag,
Lakshmi Ramasubramanian2b60c0e2019-12-11 08:47:07 -0800826 Opt_permit_directio, Opt_pcr, Opt_template, Opt_keyrings,
827 Opt_err
Mimi Zohar4af46622009-02-04 09:07:00 -0500828};
829
Mimi Zohar1a9430d2018-12-17 19:14:49 -0500830static const match_table_t policy_tokens = {
Mimi Zohar4af46622009-02-04 09:07:00 -0500831 {Opt_measure, "measure"},
832 {Opt_dont_measure, "dont_measure"},
Mimi Zohar07f6a792011-03-09 22:25:48 -0500833 {Opt_appraise, "appraise"},
834 {Opt_dont_appraise, "dont_appraise"},
Peter Moodye7c568e2012-06-14 10:04:36 -0700835 {Opt_audit, "audit"},
Mimi Zoharda1b0022016-09-29 10:04:52 -0400836 {Opt_hash, "hash"},
837 {Opt_dont_hash, "dont_hash"},
Mimi Zohar4af46622009-02-04 09:07:00 -0500838 {Opt_obj_user, "obj_user=%s"},
839 {Opt_obj_role, "obj_role=%s"},
840 {Opt_obj_type, "obj_type=%s"},
841 {Opt_subj_user, "subj_user=%s"},
842 {Opt_subj_role, "subj_role=%s"},
843 {Opt_subj_type, "subj_type=%s"},
844 {Opt_func, "func=%s"},
845 {Opt_mask, "mask=%s"},
846 {Opt_fsmagic, "fsmagic=%s"},
Mimi Zoharf1b08bb2018-01-15 11:20:36 -0500847 {Opt_fsname, "fsname=%s"},
Dmitry Kasatkin85865c12012-09-03 23:23:13 +0300848 {Opt_fsuuid, "fsuuid=%s"},
Mikhail Kurinnoi3dd0c8d2017-01-27 19:23:01 +0300849 {Opt_uid_eq, "uid=%s"},
850 {Opt_euid_eq, "euid=%s"},
851 {Opt_fowner_eq, "fowner=%s"},
852 {Opt_uid_gt, "uid>%s"},
853 {Opt_euid_gt, "euid>%s"},
854 {Opt_fowner_gt, "fowner>%s"},
855 {Opt_uid_lt, "uid<%s"},
856 {Opt_euid_lt, "euid<%s"},
857 {Opt_fowner_lt, "fowner<%s"},
Dmitry Kasatkin0e5a2472012-06-08 13:58:49 +0300858 {Opt_appraise_type, "appraise_type=%s"},
Nayna Jain273df862019-10-30 23:31:32 -0400859 {Opt_appraise_flag, "appraise_flag=%s"},
Mimi Zoharf9b2a732014-05-12 09:28:11 -0400860 {Opt_permit_directio, "permit_directio"},
Eric Richter02606432016-06-01 13:14:01 -0500861 {Opt_pcr, "pcr=%s"},
Matthew Garrett19453ce02019-06-19 15:46:11 -0700862 {Opt_template, "template=%s"},
Lakshmi Ramasubramanian2b60c0e2019-12-11 08:47:07 -0800863 {Opt_keyrings, "keyrings=%s"},
Mimi Zohar4af46622009-02-04 09:07:00 -0500864 {Opt_err, NULL}
865};
866
Mimi Zohar07f6a792011-03-09 22:25:48 -0500867static int ima_lsm_rule_init(struct ima_rule_entry *entry,
Mimi Zohar7163a992013-01-03 14:19:09 -0500868 substring_t *args, int lsm_rule, int audit_type)
Mimi Zohar4af46622009-02-04 09:07:00 -0500869{
870 int result;
871
Eric Paris7b62e162010-04-20 10:21:01 -0400872 if (entry->lsm[lsm_rule].rule)
873 return -EINVAL;
874
Mimi Zohar7163a992013-01-03 14:19:09 -0500875 entry->lsm[lsm_rule].args_p = match_strdup(args);
876 if (!entry->lsm[lsm_rule].args_p)
877 return -ENOMEM;
878
Mimi Zohar4af46622009-02-04 09:07:00 -0500879 entry->lsm[lsm_rule].type = audit_type;
880 result = security_filter_rule_init(entry->lsm[lsm_rule].type,
Mimi Zohar7163a992013-01-03 14:19:09 -0500881 Audit_equal,
882 entry->lsm[lsm_rule].args_p,
Mimi Zohar4af46622009-02-04 09:07:00 -0500883 &entry->lsm[lsm_rule].rule);
Mimi Zohar7163a992013-01-03 14:19:09 -0500884 if (!entry->lsm[lsm_rule].rule) {
Janne Karhunen483ec262020-01-15 17:42:30 +0200885 pr_warn("rule for LSM \'%s\' is undefined\n",
886 (char *)entry->lsm[lsm_rule].args_p);
887
888 if (ima_rules == &ima_default_rules) {
889 kfree(entry->lsm[lsm_rule].args_p);
890 result = -EINVAL;
891 } else
892 result = 0;
Mimi Zohar7163a992013-01-03 14:19:09 -0500893 }
894
Mimi Zohar4af46622009-02-04 09:07:00 -0500895 return result;
896}
897
Mikhail Kurinnoi3dd0c8d2017-01-27 19:23:01 +0300898static void ima_log_string_op(struct audit_buffer *ab, char *key, char *value,
899 bool (*rule_operator)(kuid_t, kuid_t))
Eric Paris2f1506c2010-04-20 10:21:30 -0400900{
Stefan Berger2afd0202018-06-04 16:54:54 -0400901 if (!ab)
902 return;
903
Mikhail Kurinnoi3dd0c8d2017-01-27 19:23:01 +0300904 if (rule_operator == &uid_gt)
905 audit_log_format(ab, "%s>", key);
906 else if (rule_operator == &uid_lt)
907 audit_log_format(ab, "%s<", key);
908 else
909 audit_log_format(ab, "%s=", key);
Stefan Berger3d2859d2018-06-04 16:54:53 -0400910 audit_log_format(ab, "%s ", value);
Eric Paris2f1506c2010-04-20 10:21:30 -0400911}
Mikhail Kurinnoi3dd0c8d2017-01-27 19:23:01 +0300912static void ima_log_string(struct audit_buffer *ab, char *key, char *value)
913{
914 ima_log_string_op(ab, key, value, NULL);
915}
Eric Paris2f1506c2010-04-20 10:21:30 -0400916
Thiago Jung Bauermann3878d502019-06-27 23:19:32 -0300917/*
918 * Validating the appended signature included in the measurement list requires
919 * the file hash calculated without the appended signature (i.e., the 'd-modsig'
920 * field). Therefore, notify the user if they have the 'modsig' field but not
921 * the 'd-modsig' field in the template.
922 */
923static void check_template_modsig(const struct ima_template_desc *template)
924{
925#define MSG "template with 'modsig' field also needs 'd-modsig' field\n"
926 bool has_modsig, has_dmodsig;
927 static bool checked;
928 int i;
929
930 /* We only need to notify the user once. */
931 if (checked)
932 return;
933
934 has_modsig = has_dmodsig = false;
935 for (i = 0; i < template->num_fields; i++) {
936 if (!strcmp(template->fields[i]->field_id, "modsig"))
937 has_modsig = true;
938 else if (!strcmp(template->fields[i]->field_id, "d-modsig"))
939 has_dmodsig = true;
940 }
941
942 if (has_modsig && !has_dmodsig)
943 pr_notice(MSG);
944
945 checked = true;
946#undef MSG
947}
948
Mimi Zohar07f6a792011-03-09 22:25:48 -0500949static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
Mimi Zohar4af46622009-02-04 09:07:00 -0500950{
951 struct audit_buffer *ab;
Mimi Zohar4351c292014-11-05 07:53:55 -0500952 char *from;
Mimi Zohar4af46622009-02-04 09:07:00 -0500953 char *p;
Mikhail Kurinnoi3dd0c8d2017-01-27 19:23:01 +0300954 bool uid_token;
Matthew Garrett19453ce02019-06-19 15:46:11 -0700955 struct ima_template_desc *template_desc;
Mimi Zohar4af46622009-02-04 09:07:00 -0500956 int result = 0;
Lakshmi Ramasubramanian5c7bac92020-01-16 18:18:21 -0800957 size_t keyrings_len;
Mimi Zohar4af46622009-02-04 09:07:00 -0500958
Stefan Bergerdba31ee2018-06-04 16:54:55 -0400959 ab = integrity_audit_log_start(audit_context(), GFP_KERNEL,
960 AUDIT_INTEGRITY_POLICY_RULE);
Mimi Zohar4af46622009-02-04 09:07:00 -0500961
Eric W. Biederman8b94eea2012-05-25 18:24:12 -0600962 entry->uid = INVALID_UID;
Linus Torvalds882653222012-10-02 21:38:48 -0700963 entry->fowner = INVALID_UID;
Mikhail Kurinnoi3dd0c8d2017-01-27 19:23:01 +0300964 entry->uid_op = &uid_eq;
965 entry->fowner_op = &uid_eq;
Eric Parisb9035b12010-04-20 10:21:07 -0400966 entry->action = UNKNOWN;
Eric Paris28ef4002010-04-20 10:21:18 -0400967 while ((p = strsep(&rule, " \t")) != NULL) {
Mimi Zohar4af46622009-02-04 09:07:00 -0500968 substring_t args[MAX_OPT_ARGS];
969 int token;
970 unsigned long lnum;
971
972 if (result < 0)
973 break;
Eric Paris28ef4002010-04-20 10:21:18 -0400974 if ((*p == '\0') || (*p == ' ') || (*p == '\t'))
975 continue;
Mimi Zohar4af46622009-02-04 09:07:00 -0500976 token = match_token(p, policy_tokens, args);
977 switch (token) {
978 case Opt_measure:
Eric Paris2f1506c2010-04-20 10:21:30 -0400979 ima_log_string(ab, "action", "measure");
Eric Paris7b62e162010-04-20 10:21:01 -0400980
981 if (entry->action != UNKNOWN)
982 result = -EINVAL;
983
Mimi Zohar4af46622009-02-04 09:07:00 -0500984 entry->action = MEASURE;
985 break;
986 case Opt_dont_measure:
Eric Paris2f1506c2010-04-20 10:21:30 -0400987 ima_log_string(ab, "action", "dont_measure");
Eric Paris7b62e162010-04-20 10:21:01 -0400988
989 if (entry->action != UNKNOWN)
990 result = -EINVAL;
991
Mimi Zohar4af46622009-02-04 09:07:00 -0500992 entry->action = DONT_MEASURE;
993 break;
Mimi Zohar07f6a792011-03-09 22:25:48 -0500994 case Opt_appraise:
995 ima_log_string(ab, "action", "appraise");
996
997 if (entry->action != UNKNOWN)
998 result = -EINVAL;
999
1000 entry->action = APPRAISE;
1001 break;
1002 case Opt_dont_appraise:
1003 ima_log_string(ab, "action", "dont_appraise");
1004
1005 if (entry->action != UNKNOWN)
1006 result = -EINVAL;
1007
1008 entry->action = DONT_APPRAISE;
1009 break;
Peter Moodye7c568e2012-06-14 10:04:36 -07001010 case Opt_audit:
1011 ima_log_string(ab, "action", "audit");
1012
1013 if (entry->action != UNKNOWN)
1014 result = -EINVAL;
1015
1016 entry->action = AUDIT;
1017 break;
Mimi Zoharda1b0022016-09-29 10:04:52 -04001018 case Opt_hash:
1019 ima_log_string(ab, "action", "hash");
1020
1021 if (entry->action != UNKNOWN)
1022 result = -EINVAL;
1023
1024 entry->action = HASH;
1025 break;
1026 case Opt_dont_hash:
1027 ima_log_string(ab, "action", "dont_hash");
1028
1029 if (entry->action != UNKNOWN)
1030 result = -EINVAL;
1031
1032 entry->action = DONT_HASH;
1033 break;
Mimi Zohar4af46622009-02-04 09:07:00 -05001034 case Opt_func:
Eric Paris2f1506c2010-04-20 10:21:30 -04001035 ima_log_string(ab, "func", args[0].from);
Eric Paris7b62e162010-04-20 10:21:01 -04001036
1037 if (entry->func)
Mimi Zohar07f6a792011-03-09 22:25:48 -05001038 result = -EINVAL;
Eric Paris7b62e162010-04-20 10:21:01 -04001039
Mimi Zohar1e93d002010-01-26 17:02:41 -05001040 if (strcmp(args[0].from, "FILE_CHECK") == 0)
1041 entry->func = FILE_CHECK;
1042 /* PATH_CHECK is for backwards compat */
1043 else if (strcmp(args[0].from, "PATH_CHECK") == 0)
1044 entry->func = FILE_CHECK;
Mimi Zoharfdf90722012-10-16 12:40:08 +10301045 else if (strcmp(args[0].from, "MODULE_CHECK") == 0)
1046 entry->func = MODULE_CHECK;
Mimi Zohar5a9196d2014-07-22 10:39:48 -04001047 else if (strcmp(args[0].from, "FIRMWARE_CHECK") == 0)
1048 entry->func = FIRMWARE_CHECK;
Mimi Zohar16cac492012-12-13 11:15:04 -05001049 else if ((strcmp(args[0].from, "FILE_MMAP") == 0)
1050 || (strcmp(args[0].from, "MMAP_CHECK") == 0))
1051 entry->func = MMAP_CHECK;
Mimi Zohar4af46622009-02-04 09:07:00 -05001052 else if (strcmp(args[0].from, "BPRM_CHECK") == 0)
1053 entry->func = BPRM_CHECK;
Matthew Garrettd906c102018-01-08 13:36:20 -08001054 else if (strcmp(args[0].from, "CREDS_CHECK") == 0)
1055 entry->func = CREDS_CHECK;
Mimi Zohard9ddf072016-01-14 20:59:14 -05001056 else if (strcmp(args[0].from, "KEXEC_KERNEL_CHECK") ==
1057 0)
1058 entry->func = KEXEC_KERNEL_CHECK;
1059 else if (strcmp(args[0].from, "KEXEC_INITRAMFS_CHECK")
1060 == 0)
1061 entry->func = KEXEC_INITRAMFS_CHECK;
Mimi Zohar19f8a842016-01-15 10:17:12 -05001062 else if (strcmp(args[0].from, "POLICY_CHECK") == 0)
1063 entry->func = POLICY_CHECK;
Prakhar Srivastavab0935122019-06-23 23:23:29 -07001064 else if (strcmp(args[0].from, "KEXEC_CMDLINE") == 0)
1065 entry->func = KEXEC_CMDLINE;
Lakshmi Ramasubramanian58086112019-12-11 08:47:03 -08001066 else if (strcmp(args[0].from, "KEY_CHECK") == 0)
1067 entry->func = KEY_CHECK;
Mimi Zohar4af46622009-02-04 09:07:00 -05001068 else
1069 result = -EINVAL;
1070 if (!result)
1071 entry->flags |= IMA_FUNC;
1072 break;
1073 case Opt_mask:
Eric Paris2f1506c2010-04-20 10:21:30 -04001074 ima_log_string(ab, "mask", args[0].from);
Eric Paris7b62e162010-04-20 10:21:01 -04001075
1076 if (entry->mask)
1077 result = -EINVAL;
1078
Mimi Zohar4351c292014-11-05 07:53:55 -05001079 from = args[0].from;
1080 if (*from == '^')
1081 from++;
1082
1083 if ((strcmp(from, "MAY_EXEC")) == 0)
Mimi Zohar4af46622009-02-04 09:07:00 -05001084 entry->mask = MAY_EXEC;
Mimi Zohar4351c292014-11-05 07:53:55 -05001085 else if (strcmp(from, "MAY_WRITE") == 0)
Mimi Zohar4af46622009-02-04 09:07:00 -05001086 entry->mask = MAY_WRITE;
Mimi Zohar4351c292014-11-05 07:53:55 -05001087 else if (strcmp(from, "MAY_READ") == 0)
Mimi Zohar4af46622009-02-04 09:07:00 -05001088 entry->mask = MAY_READ;
Mimi Zohar4351c292014-11-05 07:53:55 -05001089 else if (strcmp(from, "MAY_APPEND") == 0)
Mimi Zohar4af46622009-02-04 09:07:00 -05001090 entry->mask = MAY_APPEND;
1091 else
1092 result = -EINVAL;
1093 if (!result)
Mimi Zohar4351c292014-11-05 07:53:55 -05001094 entry->flags |= (*args[0].from == '^')
1095 ? IMA_INMASK : IMA_MASK;
Mimi Zohar4af46622009-02-04 09:07:00 -05001096 break;
1097 case Opt_fsmagic:
Eric Paris2f1506c2010-04-20 10:21:30 -04001098 ima_log_string(ab, "fsmagic", args[0].from);
Eric Paris7b62e162010-04-20 10:21:01 -04001099
1100 if (entry->fsmagic) {
1101 result = -EINVAL;
1102 break;
1103 }
1104
Dmitry Kasatkin2bb930a2014-03-04 18:04:20 +02001105 result = kstrtoul(args[0].from, 16, &entry->fsmagic);
Mimi Zohar4af46622009-02-04 09:07:00 -05001106 if (!result)
1107 entry->flags |= IMA_FSMAGIC;
1108 break;
Mimi Zoharf1b08bb2018-01-15 11:20:36 -05001109 case Opt_fsname:
1110 ima_log_string(ab, "fsname", args[0].from);
1111
1112 entry->fsname = kstrdup(args[0].from, GFP_KERNEL);
1113 if (!entry->fsname) {
1114 result = -ENOMEM;
1115 break;
1116 }
1117 result = 0;
1118 entry->flags |= IMA_FSNAME;
1119 break;
Lakshmi Ramasubramanian2b60c0e2019-12-11 08:47:07 -08001120 case Opt_keyrings:
1121 ima_log_string(ab, "keyrings", args[0].from);
1122
Lakshmi Ramasubramanian5c7bac92020-01-16 18:18:21 -08001123 keyrings_len = strlen(args[0].from) + 1;
1124
Lakshmi Ramasubramanian2b60c0e2019-12-11 08:47:07 -08001125 if ((entry->keyrings) ||
1126 (entry->action != MEASURE) ||
Lakshmi Ramasubramanian5c7bac92020-01-16 18:18:21 -08001127 (entry->func != KEY_CHECK) ||
1128 (keyrings_len < 2)) {
Lakshmi Ramasubramanian2b60c0e2019-12-11 08:47:07 -08001129 result = -EINVAL;
1130 break;
1131 }
Lakshmi Ramasubramanian5c7bac92020-01-16 18:18:21 -08001132
1133 if (keyrings_len > ima_keyrings_len) {
1134 char *tmpbuf;
1135
1136 tmpbuf = krealloc(ima_keyrings, keyrings_len,
1137 GFP_KERNEL);
1138 if (!tmpbuf) {
1139 result = -ENOMEM;
1140 break;
1141 }
1142
1143 ima_keyrings = tmpbuf;
1144 ima_keyrings_len = keyrings_len;
1145 }
1146
Lakshmi Ramasubramanian2b60c0e2019-12-11 08:47:07 -08001147 entry->keyrings = kstrdup(args[0].from, GFP_KERNEL);
1148 if (!entry->keyrings) {
Lakshmi Ramasubramanian5c7bac92020-01-16 18:18:21 -08001149 kfree(ima_keyrings);
1150 ima_keyrings = NULL;
1151 ima_keyrings_len = 0;
Lakshmi Ramasubramanian2b60c0e2019-12-11 08:47:07 -08001152 result = -ENOMEM;
1153 break;
1154 }
1155 result = 0;
1156 entry->flags |= IMA_KEYRINGS;
1157 break;
Dmitry Kasatkin85865c12012-09-03 23:23:13 +03001158 case Opt_fsuuid:
1159 ima_log_string(ab, "fsuuid", args[0].from);
1160
Mike Rapoport36447452018-01-17 20:27:11 +02001161 if (!uuid_is_null(&entry->fsuuid)) {
Dmitry Kasatkin85865c12012-09-03 23:23:13 +03001162 result = -EINVAL;
1163 break;
1164 }
1165
Christoph Hellwig787d8c52017-06-01 07:00:26 +02001166 result = uuid_parse(args[0].from, &entry->fsuuid);
Mimi Zohar446d64e2013-02-24 23:42:37 -05001167 if (!result)
1168 entry->flags |= IMA_FSUUID;
Dmitry Kasatkin85865c12012-09-03 23:23:13 +03001169 break;
Mikhail Kurinnoi3dd0c8d2017-01-27 19:23:01 +03001170 case Opt_uid_gt:
1171 case Opt_euid_gt:
1172 entry->uid_op = &uid_gt;
Gustavo A. R. Silva09186e52019-02-08 14:54:53 -06001173 /* fall through */
Mikhail Kurinnoi3dd0c8d2017-01-27 19:23:01 +03001174 case Opt_uid_lt:
1175 case Opt_euid_lt:
1176 if ((token == Opt_uid_lt) || (token == Opt_euid_lt))
1177 entry->uid_op = &uid_lt;
Gustavo A. R. Silva09186e52019-02-08 14:54:53 -06001178 /* fall through */
Mikhail Kurinnoi3dd0c8d2017-01-27 19:23:01 +03001179 case Opt_uid_eq:
1180 case Opt_euid_eq:
1181 uid_token = (token == Opt_uid_eq) ||
1182 (token == Opt_uid_gt) ||
1183 (token == Opt_uid_lt);
1184
1185 ima_log_string_op(ab, uid_token ? "uid" : "euid",
1186 args[0].from, entry->uid_op);
Eric Paris7b62e162010-04-20 10:21:01 -04001187
Eric W. Biederman8b94eea2012-05-25 18:24:12 -06001188 if (uid_valid(entry->uid)) {
Eric Paris7b62e162010-04-20 10:21:01 -04001189 result = -EINVAL;
1190 break;
1191 }
1192
Jingoo Han29707b22014-02-05 15:13:14 +09001193 result = kstrtoul(args[0].from, 10, &lnum);
Mimi Zohar4af46622009-02-04 09:07:00 -05001194 if (!result) {
Mimi Zohar139069e2014-11-05 07:48:36 -05001195 entry->uid = make_kuid(current_user_ns(),
1196 (uid_t) lnum);
1197 if (!uid_valid(entry->uid) ||
1198 (uid_t)lnum != lnum)
Mimi Zohar4af46622009-02-04 09:07:00 -05001199 result = -EINVAL;
1200 else
Mikhail Kurinnoi3dd0c8d2017-01-27 19:23:01 +03001201 entry->flags |= uid_token
Mimi Zohar139069e2014-11-05 07:48:36 -05001202 ? IMA_UID : IMA_EUID;
Mimi Zohar4af46622009-02-04 09:07:00 -05001203 }
1204 break;
Mikhail Kurinnoi3dd0c8d2017-01-27 19:23:01 +03001205 case Opt_fowner_gt:
1206 entry->fowner_op = &uid_gt;
Gustavo A. R. Silva09186e52019-02-08 14:54:53 -06001207 /* fall through */
Mikhail Kurinnoi3dd0c8d2017-01-27 19:23:01 +03001208 case Opt_fowner_lt:
1209 if (token == Opt_fowner_lt)
1210 entry->fowner_op = &uid_lt;
Gustavo A. R. Silva09186e52019-02-08 14:54:53 -06001211 /* fall through */
Mikhail Kurinnoi3dd0c8d2017-01-27 19:23:01 +03001212 case Opt_fowner_eq:
1213 ima_log_string_op(ab, "fowner", args[0].from,
1214 entry->fowner_op);
Mimi Zohar07f6a792011-03-09 22:25:48 -05001215
Linus Torvalds882653222012-10-02 21:38:48 -07001216 if (uid_valid(entry->fowner)) {
Mimi Zohar07f6a792011-03-09 22:25:48 -05001217 result = -EINVAL;
1218 break;
1219 }
1220
Jingoo Han29707b22014-02-05 15:13:14 +09001221 result = kstrtoul(args[0].from, 10, &lnum);
Mimi Zohar07f6a792011-03-09 22:25:48 -05001222 if (!result) {
Linus Torvalds882653222012-10-02 21:38:48 -07001223 entry->fowner = make_kuid(current_user_ns(), (uid_t)lnum);
1224 if (!uid_valid(entry->fowner) || (((uid_t)lnum) != lnum))
Mimi Zohar07f6a792011-03-09 22:25:48 -05001225 result = -EINVAL;
1226 else
1227 entry->flags |= IMA_FOWNER;
1228 }
1229 break;
Mimi Zohar4af46622009-02-04 09:07:00 -05001230 case Opt_obj_user:
Eric Paris2f1506c2010-04-20 10:21:30 -04001231 ima_log_string(ab, "obj_user", args[0].from);
Mimi Zohar7163a992013-01-03 14:19:09 -05001232 result = ima_lsm_rule_init(entry, args,
Mimi Zohar4af46622009-02-04 09:07:00 -05001233 LSM_OBJ_USER,
1234 AUDIT_OBJ_USER);
1235 break;
1236 case Opt_obj_role:
Eric Paris2f1506c2010-04-20 10:21:30 -04001237 ima_log_string(ab, "obj_role", args[0].from);
Mimi Zohar7163a992013-01-03 14:19:09 -05001238 result = ima_lsm_rule_init(entry, args,
Mimi Zohar4af46622009-02-04 09:07:00 -05001239 LSM_OBJ_ROLE,
1240 AUDIT_OBJ_ROLE);
1241 break;
1242 case Opt_obj_type:
Eric Paris2f1506c2010-04-20 10:21:30 -04001243 ima_log_string(ab, "obj_type", args[0].from);
Mimi Zohar7163a992013-01-03 14:19:09 -05001244 result = ima_lsm_rule_init(entry, args,
Mimi Zohar4af46622009-02-04 09:07:00 -05001245 LSM_OBJ_TYPE,
1246 AUDIT_OBJ_TYPE);
1247 break;
1248 case Opt_subj_user:
Eric Paris2f1506c2010-04-20 10:21:30 -04001249 ima_log_string(ab, "subj_user", args[0].from);
Mimi Zohar7163a992013-01-03 14:19:09 -05001250 result = ima_lsm_rule_init(entry, args,
Mimi Zohar4af46622009-02-04 09:07:00 -05001251 LSM_SUBJ_USER,
1252 AUDIT_SUBJ_USER);
1253 break;
1254 case Opt_subj_role:
Eric Paris2f1506c2010-04-20 10:21:30 -04001255 ima_log_string(ab, "subj_role", args[0].from);
Mimi Zohar7163a992013-01-03 14:19:09 -05001256 result = ima_lsm_rule_init(entry, args,
Mimi Zohar4af46622009-02-04 09:07:00 -05001257 LSM_SUBJ_ROLE,
1258 AUDIT_SUBJ_ROLE);
1259 break;
1260 case Opt_subj_type:
Eric Paris2f1506c2010-04-20 10:21:30 -04001261 ima_log_string(ab, "subj_type", args[0].from);
Mimi Zohar7163a992013-01-03 14:19:09 -05001262 result = ima_lsm_rule_init(entry, args,
Mimi Zohar4af46622009-02-04 09:07:00 -05001263 LSM_SUBJ_TYPE,
1264 AUDIT_SUBJ_TYPE);
1265 break;
Dmitry Kasatkin0e5a2472012-06-08 13:58:49 +03001266 case Opt_appraise_type:
1267 if (entry->action != APPRAISE) {
1268 result = -EINVAL;
1269 break;
1270 }
1271
1272 ima_log_string(ab, "appraise_type", args[0].from);
1273 if ((strcmp(args[0].from, "imasig")) == 0)
1274 entry->flags |= IMA_DIGSIG_REQUIRED;
Thiago Jung Bauermann9044d622019-06-27 23:19:28 -03001275 else if (ima_hook_supports_modsig(entry->func) &&
1276 strcmp(args[0].from, "imasig|modsig") == 0)
1277 entry->flags |= IMA_DIGSIG_REQUIRED |
1278 IMA_MODSIG_ALLOWED;
Dmitry Kasatkin0e5a2472012-06-08 13:58:49 +03001279 else
1280 result = -EINVAL;
1281 break;
Nayna Jain273df862019-10-30 23:31:32 -04001282 case Opt_appraise_flag:
1283 ima_log_string(ab, "appraise_flag", args[0].from);
1284 if (strstr(args[0].from, "blacklist"))
1285 entry->flags |= IMA_CHECK_BLACKLIST;
1286 break;
Mimi Zoharf9b2a732014-05-12 09:28:11 -04001287 case Opt_permit_directio:
1288 entry->flags |= IMA_PERMIT_DIRECTIO;
1289 break;
Eric Richter02606432016-06-01 13:14:01 -05001290 case Opt_pcr:
1291 if (entry->action != MEASURE) {
1292 result = -EINVAL;
1293 break;
1294 }
1295 ima_log_string(ab, "pcr", args[0].from);
1296
1297 result = kstrtoint(args[0].from, 10, &entry->pcr);
1298 if (result || INVALID_PCR(entry->pcr))
1299 result = -EINVAL;
1300 else
1301 entry->flags |= IMA_PCR;
1302
1303 break;
Matthew Garrett19453ce02019-06-19 15:46:11 -07001304 case Opt_template:
1305 ima_log_string(ab, "template", args[0].from);
1306 if (entry->action != MEASURE) {
1307 result = -EINVAL;
1308 break;
1309 }
1310 template_desc = lookup_template_desc(args[0].from);
1311 if (!template_desc || entry->template) {
1312 result = -EINVAL;
1313 break;
1314 }
1315
1316 /*
1317 * template_desc_init_fields() does nothing if
1318 * the template is already initialised, so
1319 * it's safe to do this unconditionally
1320 */
1321 template_desc_init_fields(template_desc->fmt,
1322 &(template_desc->fields),
1323 &(template_desc->num_fields));
1324 entry->template = template_desc;
1325 break;
Mimi Zohar4af46622009-02-04 09:07:00 -05001326 case Opt_err:
Eric Paris2f1506c2010-04-20 10:21:30 -04001327 ima_log_string(ab, "UNKNOWN", p);
Eric Parise9d393b2010-04-20 10:21:13 -04001328 result = -EINVAL;
Mimi Zohar4af46622009-02-04 09:07:00 -05001329 break;
1330 }
1331 }
Eric Paris7b62e162010-04-20 10:21:01 -04001332 if (!result && (entry->action == UNKNOWN))
Mimi Zohar4af46622009-02-04 09:07:00 -05001333 result = -EINVAL;
Mimi Zohar6f0911a2018-04-12 00:15:22 -04001334 else if (entry->action == APPRAISE)
1335 temp_ima_appraise |= ima_appraise_flag(entry->func);
1336
Thiago Jung Bauermann3878d502019-06-27 23:19:32 -03001337 if (!result && entry->flags & IMA_MODSIG_ALLOWED) {
1338 template_desc = entry->template ? entry->template :
1339 ima_template_desc_current();
1340 check_template_modsig(template_desc);
1341 }
1342
Eric Parisb0d5de42012-02-14 17:11:07 -05001343 audit_log_format(ab, "res=%d", !result);
Mimi Zohar4af46622009-02-04 09:07:00 -05001344 audit_log_end(ab);
1345 return result;
1346}
1347
1348/**
Mimi Zohar07f6a792011-03-09 22:25:48 -05001349 * ima_parse_add_rule - add a rule to ima_policy_rules
Mimi Zohar4af46622009-02-04 09:07:00 -05001350 * @rule - ima measurement policy rule
1351 *
Petko Manolov38d859f2015-12-02 17:47:54 +02001352 * Avoid locking by allowing just one writer at a time in ima_write_policy()
Eric Paris6ccd0452010-04-20 10:20:54 -04001353 * Returns the length of the rule parsed, an error code on failure
Mimi Zohar4af46622009-02-04 09:07:00 -05001354 */
Eric Paris6ccd0452010-04-20 10:20:54 -04001355ssize_t ima_parse_add_rule(char *rule)
Mimi Zohar4af46622009-02-04 09:07:00 -05001356{
Mimi Zohar52a13282013-12-11 14:44:04 -05001357 static const char op[] = "update_policy";
Eric Paris6ccd0452010-04-20 10:20:54 -04001358 char *p;
Mimi Zohar07f6a792011-03-09 22:25:48 -05001359 struct ima_rule_entry *entry;
Eric Paris6ccd0452010-04-20 10:20:54 -04001360 ssize_t result, len;
Mimi Zohar4af46622009-02-04 09:07:00 -05001361 int audit_info = 0;
1362
Dmitry Kasatkin272a6e92014-10-03 14:40:19 +03001363 p = strsep(&rule, "\n");
1364 len = strlen(p) + 1;
Dmitry Kasatkin71787842014-10-03 14:40:20 +03001365 p += strspn(p, " \t");
Dmitry Kasatkin272a6e92014-10-03 14:40:19 +03001366
Dmitry Kasatkin71787842014-10-03 14:40:20 +03001367 if (*p == '#' || *p == '\0')
Dmitry Kasatkin272a6e92014-10-03 14:40:19 +03001368 return len;
1369
Mimi Zohar4af46622009-02-04 09:07:00 -05001370 entry = kzalloc(sizeof(*entry), GFP_KERNEL);
1371 if (!entry) {
1372 integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL,
1373 NULL, op, "-ENOMEM", -ENOMEM, audit_info);
1374 return -ENOMEM;
1375 }
1376
1377 INIT_LIST_HEAD(&entry->list);
1378
Eric Paris6ccd0452010-04-20 10:20:54 -04001379 result = ima_parse_rule(p, entry);
Eric Paris7233e3e2010-04-20 10:21:24 -04001380 if (result) {
Mimi Zohar4af46622009-02-04 09:07:00 -05001381 kfree(entry);
Mimi Zohar523979a2009-02-11 11:12:28 -05001382 integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL,
Richard Guy Briggs7e9001f2014-06-16 15:52:07 -04001383 NULL, op, "invalid-policy", result,
Mimi Zohar523979a2009-02-11 11:12:28 -05001384 audit_info);
Eric Paris7233e3e2010-04-20 10:21:24 -04001385 return result;
Mimi Zohar523979a2009-02-11 11:12:28 -05001386 }
Eric Paris7233e3e2010-04-20 10:21:24 -04001387
Petko Manolov38d859f2015-12-02 17:47:54 +02001388 list_add_tail(&entry->list, &ima_temp_rules);
Eric Paris7233e3e2010-04-20 10:21:24 -04001389
1390 return len;
Mimi Zohar4af46622009-02-04 09:07:00 -05001391}
1392
Petko Manolov38d859f2015-12-02 17:47:54 +02001393/**
1394 * ima_delete_rules() called to cleanup invalid in-flight policy.
1395 * We don't need locking as we operate on the temp list, which is
1396 * different from the active one. There is also only one user of
1397 * ima_delete_rules() at a time.
1398 */
James Morris64c61d82009-02-05 09:28:26 +11001399void ima_delete_rules(void)
Mimi Zohar4af46622009-02-04 09:07:00 -05001400{
Mimi Zohar07f6a792011-03-09 22:25:48 -05001401 struct ima_rule_entry *entry, *tmp;
Mimi Zohar7163a992013-01-03 14:19:09 -05001402 int i;
Mimi Zohar4af46622009-02-04 09:07:00 -05001403
Mimi Zohar6ad6afa2015-12-07 14:35:47 -05001404 temp_ima_appraise = 0;
Petko Manolov38d859f2015-12-02 17:47:54 +02001405 list_for_each_entry_safe(entry, tmp, &ima_temp_rules, list) {
Mimi Zohar7163a992013-01-03 14:19:09 -05001406 for (i = 0; i < MAX_LSM_RULES; i++)
1407 kfree(entry->lsm[i].args_p);
1408
Mimi Zohar4af46622009-02-04 09:07:00 -05001409 list_del(&entry->list);
1410 kfree(entry);
1411 }
Mimi Zohar4af46622009-02-04 09:07:00 -05001412}
Petko Manolov80eae202015-12-02 17:47:56 +02001413
Thiago Jung Bauermann39b07092019-06-27 23:19:30 -03001414#define __ima_hook_stringify(str) (#str),
1415
1416const char *const func_tokens[] = {
1417 __ima_hooks(__ima_hook_stringify)
1418};
1419
Petko Manolov80eae202015-12-02 17:47:56 +02001420#ifdef CONFIG_IMA_READ_POLICY
1421enum {
1422 mask_exec = 0, mask_write, mask_read, mask_append
1423};
1424
Thiago Jung Bauermannbb543e32017-06-07 22:49:10 -03001425static const char *const mask_tokens[] = {
Roberto Sassu8cdc23a2019-05-29 15:30:35 +02001426 "^MAY_EXEC",
1427 "^MAY_WRITE",
1428 "^MAY_READ",
1429 "^MAY_APPEND"
Petko Manolov80eae202015-12-02 17:47:56 +02001430};
1431
Petko Manolov80eae202015-12-02 17:47:56 +02001432void *ima_policy_start(struct seq_file *m, loff_t *pos)
1433{
1434 loff_t l = *pos;
1435 struct ima_rule_entry *entry;
1436
1437 rcu_read_lock();
1438 list_for_each_entry_rcu(entry, ima_rules, list) {
1439 if (!l--) {
1440 rcu_read_unlock();
1441 return entry;
1442 }
1443 }
1444 rcu_read_unlock();
1445 return NULL;
1446}
1447
1448void *ima_policy_next(struct seq_file *m, void *v, loff_t *pos)
1449{
1450 struct ima_rule_entry *entry = v;
1451
1452 rcu_read_lock();
1453 entry = list_entry_rcu(entry->list.next, struct ima_rule_entry, list);
1454 rcu_read_unlock();
1455 (*pos)++;
1456
1457 return (&entry->list == ima_rules) ? NULL : entry;
1458}
1459
1460void ima_policy_stop(struct seq_file *m, void *v)
1461{
1462}
1463
Mimi Zohar1a9430d2018-12-17 19:14:49 -05001464#define pt(token) policy_tokens[token].pattern
Petko Manolov80eae202015-12-02 17:47:56 +02001465#define mt(token) mask_tokens[token]
Petko Manolov80eae202015-12-02 17:47:56 +02001466
Mimi Zoharb5269ab2016-01-28 13:10:36 -05001467/*
1468 * policy_func_show - display the ima_hooks policy rule
1469 */
1470static void policy_func_show(struct seq_file *m, enum ima_hooks func)
1471{
Thiago Jung Bauermann26632182017-06-07 22:49:11 -03001472 if (func > 0 && func < MAX_CHECK)
1473 seq_printf(m, "func=%s ", func_tokens[func]);
1474 else
1475 seq_printf(m, "func=%d ", func);
Mimi Zoharb5269ab2016-01-28 13:10:36 -05001476}
1477
Petko Manolov80eae202015-12-02 17:47:56 +02001478int ima_policy_show(struct seq_file *m, void *v)
1479{
1480 struct ima_rule_entry *entry = v;
Andy Shevchenkob8b57272016-05-20 17:00:57 -07001481 int i;
Petko Manolov80eae202015-12-02 17:47:56 +02001482 char tbuf[64] = {0,};
Roberto Sassu8cdc23a2019-05-29 15:30:35 +02001483 int offset = 0;
Petko Manolov80eae202015-12-02 17:47:56 +02001484
1485 rcu_read_lock();
1486
1487 if (entry->action & MEASURE)
1488 seq_puts(m, pt(Opt_measure));
1489 if (entry->action & DONT_MEASURE)
1490 seq_puts(m, pt(Opt_dont_measure));
1491 if (entry->action & APPRAISE)
1492 seq_puts(m, pt(Opt_appraise));
1493 if (entry->action & DONT_APPRAISE)
1494 seq_puts(m, pt(Opt_dont_appraise));
1495 if (entry->action & AUDIT)
1496 seq_puts(m, pt(Opt_audit));
Mimi Zoharda1b0022016-09-29 10:04:52 -04001497 if (entry->action & HASH)
1498 seq_puts(m, pt(Opt_hash));
1499 if (entry->action & DONT_HASH)
1500 seq_puts(m, pt(Opt_dont_hash));
Petko Manolov80eae202015-12-02 17:47:56 +02001501
1502 seq_puts(m, " ");
1503
Mimi Zoharb5269ab2016-01-28 13:10:36 -05001504 if (entry->flags & IMA_FUNC)
1505 policy_func_show(m, entry->func);
Petko Manolov80eae202015-12-02 17:47:56 +02001506
Roberto Sassu8cdc23a2019-05-29 15:30:35 +02001507 if ((entry->flags & IMA_MASK) || (entry->flags & IMA_INMASK)) {
1508 if (entry->flags & IMA_MASK)
1509 offset = 1;
Petko Manolov80eae202015-12-02 17:47:56 +02001510 if (entry->mask & MAY_EXEC)
Roberto Sassu8cdc23a2019-05-29 15:30:35 +02001511 seq_printf(m, pt(Opt_mask), mt(mask_exec) + offset);
Petko Manolov80eae202015-12-02 17:47:56 +02001512 if (entry->mask & MAY_WRITE)
Roberto Sassu8cdc23a2019-05-29 15:30:35 +02001513 seq_printf(m, pt(Opt_mask), mt(mask_write) + offset);
Petko Manolov80eae202015-12-02 17:47:56 +02001514 if (entry->mask & MAY_READ)
Roberto Sassu8cdc23a2019-05-29 15:30:35 +02001515 seq_printf(m, pt(Opt_mask), mt(mask_read) + offset);
Petko Manolov80eae202015-12-02 17:47:56 +02001516 if (entry->mask & MAY_APPEND)
Roberto Sassu8cdc23a2019-05-29 15:30:35 +02001517 seq_printf(m, pt(Opt_mask), mt(mask_append) + offset);
Petko Manolov80eae202015-12-02 17:47:56 +02001518 seq_puts(m, " ");
1519 }
1520
1521 if (entry->flags & IMA_FSMAGIC) {
1522 snprintf(tbuf, sizeof(tbuf), "0x%lx", entry->fsmagic);
1523 seq_printf(m, pt(Opt_fsmagic), tbuf);
1524 seq_puts(m, " ");
1525 }
1526
Mimi Zoharf1b08bb2018-01-15 11:20:36 -05001527 if (entry->flags & IMA_FSNAME) {
1528 snprintf(tbuf, sizeof(tbuf), "%s", entry->fsname);
1529 seq_printf(m, pt(Opt_fsname), tbuf);
1530 seq_puts(m, " ");
1531 }
1532
Lakshmi Ramasubramanian2b60c0e2019-12-11 08:47:07 -08001533 if (entry->flags & IMA_KEYRINGS) {
1534 if (entry->keyrings != NULL)
1535 snprintf(tbuf, sizeof(tbuf), "%s", entry->keyrings);
1536 seq_printf(m, pt(Opt_keyrings), tbuf);
1537 seq_puts(m, " ");
1538 }
1539
Eric Richter02606432016-06-01 13:14:01 -05001540 if (entry->flags & IMA_PCR) {
1541 snprintf(tbuf, sizeof(tbuf), "%d", entry->pcr);
1542 seq_printf(m, pt(Opt_pcr), tbuf);
1543 seq_puts(m, " ");
1544 }
1545
Petko Manolov80eae202015-12-02 17:47:56 +02001546 if (entry->flags & IMA_FSUUID) {
Christoph Hellwig787d8c52017-06-01 07:00:26 +02001547 seq_printf(m, "fsuuid=%pU", &entry->fsuuid);
Petko Manolov80eae202015-12-02 17:47:56 +02001548 seq_puts(m, " ");
1549 }
1550
1551 if (entry->flags & IMA_UID) {
1552 snprintf(tbuf, sizeof(tbuf), "%d", __kuid_val(entry->uid));
Mikhail Kurinnoi3dd0c8d2017-01-27 19:23:01 +03001553 if (entry->uid_op == &uid_gt)
1554 seq_printf(m, pt(Opt_uid_gt), tbuf);
1555 else if (entry->uid_op == &uid_lt)
1556 seq_printf(m, pt(Opt_uid_lt), tbuf);
1557 else
1558 seq_printf(m, pt(Opt_uid_eq), tbuf);
Petko Manolov80eae202015-12-02 17:47:56 +02001559 seq_puts(m, " ");
1560 }
1561
1562 if (entry->flags & IMA_EUID) {
1563 snprintf(tbuf, sizeof(tbuf), "%d", __kuid_val(entry->uid));
Mikhail Kurinnoi3dd0c8d2017-01-27 19:23:01 +03001564 if (entry->uid_op == &uid_gt)
1565 seq_printf(m, pt(Opt_euid_gt), tbuf);
1566 else if (entry->uid_op == &uid_lt)
1567 seq_printf(m, pt(Opt_euid_lt), tbuf);
1568 else
1569 seq_printf(m, pt(Opt_euid_eq), tbuf);
Petko Manolov80eae202015-12-02 17:47:56 +02001570 seq_puts(m, " ");
1571 }
1572
1573 if (entry->flags & IMA_FOWNER) {
1574 snprintf(tbuf, sizeof(tbuf), "%d", __kuid_val(entry->fowner));
Mikhail Kurinnoi3dd0c8d2017-01-27 19:23:01 +03001575 if (entry->fowner_op == &uid_gt)
1576 seq_printf(m, pt(Opt_fowner_gt), tbuf);
1577 else if (entry->fowner_op == &uid_lt)
1578 seq_printf(m, pt(Opt_fowner_lt), tbuf);
1579 else
1580 seq_printf(m, pt(Opt_fowner_eq), tbuf);
Petko Manolov80eae202015-12-02 17:47:56 +02001581 seq_puts(m, " ");
1582 }
1583
1584 for (i = 0; i < MAX_LSM_RULES; i++) {
1585 if (entry->lsm[i].rule) {
1586 switch (i) {
1587 case LSM_OBJ_USER:
1588 seq_printf(m, pt(Opt_obj_user),
1589 (char *)entry->lsm[i].args_p);
1590 break;
1591 case LSM_OBJ_ROLE:
1592 seq_printf(m, pt(Opt_obj_role),
1593 (char *)entry->lsm[i].args_p);
1594 break;
1595 case LSM_OBJ_TYPE:
1596 seq_printf(m, pt(Opt_obj_type),
1597 (char *)entry->lsm[i].args_p);
1598 break;
1599 case LSM_SUBJ_USER:
1600 seq_printf(m, pt(Opt_subj_user),
1601 (char *)entry->lsm[i].args_p);
1602 break;
1603 case LSM_SUBJ_ROLE:
1604 seq_printf(m, pt(Opt_subj_role),
1605 (char *)entry->lsm[i].args_p);
1606 break;
1607 case LSM_SUBJ_TYPE:
1608 seq_printf(m, pt(Opt_subj_type),
1609 (char *)entry->lsm[i].args_p);
1610 break;
1611 }
Clay Chang5350ceb2020-01-05 09:18:13 +08001612 seq_puts(m, " ");
Petko Manolov80eae202015-12-02 17:47:56 +02001613 }
1614 }
Matthew Garrett19453ce02019-06-19 15:46:11 -07001615 if (entry->template)
1616 seq_printf(m, "template=%s ", entry->template->name);
Thiago Jung Bauermann9044d622019-06-27 23:19:28 -03001617 if (entry->flags & IMA_DIGSIG_REQUIRED) {
1618 if (entry->flags & IMA_MODSIG_ALLOWED)
1619 seq_puts(m, "appraise_type=imasig|modsig ");
1620 else
1621 seq_puts(m, "appraise_type=imasig ");
1622 }
Nayna Jain273df862019-10-30 23:31:32 -04001623 if (entry->flags & IMA_CHECK_BLACKLIST)
1624 seq_puts(m, "appraise_flag=check_blacklist ");
Petko Manolov80eae202015-12-02 17:47:56 +02001625 if (entry->flags & IMA_PERMIT_DIRECTIO)
1626 seq_puts(m, "permit_directio ");
1627 rcu_read_unlock();
1628 seq_puts(m, "\n");
1629 return 0;
1630}
1631#endif /* CONFIG_IMA_READ_POLICY */
Matthew Garrett29d3c1c2019-08-19 17:18:01 -07001632
1633#if defined(CONFIG_IMA_APPRAISE) && defined(CONFIG_INTEGRITY_TRUSTED_KEYRING)
1634/*
1635 * ima_appraise_signature: whether IMA will appraise a given function using
1636 * an IMA digital signature. This is restricted to cases where the kernel
1637 * has a set of built-in trusted keys in order to avoid an attacker simply
1638 * loading additional keys.
1639 */
1640bool ima_appraise_signature(enum kernel_read_file_id id)
1641{
1642 struct ima_rule_entry *entry;
1643 bool found = false;
1644 enum ima_hooks func;
1645
1646 if (id >= READING_MAX_ID)
1647 return false;
1648
1649 func = read_idmap[id] ?: FILE_CHECK;
1650
1651 rcu_read_lock();
1652 list_for_each_entry_rcu(entry, ima_rules, list) {
1653 if (entry->action != APPRAISE)
1654 continue;
1655
1656 /*
1657 * A generic entry will match, but otherwise require that it
1658 * match the func we're looking for
1659 */
1660 if (entry->func && entry->func != func)
1661 continue;
1662
1663 /*
1664 * We require this to be a digital signature, not a raw IMA
1665 * hash.
1666 */
1667 if (entry->flags & IMA_DIGSIG_REQUIRED)
1668 found = true;
1669
1670 /*
1671 * We've found a rule that matches, so break now even if it
1672 * didn't require a digital signature - a later rule that does
1673 * won't override it, so would be a false positive.
1674 */
1675 break;
1676 }
1677
1678 rcu_read_unlock();
1679 return found;
1680}
1681#endif /* CONFIG_IMA_APPRAISE && CONFIG_INTEGRITY_TRUSTED_KEYRING */