162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * AppArmor security module
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * This file contains AppArmor policy loading interface function definitions.
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * Copyright (C) 1998-2008 Novell/SUSE
862306a36Sopenharmony_ci * Copyright 2009-2010 Canonical Ltd.
962306a36Sopenharmony_ci */
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci#ifndef __POLICY_INTERFACE_H
1262306a36Sopenharmony_ci#define __POLICY_INTERFACE_H
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci#include <linux/list.h>
1562306a36Sopenharmony_ci#include <linux/kref.h>
1662306a36Sopenharmony_ci#include <linux/dcache.h>
1762306a36Sopenharmony_ci#include <linux/workqueue.h>
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_cistruct aa_load_ent {
2162306a36Sopenharmony_ci	struct list_head list;
2262306a36Sopenharmony_ci	struct aa_profile *new;
2362306a36Sopenharmony_ci	struct aa_profile *old;
2462306a36Sopenharmony_ci	struct aa_profile *rename;
2562306a36Sopenharmony_ci	const char *ns_name;
2662306a36Sopenharmony_ci};
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_civoid aa_load_ent_free(struct aa_load_ent *ent);
2962306a36Sopenharmony_cistruct aa_load_ent *aa_load_ent_alloc(void);
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci#define PACKED_FLAG_HAT		1
3262306a36Sopenharmony_ci#define PACKED_FLAG_DEBUG1	2
3362306a36Sopenharmony_ci#define PACKED_FLAG_DEBUG2	4
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci#define PACKED_MODE_ENFORCE	0
3662306a36Sopenharmony_ci#define PACKED_MODE_COMPLAIN	1
3762306a36Sopenharmony_ci#define PACKED_MODE_KILL	2
3862306a36Sopenharmony_ci#define PACKED_MODE_UNCONFINED	3
3962306a36Sopenharmony_ci#define PACKED_MODE_USER	4
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_cistruct aa_ns;
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_cienum {
4462306a36Sopenharmony_ci	AAFS_LOADDATA_ABI = 0,
4562306a36Sopenharmony_ci	AAFS_LOADDATA_REVISION,
4662306a36Sopenharmony_ci	AAFS_LOADDATA_HASH,
4762306a36Sopenharmony_ci	AAFS_LOADDATA_DATA,
4862306a36Sopenharmony_ci	AAFS_LOADDATA_COMPRESSED_SIZE,
4962306a36Sopenharmony_ci	AAFS_LOADDATA_DIR,		/* must be last actual entry */
5062306a36Sopenharmony_ci	AAFS_LOADDATA_NDENTS		/* count of entries */
5162306a36Sopenharmony_ci};
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci/*
5462306a36Sopenharmony_ci * The AppArmor interface treats data as a type byte followed by the
5562306a36Sopenharmony_ci * actual data.  The interface has the notion of a named entry
5662306a36Sopenharmony_ci * which has a name (AA_NAME typecode followed by name string) followed by
5762306a36Sopenharmony_ci * the entries typecode and data.  Named types allow for optional
5862306a36Sopenharmony_ci * elements and extensions to be added and tested for without breaking
5962306a36Sopenharmony_ci * backwards compatibility.
6062306a36Sopenharmony_ci */
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_cienum aa_code {
6362306a36Sopenharmony_ci	AA_U8,
6462306a36Sopenharmony_ci	AA_U16,
6562306a36Sopenharmony_ci	AA_U32,
6662306a36Sopenharmony_ci	AA_U64,
6762306a36Sopenharmony_ci	AA_NAME,		/* same as string except it is items name */
6862306a36Sopenharmony_ci	AA_STRING,
6962306a36Sopenharmony_ci	AA_BLOB,
7062306a36Sopenharmony_ci	AA_STRUCT,
7162306a36Sopenharmony_ci	AA_STRUCTEND,
7262306a36Sopenharmony_ci	AA_LIST,
7362306a36Sopenharmony_ci	AA_LISTEND,
7462306a36Sopenharmony_ci	AA_ARRAY,
7562306a36Sopenharmony_ci	AA_ARRAYEND,
7662306a36Sopenharmony_ci};
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ci/*
7962306a36Sopenharmony_ci * aa_ext is the read of the buffer containing the serialized profile.  The
8062306a36Sopenharmony_ci * data is copied into a kernel buffer in apparmorfs and then handed off to
8162306a36Sopenharmony_ci * the unpack routines.
8262306a36Sopenharmony_ci */
8362306a36Sopenharmony_cistruct aa_ext {
8462306a36Sopenharmony_ci	void *start;
8562306a36Sopenharmony_ci	void *end;
8662306a36Sopenharmony_ci	void *pos;		/* pointer to current position in the buffer */
8762306a36Sopenharmony_ci	u32 version;
8862306a36Sopenharmony_ci};
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ci/*
9162306a36Sopenharmony_ci * struct aa_loaddata - buffer of policy raw_data set
9262306a36Sopenharmony_ci *
9362306a36Sopenharmony_ci * there is no loaddata ref for being on ns list, nor a ref from
9462306a36Sopenharmony_ci * d_inode(@dentry) when grab a ref from these, @ns->lock must be held
9562306a36Sopenharmony_ci * && __aa_get_loaddata() needs to be used, and the return value
9662306a36Sopenharmony_ci * checked, if NULL the loaddata is already being reaped and should be
9762306a36Sopenharmony_ci * considered dead.
9862306a36Sopenharmony_ci */
9962306a36Sopenharmony_cistruct aa_loaddata {
10062306a36Sopenharmony_ci	struct kref count;
10162306a36Sopenharmony_ci	struct list_head list;
10262306a36Sopenharmony_ci	struct work_struct work;
10362306a36Sopenharmony_ci	struct dentry *dents[AAFS_LOADDATA_NDENTS];
10462306a36Sopenharmony_ci	struct aa_ns *ns;
10562306a36Sopenharmony_ci	char *name;
10662306a36Sopenharmony_ci	size_t size;			/* the original size of the payload */
10762306a36Sopenharmony_ci	size_t compressed_size;		/* the compressed size of the payload */
10862306a36Sopenharmony_ci	long revision;			/* the ns policy revision this caused */
10962306a36Sopenharmony_ci	int abi;
11062306a36Sopenharmony_ci	unsigned char *hash;
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_ci	/* Pointer to payload. If @compressed_size > 0, then this is the
11362306a36Sopenharmony_ci	 * compressed version of the payload, else it is the uncompressed
11462306a36Sopenharmony_ci	 * version (with the size indicated by @size).
11562306a36Sopenharmony_ci	 */
11662306a36Sopenharmony_ci	char *data;
11762306a36Sopenharmony_ci};
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_ciint aa_unpack(struct aa_loaddata *udata, struct list_head *lh, const char **ns);
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_ci/**
12262306a36Sopenharmony_ci * __aa_get_loaddata - get a reference count to uncounted data reference
12362306a36Sopenharmony_ci * @data: reference to get a count on
12462306a36Sopenharmony_ci *
12562306a36Sopenharmony_ci * Returns: pointer to reference OR NULL if race is lost and reference is
12662306a36Sopenharmony_ci *          being repeated.
12762306a36Sopenharmony_ci * Requires: @data->ns->lock held, and the return code MUST be checked
12862306a36Sopenharmony_ci *
12962306a36Sopenharmony_ci * Use only from inode->i_private and @data->list found references
13062306a36Sopenharmony_ci */
13162306a36Sopenharmony_cistatic inline struct aa_loaddata *
13262306a36Sopenharmony_ci__aa_get_loaddata(struct aa_loaddata *data)
13362306a36Sopenharmony_ci{
13462306a36Sopenharmony_ci	if (data && kref_get_unless_zero(&(data->count)))
13562306a36Sopenharmony_ci		return data;
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_ci	return NULL;
13862306a36Sopenharmony_ci}
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_ci/**
14162306a36Sopenharmony_ci * aa_get_loaddata - get a reference count from a counted data reference
14262306a36Sopenharmony_ci * @data: reference to get a count on
14362306a36Sopenharmony_ci *
14462306a36Sopenharmony_ci * Returns: point to reference
14562306a36Sopenharmony_ci * Requires: @data to have a valid reference count on it. It is a bug
14662306a36Sopenharmony_ci *           if the race to reap can be encountered when it is used.
14762306a36Sopenharmony_ci */
14862306a36Sopenharmony_cistatic inline struct aa_loaddata *
14962306a36Sopenharmony_ciaa_get_loaddata(struct aa_loaddata *data)
15062306a36Sopenharmony_ci{
15162306a36Sopenharmony_ci	struct aa_loaddata *tmp = __aa_get_loaddata(data);
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ci	AA_BUG(data && !tmp);
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_ci	return tmp;
15662306a36Sopenharmony_ci}
15762306a36Sopenharmony_ci
15862306a36Sopenharmony_civoid __aa_loaddata_update(struct aa_loaddata *data, long revision);
15962306a36Sopenharmony_cibool aa_rawdata_eq(struct aa_loaddata *l, struct aa_loaddata *r);
16062306a36Sopenharmony_civoid aa_loaddata_kref(struct kref *kref);
16162306a36Sopenharmony_cistruct aa_loaddata *aa_loaddata_alloc(size_t size);
16262306a36Sopenharmony_cistatic inline void aa_put_loaddata(struct aa_loaddata *data)
16362306a36Sopenharmony_ci{
16462306a36Sopenharmony_ci	if (data)
16562306a36Sopenharmony_ci		kref_put(&data->count, aa_loaddata_kref);
16662306a36Sopenharmony_ci}
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_KUNIT)
16962306a36Sopenharmony_cibool aa_inbounds(struct aa_ext *e, size_t size);
17062306a36Sopenharmony_cisize_t aa_unpack_u16_chunk(struct aa_ext *e, char **chunk);
17162306a36Sopenharmony_cibool aa_unpack_X(struct aa_ext *e, enum aa_code code);
17262306a36Sopenharmony_cibool aa_unpack_nameX(struct aa_ext *e, enum aa_code code, const char *name);
17362306a36Sopenharmony_cibool aa_unpack_u32(struct aa_ext *e, u32 *data, const char *name);
17462306a36Sopenharmony_cibool aa_unpack_u64(struct aa_ext *e, u64 *data, const char *name);
17562306a36Sopenharmony_cibool aa_unpack_array(struct aa_ext *e, const char *name, u16 *size);
17662306a36Sopenharmony_cisize_t aa_unpack_blob(struct aa_ext *e, char **blob, const char *name);
17762306a36Sopenharmony_ciint aa_unpack_str(struct aa_ext *e, const char **string, const char *name);
17862306a36Sopenharmony_ciint aa_unpack_strdup(struct aa_ext *e, char **string, const char *name);
17962306a36Sopenharmony_ci#endif
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_ci#endif /* __POLICY_INTERFACE_H */
182