diff options
author | Yannick GICQUEL <yannick.gicquel@iot.bzh> | 2015-10-19 15:57:07 +0200 |
---|---|---|
committer | Gerrit Code Review <gerrit@172.30.200.200> | 2015-11-06 15:23:36 +0000 |
commit | ede19ea0c47fb23f3fc779833d1e57cf76f3371e (patch) | |
tree | 47d6fae2283c54def1871aaf2a73828ac68b1b34 /meta-rcar-gen2/recipes-kernel/linux/linux-renesas/smack/0012-Smack-parse-multiple-rules-per-write-to-load2-up-to-.patch | |
parent | 1cd8ab18abca96e4ee108f80225058d875b28347 (diff) |
kernel: smack security backport from kernel 4
Here is the backport of all patches relating to smack support
on kernel side. For more details, see file:
meta-rcar-gen2/recipes-kernel/linux/linux-renesas/smack/README
Please note that patches are applied only if "smack" is in the
ditro features. Here are the 2 lines to add in the local.conf
OVERRIDES .= ":smack"
DISTRO_FEATURES_append = " smack"
Change-Id: I147a3532aec531f977d6ec34c576261835711f1e
Signed-off-by: Yannick GICQUEL <yannick.gicquel@iot.bzh>
Signed-off-by: José Bollo <jose.bollo@iot.bzh>
Diffstat (limited to 'meta-rcar-gen2/recipes-kernel/linux/linux-renesas/smack/0012-Smack-parse-multiple-rules-per-write-to-load2-up-to-.patch')
-rw-r--r-- | meta-rcar-gen2/recipes-kernel/linux/linux-renesas/smack/0012-Smack-parse-multiple-rules-per-write-to-load2-up-to-.patch | 252 |
1 files changed, 252 insertions, 0 deletions
diff --git a/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/smack/0012-Smack-parse-multiple-rules-per-write-to-load2-up-to-.patch b/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/smack/0012-Smack-parse-multiple-rules-per-write-to-load2-up-to-.patch new file mode 100644 index 0000000..b11e14e --- /dev/null +++ b/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/smack/0012-Smack-parse-multiple-rules-per-write-to-load2-up-to-.patch @@ -0,0 +1,252 @@ +From af18e4fa19be1e914781acd5a9e3ad4ee62b4fac Mon Sep 17 00:00:00 2001 +From: Rafal Krypa <r.krypa@samsung.com> +Date: Fri, 9 Aug 2013 11:47:07 +0200 +Subject: [PATCH 12/54] Smack: parse multiple rules per write to load2, up to + PAGE_SIZE-1 bytes + +Smack interface for loading rules has always parsed only single rule from +data written to it. This requires user program to call one write() per +each rule it wants to load. +This change makes it possible to write multiple rules, separated by new +line character. Smack will load at most PAGE_SIZE-1 characters and properly +return number of processed bytes. In case when user buffer is larger, it +will be additionally truncated. All characters after last \n will not get +parsed to avoid partial rule near input buffer boundary. + +Signed-off-by: Rafal Krypa <r.krypa@samsung.com> +--- + security/smack/smackfs.c | 167 +++++++++++++++++++++++------------------------ + 1 file changed, 82 insertions(+), 85 deletions(-) + +diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c +index a07e93f..80f4b4a 100644 +--- a/security/smack/smackfs.c ++++ b/security/smack/smackfs.c +@@ -368,56 +368,43 @@ static int smk_parse_rule(const char *data, struct smack_parsed_rule *rule, + * @data: string to be parsed, null terminated + * @rule: Will be filled with Smack parsed rule + * @import: if non-zero, import labels +- * @change: if non-zero, data is from /smack/change-rule ++ * @tokens: numer of substrings expected in data + * +- * Returns 0 on success, -1 on failure ++ * Returns number of processed bytes on success, -1 on failure. + */ +-static int smk_parse_long_rule(const char *data, struct smack_parsed_rule *rule, +- int import, int change) ++static ssize_t smk_parse_long_rule(char *data, struct smack_parsed_rule *rule, ++ int import, int tokens) + { +- char *subject; +- char *object; +- char *access1; +- char *access2; +- int datalen; +- int rc = -1; ++ ssize_t cnt = 0; ++ char *tok[4]; ++ int i; + +- /* This is inefficient */ +- datalen = strlen(data); ++ /* ++ * Parsing the rule in-place, filling all white-spaces with '\0' ++ */ ++ for (i = 0; i < tokens; ++i) { ++ while (isspace(data[cnt])) ++ data[cnt++] = '\0'; + +- /* Our first element can be 64 + \0 with no spaces */ +- subject = kzalloc(datalen + 1, GFP_KERNEL); +- if (subject == NULL) +- return -1; +- object = kzalloc(datalen, GFP_KERNEL); +- if (object == NULL) +- goto free_out_s; +- access1 = kzalloc(datalen, GFP_KERNEL); +- if (access1 == NULL) +- goto free_out_o; +- access2 = kzalloc(datalen, GFP_KERNEL); +- if (access2 == NULL) +- goto free_out_a; +- +- if (change) { +- if (sscanf(data, "%s %s %s %s", +- subject, object, access1, access2) == 4) +- rc = smk_fill_rule(subject, object, access1, access2, +- rule, import, 0); +- } else { +- if (sscanf(data, "%s %s %s", subject, object, access1) == 3) +- rc = smk_fill_rule(subject, object, access1, NULL, +- rule, import, 0); ++ if (data[cnt] == '\0') ++ /* Unexpected end of data */ ++ return -1; ++ ++ tok[i] = data + cnt; ++ ++ while (data[cnt] && !isspace(data[cnt])) ++ ++cnt; + } ++ while (isspace(data[cnt])) ++ data[cnt++] = '\0'; + +- kfree(access2); +-free_out_a: +- kfree(access1); +-free_out_o: +- kfree(object); +-free_out_s: +- kfree(subject); +- return rc; ++ while (i < 4) ++ tok[i++] = NULL; ++ ++ if (smk_fill_rule(tok[0], tok[1], tok[2], tok[3], rule, import, 0)) ++ return -1; ++ ++ return cnt; + } + + #define SMK_FIXED24_FMT 0 /* Fixed 24byte label format */ +@@ -449,9 +436,10 @@ static ssize_t smk_write_rules_list(struct file *file, const char __user *buf, + { + struct smack_parsed_rule rule; + char *data; +- int datalen; +- int rc = -EINVAL; +- int load = 0; ++ int rc; ++ int trunc = 0; ++ int tokens; ++ ssize_t cnt = 0; + + /* + * No partial writes. +@@ -466,11 +454,14 @@ static ssize_t smk_write_rules_list(struct file *file, const char __user *buf, + */ + if (count != SMK_OLOADLEN && count != SMK_LOADLEN) + return -EINVAL; +- datalen = SMK_LOADLEN; +- } else +- datalen = count + 1; ++ } else { ++ if (count >= PAGE_SIZE) { ++ count = PAGE_SIZE - 1; ++ trunc = 1; ++ } ++ } + +- data = kzalloc(datalen, GFP_KERNEL); ++ data = kmalloc(count + 1, GFP_KERNEL); + if (data == NULL) + return -ENOMEM; + +@@ -479,36 +470,49 @@ static ssize_t smk_write_rules_list(struct file *file, const char __user *buf, + goto out; + } + +- if (format == SMK_LONG_FMT) { +- /* +- * Be sure the data string is terminated. +- */ +- data[count] = '\0'; +- if (smk_parse_long_rule(data, &rule, 1, 0)) +- goto out; +- } else if (format == SMK_CHANGE_FMT) { +- data[count] = '\0'; +- if (smk_parse_long_rule(data, &rule, 1, 1)) +- goto out; +- } else { +- /* +- * More on the minor hack for backward compatibility +- */ +- if (count == (SMK_OLOADLEN)) +- data[SMK_OLOADLEN] = '-'; +- if (smk_parse_rule(data, &rule, 1)) ++ /* ++ * In case of parsing only part of user buf, ++ * avoid having partial rule at the data buffer ++ */ ++ if (trunc) { ++ while (count > 0 && (data[count - 1] != '\n')) ++ --count; ++ if (count == 0) { ++ rc = -EINVAL; + goto out; ++ } + } + +- if (rule_list == NULL) { +- load = 1; +- rule_list = &rule.smk_subject->smk_rules; +- rule_lock = &rule.smk_subject->smk_rules_lock; ++ data[count] = '\0'; ++ tokens = (format == SMK_CHANGE_FMT ? 4 : 3); ++ while (cnt < count) { ++ if (format == SMK_FIXED24_FMT) { ++ rc = smk_parse_rule(data, &rule, 1); ++ if (rc != 0) { ++ rc = -EINVAL; ++ goto out; ++ } ++ cnt = count; ++ } else { ++ rc = smk_parse_long_rule(data + cnt, &rule, 1, tokens); ++ if (rc <= 0) { ++ rc = -EINVAL; ++ goto out; ++ } ++ cnt += rc; ++ } ++ ++ if (rule_list == NULL) ++ rc = smk_set_access(&rule, &rule.smk_subject->smk_rules, ++ &rule.smk_subject->smk_rules_lock, 1); ++ else ++ rc = smk_set_access(&rule, rule_list, rule_lock, 0); ++ ++ if (rc) ++ goto out; + } + +- rc = smk_set_access(&rule, rule_list, rule_lock, load); +- if (rc == 0) +- rc = count; ++ rc = cnt; + out: + kfree(data); + return rc; +@@ -1829,7 +1833,6 @@ static ssize_t smk_user_access(struct file *file, const char __user *buf, + { + struct smack_parsed_rule rule; + char *data; +- char *cod; + int res; + + data = simple_transaction_get(file, buf, count); +@@ -1842,18 +1845,12 @@ static ssize_t smk_user_access(struct file *file, const char __user *buf, + res = smk_parse_rule(data, &rule, 0); + } else { + /* +- * Copy the data to make sure the string is terminated. ++ * simple_transaction_get() returns null-terminated data + */ +- cod = kzalloc(count + 1, GFP_KERNEL); +- if (cod == NULL) +- return -ENOMEM; +- memcpy(cod, data, count); +- cod[count] = '\0'; +- res = smk_parse_long_rule(cod, &rule, 0, 0); +- kfree(cod); ++ res = smk_parse_long_rule(data, &rule, 0, 3); + } + +- if (res) ++ if (res < 0) + return -EINVAL; + + res = smk_access(rule.smk_subject, rule.smk_object, +-- +2.1.4 + |