// SPDX-License-Identifier: GPL-2.0
/*
 * SafeSetID Linux Security Module
 *
 * Author: Micah Morton <mortonm@chromium.org>
 *
 * Copyright (C) 2018 The Chromium OS Authors.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2, as
 * published by the Free Software Foundation.
 *
 */

#define pr_fmt(fmt) "SafeSetID: " fmt

#include <linux/security.h>
#include <linux/cred.h>

#include "lsm.h"

static DEFINE_MUTEX(policy_update_lock);

/*
 * 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
 * function will return an error.
 * Contents of @buf may be modified.
 */
static int parse_policy_line(struct file *file, char *buf,
	struct setuid_rule *rule)
{
	char *child_str;
	int ret;
	u32 parsed_parent, parsed_child;

	/* Format of |buf| string should be <UID>:<UID>. */
	child_str = strchr(buf, ':');
	if (child_str == NULL)
		return -EINVAL;
	*child_str = '\0';
	child_str++;

	ret = kstrtou32(buf, 0, &parsed_parent);
	if (ret)
		return ret;

	ret = kstrtou32(child_str, 0, &parsed_child);
	if (ret)
		return ret;

	rule->src_uid = make_kuid(file->f_cred->user_ns, parsed_parent);
	rule->dst_uid = make_kuid(file->f_cred->user_ns, parsed_child);
	if (!uid_valid(rule->src_uid) || !uid_valid(rule->dst_uid))
		return -EINVAL;

	return 0;
}

static void __release_ruleset(struct rcu_head *rcu)
{
	struct setuid_ruleset *pol =
		container_of(rcu, struct setuid_ruleset, rcu);
	int bucket;
	struct setuid_rule *rule;
	struct hlist_node *tmp;

	hash_for_each_safe(pol->rules, bucket, tmp, rule, next)
		kfree(rule);
	kfree(pol->policy_str);
	kfree(pol);
}

static void release_ruleset(struct setuid_ruleset *pol)
{
	call_rcu(&pol->rcu, __release_ruleset);
}

static void insert_rule(struct setuid_ruleset *pol, struct setuid_rule *rule)
{
	hash_add(pol->rules, &rule->next, __kuid_val(rule->src_uid));
}

static int verify_ruleset(struct setuid_ruleset *pol)
{
	int bucket;
	struct setuid_rule *rule, *nrule;
	int res = 0;

	hash_for_each(pol->rules, bucket, rule, next) {
		if (_setuid_policy_lookup(pol, rule->dst_uid, INVALID_UID) ==
		    SIDPOL_DEFAULT) {
			pr_warn("insecure policy detected: uid %d is constrained but transitively unconstrained through uid %d\n",
				__kuid_val(rule->src_uid),
				__kuid_val(rule->dst_uid));
			res = -EINVAL;

			/* fix it up */
			nrule = kmalloc(sizeof(struct setuid_rule), GFP_KERNEL);
			if (!nrule)
				return -ENOMEM;
			nrule->src_uid = rule->dst_uid;
			nrule->dst_uid = rule->dst_uid;
			insert_rule(pol, nrule);
		}
	}
	return res;
}

static ssize_t handle_policy_update(struct file *file,
				    const char __user *ubuf, size_t len)
{
	struct setuid_ruleset *pol;
	char *buf, *p, *end;
	int err;

	pol = kmalloc(sizeof(struct setuid_ruleset), GFP_KERNEL);
	if (!pol)
		return -ENOMEM;
	pol->policy_str = NULL;
	hash_init(pol->rules);

	p = buf = memdup_user_nul(ubuf, len);
	if (IS_ERR(buf)) {
		err = PTR_ERR(buf);
		goto out_free_pol;
	}
	pol->policy_str = kstrdup(buf, GFP_KERNEL);
	if (pol->policy_str == NULL) {
		err = -ENOMEM;
		goto out_free_buf;
	}

	/* policy lines, including the last one, end with \n */
	while (*p != '\0') {
		struct setuid_rule *rule;

		end = strchr(p, '\n');
		if (end == NULL) {
			err = -EINVAL;
			goto out_free_buf;
		}
		*end = '\0';

		rule = kmalloc(sizeof(struct setuid_rule), GFP_KERNEL);
		if (!rule) {
			err = -ENOMEM;
			goto out_free_buf;
		}

		err = parse_policy_line(file, p, rule);
		if (err)
			goto out_free_rule;

		if (_setuid_policy_lookup(pol, rule->src_uid, rule->dst_uid) ==
		    SIDPOL_ALLOWED) {
			pr_warn("bad policy: duplicate entry\n");
			err = -EEXIST;
			goto out_free_rule;
		}

		insert_rule(pol, rule);
		p = end + 1;
		continue;

out_free_rule:
		kfree(rule);
		goto out_free_buf;
	}

	err = verify_ruleset(pol);
	/* bogus policy falls through after fixing it up */
	if (err && err != -EINVAL)
		goto out_free_buf;

	/*
	 * Everything looks good, apply the policy and release the old one.
	 * What we really want here is an xchg() wrapper for RCU, but since that
	 * doesn't currently exist, just use a spinlock for now.
	 */
	mutex_lock(&policy_update_lock);
	pol = rcu_replace_pointer(safesetid_setuid_rules, pol,
				  lockdep_is_held(&policy_update_lock));
	mutex_unlock(&policy_update_lock);
	err = len;

out_free_buf:
	kfree(buf);
out_free_pol:
	if (pol)
                release_ruleset(pol);
	return err;
}

static ssize_t safesetid_file_write(struct file *file,
				    const char __user *buf,
				    size_t len,
				    loff_t *ppos)
{
	if (!file_ns_capable(file, &init_user_ns, CAP_MAC_ADMIN))
		return -EPERM;

	if (*ppos != 0)
		return -EINVAL;

	return handle_policy_update(file, buf, len);
}

static ssize_t safesetid_file_read(struct file *file, char __user *buf,
				   size_t len, loff_t *ppos)
{
	ssize_t res = 0;
	struct setuid_ruleset *pol;
	const char *kbuf;

	mutex_lock(&policy_update_lock);
	pol = rcu_dereference_protected(safesetid_setuid_rules,
					lockdep_is_held(&policy_update_lock));
	if (pol) {
		kbuf = pol->policy_str;
		res = simple_read_from_buffer(buf, len, ppos,
					      kbuf, strlen(kbuf));
	}
	mutex_unlock(&policy_update_lock);
	return res;
}

static const struct file_operations safesetid_file_fops = {
	.read = safesetid_file_read,
	.write = safesetid_file_write,
};

static int __init safesetid_init_securityfs(void)
{
	int ret;
	struct dentry *policy_dir;
	struct dentry *policy_file;

	if (!safesetid_initialized)
		return 0;

	policy_dir = securityfs_create_dir("safesetid", NULL);
	if (IS_ERR(policy_dir)) {
		ret = PTR_ERR(policy_dir);
		goto error;
	}

	policy_file = securityfs_create_file("whitelist_policy", 0600,
			policy_dir, NULL, &safesetid_file_fops);
	if (IS_ERR(policy_file)) {
		ret = PTR_ERR(policy_file);
		goto error;
	}

	return 0;

error:
	securityfs_remove(policy_dir);
	return ret;
}
fs_initcall(safesetid_init_securityfs);
