Commit 78ae7df9 authored by Jann Horn's avatar Jann Horn Committed by Micah Morton

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: default avatarJann Horn <jannh@google.com>
Signed-off-by: default avatarMicah Morton <mortonm@chromium.org>
parent 8068866c
...@@ -33,68 +33,50 @@ static struct safesetid_file_entry safesetid_files[] = { ...@@ -33,68 +33,50 @@ static struct safesetid_file_entry safesetid_files[] = {
/* /*
* In the case the input buffer contains one or more invalid UIDs, the kuid_t * In the case the input buffer contains one or more invalid UIDs, the kuid_t
* variables pointed to by 'parent' and 'child' will get updated but this * variables pointed to by @parent and @child will get updated but this
* function will return an error. * function will return an error.
* Contents of @buf may be modified.
*/ */
static int parse_safesetid_whitelist_policy(const char __user *buf, static int parse_policy_line(
size_t len, struct file *file, char *buf, kuid_t *parent, kuid_t *child)
kuid_t *parent,
kuid_t *child)
{ {
char *kern_buf; char *child_str;
char *parent_buf;
char *child_buf;
const char separator[] = ":";
int ret; int ret;
size_t first_substring_length; u32 parsed_parent, parsed_child;
long parsed_parent;
long parsed_child;
/* Duplicate string from user memory and NULL-terminate */ /* Format of |buf| string should be <UID>:<UID>. */
kern_buf = memdup_user_nul(buf, len); child_str = strchr(buf, ':');
if (IS_ERR(kern_buf)) if (child_str == NULL)
return PTR_ERR(kern_buf); return -EINVAL;
*child_str = '\0';
/* child_str++;
* Format of |buf| string should be <UID>:<UID>.
* Find location of ":" in kern_buf (copied from |buf|).
*/
first_substring_length = strcspn(kern_buf, separator);
if (first_substring_length == 0 || first_substring_length == len) {
ret = -EINVAL;
goto free_kern;
}
parent_buf = kmemdup_nul(kern_buf, first_substring_length, GFP_KERNEL);
if (!parent_buf) {
ret = -ENOMEM;
goto free_kern;
}
ret = kstrtol(parent_buf, 0, &parsed_parent); ret = kstrtou32(buf, 0, &parsed_parent);
if (ret) if (ret)
goto free_both; return ret;
child_buf = kern_buf + first_substring_length + 1; ret = kstrtou32(child_str, 0, &parsed_child);
ret = kstrtol(child_buf, 0, &parsed_child);
if (ret) if (ret)
goto free_both; return ret;
*parent = make_kuid(current_user_ns(), parsed_parent); *parent = make_kuid(current_user_ns(), parsed_parent);
if (!uid_valid(*parent)) {
ret = -EINVAL;
goto free_both;
}
*child = make_kuid(current_user_ns(), parsed_child); *child = make_kuid(current_user_ns(), parsed_child);
if (!uid_valid(*child)) { if (!uid_valid(*parent) || !uid_valid(*child))
ret = -EINVAL; return -EINVAL;
goto free_both;
}
free_both: return 0;
kfree(parent_buf); }
free_kern:
static int parse_safesetid_whitelist_policy(
struct file *file, const char __user *buf, size_t len,
kuid_t *parent, kuid_t *child)
{
char *kern_buf = memdup_user_nul(buf, len);
int ret;
if (IS_ERR(kern_buf))
return PTR_ERR(kern_buf);
ret = parse_policy_line(file, kern_buf, parent, child);
kfree(kern_buf); kfree(kern_buf);
return ret; return ret;
} }
...@@ -121,8 +103,8 @@ static ssize_t safesetid_file_write(struct file *file, ...@@ -121,8 +103,8 @@ static ssize_t safesetid_file_write(struct file *file,
flush_safesetid_whitelist_entries(); flush_safesetid_whitelist_entries();
break; break;
case SAFESETID_WHITELIST_ADD: case SAFESETID_WHITELIST_ADD:
ret = parse_safesetid_whitelist_policy(buf, len, &parent, ret = parse_safesetid_whitelist_policy(file, buf, len,
&child); &parent, &child);
if (ret) if (ret)
return ret; return ret;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment