diff options
author | Jann Horn <jannh@google.com> | 2019-04-10 12:55:48 -0400 |
---|---|---|
committer | Micah Morton <mortonm@chromium.org> | 2019-07-15 11:07:09 -0400 |
commit | 78ae7df96d647627ceae0b65eea9e4f83a0a4b66 (patch) | |
tree | 1f7f4fb2c97ee93390fe7527e4d026ee87214422 /security | |
parent | 8068866c4af124345e2a129be921278aada7830f (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.c | 84 |
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 | */ |
39 | static int parse_safesetid_whitelist_policy(const char __user *buf, | 40 | static 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 | ||
95 | free_both: | 67 | return 0; |
96 | kfree(parent_buf); | 68 | } |
97 | free_kern: | 69 | |
70 | static 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 | ||