summaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
authorJann Horn <jannh@google.com>2019-04-10 12:55:48 -0400
committerMicah Morton <mortonm@chromium.org>2019-07-15 11:07:09 -0400
commit78ae7df96d647627ceae0b65eea9e4f83a0a4b66 (patch)
tree1f7f4fb2c97ee93390fe7527e4d026ee87214422 /security
parent8068866c4af124345e2a129be921278aada7830f (diff)
LSM: SafeSetID: refactor policy parsing
In preparation for changing the policy parsing logic, refactor the line parsing logic to be less verbose and move it into a separate function. Signed-off-by: Jann Horn <jannh@google.com> Signed-off-by: Micah Morton <mortonm@chromium.org>
Diffstat (limited to 'security')
-rw-r--r--security/safesetid/securityfs.c84
1 files changed, 33 insertions, 51 deletions
diff --git a/security/safesetid/securityfs.c b/security/safesetid/securityfs.c
index 2c6c829be044..90784a8d950a 100644
--- a/security/safesetid/securityfs.c
+++ b/security/safesetid/securityfs.c
@@ -33,68 +33,50 @@ static struct safesetid_file_entry safesetid_files[] = {
33 33
34/* 34/*
35 * In the case the input buffer contains one or more invalid UIDs, the kuid_t 35 * In the case the input buffer contains one or more invalid UIDs, the kuid_t
36 * variables pointed to by 'parent' and 'child' will get updated but this 36 * variables pointed to by @parent and @child will get updated but this
37 * function will return an error. 37 * function will return an error.
38 * Contents of @buf may be modified.
38 */ 39 */
39static int parse_safesetid_whitelist_policy(const char __user *buf, 40static int parse_policy_line(
40 size_t len, 41 struct file *file, char *buf, kuid_t *parent, kuid_t *child)
41 kuid_t *parent,
42 kuid_t *child)
43{ 42{
44 char *kern_buf; 43 char *child_str;
45 char *parent_buf;
46 char *child_buf;
47 const char separator[] = ":";
48 int ret; 44 int ret;
49 size_t first_substring_length; 45 u32 parsed_parent, parsed_child;
50 long parsed_parent;
51 long parsed_child;
52 46
53 /* Duplicate string from user memory and NULL-terminate */ 47 /* Format of |buf| string should be <UID>:<UID>. */
54 kern_buf = memdup_user_nul(buf, len); 48 child_str = strchr(buf, ':');
55 if (IS_ERR(kern_buf)) 49 if (child_str == NULL)
56 return PTR_ERR(kern_buf); 50 return -EINVAL;
57 51 *child_str = '\0';
58 /* 52 child_str++;
59 * Format of |buf| string should be <UID>:<UID>.
60 * Find location of ":" in kern_buf (copied from |buf|).
61 */
62 first_substring_length = strcspn(kern_buf, separator);
63 if (first_substring_length == 0 || first_substring_length == len) {
64 ret = -EINVAL;
65 goto free_kern;
66 }
67
68 parent_buf = kmemdup_nul(kern_buf, first_substring_length, GFP_KERNEL);
69 if (!parent_buf) {
70 ret = -ENOMEM;
71 goto free_kern;
72 }
73 53
74 ret = kstrtol(parent_buf, 0, &parsed_parent); 54 ret = kstrtou32(buf, 0, &parsed_parent);
75 if (ret) 55 if (ret)
76 goto free_both; 56 return ret;
77 57
78 child_buf = kern_buf + first_substring_length + 1; 58 ret = kstrtou32(child_str, 0, &parsed_child);
79 ret = kstrtol(child_buf, 0, &parsed_child);
80 if (ret) 59 if (ret)
81 goto free_both; 60 return ret;
82 61
83 *parent = make_kuid(current_user_ns(), parsed_parent); 62 *parent = make_kuid(current_user_ns(), parsed_parent);
84 if (!uid_valid(*parent)) {
85 ret = -EINVAL;
86 goto free_both;
87 }
88
89 *child = make_kuid(current_user_ns(), parsed_child); 63 *child = make_kuid(current_user_ns(), parsed_child);
90 if (!uid_valid(*child)) { 64 if (!uid_valid(*parent) || !uid_valid(*child))
91 ret = -EINVAL; 65 return -EINVAL;
92 goto free_both;
93 }
94 66
95free_both: 67 return 0;
96 kfree(parent_buf); 68}
97free_kern: 69
70static int parse_safesetid_whitelist_policy(
71 struct file *file, const char __user *buf, size_t len,
72 kuid_t *parent, kuid_t *child)
73{
74 char *kern_buf = memdup_user_nul(buf, len);
75 int ret;
76
77 if (IS_ERR(kern_buf))
78 return PTR_ERR(kern_buf);
79 ret = parse_policy_line(file, kern_buf, parent, child);
98 kfree(kern_buf); 80 kfree(kern_buf);
99 return ret; 81 return ret;
100} 82}
@@ -121,8 +103,8 @@ static ssize_t safesetid_file_write(struct file *file,
121 flush_safesetid_whitelist_entries(); 103 flush_safesetid_whitelist_entries();
122 break; 104 break;
123 case SAFESETID_WHITELIST_ADD: 105 case SAFESETID_WHITELIST_ADD:
124 ret = parse_safesetid_whitelist_policy(buf, len, &parent, 106 ret = parse_safesetid_whitelist_policy(file, buf, len,
125 &child); 107 &parent, &child);
126 if (ret) 108 if (ret)
127 return ret; 109 return ret;
128 110