// SPDX-License-Identifier: GPL-2.0-only
/*
 * AppArmor security module
 *
 * This file contains AppArmor functions for unpacking policy loaded
 * from userspace.
 *
 * Copyright (C) 1998-2008 Novell/SUSE
 * Copyright 2009-2022 Canonical Ltd.
 *
 * Code to provide backwards compatibility with older policy versions,
 * by converting/mapping older policy formats into the newer internal
 * formats.
 */

#include <linux/ctype.h>
#include <linux/errno.h>

#include "include/lib.h"
#include "include/policy_unpack.h"
#include "include/policy_compat.h"

/* remap old accept table embedded permissions to separate permission table */
static u32 dfa_map_xindex(u16 mask)
{
	u16 old_index = (mask >> 10) & 0xf;
	u32 index = 0;

	if (mask & 0x100)
		index |= AA_X_UNSAFE;
	if (mask & 0x200)
		index |= AA_X_INHERIT;
	if (mask & 0x80)
		index |= AA_X_UNCONFINED;

	if (old_index == 1) {
		index |= AA_X_UNCONFINED;
	} else if (old_index == 2) {
		index |= AA_X_NAME;
	} else if (old_index == 3) {
		index |= AA_X_NAME | AA_X_CHILD;
	} else if (old_index) {
		index |= AA_X_TABLE;
		index |= old_index - 4;
	}

	return index;
}

/*
 * map old dfa inline permissions to new format
 */
#define dfa_user_allow(dfa, state) (((ACCEPT_TABLE(dfa)[state]) & 0x7f) | \
				    ((ACCEPT_TABLE(dfa)[state]) & 0x80000000))
#define dfa_user_xbits(dfa, state) (((ACCEPT_TABLE(dfa)[state]) >> 7) & 0x7f)
#define dfa_user_audit(dfa, state) ((ACCEPT_TABLE2(dfa)[state]) & 0x7f)
#define dfa_user_quiet(dfa, state) (((ACCEPT_TABLE2(dfa)[state]) >> 7) & 0x7f)
#define dfa_user_xindex(dfa, state) \
	(dfa_map_xindex(ACCEPT_TABLE(dfa)[state] & 0x3fff))

#define dfa_other_allow(dfa, state) ((((ACCEPT_TABLE(dfa)[state]) >> 14) & \
				      0x7f) |				\
				     ((ACCEPT_TABLE(dfa)[state]) & 0x80000000))
#define dfa_other_xbits(dfa, state) \
	((((ACCEPT_TABLE(dfa)[state]) >> 7) >> 14) & 0x7f)
#define dfa_other_audit(dfa, state) (((ACCEPT_TABLE2(dfa)[state]) >> 14) & 0x7f)
#define dfa_other_quiet(dfa, state) \
	((((ACCEPT_TABLE2(dfa)[state]) >> 7) >> 14) & 0x7f)
#define dfa_other_xindex(dfa, state) \
	dfa_map_xindex((ACCEPT_TABLE(dfa)[state] >> 14) & 0x3fff)

/**
 * map_old_perms - map old file perms layout to the new layout
 * @old: permission set in old mapping
 *
 * Returns: new permission mapping
 */
static u32 map_old_perms(u32 old)
{
	u32 new = old & 0xf;

	if (old & MAY_READ)
		new |= AA_MAY_GETATTR | AA_MAY_OPEN;
	if (old & MAY_WRITE)
		new |= AA_MAY_SETATTR | AA_MAY_CREATE | AA_MAY_DELETE |
		       AA_MAY_CHMOD | AA_MAY_CHOWN | AA_MAY_OPEN;
	if (old & 0x10)
		new |= AA_MAY_LINK;
	/* the old mapping lock and link_subset flags where overlaid
	 * and use was determined by part of a pair that they were in
	 */
	if (old & 0x20)
		new |= AA_MAY_LOCK | AA_LINK_SUBSET;
	if (old & 0x40)	/* AA_EXEC_MMAP */
		new |= AA_EXEC_MMAP;

	return new;
}

static void compute_fperms_allow(struct aa_perms *perms, const struct aa_dfa *dfa,
				 aa_state_t state)
{
	perms->allow |= AA_MAY_GETATTR;

	/* change_profile wasn't determined by ownership in old mapping */
	if (ACCEPT_TABLE(dfa)[state] & 0x80000000)
		perms->allow |= AA_MAY_CHANGE_PROFILE;
	if (ACCEPT_TABLE(dfa)[state] & 0x40000000)
		perms->allow |= AA_MAY_ONEXEC;
}

static struct aa_perms compute_fperms_user(const struct aa_dfa *dfa,
					   aa_state_t state)
{
	struct aa_perms perms = { };

	perms.allow = map_old_perms(dfa_user_allow(dfa, state));
	perms.audit = map_old_perms(dfa_user_audit(dfa, state));
	perms.quiet = map_old_perms(dfa_user_quiet(dfa, state));
	perms.xindex = dfa_user_xindex(dfa, state);

	compute_fperms_allow(&perms, dfa, state);

	return perms;
}

static struct aa_perms compute_fperms_other(const struct aa_dfa *dfa,
					    aa_state_t state)
{
	struct aa_perms perms = { };

	perms.allow = map_old_perms(dfa_other_allow(dfa, state));
	perms.audit = map_old_perms(dfa_other_audit(dfa, state));
	perms.quiet = map_old_perms(dfa_other_quiet(dfa, state));
	perms.xindex = dfa_other_xindex(dfa, state);

	compute_fperms_allow(&perms, dfa, state);

	return perms;
}

/**
 * compute_fperms - convert dfa compressed perms to internal perms and store
 *		    them so they can be retrieved later.
 * @dfa: a dfa using fperms to remap to internal permissions
 * @size: Returns the permission table size
 *
 * Returns: remapped perm table
 */
static struct aa_perms *compute_fperms(const struct aa_dfa *dfa,
				       u32 *size)
{
	aa_state_t state;
	unsigned int state_count;
	struct aa_perms *table;

	AA_BUG(!dfa);

	state_count = dfa->tables[YYTD_ID_BASE]->td_lolen;
	/* DFAs are restricted from having a state_count of less than 2 */
	table = kvzalloc_objs(struct aa_perms, state_count * 2);
	if (!table)
		return NULL;
	*size = state_count * 2;

	for (state = 0; state < state_count; state++) {
		table[state * 2] = compute_fperms_user(dfa, state);
		table[state * 2 + 1] = compute_fperms_other(dfa, state);
	}

	return table;
}

static struct aa_perms *compute_xmatch_perms(const struct aa_dfa *xmatch,
				      u32 *size)
{
	struct aa_perms *perms;
	int state;
	int state_count;

	AA_BUG(!xmatch);

	state_count = xmatch->tables[YYTD_ID_BASE]->td_lolen;
	/* DFAs are restricted from having a state_count of less than 2 */
	perms = kvzalloc_objs(struct aa_perms, state_count);
	if (!perms)
		return NULL;
	*size = state_count;

	/* zero init so skip the trap state (state == 0) */
	for (state = 1; state < state_count; state++)
		perms[state].allow = dfa_user_allow(xmatch, state);

	return perms;
}

static u32 map_other(u32 x)
{
	return ((x & 0x3) << 8) |	/* SETATTR/GETATTR */
		((x & 0x1c) << 18) |	/* ACCEPT/BIND/LISTEN */
		((x & 0x60) << 19);	/* SETOPT/GETOPT */
}

static u32 map_xbits(u32 x)
{
	return ((x & 0x1) << 7) |
		((x & 0x7e) << 9);
}

static struct aa_perms compute_perms_entry(const struct aa_dfa *dfa,
					   aa_state_t state,
					   u32 version)
{
	struct aa_perms perms = { };

	perms.allow = dfa_user_allow(dfa, state);
	perms.audit = dfa_user_audit(dfa, state);
	perms.quiet = dfa_user_quiet(dfa, state);

	/*
	 * This mapping is convulated due to history.
	 * v1-v4: only file perms, which are handled by compute_fperms
	 * v5: added policydb which dropped user conditional to gain new
	 *     perm bits, but had to map around the xbits because the
	 *     userspace compiler was still munging them.
	 * v9: adds using the xbits in policydb because the compiler now
	 *     supports treating policydb permission bits different.
	 *     Unfortunately there is no way to force auditing on the
	 *     perms represented by the xbits
	 */
	perms.allow |= map_other(dfa_other_allow(dfa, state));
	if (VERSION_LE(version, v8))
		perms.allow |= AA_MAY_LOCK;
	else
		perms.allow |= map_xbits(dfa_user_xbits(dfa, state));

	/*
	 * for v5-v9 perm mapping in the policydb, the other set is used
	 * to extend the general perm set
	 */
	perms.audit |= map_other(dfa_other_audit(dfa, state));
	perms.quiet |= map_other(dfa_other_quiet(dfa, state));
	if (VERSION_GT(version, v8))
		perms.quiet |= map_xbits(dfa_other_xbits(dfa, state));

	return perms;
}

static struct aa_perms *compute_perms(const struct aa_dfa *dfa, u32 version,
				      u32 *size)
{
	unsigned int state;
	unsigned int state_count;
	struct aa_perms *table;

	AA_BUG(!dfa);

	state_count = dfa->tables[YYTD_ID_BASE]->td_lolen;
	/* DFAs are restricted from having a state_count of less than 2 */
	table = kvzalloc_objs(struct aa_perms, state_count);
	if (!table)
		return NULL;
	*size = state_count;

	/* zero init so skip the trap state (state == 0) */
	for (state = 1; state < state_count; state++) {
		table[state] = compute_perms_entry(dfa, state, version);
		AA_DEBUG(DEBUG_UNPACK,
			 "[%d]: (0x%x/0x%x/0x%x//0x%x/0x%x//0x%x), converted from accept1: 0x%x, accept2: 0x%x",
			 state, table[state].allow, table[state].deny,
			 table[state].prompt, table[state].audit,
			 table[state].quiet, table[state].xindex,
			 ACCEPT_TABLE(dfa)[state], ACCEPT_TABLE2(dfa)[state]);
	}
	return table;
}

/**
 * remap_dfa_accept - remap old dfa accept table to be an index
 * @dfa: dfa to do the remapping on
 * @factor: scaling factor for the index conversion.
 *
 * Used in conjunction with compute_Xperms, it converts old style perms
 * that are encoded in the dfa accept tables to the new style where
 * there is a permission table and the accept table is an index into
 * the permission table.
 */
static void remap_dfa_accept(struct aa_dfa *dfa, unsigned int factor)
{
	unsigned int state;
	unsigned int state_count = dfa->tables[YYTD_ID_BASE]->td_lolen;

	AA_BUG(!dfa);

	for (state = 0; state < state_count; state++) {
		ACCEPT_TABLE(dfa)[state] = state * factor;
		ACCEPT_TABLE2(dfa)[state] = factor > 1 ? ACCEPT_FLAG_OWNER : 0;
	}
}

/* TODO: merge different dfa mappings into single map_policy fn */
int aa_compat_map_xmatch(struct aa_policydb *policy)
{
	policy->perms = compute_xmatch_perms(policy->dfa, &policy->size);
	if (!policy->perms)
		return -ENOMEM;

	remap_dfa_accept(policy->dfa, 1);

	return 0;
}

int aa_compat_map_policy(struct aa_policydb *policy, u32 version)
{
	policy->perms = compute_perms(policy->dfa, version, &policy->size);
	if (!policy->perms)
		return -ENOMEM;

	remap_dfa_accept(policy->dfa, 1);

	return 0;
}

int aa_compat_map_file(struct aa_policydb *policy)
{
	policy->perms = compute_fperms(policy->dfa, &policy->size);
	if (!policy->perms)
		return -ENOMEM;

	remap_dfa_accept(policy->dfa, 2);

	return 0;
}
