summaryrefslogtreecommitdiffstats
path: root/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/smack/0012-Smack-parse-multiple-rules-per-write-to-load2-up-to-.patch
diff options
context:
space:
mode:
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-.patch252
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
+