Linux-Integrity Archive on lore.kernel.org
 help / color / Atom feed
From: Lev Olshvang <levonshe@gmail.com>
To: linux-integrity@vger.kernel.org, Mimi Zohar <zohar@us.ibm.com>
Subject: [PATCH] integrity ima_policy : Select files by suffix
Date: Mon, 30 Mar 2020 15:27:37 +0300
Message-ID: <20200330122434.GB28214@kl> (raw)

From: Lev Olshvang <levonshe@gmail.com>
Date: Fri, 27 Mar 2020 20:50:01 +0300
Reply-To:
Subject: [PATCH] integrity ima_policy : Select files by suffix

IMA policy rule allows to select files based on uid, gid, fsuid. etc.
One tremendously useful selector(IMHO) is the file suffix.

I think of systemd service files, configurution files, etc.

But the real goal of the patch is the ability to validate shell scripts.
Shell provides too many different ways to run the script:
input redirrection, pipe, command line parameters.

IMA police rule below will catch any execution of file with sh suffix :

appraise FILE_OPEN suffix=sh

Another interesting byproduct of this feature is that any file might be put under validation.
All that you need is just create hard link to this file and apply immutable attribute to the link.
Example
appraise FILE_OPEN suffix=ini
ln /etc/shadow /etc/shadow.ini
chattr -i /etc/shadow.ini

Signed-off-by: Lev Olshvang <levonshe@gmail.com>
---
 security/integrity/ima/ima_policy.c | 41 ++++++++++++++++++++++++++++-
 1 file changed, 40 insertions(+), 1 deletion(-)

diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
index 453427048999..e8c7a4016fc6 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -35,6 +35,7 @@
 #define IMA_PCR		0x0100
 #define IMA_FSNAME	0x0200
 #define IMA_KEYRINGS	0x0400
+#define IMA_SUFFIX	0x0800

 #define UNKNOWN		0
 #define MEASURE		0x0001	/* same as IMA_MEASURE */
@@ -45,6 +46,8 @@
 #define HASH		0x0100
 #define DONT_HASH	0x0200

+#define IMA_SUFFIX_LEN 4
+
 #define INVALID_PCR(a) (((a) < 0) || \
 	(a) >= (sizeof_field(struct integrity_iint_cache, measured_pcrs) * 8))

@@ -82,6 +85,8 @@ struct ima_rule_entry {
 	char *fsname;
 	char *keyrings; /* Measure keys added to these keyrings */
 	struct ima_template_desc *template;
+	// In the first byte we encode length, then string itself
+	char suffix[IMA_SUFFIX_LEN+2];
 };

 /*
@@ -419,6 +424,9 @@ static bool ima_match_rules(struct ima_rule_entry *rule, struct inode *inode,
 			    const char *keyring)
 {
 	int i;
+	u8 sfx_len;
+	u16 name_offset;
+	struct dentry *dentry;

 	if ((func == KEXEC_CMDLINE) || (func == KEY_CHECK)) {
 		if ((rule->flags & IMA_FUNC) && (rule->func == func)) {
@@ -443,6 +451,13 @@ static bool ima_match_rules(struct ima_rule_entry *rule, struct inode *inode,
 	if ((rule->flags & IMA_FSNAME)
 	    && strcmp(rule->fsname, inode->i_sb->s_type->name))
 		return false;
+	if (rule->flags & IMA_SUFFIX) {
+		dentry = container_of(inode->i_dentry.first, struct dentry, d_u.d_alias);
+		sfx_len = (u8)rule->suffix[0] - 1;
+		name_offset = (u16) strlen(dentry->d_name.name) - sfx_len;
+		if ((memcmp(rule->suffix + 1, dentry->d_name.name + name_offset, sfx_len) != 0))
+			return false;
+	}
 	if ((rule->flags & IMA_FSUUID) &&
 	    !uuid_equal(&rule->fsuuid, &inode->i_sb->s_uuid))
 		return false;
@@ -822,6 +837,7 @@ enum {
 	Opt_obj_user, Opt_obj_role, Opt_obj_type,
 	Opt_subj_user, Opt_subj_role, Opt_subj_type,
 	Opt_func, Opt_mask, Opt_fsmagic, Opt_fsname,
+	Opt_suffix,
 	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,
@@ -849,6 +865,7 @@ static const match_table_t policy_tokens = {
 	{Opt_fsmagic, "fsmagic=%s"},
 	{Opt_fsname, "fsname=%s"},
 	{Opt_fsuuid, "fsuuid=%s"},
+	{Opt_suffix, "suffix=%s"},
 	{Opt_uid_eq, "uid=%s"},
 	{Opt_euid_eq, "euid=%s"},
 	{Opt_fowner_eq, "fowner=%s"},
@@ -991,7 +1008,6 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)

 			if (entry->action != UNKNOWN)
 				result = -EINVAL;
-
 			entry->action = DONT_MEASURE;
 			break;
 		case Opt_appraise:
@@ -1120,6 +1136,21 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
 			result = 0;
 			entry->flags |= IMA_FSNAME;
 			break;
+		case Opt_suffix:
+			ima_log_string(ab, "suffix", args[0].from);
+			result = strlen(args[0].from);
+			result++; // add '\0'
+			if (result > IMA_SUFFIX_LEN) {
+				result = -E2BIG;
+				break;
+			}
+
+			/* encode suffix len in the first byte */
+			entry->suffix[0] = (u8) result;
+			memcpy(entry->suffix + 1, args[0].from, result);
+			result = 0;
+			entry->flags |= IMA_SUFFIX;
+			break;
 		case Opt_keyrings:
 			ima_log_string(ab, "keyrings", args[0].from);

@@ -1526,6 +1557,10 @@ int ima_policy_show(struct seq_file *m, void *v)
 		seq_printf(m, pt(Opt_fsmagic), tbuf);
 		seq_puts(m, " ");
 	}
+	if (entry->flags & IMA_SUFFIX) {
+		seq_printf(m, "suffix=%s", entry->suffix + 1);
+		seq_puts(m, " ");
+	}

 	if (entry->flags & IMA_FSNAME) {
 		snprintf(tbuf, sizeof(tbuf), "%s", entry->fsname);
@@ -1546,6 +1581,10 @@ int ima_policy_show(struct seq_file *m, void *v)
 		seq_puts(m, " ");
 	}

+	if (entry->flags & IMA_SUFFIX) {
+		seq_printf(m, "suffix=%s", entry->suffix + 1);
+		seq_puts(m, " ");
+	}
 	if (entry->flags & IMA_FSUUID) {
 		seq_printf(m, "fsuuid=%pU", &entry->fsuuid);
 		seq_puts(m, " ");
--
2.17.1


             reply index

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-03-30 12:27 Lev Olshvang [this message]
2020-03-30 16:45 ` Roberto Sassu
2020-03-30 17:21   ` Lev R. Oshvang .
2020-03-30 18:05     ` Mimi Zohar
2020-03-30 20:01       ` Lev R. Oshvang .

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200330122434.GB28214@kl \
    --to=levonshe@gmail.com \
    --cc=linux-integrity@vger.kernel.org \
    --cc=zohar@us.ibm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

Linux-Integrity Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/linux-integrity/0 linux-integrity/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 linux-integrity linux-integrity/ https://lore.kernel.org/linux-integrity \
		linux-integrity@vger.kernel.org
	public-inbox-index linux-integrity

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.linux-integrity


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git