summaryrefslogtreecommitdiffstats
path: root/security/apparmor/include
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 18:49:45 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 18:49:45 +0000
commit2c3c1048746a4622d8c89a29670120dc8fab93c4 (patch)
tree848558de17fb3008cdf4d861b01ac7781903ce39 /security/apparmor/include
parentInitial commit. (diff)
downloadlinux-2c3c1048746a4622d8c89a29670120dc8fab93c4.tar.xz
linux-2c3c1048746a4622d8c89a29670120dc8fab93c4.zip
Adding upstream version 6.1.76.upstream/6.1.76
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'security/apparmor/include')
-rw-r--r--security/apparmor/include/apparmor.h46
-rw-r--r--security/apparmor/include/apparmorfs.h134
-rw-r--r--security/apparmor/include/audit.h193
-rw-r--r--security/apparmor/include/capability.h46
-rw-r--r--security/apparmor/include/cred.h188
-rw-r--r--security/apparmor/include/crypto.h37
-rw-r--r--security/apparmor/include/domain.h39
-rw-r--r--security/apparmor/include/file.h240
-rw-r--r--security/apparmor/include/ipc.h18
-rw-r--r--security/apparmor/include/label.h467
-rw-r--r--security/apparmor/include/lib.h298
-rw-r--r--security/apparmor/include/match.h196
-rw-r--r--security/apparmor/include/mount.h50
-rw-r--r--security/apparmor/include/net.h112
-rw-r--r--security/apparmor/include/path.h32
-rw-r--r--security/apparmor/include/perms.h156
-rw-r--r--security/apparmor/include/policy.h315
-rw-r--r--security/apparmor/include/policy_ns.h165
-rw-r--r--security/apparmor/include/policy_unpack.h179
-rw-r--r--security/apparmor/include/procattr.h17
-rw-r--r--security/apparmor/include/resource.h46
-rw-r--r--security/apparmor/include/secid.h37
-rw-r--r--security/apparmor/include/sig_names.h101
-rw-r--r--security/apparmor/include/task.h98
24 files changed, 3210 insertions, 0 deletions
diff --git a/security/apparmor/include/apparmor.h b/security/apparmor/include/apparmor.h
new file mode 100644
index 000000000..9c3fc36a0
--- /dev/null
+++ b/security/apparmor/include/apparmor.h
@@ -0,0 +1,46 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor basic global
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2017 Canonical Ltd.
+ */
+
+#ifndef __APPARMOR_H
+#define __APPARMOR_H
+
+#include <linux/types.h>
+
+/*
+ * Class of mediation types in the AppArmor policy db
+ */
+#define AA_CLASS_ENTRY 0
+#define AA_CLASS_UNKNOWN 1
+#define AA_CLASS_FILE 2
+#define AA_CLASS_CAP 3
+#define AA_CLASS_DEPRECATED 4
+#define AA_CLASS_RLIMITS 5
+#define AA_CLASS_DOMAIN 6
+#define AA_CLASS_MOUNT 7
+#define AA_CLASS_PTRACE 9
+#define AA_CLASS_SIGNAL 10
+#define AA_CLASS_NET 14
+#define AA_CLASS_LABEL 16
+
+#define AA_CLASS_LAST AA_CLASS_LABEL
+
+/* Control parameters settable through module/boot flags */
+extern enum audit_mode aa_g_audit;
+extern bool aa_g_audit_header;
+extern bool aa_g_debug;
+extern bool aa_g_hash_policy;
+extern bool aa_g_export_binary;
+extern int aa_g_rawdata_compression_level;
+extern bool aa_g_lock_policy;
+extern bool aa_g_logsyscall;
+extern bool aa_g_paranoid_load;
+extern unsigned int aa_g_path_max;
+
+#endif /* __APPARMOR_H */
diff --git a/security/apparmor/include/apparmorfs.h b/security/apparmor/include/apparmorfs.h
new file mode 100644
index 000000000..1e94904f6
--- /dev/null
+++ b/security/apparmor/include/apparmorfs.h
@@ -0,0 +1,134 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor filesystem definitions.
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2010 Canonical Ltd.
+ */
+
+#ifndef __AA_APPARMORFS_H
+#define __AA_APPARMORFS_H
+
+extern struct path aa_null;
+
+enum aa_sfs_type {
+ AA_SFS_TYPE_BOOLEAN,
+ AA_SFS_TYPE_STRING,
+ AA_SFS_TYPE_U64,
+ AA_SFS_TYPE_FOPS,
+ AA_SFS_TYPE_DIR,
+};
+
+struct aa_sfs_entry;
+
+struct aa_sfs_entry {
+ const char *name;
+ struct dentry *dentry;
+ umode_t mode;
+ enum aa_sfs_type v_type;
+ union {
+ bool boolean;
+ char *string;
+ unsigned long u64;
+ struct aa_sfs_entry *files;
+ } v;
+ const struct file_operations *file_ops;
+};
+
+extern const struct file_operations aa_sfs_seq_file_ops;
+
+#define AA_SFS_FILE_BOOLEAN(_name, _value) \
+ { .name = (_name), .mode = 0444, \
+ .v_type = AA_SFS_TYPE_BOOLEAN, .v.boolean = (_value), \
+ .file_ops = &aa_sfs_seq_file_ops }
+#define AA_SFS_FILE_STRING(_name, _value) \
+ { .name = (_name), .mode = 0444, \
+ .v_type = AA_SFS_TYPE_STRING, .v.string = (_value), \
+ .file_ops = &aa_sfs_seq_file_ops }
+#define AA_SFS_FILE_U64(_name, _value) \
+ { .name = (_name), .mode = 0444, \
+ .v_type = AA_SFS_TYPE_U64, .v.u64 = (_value), \
+ .file_ops = &aa_sfs_seq_file_ops }
+#define AA_SFS_FILE_FOPS(_name, _mode, _fops) \
+ { .name = (_name), .v_type = AA_SFS_TYPE_FOPS, \
+ .mode = (_mode), .file_ops = (_fops) }
+#define AA_SFS_DIR(_name, _value) \
+ { .name = (_name), .v_type = AA_SFS_TYPE_DIR, .v.files = (_value) }
+
+extern void __init aa_destroy_aafs(void);
+
+struct aa_profile;
+struct aa_ns;
+
+enum aafs_ns_type {
+ AAFS_NS_DIR,
+ AAFS_NS_PROFS,
+ AAFS_NS_NS,
+ AAFS_NS_RAW_DATA,
+ AAFS_NS_LOAD,
+ AAFS_NS_REPLACE,
+ AAFS_NS_REMOVE,
+ AAFS_NS_REVISION,
+ AAFS_NS_COUNT,
+ AAFS_NS_MAX_COUNT,
+ AAFS_NS_SIZE,
+ AAFS_NS_MAX_SIZE,
+ AAFS_NS_OWNER,
+ AAFS_NS_SIZEOF,
+};
+
+enum aafs_prof_type {
+ AAFS_PROF_DIR,
+ AAFS_PROF_PROFS,
+ AAFS_PROF_NAME,
+ AAFS_PROF_MODE,
+ AAFS_PROF_ATTACH,
+ AAFS_PROF_HASH,
+ AAFS_PROF_RAW_DATA,
+ AAFS_PROF_RAW_HASH,
+ AAFS_PROF_RAW_ABI,
+ AAFS_PROF_SIZEOF,
+};
+
+#define ns_dir(X) ((X)->dents[AAFS_NS_DIR])
+#define ns_subns_dir(X) ((X)->dents[AAFS_NS_NS])
+#define ns_subprofs_dir(X) ((X)->dents[AAFS_NS_PROFS])
+#define ns_subdata_dir(X) ((X)->dents[AAFS_NS_RAW_DATA])
+#define ns_subload(X) ((X)->dents[AAFS_NS_LOAD])
+#define ns_subreplace(X) ((X)->dents[AAFS_NS_REPLACE])
+#define ns_subremove(X) ((X)->dents[AAFS_NS_REMOVE])
+#define ns_subrevision(X) ((X)->dents[AAFS_NS_REVISION])
+
+#define prof_dir(X) ((X)->dents[AAFS_PROF_DIR])
+#define prof_child_dir(X) ((X)->dents[AAFS_PROF_PROFS])
+
+void __aa_bump_ns_revision(struct aa_ns *ns);
+void __aafs_profile_rmdir(struct aa_profile *profile);
+void __aafs_profile_migrate_dents(struct aa_profile *old,
+ struct aa_profile *new);
+int __aafs_profile_mkdir(struct aa_profile *profile, struct dentry *parent);
+void __aafs_ns_rmdir(struct aa_ns *ns);
+int __aafs_ns_mkdir(struct aa_ns *ns, struct dentry *parent, const char *name,
+ struct dentry *dent);
+
+struct aa_loaddata;
+
+#ifdef CONFIG_SECURITY_APPARMOR_EXPORT_BINARY
+void __aa_fs_remove_rawdata(struct aa_loaddata *rawdata);
+int __aa_fs_create_rawdata(struct aa_ns *ns, struct aa_loaddata *rawdata);
+#else
+static inline void __aa_fs_remove_rawdata(struct aa_loaddata *rawdata)
+{
+ /* empty stub */
+}
+
+static inline int __aa_fs_create_rawdata(struct aa_ns *ns,
+ struct aa_loaddata *rawdata)
+{
+ return 0;
+}
+#endif /* CONFIG_SECURITY_APPARMOR_EXPORT_BINARY */
+
+#endif /* __AA_APPARMORFS_H */
diff --git a/security/apparmor/include/audit.h b/security/apparmor/include/audit.h
new file mode 100644
index 000000000..18519a4eb
--- /dev/null
+++ b/security/apparmor/include/audit.h
@@ -0,0 +1,193 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor auditing function definitions.
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2010 Canonical Ltd.
+ */
+
+#ifndef __AA_AUDIT_H
+#define __AA_AUDIT_H
+
+#include <linux/audit.h>
+#include <linux/fs.h>
+#include <linux/lsm_audit.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+
+#include "file.h"
+#include "label.h"
+
+extern const char *const audit_mode_names[];
+#define AUDIT_MAX_INDEX 5
+enum audit_mode {
+ AUDIT_NORMAL, /* follow normal auditing of accesses */
+ AUDIT_QUIET_DENIED, /* quiet all denied access messages */
+ AUDIT_QUIET, /* quiet all messages */
+ AUDIT_NOQUIET, /* do not quiet audit messages */
+ AUDIT_ALL /* audit all accesses */
+};
+
+enum audit_type {
+ AUDIT_APPARMOR_AUDIT,
+ AUDIT_APPARMOR_ALLOWED,
+ AUDIT_APPARMOR_DENIED,
+ AUDIT_APPARMOR_HINT,
+ AUDIT_APPARMOR_STATUS,
+ AUDIT_APPARMOR_ERROR,
+ AUDIT_APPARMOR_KILL,
+ AUDIT_APPARMOR_AUTO
+};
+
+#define OP_NULL NULL
+
+#define OP_SYSCTL "sysctl"
+#define OP_CAPABLE "capable"
+
+#define OP_UNLINK "unlink"
+#define OP_MKDIR "mkdir"
+#define OP_RMDIR "rmdir"
+#define OP_MKNOD "mknod"
+#define OP_TRUNC "truncate"
+#define OP_LINK "link"
+#define OP_SYMLINK "symlink"
+#define OP_RENAME_SRC "rename_src"
+#define OP_RENAME_DEST "rename_dest"
+#define OP_CHMOD "chmod"
+#define OP_CHOWN "chown"
+#define OP_GETATTR "getattr"
+#define OP_OPEN "open"
+
+#define OP_FRECEIVE "file_receive"
+#define OP_FPERM "file_perm"
+#define OP_FLOCK "file_lock"
+#define OP_FMMAP "file_mmap"
+#define OP_FMPROT "file_mprotect"
+#define OP_INHERIT "file_inherit"
+
+#define OP_PIVOTROOT "pivotroot"
+#define OP_MOUNT "mount"
+#define OP_UMOUNT "umount"
+
+#define OP_CREATE "create"
+#define OP_POST_CREATE "post_create"
+#define OP_BIND "bind"
+#define OP_CONNECT "connect"
+#define OP_LISTEN "listen"
+#define OP_ACCEPT "accept"
+#define OP_SENDMSG "sendmsg"
+#define OP_RECVMSG "recvmsg"
+#define OP_GETSOCKNAME "getsockname"
+#define OP_GETPEERNAME "getpeername"
+#define OP_GETSOCKOPT "getsockopt"
+#define OP_SETSOCKOPT "setsockopt"
+#define OP_SHUTDOWN "socket_shutdown"
+
+#define OP_PTRACE "ptrace"
+#define OP_SIGNAL "signal"
+
+#define OP_EXEC "exec"
+
+#define OP_CHANGE_HAT "change_hat"
+#define OP_CHANGE_PROFILE "change_profile"
+#define OP_CHANGE_ONEXEC "change_onexec"
+#define OP_STACK "stack"
+#define OP_STACK_ONEXEC "stack_onexec"
+
+#define OP_SETPROCATTR "setprocattr"
+#define OP_SETRLIMIT "setrlimit"
+
+#define OP_PROF_REPL "profile_replace"
+#define OP_PROF_LOAD "profile_load"
+#define OP_PROF_RM "profile_remove"
+
+
+struct apparmor_audit_data {
+ int error;
+ int type;
+ const char *op;
+ struct aa_label *label;
+ const char *name;
+ const char *info;
+ u32 request;
+ u32 denied;
+ union {
+ /* these entries require a custom callback fn */
+ struct {
+ struct aa_label *peer;
+ union {
+ struct {
+ const char *target;
+ kuid_t ouid;
+ } fs;
+ struct {
+ int rlim;
+ unsigned long max;
+ } rlim;
+ struct {
+ int signal;
+ int unmappedsig;
+ };
+ struct {
+ int type, protocol;
+ struct sock *peer_sk;
+ void *addr;
+ int addrlen;
+ } net;
+ };
+ };
+ struct {
+ struct aa_profile *profile;
+ const char *ns;
+ long pos;
+ } iface;
+ struct {
+ const char *src_name;
+ const char *type;
+ const char *trans;
+ const char *data;
+ unsigned long flags;
+ } mnt;
+ };
+};
+
+/* macros for dealing with apparmor_audit_data structure */
+#define aad(SA) ((SA)->apparmor_audit_data)
+#define DEFINE_AUDIT_DATA(NAME, T, X) \
+ /* TODO: cleanup audit init so we don't need _aad = {0,} */ \
+ struct apparmor_audit_data NAME ## _aad = { .op = (X), }; \
+ struct common_audit_data NAME = \
+ { \
+ .type = (T), \
+ .u.tsk = NULL, \
+ }; \
+ NAME.apparmor_audit_data = &(NAME ## _aad)
+
+void aa_audit_msg(int type, struct common_audit_data *sa,
+ void (*cb) (struct audit_buffer *, void *));
+int aa_audit(int type, struct aa_profile *profile, struct common_audit_data *sa,
+ void (*cb) (struct audit_buffer *, void *));
+
+#define aa_audit_error(ERROR, SA, CB) \
+({ \
+ aad((SA))->error = (ERROR); \
+ aa_audit_msg(AUDIT_APPARMOR_ERROR, (SA), (CB)); \
+ aad((SA))->error; \
+})
+
+
+static inline int complain_error(int error)
+{
+ if (error == -EPERM || error == -EACCES)
+ return 0;
+ return error;
+}
+
+void aa_audit_rule_free(void *vrule);
+int aa_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule);
+int aa_audit_rule_known(struct audit_krule *rule);
+int aa_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule);
+
+#endif /* __AA_AUDIT_H */
diff --git a/security/apparmor/include/capability.h b/security/apparmor/include/capability.h
new file mode 100644
index 000000000..d420e2d10
--- /dev/null
+++ b/security/apparmor/include/capability.h
@@ -0,0 +1,46 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor capability mediation definitions.
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2013 Canonical Ltd.
+ */
+
+#ifndef __AA_CAPABILITY_H
+#define __AA_CAPABILITY_H
+
+#include <linux/sched.h>
+
+#include "apparmorfs.h"
+
+struct aa_label;
+
+/* aa_caps - confinement data for capabilities
+ * @allowed: capabilities mask
+ * @audit: caps that are to be audited
+ * @denied: caps that are explicitly denied
+ * @quiet: caps that should not be audited
+ * @kill: caps that when requested will result in the task being killed
+ * @extended: caps that are subject finer grained mediation
+ */
+struct aa_caps {
+ kernel_cap_t allow;
+ kernel_cap_t audit;
+ kernel_cap_t denied;
+ kernel_cap_t quiet;
+ kernel_cap_t kill;
+ kernel_cap_t extended;
+};
+
+extern struct aa_sfs_entry aa_sfs_entry_caps[];
+
+int aa_capable(struct aa_label *label, int cap, unsigned int opts);
+
+static inline void aa_free_cap_rules(struct aa_caps *caps)
+{
+ /* NOP */
+}
+
+#endif /* __AA_CAPBILITY_H */
diff --git a/security/apparmor/include/cred.h b/security/apparmor/include/cred.h
new file mode 100644
index 000000000..0b9ae4804
--- /dev/null
+++ b/security/apparmor/include/cred.h
@@ -0,0 +1,188 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor contexts used to associate "labels" to objects.
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2010 Canonical Ltd.
+ */
+
+#ifndef __AA_CONTEXT_H
+#define __AA_CONTEXT_H
+
+#include <linux/cred.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+
+#include "label.h"
+#include "policy_ns.h"
+#include "task.h"
+
+static inline struct aa_label *cred_label(const struct cred *cred)
+{
+ struct aa_label **blob = cred->security + apparmor_blob_sizes.lbs_cred;
+
+ AA_BUG(!blob);
+ return *blob;
+}
+
+static inline void set_cred_label(const struct cred *cred,
+ struct aa_label *label)
+{
+ struct aa_label **blob = cred->security + apparmor_blob_sizes.lbs_cred;
+
+ AA_BUG(!blob);
+ *blob = label;
+}
+
+/**
+ * aa_cred_raw_label - obtain cred's label
+ * @cred: cred to obtain label from (NOT NULL)
+ *
+ * Returns: confining label
+ *
+ * does NOT increment reference count
+ */
+static inline struct aa_label *aa_cred_raw_label(const struct cred *cred)
+{
+ struct aa_label *label = cred_label(cred);
+
+ AA_BUG(!label);
+ return label;
+}
+
+/**
+ * aa_get_newest_cred_label - obtain the newest label on a cred
+ * @cred: cred to obtain label from (NOT NULL)
+ *
+ * Returns: newest version of confining label
+ */
+static inline struct aa_label *aa_get_newest_cred_label(const struct cred *cred)
+{
+ return aa_get_newest_label(aa_cred_raw_label(cred));
+}
+
+/**
+ * __aa_task_raw_label - retrieve another task's label
+ * @task: task to query (NOT NULL)
+ *
+ * Returns: @task's label without incrementing its ref count
+ *
+ * If @task != current needs to be called in RCU safe critical section
+ */
+static inline struct aa_label *__aa_task_raw_label(struct task_struct *task)
+{
+ return aa_cred_raw_label(__task_cred(task));
+}
+
+/**
+ * aa_current_raw_label - find the current tasks confining label
+ *
+ * Returns: up to date confining label or the ns unconfined label (NOT NULL)
+ *
+ * This fn will not update the tasks cred to the most up to date version
+ * of the label so it is safe to call when inside of locks.
+ */
+static inline struct aa_label *aa_current_raw_label(void)
+{
+ return aa_cred_raw_label(current_cred());
+}
+
+/**
+ * aa_get_current_label - get the newest version of the current tasks label
+ *
+ * Returns: newest version of confining label (NOT NULL)
+ *
+ * This fn will not update the tasks cred, so it is safe inside of locks
+ *
+ * The returned reference must be put with aa_put_label()
+ */
+static inline struct aa_label *aa_get_current_label(void)
+{
+ struct aa_label *l = aa_current_raw_label();
+
+ if (label_is_stale(l))
+ return aa_get_newest_label(l);
+ return aa_get_label(l);
+}
+
+#define __end_current_label_crit_section(X) end_current_label_crit_section(X)
+
+/**
+ * end_label_crit_section - put a reference found with begin_current_label..
+ * @label: label reference to put
+ *
+ * Should only be used with a reference obtained with
+ * begin_current_label_crit_section and never used in situations where the
+ * task cred may be updated
+ */
+static inline void end_current_label_crit_section(struct aa_label *label)
+{
+ if (label != aa_current_raw_label())
+ aa_put_label(label);
+}
+
+/**
+ * __begin_current_label_crit_section - current's confining label
+ *
+ * Returns: up to date confining label or the ns unconfined label (NOT NULL)
+ *
+ * safe to call inside locks
+ *
+ * The returned reference must be put with __end_current_label_crit_section()
+ * This must NOT be used if the task cred could be updated within the
+ * critical section between __begin_current_label_crit_section() ..
+ * __end_current_label_crit_section()
+ */
+static inline struct aa_label *__begin_current_label_crit_section(void)
+{
+ struct aa_label *label = aa_current_raw_label();
+
+ if (label_is_stale(label))
+ label = aa_get_newest_label(label);
+
+ return label;
+}
+
+/**
+ * begin_current_label_crit_section - current's confining label and update it
+ *
+ * Returns: up to date confining label or the ns unconfined label (NOT NULL)
+ *
+ * Not safe to call inside locks
+ *
+ * The returned reference must be put with end_current_label_crit_section()
+ * This must NOT be used if the task cred could be updated within the
+ * critical section between begin_current_label_crit_section() ..
+ * end_current_label_crit_section()
+ */
+static inline struct aa_label *begin_current_label_crit_section(void)
+{
+ struct aa_label *label = aa_current_raw_label();
+
+ might_sleep();
+
+ if (label_is_stale(label)) {
+ label = aa_get_newest_label(label);
+ if (aa_replace_current_label(label) == 0)
+ /* task cred will keep the reference */
+ aa_put_label(label);
+ }
+
+ return label;
+}
+
+static inline struct aa_ns *aa_get_current_ns(void)
+{
+ struct aa_label *label;
+ struct aa_ns *ns;
+
+ label = __begin_current_label_crit_section();
+ ns = aa_get_ns(labels_ns(label));
+ __end_current_label_crit_section(label);
+
+ return ns;
+}
+
+#endif /* __AA_CONTEXT_H */
diff --git a/security/apparmor/include/crypto.h b/security/apparmor/include/crypto.h
new file mode 100644
index 000000000..636a04e20
--- /dev/null
+++ b/security/apparmor/include/crypto.h
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor policy loading interface function definitions.
+ *
+ * Copyright 2013 Canonical Ltd.
+ */
+
+#ifndef __APPARMOR_CRYPTO_H
+#define __APPARMOR_CRYPTO_H
+
+#include "policy.h"
+
+#ifdef CONFIG_SECURITY_APPARMOR_HASH
+unsigned int aa_hash_size(void);
+char *aa_calc_hash(void *data, size_t len);
+int aa_calc_profile_hash(struct aa_profile *profile, u32 version, void *start,
+ size_t len);
+#else
+static inline char *aa_calc_hash(void *data, size_t len)
+{
+ return NULL;
+}
+static inline int aa_calc_profile_hash(struct aa_profile *profile, u32 version,
+ void *start, size_t len)
+{
+ return 0;
+}
+
+static inline unsigned int aa_hash_size(void)
+{
+ return 0;
+}
+#endif
+
+#endif /* __APPARMOR_CRYPTO_H */
diff --git a/security/apparmor/include/domain.h b/security/apparmor/include/domain.h
new file mode 100644
index 000000000..d14928fe1
--- /dev/null
+++ b/security/apparmor/include/domain.h
@@ -0,0 +1,39 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor security domain transition function definitions.
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2010 Canonical Ltd.
+ */
+
+#include <linux/binfmts.h>
+#include <linux/types.h>
+
+#include "label.h"
+
+#ifndef __AA_DOMAIN_H
+#define __AA_DOMAIN_H
+
+struct aa_domain {
+ int size;
+ char **table;
+};
+
+#define AA_CHANGE_NOFLAGS 0
+#define AA_CHANGE_TEST 1
+#define AA_CHANGE_CHILD 2
+#define AA_CHANGE_ONEXEC 4
+#define AA_CHANGE_STACK 8
+
+struct aa_label *x_table_lookup(struct aa_profile *profile, u32 xindex,
+ const char **name);
+
+int apparmor_bprm_creds_for_exec(struct linux_binprm *bprm);
+
+void aa_free_domain_entries(struct aa_domain *domain);
+int aa_change_hat(const char *hats[], int count, u64 token, int flags);
+int aa_change_profile(const char *fqname, int flags);
+
+#endif /* __AA_DOMAIN_H */
diff --git a/security/apparmor/include/file.h b/security/apparmor/include/file.h
new file mode 100644
index 000000000..029cb20e3
--- /dev/null
+++ b/security/apparmor/include/file.h
@@ -0,0 +1,240 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor file mediation function definitions.
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2010 Canonical Ltd.
+ */
+
+#ifndef __AA_FILE_H
+#define __AA_FILE_H
+
+#include <linux/spinlock.h>
+
+#include "domain.h"
+#include "match.h"
+#include "perms.h"
+
+struct aa_profile;
+struct path;
+
+#define mask_mode_t(X) (X & (MAY_EXEC | MAY_WRITE | MAY_READ | MAY_APPEND))
+
+#define AA_AUDIT_FILE_MASK (MAY_READ | MAY_WRITE | MAY_EXEC | MAY_APPEND |\
+ AA_MAY_CREATE | AA_MAY_DELETE | \
+ AA_MAY_GETATTR | AA_MAY_SETATTR | \
+ AA_MAY_CHMOD | AA_MAY_CHOWN | AA_MAY_LOCK | \
+ AA_EXEC_MMAP | AA_MAY_LINK)
+
+static inline struct aa_file_ctx *file_ctx(struct file *file)
+{
+ return file->f_security + apparmor_blob_sizes.lbs_file;
+}
+
+/* struct aa_file_ctx - the AppArmor context the file was opened in
+ * @lock: lock to update the ctx
+ * @label: label currently cached on the ctx
+ * @perms: the permission the file was opened with
+ */
+struct aa_file_ctx {
+ spinlock_t lock;
+ struct aa_label __rcu *label;
+ u32 allow;
+};
+
+/**
+ * aa_alloc_file_ctx - allocate file_ctx
+ * @label: initial label of task creating the file
+ * @gfp: gfp flags for allocation
+ *
+ * Returns: file_ctx or NULL on failure
+ */
+static inline struct aa_file_ctx *aa_alloc_file_ctx(struct aa_label *label,
+ gfp_t gfp)
+{
+ struct aa_file_ctx *ctx;
+
+ ctx = kzalloc(sizeof(struct aa_file_ctx), gfp);
+ if (ctx) {
+ spin_lock_init(&ctx->lock);
+ rcu_assign_pointer(ctx->label, aa_get_label(label));
+ }
+ return ctx;
+}
+
+/**
+ * aa_free_file_ctx - free a file_ctx
+ * @ctx: file_ctx to free (MAYBE_NULL)
+ */
+static inline void aa_free_file_ctx(struct aa_file_ctx *ctx)
+{
+ if (ctx) {
+ aa_put_label(rcu_access_pointer(ctx->label));
+ kfree_sensitive(ctx);
+ }
+}
+
+static inline struct aa_label *aa_get_file_label(struct aa_file_ctx *ctx)
+{
+ return aa_get_label_rcu(&ctx->label);
+}
+
+/*
+ * The xindex is broken into 3 parts
+ * - index - an index into either the exec name table or the variable table
+ * - exec type - which determines how the executable name and index are used
+ * - flags - which modify how the destination name is applied
+ */
+#define AA_X_INDEX_MASK 0x03ff
+
+#define AA_X_TYPE_MASK 0x0c00
+#define AA_X_TYPE_SHIFT 10
+#define AA_X_NONE 0x0000
+#define AA_X_NAME 0x0400 /* use executable name px */
+#define AA_X_TABLE 0x0800 /* use a specified name ->n# */
+
+#define AA_X_UNSAFE 0x1000
+#define AA_X_CHILD 0x2000 /* make >AA_X_NONE apply to children */
+#define AA_X_INHERIT 0x4000
+#define AA_X_UNCONFINED 0x8000
+
+/* need to make conditional which ones are being set */
+struct path_cond {
+ kuid_t uid;
+ umode_t mode;
+};
+
+#define COMBINED_PERM_MASK(X) ((X).allow | (X).audit | (X).quiet | (X).kill)
+
+/* FIXME: split perms from dfa and match this to description
+ * also add delegation info.
+ */
+static inline u16 dfa_map_xindex(u16 mask)
+{
+ u16 old_index = (mask >> 10) & 0xf;
+ u16 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)
+
+int aa_audit_file(struct aa_profile *profile, struct aa_perms *perms,
+ const char *op, u32 request, const char *name,
+ const char *target, struct aa_label *tlabel, kuid_t ouid,
+ const char *info, int error);
+
+/**
+ * struct aa_file_rules - components used for file rule permissions
+ * @dfa: dfa to match path names and conditionals against
+ * @perms: permission table indexed by the matched state accept entry of @dfa
+ * @trans: transition table for indexed by named x transitions
+ *
+ * File permission are determined by matching a path against @dfa and
+ * then using the value of the accept entry for the matching state as
+ * an index into @perms. If a named exec transition is required it is
+ * looked up in the transition table.
+ */
+struct aa_file_rules {
+ unsigned int start;
+ struct aa_dfa *dfa;
+ /* struct perms perms; */
+ struct aa_domain trans;
+ /* TODO: add delegate table */
+};
+
+struct aa_perms aa_compute_fperms(struct aa_dfa *dfa, unsigned int state,
+ struct path_cond *cond);
+unsigned int aa_str_perms(struct aa_dfa *dfa, unsigned int start,
+ const char *name, struct path_cond *cond,
+ struct aa_perms *perms);
+
+int __aa_path_perm(const char *op, struct aa_profile *profile,
+ const char *name, u32 request, struct path_cond *cond,
+ int flags, struct aa_perms *perms);
+int aa_path_perm(const char *op, struct aa_label *label,
+ const struct path *path, int flags, u32 request,
+ struct path_cond *cond);
+
+int aa_path_link(struct aa_label *label, struct dentry *old_dentry,
+ const struct path *new_dir, struct dentry *new_dentry);
+
+int aa_file_perm(const char *op, struct aa_label *label, struct file *file,
+ u32 request, bool in_atomic);
+
+void aa_inherit_files(const struct cred *cred, struct files_struct *files);
+
+static inline void aa_free_file_rules(struct aa_file_rules *rules)
+{
+ aa_put_dfa(rules->dfa);
+ aa_free_domain_entries(&rules->trans);
+}
+
+/**
+ * aa_map_file_perms - map file flags to AppArmor permissions
+ * @file: open file to map flags to AppArmor permissions
+ *
+ * Returns: apparmor permission set for the file
+ */
+static inline u32 aa_map_file_to_perms(struct file *file)
+{
+ int flags = file->f_flags;
+ u32 perms = 0;
+
+ if (file->f_mode & FMODE_WRITE)
+ perms |= MAY_WRITE;
+ if (file->f_mode & FMODE_READ)
+ perms |= MAY_READ;
+
+ if ((flags & O_APPEND) && (perms & MAY_WRITE))
+ perms = (perms & ~MAY_WRITE) | MAY_APPEND;
+ /* trunc implies write permission */
+ if (flags & O_TRUNC)
+ perms |= MAY_WRITE;
+ if (flags & O_CREAT)
+ perms |= AA_MAY_CREATE;
+
+ return perms;
+}
+
+#endif /* __AA_FILE_H */
diff --git a/security/apparmor/include/ipc.h b/security/apparmor/include/ipc.h
new file mode 100644
index 000000000..a1ac6ffb9
--- /dev/null
+++ b/security/apparmor/include/ipc.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor ipc mediation function definitions.
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2017 Canonical Ltd.
+ */
+
+#ifndef __AA_IPC_H
+#define __AA_IPC_H
+
+#include <linux/sched.h>
+
+int aa_may_signal(struct aa_label *sender, struct aa_label *target, int sig);
+
+#endif /* __AA_IPC_H */
diff --git a/security/apparmor/include/label.h b/security/apparmor/include/label.h
new file mode 100644
index 000000000..860484c6f
--- /dev/null
+++ b/security/apparmor/include/label.h
@@ -0,0 +1,467 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor label definitions
+ *
+ * Copyright 2017 Canonical Ltd.
+ */
+
+#ifndef __AA_LABEL_H
+#define __AA_LABEL_H
+
+#include <linux/atomic.h>
+#include <linux/audit.h>
+#include <linux/rbtree.h>
+#include <linux/rcupdate.h>
+
+#include "apparmor.h"
+#include "lib.h"
+
+struct aa_ns;
+
+#define LOCAL_VEC_ENTRIES 8
+#define DEFINE_VEC(T, V) \
+ struct aa_ ## T *(_ ## V ## _localtmp)[LOCAL_VEC_ENTRIES]; \
+ struct aa_ ## T **(V)
+
+#define vec_setup(T, V, N, GFP) \
+({ \
+ if ((N) <= LOCAL_VEC_ENTRIES) { \
+ typeof(N) i; \
+ (V) = (_ ## V ## _localtmp); \
+ for (i = 0; i < (N); i++) \
+ (V)[i] = NULL; \
+ } else \
+ (V) = kzalloc(sizeof(struct aa_ ## T *) * (N), (GFP)); \
+ (V) ? 0 : -ENOMEM; \
+})
+
+#define vec_cleanup(T, V, N) \
+do { \
+ int i; \
+ for (i = 0; i < (N); i++) { \
+ if (!IS_ERR_OR_NULL((V)[i])) \
+ aa_put_ ## T((V)[i]); \
+ } \
+ if ((V) != _ ## V ## _localtmp) \
+ kfree(V); \
+} while (0)
+
+#define vec_last(VEC, SIZE) ((VEC)[(SIZE) - 1])
+#define vec_ns(VEC, SIZE) (vec_last((VEC), (SIZE))->ns)
+#define vec_labelset(VEC, SIZE) (&vec_ns((VEC), (SIZE))->labels)
+#define cleanup_domain_vec(V, L) cleanup_label_vec((V), (L)->size)
+
+struct aa_profile;
+#define VEC_FLAG_TERMINATE 1
+int aa_vec_unique(struct aa_profile **vec, int n, int flags);
+struct aa_label *aa_vec_find_or_create_label(struct aa_profile **vec, int len,
+ gfp_t gfp);
+#define aa_sort_and_merge_vec(N, V) \
+ aa_sort_and_merge_profiles((N), (struct aa_profile **)(V))
+
+
+/* struct aa_labelset - set of labels for a namespace
+ *
+ * Labels are reference counted; aa_labelset does not contribute to label
+ * reference counts. Once a label's last refcount is put it is removed from
+ * the set.
+ */
+struct aa_labelset {
+ rwlock_t lock;
+
+ struct rb_root root;
+};
+
+#define __labelset_for_each(LS, N) \
+ for ((N) = rb_first(&(LS)->root); (N); (N) = rb_next(N))
+
+enum label_flags {
+ FLAG_HAT = 1, /* profile is a hat */
+ FLAG_UNCONFINED = 2, /* label unconfined only if all */
+ FLAG_NULL = 4, /* profile is null learning profile */
+ FLAG_IX_ON_NAME_ERROR = 8, /* fallback to ix on name lookup fail */
+ FLAG_IMMUTIBLE = 0x10, /* don't allow changes/replacement */
+ FLAG_USER_DEFINED = 0x20, /* user based profile - lower privs */
+ FLAG_NO_LIST_REF = 0x40, /* list doesn't keep profile ref */
+ FLAG_NS_COUNT = 0x80, /* carries NS ref count */
+ FLAG_IN_TREE = 0x100, /* label is in tree */
+ FLAG_PROFILE = 0x200, /* label is a profile */
+ FLAG_EXPLICIT = 0x400, /* explicit static label */
+ FLAG_STALE = 0x800, /* replaced/removed */
+ FLAG_RENAMED = 0x1000, /* label has renaming in it */
+ FLAG_REVOKED = 0x2000, /* label has revocation in it */
+ FLAG_DEBUG1 = 0x4000,
+ FLAG_DEBUG2 = 0x8000,
+
+ /* These flags must correspond with PATH_flags */
+ /* TODO: add new path flags */
+};
+
+struct aa_label;
+struct aa_proxy {
+ struct kref count;
+ struct aa_label __rcu *label;
+};
+
+struct label_it {
+ int i, j;
+};
+
+/* struct aa_label - lazy labeling struct
+ * @count: ref count of active users
+ * @node: rbtree position
+ * @rcu: rcu callback struct
+ * @proxy: is set to the label that replaced this label
+ * @hname: text representation of the label (MAYBE_NULL)
+ * @flags: stale and other flags - values may change under label set lock
+ * @secid: secid that references this label
+ * @size: number of entries in @ent[]
+ * @ent: set of profiles for label, actual size determined by @size
+ */
+struct aa_label {
+ struct kref count;
+ struct rb_node node;
+ struct rcu_head rcu;
+ struct aa_proxy *proxy;
+ __counted char *hname;
+ long flags;
+ u32 secid;
+ int size;
+ struct aa_profile *vec[];
+};
+
+#define last_error(E, FN) \
+do { \
+ int __subE = (FN); \
+ if (__subE) \
+ (E) = __subE; \
+} while (0)
+
+#define label_isprofile(X) ((X)->flags & FLAG_PROFILE)
+#define label_unconfined(X) ((X)->flags & FLAG_UNCONFINED)
+#define unconfined(X) label_unconfined(X)
+#define label_is_stale(X) ((X)->flags & FLAG_STALE)
+#define __label_make_stale(X) ((X)->flags |= FLAG_STALE)
+#define labels_ns(X) (vec_ns(&((X)->vec[0]), (X)->size))
+#define labels_set(X) (&labels_ns(X)->labels)
+#define labels_view(X) labels_ns(X)
+#define labels_profile(X) ((X)->vec[(X)->size - 1])
+
+
+int aa_label_next_confined(struct aa_label *l, int i);
+
+/* for each profile in a label */
+#define label_for_each(I, L, P) \
+ for ((I).i = 0; ((P) = (L)->vec[(I).i]); ++((I).i))
+
+/* assumes break/goto ended label_for_each */
+#define label_for_each_cont(I, L, P) \
+ for (++((I).i); ((P) = (L)->vec[(I).i]); ++((I).i))
+
+#define next_comb(I, L1, L2) \
+do { \
+ (I).j++; \
+ if ((I).j >= (L2)->size) { \
+ (I).i++; \
+ (I).j = 0; \
+ } \
+} while (0)
+
+
+/* for each combination of P1 in L1, and P2 in L2 */
+#define label_for_each_comb(I, L1, L2, P1, P2) \
+for ((I).i = (I).j = 0; \
+ ((P1) = (L1)->vec[(I).i]) && ((P2) = (L2)->vec[(I).j]); \
+ (I) = next_comb(I, L1, L2))
+
+#define fn_for_each_comb(L1, L2, P1, P2, FN) \
+({ \
+ struct label_it i; \
+ int __E = 0; \
+ label_for_each_comb(i, (L1), (L2), (P1), (P2)) { \
+ last_error(__E, (FN)); \
+ } \
+ __E; \
+})
+
+/* for each profile that is enforcing confinement in a label */
+#define label_for_each_confined(I, L, P) \
+ for ((I).i = aa_label_next_confined((L), 0); \
+ ((P) = (L)->vec[(I).i]); \
+ (I).i = aa_label_next_confined((L), (I).i + 1))
+
+#define label_for_each_in_merge(I, A, B, P) \
+ for ((I).i = (I).j = 0; \
+ ((P) = aa_label_next_in_merge(&(I), (A), (B))); \
+ )
+
+#define label_for_each_not_in_set(I, SET, SUB, P) \
+ for ((I).i = (I).j = 0; \
+ ((P) = __aa_label_next_not_in_set(&(I), (SET), (SUB))); \
+ )
+
+#define next_in_ns(i, NS, L) \
+({ \
+ typeof(i) ___i = (i); \
+ while ((L)->vec[___i] && (L)->vec[___i]->ns != (NS)) \
+ (___i)++; \
+ (___i); \
+})
+
+#define label_for_each_in_ns(I, NS, L, P) \
+ for ((I).i = next_in_ns(0, (NS), (L)); \
+ ((P) = (L)->vec[(I).i]); \
+ (I).i = next_in_ns((I).i + 1, (NS), (L)))
+
+#define fn_for_each_in_ns(L, P, FN) \
+({ \
+ struct label_it __i; \
+ struct aa_ns *__ns = labels_ns(L); \
+ int __E = 0; \
+ label_for_each_in_ns(__i, __ns, (L), (P)) { \
+ last_error(__E, (FN)); \
+ } \
+ __E; \
+})
+
+
+#define fn_for_each_XXX(L, P, FN, ...) \
+({ \
+ struct label_it i; \
+ int __E = 0; \
+ label_for_each ## __VA_ARGS__(i, (L), (P)) { \
+ last_error(__E, (FN)); \
+ } \
+ __E; \
+})
+
+#define fn_for_each(L, P, FN) fn_for_each_XXX(L, P, FN)
+#define fn_for_each_confined(L, P, FN) fn_for_each_XXX(L, P, FN, _confined)
+
+#define fn_for_each2_XXX(L1, L2, P, FN, ...) \
+({ \
+ struct label_it i; \
+ int __E = 0; \
+ label_for_each ## __VA_ARGS__(i, (L1), (L2), (P)) { \
+ last_error(__E, (FN)); \
+ } \
+ __E; \
+})
+
+#define fn_for_each_in_merge(L1, L2, P, FN) \
+ fn_for_each2_XXX((L1), (L2), P, FN, _in_merge)
+#define fn_for_each_not_in_set(L1, L2, P, FN) \
+ fn_for_each2_XXX((L1), (L2), P, FN, _not_in_set)
+
+#define LABEL_MEDIATES(L, C) \
+({ \
+ struct aa_profile *profile; \
+ struct label_it i; \
+ int ret = 0; \
+ label_for_each(i, (L), profile) { \
+ if (PROFILE_MEDIATES(profile, (C))) { \
+ ret = 1; \
+ break; \
+ } \
+ } \
+ ret; \
+})
+
+
+void aa_labelset_destroy(struct aa_labelset *ls);
+void aa_labelset_init(struct aa_labelset *ls);
+void __aa_labelset_update_subtree(struct aa_ns *ns);
+
+void aa_label_destroy(struct aa_label *label);
+void aa_label_free(struct aa_label *label);
+void aa_label_kref(struct kref *kref);
+bool aa_label_init(struct aa_label *label, int size, gfp_t gfp);
+struct aa_label *aa_label_alloc(int size, struct aa_proxy *proxy, gfp_t gfp);
+
+bool aa_label_is_subset(struct aa_label *set, struct aa_label *sub);
+bool aa_label_is_unconfined_subset(struct aa_label *set, struct aa_label *sub);
+struct aa_profile *__aa_label_next_not_in_set(struct label_it *I,
+ struct aa_label *set,
+ struct aa_label *sub);
+bool aa_label_remove(struct aa_label *label);
+struct aa_label *aa_label_insert(struct aa_labelset *ls, struct aa_label *l);
+bool aa_label_replace(struct aa_label *old, struct aa_label *new);
+bool aa_label_make_newest(struct aa_labelset *ls, struct aa_label *old,
+ struct aa_label *new);
+
+struct aa_label *aa_label_find(struct aa_label *l);
+
+struct aa_profile *aa_label_next_in_merge(struct label_it *I,
+ struct aa_label *a,
+ struct aa_label *b);
+struct aa_label *aa_label_find_merge(struct aa_label *a, struct aa_label *b);
+struct aa_label *aa_label_merge(struct aa_label *a, struct aa_label *b,
+ gfp_t gfp);
+
+
+bool aa_update_label_name(struct aa_ns *ns, struct aa_label *label, gfp_t gfp);
+
+#define FLAGS_NONE 0
+#define FLAG_SHOW_MODE 1
+#define FLAG_VIEW_SUBNS 2
+#define FLAG_HIDDEN_UNCONFINED 4
+#define FLAG_ABS_ROOT 8
+int aa_label_snxprint(char *str, size_t size, struct aa_ns *view,
+ struct aa_label *label, int flags);
+int aa_label_asxprint(char **strp, struct aa_ns *ns, struct aa_label *label,
+ int flags, gfp_t gfp);
+int aa_label_acntsxprint(char __counted **strp, struct aa_ns *ns,
+ struct aa_label *label, int flags, gfp_t gfp);
+void aa_label_xaudit(struct audit_buffer *ab, struct aa_ns *ns,
+ struct aa_label *label, int flags, gfp_t gfp);
+void aa_label_seq_xprint(struct seq_file *f, struct aa_ns *ns,
+ struct aa_label *label, int flags, gfp_t gfp);
+void aa_label_xprintk(struct aa_ns *ns, struct aa_label *label, int flags,
+ gfp_t gfp);
+void aa_label_audit(struct audit_buffer *ab, struct aa_label *label, gfp_t gfp);
+void aa_label_seq_print(struct seq_file *f, struct aa_label *label, gfp_t gfp);
+void aa_label_printk(struct aa_label *label, gfp_t gfp);
+
+struct aa_label *aa_label_strn_parse(struct aa_label *base, const char *str,
+ size_t n, gfp_t gfp, bool create,
+ bool force_stack);
+struct aa_label *aa_label_parse(struct aa_label *base, const char *str,
+ gfp_t gfp, bool create, bool force_stack);
+
+static inline const char *aa_label_strn_split(const char *str, int n)
+{
+ const char *pos;
+ unsigned int state;
+
+ state = aa_dfa_matchn_until(stacksplitdfa, DFA_START, str, n, &pos);
+ if (!ACCEPT_TABLE(stacksplitdfa)[state])
+ return NULL;
+
+ return pos - 3;
+}
+
+static inline const char *aa_label_str_split(const char *str)
+{
+ const char *pos;
+ unsigned int state;
+
+ state = aa_dfa_match_until(stacksplitdfa, DFA_START, str, &pos);
+ if (!ACCEPT_TABLE(stacksplitdfa)[state])
+ return NULL;
+
+ return pos - 3;
+}
+
+
+
+struct aa_perms;
+int aa_label_match(struct aa_profile *profile, struct aa_label *label,
+ unsigned int state, bool subns, u32 request,
+ struct aa_perms *perms);
+
+
+/**
+ * __aa_get_label - get a reference count to uncounted label reference
+ * @l: reference to get a count on
+ *
+ * Returns: pointer to reference OR NULL if race is lost and reference is
+ * being repeated.
+ * Requires: lock held, and the return code MUST be checked
+ */
+static inline struct aa_label *__aa_get_label(struct aa_label *l)
+{
+ if (l && kref_get_unless_zero(&l->count))
+ return l;
+
+ return NULL;
+}
+
+static inline struct aa_label *aa_get_label(struct aa_label *l)
+{
+ if (l)
+ kref_get(&(l->count));
+
+ return l;
+}
+
+
+/**
+ * aa_get_label_rcu - increment refcount on a label that can be replaced
+ * @l: pointer to label that can be replaced (NOT NULL)
+ *
+ * Returns: pointer to a refcounted label.
+ * else NULL if no label
+ */
+static inline struct aa_label *aa_get_label_rcu(struct aa_label __rcu **l)
+{
+ struct aa_label *c;
+
+ rcu_read_lock();
+ do {
+ c = rcu_dereference(*l);
+ } while (c && !kref_get_unless_zero(&c->count));
+ rcu_read_unlock();
+
+ return c;
+}
+
+/**
+ * aa_get_newest_label - find the newest version of @l
+ * @l: the label to check for newer versions of
+ *
+ * Returns: refcounted newest version of @l taking into account
+ * replacement, renames and removals
+ * return @l.
+ */
+static inline struct aa_label *aa_get_newest_label(struct aa_label *l)
+{
+ if (!l)
+ return NULL;
+
+ if (label_is_stale(l)) {
+ struct aa_label *tmp;
+
+ AA_BUG(!l->proxy);
+ AA_BUG(!l->proxy->label);
+ /* BUG: only way this can happen is @l ref count and its
+ * replacement count have gone to 0 and are on their way
+ * to destruction. ie. we have a refcounting error
+ */
+ tmp = aa_get_label_rcu(&l->proxy->label);
+ AA_BUG(!tmp);
+
+ return tmp;
+ }
+
+ return aa_get_label(l);
+}
+
+static inline void aa_put_label(struct aa_label *l)
+{
+ if (l)
+ kref_put(&l->count, aa_label_kref);
+}
+
+
+struct aa_proxy *aa_alloc_proxy(struct aa_label *l, gfp_t gfp);
+void aa_proxy_kref(struct kref *kref);
+
+static inline struct aa_proxy *aa_get_proxy(struct aa_proxy *proxy)
+{
+ if (proxy)
+ kref_get(&(proxy->count));
+
+ return proxy;
+}
+
+static inline void aa_put_proxy(struct aa_proxy *proxy)
+{
+ if (proxy)
+ kref_put(&proxy->count, aa_proxy_kref);
+}
+
+void __aa_proxy_redirect(struct aa_label *orig, struct aa_label *new);
+
+#endif /* __AA_LABEL_H */
diff --git a/security/apparmor/include/lib.h b/security/apparmor/include/lib.h
new file mode 100644
index 000000000..f42359f58
--- /dev/null
+++ b/security/apparmor/include/lib.h
@@ -0,0 +1,298 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor lib definitions
+ *
+ * 2017 Canonical Ltd.
+ */
+
+#ifndef __AA_LIB_H
+#define __AA_LIB_H
+
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/lsm_hooks.h>
+
+#include "match.h"
+
+/*
+ * DEBUG remains global (no per profile flag) since it is mostly used in sysctl
+ * which is not related to profile accesses.
+ */
+
+#define DEBUG_ON (aa_g_debug)
+/*
+ * split individual debug cases out in preparation for finer grained
+ * debug controls in the future.
+ */
+#define AA_DEBUG_LABEL DEBUG_ON
+#define dbg_printk(__fmt, __args...) pr_debug(__fmt, ##__args)
+#define AA_DEBUG(fmt, args...) \
+ do { \
+ if (DEBUG_ON) \
+ pr_debug_ratelimited("AppArmor: " fmt, ##args); \
+ } while (0)
+
+#define AA_WARN(X) WARN((X), "APPARMOR WARN %s: %s\n", __func__, #X)
+
+#define AA_BUG(X, args...) \
+ do { \
+ _Pragma("GCC diagnostic ignored \"-Wformat-zero-length\""); \
+ AA_BUG_FMT((X), "" args); \
+ _Pragma("GCC diagnostic warning \"-Wformat-zero-length\""); \
+ } while (0)
+#ifdef CONFIG_SECURITY_APPARMOR_DEBUG_ASSERTS
+#define AA_BUG_FMT(X, fmt, args...) \
+ WARN((X), "AppArmor WARN %s: (" #X "): " fmt, __func__, ##args)
+#else
+#define AA_BUG_FMT(X, fmt, args...) no_printk(fmt, ##args)
+#endif
+
+#define AA_ERROR(fmt, args...) \
+ pr_err_ratelimited("AppArmor: " fmt, ##args)
+
+/* Flag indicating whether initialization completed */
+extern int apparmor_initialized;
+
+/* fn's in lib */
+const char *skipn_spaces(const char *str, size_t n);
+char *aa_split_fqname(char *args, char **ns_name);
+const char *aa_splitn_fqname(const char *fqname, size_t n, const char **ns_name,
+ size_t *ns_len);
+void aa_info_message(const char *str);
+
+/* Security blob offsets */
+extern struct lsm_blob_sizes apparmor_blob_sizes;
+
+/**
+ * aa_strneq - compare null terminated @str to a non null terminated substring
+ * @str: a null terminated string
+ * @sub: a substring, not necessarily null terminated
+ * @len: length of @sub to compare
+ *
+ * The @str string must be full consumed for this to be considered a match
+ */
+static inline bool aa_strneq(const char *str, const char *sub, int len)
+{
+ return !strncmp(str, sub, len) && !str[len];
+}
+
+/**
+ * aa_dfa_null_transition - step to next state after null character
+ * @dfa: the dfa to match against
+ * @start: the state of the dfa to start matching in
+ *
+ * aa_dfa_null_transition transitions to the next state after a null
+ * character which is not used in standard matching and is only
+ * used to separate pairs.
+ */
+static inline unsigned int aa_dfa_null_transition(struct aa_dfa *dfa,
+ unsigned int start)
+{
+ /* the null transition only needs the string's null terminator byte */
+ return aa_dfa_next(dfa, start, 0);
+}
+
+static inline bool path_mediated_fs(struct dentry *dentry)
+{
+ return !(dentry->d_sb->s_flags & SB_NOUSER);
+}
+
+
+struct counted_str {
+ struct kref count;
+ char name[];
+};
+
+#define str_to_counted(str) \
+ ((struct counted_str *)(str - offsetof(struct counted_str, name)))
+
+#define __counted /* atm just a notation */
+
+void aa_str_kref(struct kref *kref);
+char *aa_str_alloc(int size, gfp_t gfp);
+
+
+static inline __counted char *aa_get_str(__counted char *str)
+{
+ if (str)
+ kref_get(&(str_to_counted(str)->count));
+
+ return str;
+}
+
+static inline void aa_put_str(__counted char *str)
+{
+ if (str)
+ kref_put(&str_to_counted(str)->count, aa_str_kref);
+}
+
+
+/* struct aa_policy - common part of both namespaces and profiles
+ * @name: name of the object
+ * @hname - The hierarchical name
+ * @list: list policy object is on
+ * @profiles: head of the profiles list contained in the object
+ */
+struct aa_policy {
+ const char *name;
+ __counted char *hname;
+ struct list_head list;
+ struct list_head profiles;
+};
+
+/**
+ * basename - find the last component of an hname
+ * @name: hname to find the base profile name component of (NOT NULL)
+ *
+ * Returns: the tail (base profile name) name component of an hname
+ */
+static inline const char *basename(const char *hname)
+{
+ char *split;
+
+ hname = strim((char *)hname);
+ for (split = strstr(hname, "//"); split; split = strstr(hname, "//"))
+ hname = split + 2;
+
+ return hname;
+}
+
+/**
+ * __policy_find - find a policy by @name on a policy list
+ * @head: list to search (NOT NULL)
+ * @name: name to search for (NOT NULL)
+ *
+ * Requires: rcu_read_lock be held
+ *
+ * Returns: unrefcounted policy that match @name or NULL if not found
+ */
+static inline struct aa_policy *__policy_find(struct list_head *head,
+ const char *name)
+{
+ struct aa_policy *policy;
+
+ list_for_each_entry_rcu(policy, head, list) {
+ if (!strcmp(policy->name, name))
+ return policy;
+ }
+ return NULL;
+}
+
+/**
+ * __policy_strn_find - find a policy that's name matches @len chars of @str
+ * @head: list to search (NOT NULL)
+ * @str: string to search for (NOT NULL)
+ * @len: length of match required
+ *
+ * Requires: rcu_read_lock be held
+ *
+ * Returns: unrefcounted policy that match @str or NULL if not found
+ *
+ * if @len == strlen(@strlen) then this is equiv to __policy_find
+ * other wise it allows searching for policy by a partial match of name
+ */
+static inline struct aa_policy *__policy_strn_find(struct list_head *head,
+ const char *str, int len)
+{
+ struct aa_policy *policy;
+
+ list_for_each_entry_rcu(policy, head, list) {
+ if (aa_strneq(policy->name, str, len))
+ return policy;
+ }
+
+ return NULL;
+}
+
+bool aa_policy_init(struct aa_policy *policy, const char *prefix,
+ const char *name, gfp_t gfp);
+void aa_policy_destroy(struct aa_policy *policy);
+
+
+/*
+ * fn_label_build - abstract out the build of a label transition
+ * @L: label the transition is being computed for
+ * @P: profile parameter derived from L by this macro, can be passed to FN
+ * @GFP: memory allocation type to use
+ * @FN: fn to call for each profile transition. @P is set to the profile
+ *
+ * Returns: new label on success
+ * ERR_PTR if build @FN fails
+ * NULL if label_build fails due to low memory conditions
+ *
+ * @FN must return a label or ERR_PTR on failure. NULL is not allowed
+ */
+#define fn_label_build(L, P, GFP, FN) \
+({ \
+ __label__ __cleanup, __done; \
+ struct aa_label *__new_; \
+ \
+ if ((L)->size > 1) { \
+ /* TODO: add cache of transitions already done */ \
+ struct label_it __i; \
+ int __j, __k, __count; \
+ DEFINE_VEC(label, __lvec); \
+ DEFINE_VEC(profile, __pvec); \
+ if (vec_setup(label, __lvec, (L)->size, (GFP))) { \
+ __new_ = NULL; \
+ goto __done; \
+ } \
+ __j = 0; \
+ label_for_each(__i, (L), (P)) { \
+ __new_ = (FN); \
+ AA_BUG(!__new_); \
+ if (IS_ERR(__new_)) \
+ goto __cleanup; \
+ __lvec[__j++] = __new_; \
+ } \
+ for (__j = __count = 0; __j < (L)->size; __j++) \
+ __count += __lvec[__j]->size; \
+ if (!vec_setup(profile, __pvec, __count, (GFP))) { \
+ for (__j = __k = 0; __j < (L)->size; __j++) { \
+ label_for_each(__i, __lvec[__j], (P)) \
+ __pvec[__k++] = aa_get_profile(P); \
+ } \
+ __count -= aa_vec_unique(__pvec, __count, 0); \
+ if (__count > 1) { \
+ __new_ = aa_vec_find_or_create_label(__pvec,\
+ __count, (GFP)); \
+ /* only fails if out of Mem */ \
+ if (!__new_) \
+ __new_ = NULL; \
+ } else \
+ __new_ = aa_get_label(&__pvec[0]->label); \
+ vec_cleanup(profile, __pvec, __count); \
+ } else \
+ __new_ = NULL; \
+__cleanup: \
+ vec_cleanup(label, __lvec, (L)->size); \
+ } else { \
+ (P) = labels_profile(L); \
+ __new_ = (FN); \
+ } \
+__done: \
+ if (!__new_) \
+ AA_DEBUG("label build failed\n"); \
+ (__new_); \
+})
+
+
+#define __fn_build_in_ns(NS, P, NS_FN, OTHER_FN) \
+({ \
+ struct aa_label *__new; \
+ if ((P)->ns != (NS)) \
+ __new = (OTHER_FN); \
+ else \
+ __new = (NS_FN); \
+ (__new); \
+})
+
+#define fn_label_build_in_ns(L, P, GFP, NS_FN, OTHER_FN) \
+({ \
+ fn_label_build((L), (P), (GFP), \
+ __fn_build_in_ns(labels_ns(L), (P), (NS_FN), (OTHER_FN))); \
+})
+
+#endif /* __AA_LIB_H */
diff --git a/security/apparmor/include/match.h b/security/apparmor/include/match.h
new file mode 100644
index 000000000..884489590
--- /dev/null
+++ b/security/apparmor/include/match.h
@@ -0,0 +1,196 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor policy dfa matching engine definitions.
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2012 Canonical Ltd.
+ */
+
+#ifndef __AA_MATCH_H
+#define __AA_MATCH_H
+
+#include <linux/kref.h>
+
+#define DFA_NOMATCH 0
+#define DFA_START 1
+
+
+/**
+ * The format used for transition tables is based on the GNU flex table
+ * file format (--tables-file option; see Table File Format in the flex
+ * info pages and the flex sources for documentation). The magic number
+ * used in the header is 0x1B5E783D instead of 0xF13C57B1 though, because
+ * new tables have been defined and others YY_ID_CHK (check) and YY_ID_DEF
+ * (default) tables are used slightly differently (see the apparmor-parser
+ * package).
+ *
+ *
+ * The data in the packed dfa is stored in network byte order, and the tables
+ * are arranged for flexibility. We convert the table data to host native
+ * byte order.
+ *
+ * The dfa begins with a table set header, and is followed by the actual
+ * tables.
+ */
+
+#define YYTH_MAGIC 0x1B5E783D
+#define YYTH_FLAG_DIFF_ENCODE 1
+#define YYTH_FLAG_OOB_TRANS 2
+#define YYTH_FLAGS (YYTH_FLAG_DIFF_ENCODE | YYTH_FLAG_OOB_TRANS)
+
+#define MAX_OOB_SUPPORTED 1
+
+struct table_set_header {
+ u32 th_magic; /* YYTH_MAGIC */
+ u32 th_hsize;
+ u32 th_ssize;
+ u16 th_flags;
+ char th_version[];
+};
+
+/* The YYTD_ID are one less than flex table mappings. The flex id
+ * has 1 subtracted at table load time, this allows us to directly use the
+ * ID's as indexes.
+ */
+#define YYTD_ID_ACCEPT 0
+#define YYTD_ID_BASE 1
+#define YYTD_ID_CHK 2
+#define YYTD_ID_DEF 3
+#define YYTD_ID_EC 4
+#define YYTD_ID_META 5
+#define YYTD_ID_ACCEPT2 6
+#define YYTD_ID_NXT 7
+#define YYTD_ID_TSIZE 8
+#define YYTD_ID_MAX 8
+
+#define YYTD_DATA8 1
+#define YYTD_DATA16 2
+#define YYTD_DATA32 4
+#define YYTD_DATA64 8
+
+/* ACCEPT & ACCEPT2 tables gets 6 dedicated flags, YYTD_DATAX define the
+ * first flags
+ */
+#define ACCEPT1_FLAGS(X) ((X) & 0x3f)
+#define ACCEPT2_FLAGS(X) ACCEPT1_FLAGS((X) >> YYTD_ID_ACCEPT2)
+#define TO_ACCEPT1_FLAG(X) ACCEPT1_FLAGS(X)
+#define TO_ACCEPT2_FLAG(X) (ACCEPT1_FLAGS(X) << YYTD_ID_ACCEPT2)
+#define DFA_FLAG_VERIFY_STATES 0x1000
+
+struct table_header {
+ u16 td_id;
+ u16 td_flags;
+ u32 td_hilen;
+ u32 td_lolen;
+ char td_data[];
+};
+
+#define DEFAULT_TABLE(DFA) ((u16 *)((DFA)->tables[YYTD_ID_DEF]->td_data))
+#define BASE_TABLE(DFA) ((u32 *)((DFA)->tables[YYTD_ID_BASE]->td_data))
+#define NEXT_TABLE(DFA) ((u16 *)((DFA)->tables[YYTD_ID_NXT]->td_data))
+#define CHECK_TABLE(DFA) ((u16 *)((DFA)->tables[YYTD_ID_CHK]->td_data))
+#define EQUIV_TABLE(DFA) ((u8 *)((DFA)->tables[YYTD_ID_EC]->td_data))
+#define ACCEPT_TABLE(DFA) ((u32 *)((DFA)->tables[YYTD_ID_ACCEPT]->td_data))
+#define ACCEPT_TABLE2(DFA) ((u32 *)((DFA)->tables[YYTD_ID_ACCEPT2]->td_data))
+
+struct aa_dfa {
+ struct kref count;
+ u16 flags;
+ u32 max_oob;
+ struct table_header *tables[YYTD_ID_TSIZE];
+};
+
+extern struct aa_dfa *nulldfa;
+extern struct aa_dfa *stacksplitdfa;
+
+#define byte_to_byte(X) (X)
+
+#define UNPACK_ARRAY(TABLE, BLOB, LEN, TTYPE, BTYPE, NTOHX) \
+ do { \
+ typeof(LEN) __i; \
+ TTYPE *__t = (TTYPE *) TABLE; \
+ BTYPE *__b = (BTYPE *) BLOB; \
+ for (__i = 0; __i < LEN; __i++) { \
+ __t[__i] = NTOHX(__b[__i]); \
+ } \
+ } while (0)
+
+static inline size_t table_size(size_t len, size_t el_size)
+{
+ return ALIGN(sizeof(struct table_header) + len * el_size, 8);
+}
+
+int aa_setup_dfa_engine(void);
+void aa_teardown_dfa_engine(void);
+
+struct aa_dfa *aa_dfa_unpack(void *blob, size_t size, int flags);
+unsigned int aa_dfa_match_len(struct aa_dfa *dfa, unsigned int start,
+ const char *str, int len);
+unsigned int aa_dfa_match(struct aa_dfa *dfa, unsigned int start,
+ const char *str);
+unsigned int aa_dfa_next(struct aa_dfa *dfa, unsigned int state,
+ const char c);
+unsigned int aa_dfa_outofband_transition(struct aa_dfa *dfa,
+ unsigned int state);
+unsigned int aa_dfa_match_until(struct aa_dfa *dfa, unsigned int start,
+ const char *str, const char **retpos);
+unsigned int aa_dfa_matchn_until(struct aa_dfa *dfa, unsigned int start,
+ const char *str, int n, const char **retpos);
+
+void aa_dfa_free_kref(struct kref *kref);
+
+#define WB_HISTORY_SIZE 24
+struct match_workbuf {
+ unsigned int count;
+ unsigned int pos;
+ unsigned int len;
+ unsigned int size; /* power of 2, same as history size */
+ unsigned int history[WB_HISTORY_SIZE];
+};
+#define DEFINE_MATCH_WB(N) \
+struct match_workbuf N = { \
+ .count = 0, \
+ .pos = 0, \
+ .len = 0, \
+}
+
+unsigned int aa_dfa_leftmatch(struct aa_dfa *dfa, unsigned int start,
+ const char *str, unsigned int *count);
+
+/**
+ * aa_get_dfa - increment refcount on dfa @p
+ * @dfa: dfa (MAYBE NULL)
+ *
+ * Returns: pointer to @dfa if @dfa is NULL will return NULL
+ * Requires: @dfa must be held with valid refcount when called
+ */
+static inline struct aa_dfa *aa_get_dfa(struct aa_dfa *dfa)
+{
+ if (dfa)
+ kref_get(&(dfa->count));
+
+ return dfa;
+}
+
+/**
+ * aa_put_dfa - put a dfa refcount
+ * @dfa: dfa to put refcount (MAYBE NULL)
+ *
+ * Requires: if @dfa != NULL that a valid refcount be held
+ */
+static inline void aa_put_dfa(struct aa_dfa *dfa)
+{
+ if (dfa)
+ kref_put(&dfa->count, aa_dfa_free_kref);
+}
+
+#define MATCH_FLAG_DIFF_ENCODE 0x80000000
+#define MARK_DIFF_ENCODE 0x40000000
+#define MATCH_FLAG_OOB_TRANSITION 0x20000000
+#define MATCH_FLAGS_MASK 0xff000000
+#define MATCH_FLAGS_VALID (MATCH_FLAG_DIFF_ENCODE | MATCH_FLAG_OOB_TRANSITION)
+#define MATCH_FLAGS_INVALID (MATCH_FLAGS_MASK & ~MATCH_FLAGS_VALID)
+
+#endif /* __AA_MATCH_H */
diff --git a/security/apparmor/include/mount.h b/security/apparmor/include/mount.h
new file mode 100644
index 000000000..a710683b2
--- /dev/null
+++ b/security/apparmor/include/mount.h
@@ -0,0 +1,50 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor file mediation function definitions.
+ *
+ * Copyright 2017 Canonical Ltd.
+ */
+
+#ifndef __AA_MOUNT_H
+#define __AA_MOUNT_H
+
+#include <linux/fs.h>
+#include <linux/path.h>
+
+#include "domain.h"
+#include "policy.h"
+
+/* mount perms */
+#define AA_MAY_PIVOTROOT 0x01
+#define AA_MAY_MOUNT 0x02
+#define AA_MAY_UMOUNT 0x04
+#define AA_AUDIT_DATA 0x40
+#define AA_MNT_CONT_MATCH 0x40
+
+#define AA_MS_IGNORE_MASK (MS_KERNMOUNT | MS_NOSEC | MS_ACTIVE | MS_BORN)
+
+int aa_remount(struct aa_label *label, const struct path *path,
+ unsigned long flags, void *data);
+
+int aa_bind_mount(struct aa_label *label, const struct path *path,
+ const char *old_name, unsigned long flags);
+
+
+int aa_mount_change_type(struct aa_label *label, const struct path *path,
+ unsigned long flags);
+
+int aa_move_mount(struct aa_label *label, const struct path *path,
+ const char *old_name);
+
+int aa_new_mount(struct aa_label *label, const char *dev_name,
+ const struct path *path, const char *type, unsigned long flags,
+ void *data);
+
+int aa_umount(struct aa_label *label, struct vfsmount *mnt, int flags);
+
+int aa_pivotroot(struct aa_label *label, const struct path *old_path,
+ const struct path *new_path);
+
+#endif /* __AA_MOUNT_H */
diff --git a/security/apparmor/include/net.h b/security/apparmor/include/net.h
new file mode 100644
index 000000000..aadb4b29f
--- /dev/null
+++ b/security/apparmor/include/net.h
@@ -0,0 +1,112 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor network mediation definitions.
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2017 Canonical Ltd.
+ */
+
+#ifndef __AA_NET_H
+#define __AA_NET_H
+
+#include <net/sock.h>
+#include <linux/path.h>
+
+#include "apparmorfs.h"
+#include "label.h"
+#include "perms.h"
+#include "policy.h"
+
+#define AA_MAY_SEND AA_MAY_WRITE
+#define AA_MAY_RECEIVE AA_MAY_READ
+
+#define AA_MAY_SHUTDOWN AA_MAY_DELETE
+
+#define AA_MAY_CONNECT AA_MAY_OPEN
+#define AA_MAY_ACCEPT 0x00100000
+
+#define AA_MAY_BIND 0x00200000
+#define AA_MAY_LISTEN 0x00400000
+
+#define AA_MAY_SETOPT 0x01000000
+#define AA_MAY_GETOPT 0x02000000
+
+#define NET_PERMS_MASK (AA_MAY_SEND | AA_MAY_RECEIVE | AA_MAY_CREATE | \
+ AA_MAY_SHUTDOWN | AA_MAY_BIND | AA_MAY_LISTEN | \
+ AA_MAY_CONNECT | AA_MAY_ACCEPT | AA_MAY_SETATTR | \
+ AA_MAY_GETATTR | AA_MAY_SETOPT | AA_MAY_GETOPT)
+
+#define NET_FS_PERMS (AA_MAY_SEND | AA_MAY_RECEIVE | AA_MAY_CREATE | \
+ AA_MAY_SHUTDOWN | AA_MAY_CONNECT | AA_MAY_RENAME |\
+ AA_MAY_SETATTR | AA_MAY_GETATTR | AA_MAY_CHMOD | \
+ AA_MAY_CHOWN | AA_MAY_CHGRP | AA_MAY_LOCK | \
+ AA_MAY_MPROT)
+
+#define NET_PEER_MASK (AA_MAY_SEND | AA_MAY_RECEIVE | AA_MAY_CONNECT | \
+ AA_MAY_ACCEPT)
+struct aa_sk_ctx {
+ struct aa_label *label;
+ struct aa_label *peer;
+};
+
+#define SK_CTX(X) ((X)->sk_security)
+#define SOCK_ctx(X) SOCK_INODE(X)->i_security
+#define DEFINE_AUDIT_NET(NAME, OP, SK, F, T, P) \
+ struct lsm_network_audit NAME ## _net = { .sk = (SK), \
+ .family = (F)}; \
+ DEFINE_AUDIT_DATA(NAME, \
+ ((SK) && (F) != AF_UNIX) ? LSM_AUDIT_DATA_NET : \
+ LSM_AUDIT_DATA_NONE, \
+ OP); \
+ NAME.u.net = &(NAME ## _net); \
+ aad(&NAME)->net.type = (T); \
+ aad(&NAME)->net.protocol = (P)
+
+#define DEFINE_AUDIT_SK(NAME, OP, SK) \
+ DEFINE_AUDIT_NET(NAME, OP, SK, (SK)->sk_family, (SK)->sk_type, \
+ (SK)->sk_protocol)
+
+
+#define af_select(FAMILY, FN, DEF_FN) \
+({ \
+ int __e; \
+ switch ((FAMILY)) { \
+ default: \
+ __e = DEF_FN; \
+ } \
+ __e; \
+})
+
+struct aa_secmark {
+ u8 audit;
+ u8 deny;
+ u32 secid;
+ char *label;
+};
+
+extern struct aa_sfs_entry aa_sfs_entry_network[];
+
+void audit_net_cb(struct audit_buffer *ab, void *va);
+int aa_profile_af_perm(struct aa_profile *profile, struct common_audit_data *sa,
+ u32 request, u16 family, int type);
+int aa_af_perm(struct aa_label *label, const char *op, u32 request, u16 family,
+ int type, int protocol);
+static inline int aa_profile_af_sk_perm(struct aa_profile *profile,
+ struct common_audit_data *sa,
+ u32 request,
+ struct sock *sk)
+{
+ return aa_profile_af_perm(profile, sa, request, sk->sk_family,
+ sk->sk_type);
+}
+int aa_sk_perm(const char *op, u32 request, struct sock *sk);
+
+int aa_sock_file_perm(struct aa_label *label, const char *op, u32 request,
+ struct socket *sock);
+
+int apparmor_secmark_check(struct aa_label *label, char *op, u32 request,
+ u32 secid, const struct sock *sk);
+
+#endif /* __AA_NET_H */
diff --git a/security/apparmor/include/path.h b/security/apparmor/include/path.h
new file mode 100644
index 000000000..343189903
--- /dev/null
+++ b/security/apparmor/include/path.h
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor basic path manipulation function definitions.
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2010 Canonical Ltd.
+ */
+
+#ifndef __AA_PATH_H
+#define __AA_PATH_H
+
+enum path_flags {
+ PATH_IS_DIR = 0x1, /* path is a directory */
+ PATH_CONNECT_PATH = 0x4, /* connect disconnected paths to / */
+ PATH_CHROOT_REL = 0x8, /* do path lookup relative to chroot */
+ PATH_CHROOT_NSCONNECT = 0x10, /* connect paths that are at ns root */
+
+ PATH_DELEGATE_DELETED = 0x10000, /* delegate deleted files */
+ PATH_MEDIATE_DELETED = 0x20000, /* mediate deleted paths */
+};
+
+int aa_path_name(const struct path *path, int flags, char *buffer,
+ const char **name, const char **info,
+ const char *disconnected);
+
+#define IN_ATOMIC true
+char *aa_get_buffer(bool in_atomic);
+void aa_put_buffer(char *buf);
+
+#endif /* __AA_PATH_H */
diff --git a/security/apparmor/include/perms.h b/security/apparmor/include/perms.h
new file mode 100644
index 000000000..13f20c598
--- /dev/null
+++ b/security/apparmor/include/perms.h
@@ -0,0 +1,156 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor basic permission sets definitions.
+ *
+ * Copyright 2017 Canonical Ltd.
+ */
+
+#ifndef __AA_PERM_H
+#define __AA_PERM_H
+
+#include <linux/fs.h>
+#include "label.h"
+
+#define AA_MAY_EXEC MAY_EXEC
+#define AA_MAY_WRITE MAY_WRITE
+#define AA_MAY_READ MAY_READ
+#define AA_MAY_APPEND MAY_APPEND
+
+#define AA_MAY_CREATE 0x0010
+#define AA_MAY_DELETE 0x0020
+#define AA_MAY_OPEN 0x0040
+#define AA_MAY_RENAME 0x0080 /* pair */
+
+#define AA_MAY_SETATTR 0x0100 /* meta write */
+#define AA_MAY_GETATTR 0x0200 /* meta read */
+#define AA_MAY_SETCRED 0x0400 /* security cred/attr */
+#define AA_MAY_GETCRED 0x0800
+
+#define AA_MAY_CHMOD 0x1000 /* pair */
+#define AA_MAY_CHOWN 0x2000 /* pair */
+#define AA_MAY_CHGRP 0x4000 /* pair */
+#define AA_MAY_LOCK 0x8000 /* LINK_SUBSET overlaid */
+
+#define AA_EXEC_MMAP 0x00010000
+#define AA_MAY_MPROT 0x00020000 /* extend conditions */
+#define AA_MAY_LINK 0x00040000 /* pair */
+#define AA_MAY_SNAPSHOT 0x00080000 /* pair */
+
+#define AA_MAY_DELEGATE
+#define AA_CONT_MATCH 0x08000000
+
+#define AA_MAY_STACK 0x10000000
+#define AA_MAY_ONEXEC 0x20000000 /* either stack or change_profile */
+#define AA_MAY_CHANGE_PROFILE 0x40000000
+#define AA_MAY_CHANGEHAT 0x80000000
+
+#define AA_LINK_SUBSET AA_MAY_LOCK /* overlaid */
+
+
+#define PERMS_CHRS_MASK (MAY_READ | MAY_WRITE | AA_MAY_CREATE | \
+ AA_MAY_DELETE | AA_MAY_LINK | AA_MAY_LOCK | \
+ AA_MAY_EXEC | AA_EXEC_MMAP | AA_MAY_APPEND)
+
+#define PERMS_NAMES_MASK (PERMS_CHRS_MASK | AA_MAY_OPEN | AA_MAY_RENAME | \
+ AA_MAY_SETATTR | AA_MAY_GETATTR | AA_MAY_SETCRED | \
+ AA_MAY_GETCRED | AA_MAY_CHMOD | AA_MAY_CHOWN | \
+ AA_MAY_CHGRP | AA_MAY_MPROT | AA_MAY_SNAPSHOT | \
+ AA_MAY_STACK | AA_MAY_ONEXEC | \
+ AA_MAY_CHANGE_PROFILE | AA_MAY_CHANGEHAT)
+
+extern const char aa_file_perm_chrs[];
+extern const char *aa_file_perm_names[];
+
+struct aa_perms {
+ u32 allow;
+ u32 audit; /* set only when allow is set */
+
+ u32 deny; /* explicit deny, or conflict if allow also set */
+ u32 quiet; /* set only when ~allow | deny */
+ u32 kill; /* set only when ~allow | deny */
+ u32 stop; /* set only when ~allow | deny */
+
+ u32 complain; /* accumulates only used when ~allow & ~deny */
+ u32 cond; /* set only when ~allow and ~deny */
+
+ u32 hide; /* set only when ~allow | deny */
+ u32 prompt; /* accumulates only used when ~allow & ~deny */
+
+ /* Reserved:
+ * u32 subtree; / * set only when allow is set * /
+ */
+ u16 xindex;
+};
+
+#define ALL_PERMS_MASK 0xffffffff
+extern struct aa_perms nullperms;
+extern struct aa_perms allperms;
+
+
+#define xcheck(FN1, FN2) \
+({ \
+ int e, error = FN1; \
+ e = FN2; \
+ if (e) \
+ error = e; \
+ error; \
+})
+
+
+/*
+ * TODO: update for labels pointing to labels instead of profiles
+ * TODO: optimize the walk, currently does subwalk of L2 for each P in L1
+ * gah this doesn't allow for label compound check!!!!
+ */
+#define xcheck_ns_profile_profile(P1, P2, FN, args...) \
+({ \
+ int ____e = 0; \
+ if (P1->ns == P2->ns) \
+ ____e = FN((P1), (P2), args); \
+ (____e); \
+})
+
+#define xcheck_ns_profile_label(P, L, FN, args...) \
+({ \
+ struct aa_profile *__p2; \
+ fn_for_each((L), __p2, \
+ xcheck_ns_profile_profile((P), __p2, (FN), args)); \
+})
+
+#define xcheck_ns_labels(L1, L2, FN, args...) \
+({ \
+ struct aa_profile *__p1; \
+ fn_for_each((L1), __p1, FN(__p1, (L2), args)); \
+})
+
+/* Do the cross check but applying FN at the profiles level */
+#define xcheck_labels_profiles(L1, L2, FN, args...) \
+ xcheck_ns_labels((L1), (L2), xcheck_ns_profile_label, (FN), args)
+
+#define xcheck_labels(L1, L2, P, FN1, FN2) \
+ xcheck(fn_for_each((L1), (P), (FN1)), fn_for_each((L2), (P), (FN2)))
+
+
+void aa_perm_mask_to_str(char *str, size_t str_size, const char *chrs,
+ u32 mask);
+void aa_audit_perm_names(struct audit_buffer *ab, const char * const *names,
+ u32 mask);
+void aa_audit_perm_mask(struct audit_buffer *ab, u32 mask, const char *chrs,
+ u32 chrsmask, const char * const *names, u32 namesmask);
+void aa_apply_modes_to_perms(struct aa_profile *profile,
+ struct aa_perms *perms);
+void aa_compute_perms(struct aa_dfa *dfa, unsigned int state,
+ struct aa_perms *perms);
+void aa_perms_accum(struct aa_perms *accum, struct aa_perms *addend);
+void aa_perms_accum_raw(struct aa_perms *accum, struct aa_perms *addend);
+void aa_profile_match_label(struct aa_profile *profile, struct aa_label *label,
+ int type, u32 request, struct aa_perms *perms);
+int aa_profile_label_perm(struct aa_profile *profile, struct aa_profile *target,
+ u32 request, int type, u32 *deny,
+ struct common_audit_data *sa);
+int aa_check_perms(struct aa_profile *profile, struct aa_perms *perms,
+ u32 request, struct common_audit_data *sa,
+ void (*cb)(struct audit_buffer *, void *));
+#endif /* __AA_PERM_H */
diff --git a/security/apparmor/include/policy.h b/security/apparmor/include/policy.h
new file mode 100644
index 000000000..639b5b248
--- /dev/null
+++ b/security/apparmor/include/policy.h
@@ -0,0 +1,315 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor policy definitions.
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2010 Canonical Ltd.
+ */
+
+#ifndef __AA_POLICY_H
+#define __AA_POLICY_H
+
+#include <linux/capability.h>
+#include <linux/cred.h>
+#include <linux/kref.h>
+#include <linux/rhashtable.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/socket.h>
+
+#include "apparmor.h"
+#include "audit.h"
+#include "capability.h"
+#include "domain.h"
+#include "file.h"
+#include "lib.h"
+#include "label.h"
+#include "net.h"
+#include "perms.h"
+#include "resource.h"
+
+
+struct aa_ns;
+
+extern int unprivileged_userns_apparmor_policy;
+
+extern const char *const aa_profile_mode_names[];
+#define APPARMOR_MODE_NAMES_MAX_INDEX 4
+
+#define PROFILE_MODE(_profile, _mode) \
+ ((aa_g_profile_mode == (_mode)) || \
+ ((_profile)->mode == (_mode)))
+
+#define COMPLAIN_MODE(_profile) PROFILE_MODE((_profile), APPARMOR_COMPLAIN)
+
+#define KILL_MODE(_profile) PROFILE_MODE((_profile), APPARMOR_KILL)
+
+#define PROFILE_IS_HAT(_profile) ((_profile)->label.flags & FLAG_HAT)
+
+#define CHECK_DEBUG1(_profile) ((_profile)->label.flags & FLAG_DEBUG1)
+
+#define CHECK_DEBUG2(_profile) ((_profile)->label.flags & FLAG_DEBUG2)
+
+#define profile_is_stale(_profile) (label_is_stale(&(_profile)->label))
+
+#define on_list_rcu(X) (!list_empty(X) && (X)->prev != LIST_POISON2)
+
+/*
+ * FIXME: currently need a clean way to replace and remove profiles as a
+ * set. It should be done at the namespace level.
+ * Either, with a set of profiles loaded at the namespace level or via
+ * a mark and remove marked interface.
+ */
+enum profile_mode {
+ APPARMOR_ENFORCE, /* enforce access rules */
+ APPARMOR_COMPLAIN, /* allow and log access violations */
+ APPARMOR_KILL, /* kill task on access violation */
+ APPARMOR_UNCONFINED, /* profile set to unconfined */
+};
+
+
+/* struct aa_policydb - match engine for a policy
+ * dfa: dfa pattern match
+ * start: set of start states for the different classes of data
+ */
+struct aa_policydb {
+ /* Generic policy DFA specific rule types will be subsections of it */
+ struct aa_dfa *dfa;
+ unsigned int start[AA_CLASS_LAST + 1];
+
+};
+
+/* struct aa_data - generic data structure
+ * key: name for retrieving this data
+ * size: size of data in bytes
+ * data: binary data
+ * head: reserved for rhashtable
+ */
+struct aa_data {
+ char *key;
+ u32 size;
+ char *data;
+ struct rhash_head head;
+};
+
+
+/* struct aa_profile - basic confinement data
+ * @base - base components of the profile (name, refcount, lists, lock ...)
+ * @label - label this profile is an extension of
+ * @parent: parent of profile
+ * @ns: namespace the profile is in
+ * @rename: optional profile name that this profile renamed
+ * @attach: human readable attachment string
+ * @xmatch: optional extended matching for unconfined executables names
+ * @xmatch_len: xmatch prefix len, used to determine xmatch priority
+ * @audit: the auditing mode of the profile
+ * @mode: the enforcement mode of the profile
+ * @path_flags: flags controlling path generation behavior
+ * @disconnected: what to prepend if attach_disconnected is specified
+ * @size: the memory consumed by this profiles rules
+ * @policy: general match rules governing policy
+ * @file: The set of rules governing basic file access and domain transitions
+ * @caps: capabilities for the profile
+ * @rlimits: rlimits for the profile
+ *
+ * @dents: dentries for the profiles file entries in apparmorfs
+ * @dirname: name of the profile dir in apparmorfs
+ * @data: hashtable for free-form policy aa_data
+ *
+ * The AppArmor profile contains the basic confinement data. Each profile
+ * has a name, and exists in a namespace. The @name and @exec_match are
+ * used to determine profile attachment against unconfined tasks. All other
+ * attachments are determined by profile X transition rules.
+ *
+ * Profiles have a hierarchy where hats and children profiles keep
+ * a reference to their parent.
+ *
+ * Profile names can not begin with a : and can not contain the \0
+ * character. If a profile name begins with / it will be considered when
+ * determining profile attachment on "unconfined" tasks.
+ */
+struct aa_profile {
+ struct aa_policy base;
+ struct aa_profile __rcu *parent;
+
+ struct aa_ns *ns;
+ const char *rename;
+
+ const char *attach;
+ struct aa_dfa *xmatch;
+ unsigned int xmatch_len;
+ enum audit_mode audit;
+ long mode;
+ u32 path_flags;
+ const char *disconnected;
+ int size;
+
+ struct aa_policydb policy;
+ struct aa_file_rules file;
+ struct aa_caps caps;
+
+ int xattr_count;
+ char **xattrs;
+
+ struct aa_rlimit rlimits;
+
+ int secmark_count;
+ struct aa_secmark *secmark;
+
+ struct aa_loaddata *rawdata;
+ unsigned char *hash;
+ char *dirname;
+ struct dentry *dents[AAFS_PROF_SIZEOF];
+ struct rhashtable *data;
+ struct aa_label label;
+};
+
+extern enum profile_mode aa_g_profile_mode;
+
+#define AA_MAY_LOAD_POLICY AA_MAY_APPEND
+#define AA_MAY_REPLACE_POLICY AA_MAY_WRITE
+#define AA_MAY_REMOVE_POLICY AA_MAY_DELETE
+
+#define profiles_ns(P) ((P)->ns)
+#define name_is_shared(A, B) ((A)->hname && (A)->hname == (B)->hname)
+
+void aa_add_profile(struct aa_policy *common, struct aa_profile *profile);
+
+
+void aa_free_proxy_kref(struct kref *kref);
+struct aa_profile *aa_alloc_profile(const char *name, struct aa_proxy *proxy,
+ gfp_t gfp);
+struct aa_profile *aa_new_null_profile(struct aa_profile *parent, bool hat,
+ const char *base, gfp_t gfp);
+void aa_free_profile(struct aa_profile *profile);
+void aa_free_profile_kref(struct kref *kref);
+struct aa_profile *aa_find_child(struct aa_profile *parent, const char *name);
+struct aa_profile *aa_lookupn_profile(struct aa_ns *ns, const char *hname,
+ size_t n);
+struct aa_profile *aa_lookup_profile(struct aa_ns *ns, const char *name);
+struct aa_profile *aa_fqlookupn_profile(struct aa_label *base,
+ const char *fqname, size_t n);
+struct aa_profile *aa_match_profile(struct aa_ns *ns, const char *name);
+
+ssize_t aa_replace_profiles(struct aa_ns *view, struct aa_label *label,
+ u32 mask, struct aa_loaddata *udata);
+ssize_t aa_remove_profiles(struct aa_ns *view, struct aa_label *label,
+ char *name, size_t size);
+void __aa_profile_list_release(struct list_head *head);
+
+#define PROF_ADD 1
+#define PROF_REPLACE 0
+
+#define profile_unconfined(X) ((X)->mode == APPARMOR_UNCONFINED)
+
+/**
+ * aa_get_newest_profile - simple wrapper fn to wrap the label version
+ * @p: profile (NOT NULL)
+ *
+ * Returns refcount to newest version of the profile (maybe @p)
+ *
+ * Requires: @p must be held with a valid refcount
+ */
+static inline struct aa_profile *aa_get_newest_profile(struct aa_profile *p)
+{
+ return labels_profile(aa_get_newest_label(&p->label));
+}
+
+static inline unsigned int PROFILE_MEDIATES(struct aa_profile *profile,
+ unsigned char class)
+{
+ if (class <= AA_CLASS_LAST)
+ return profile->policy.start[class];
+ else
+ return aa_dfa_match_len(profile->policy.dfa,
+ profile->policy.start[0], &class, 1);
+}
+
+static inline unsigned int PROFILE_MEDIATES_AF(struct aa_profile *profile,
+ u16 AF) {
+ unsigned int state = PROFILE_MEDIATES(profile, AA_CLASS_NET);
+ __be16 be_af = cpu_to_be16(AF);
+
+ if (!state)
+ return 0;
+ return aa_dfa_match_len(profile->policy.dfa, state, (char *) &be_af, 2);
+}
+
+/**
+ * aa_get_profile - increment refcount on profile @p
+ * @p: profile (MAYBE NULL)
+ *
+ * Returns: pointer to @p if @p is NULL will return NULL
+ * Requires: @p must be held with valid refcount when called
+ */
+static inline struct aa_profile *aa_get_profile(struct aa_profile *p)
+{
+ if (p)
+ kref_get(&(p->label.count));
+
+ return p;
+}
+
+/**
+ * aa_get_profile_not0 - increment refcount on profile @p found via lookup
+ * @p: profile (MAYBE NULL)
+ *
+ * Returns: pointer to @p if @p is NULL will return NULL
+ * Requires: @p must be held with valid refcount when called
+ */
+static inline struct aa_profile *aa_get_profile_not0(struct aa_profile *p)
+{
+ if (p && kref_get_unless_zero(&p->label.count))
+ return p;
+
+ return NULL;
+}
+
+/**
+ * aa_get_profile_rcu - increment a refcount profile that can be replaced
+ * @p: pointer to profile that can be replaced (NOT NULL)
+ *
+ * Returns: pointer to a refcounted profile.
+ * else NULL if no profile
+ */
+static inline struct aa_profile *aa_get_profile_rcu(struct aa_profile __rcu **p)
+{
+ struct aa_profile *c;
+
+ rcu_read_lock();
+ do {
+ c = rcu_dereference(*p);
+ } while (c && !kref_get_unless_zero(&c->label.count));
+ rcu_read_unlock();
+
+ return c;
+}
+
+/**
+ * aa_put_profile - decrement refcount on profile @p
+ * @p: profile (MAYBE NULL)
+ */
+static inline void aa_put_profile(struct aa_profile *p)
+{
+ if (p)
+ kref_put(&p->label.count, aa_label_kref);
+}
+
+static inline int AUDIT_MODE(struct aa_profile *profile)
+{
+ if (aa_g_audit != AUDIT_NORMAL)
+ return aa_g_audit;
+
+ return profile->audit;
+}
+
+bool aa_policy_view_capable(struct aa_label *label, struct aa_ns *ns);
+bool aa_policy_admin_capable(struct aa_label *label, struct aa_ns *ns);
+int aa_may_manage_policy(struct aa_label *label, struct aa_ns *ns,
+ u32 mask);
+bool aa_current_policy_view_capable(struct aa_ns *ns);
+bool aa_current_policy_admin_capable(struct aa_ns *ns);
+
+#endif /* __AA_POLICY_H */
diff --git a/security/apparmor/include/policy_ns.h b/security/apparmor/include/policy_ns.h
new file mode 100644
index 000000000..33d665516
--- /dev/null
+++ b/security/apparmor/include/policy_ns.h
@@ -0,0 +1,165 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor policy definitions.
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2017 Canonical Ltd.
+ */
+
+#ifndef __AA_NAMESPACE_H
+#define __AA_NAMESPACE_H
+
+#include <linux/kref.h>
+
+#include "apparmor.h"
+#include "apparmorfs.h"
+#include "label.h"
+#include "policy.h"
+
+
+/* struct aa_ns_acct - accounting of profiles in namespace
+ * @max_size: maximum space allowed for all profiles in namespace
+ * @max_count: maximum number of profiles that can be in this namespace
+ * @size: current size of profiles
+ * @count: current count of profiles (includes null profiles)
+ */
+struct aa_ns_acct {
+ int max_size;
+ int max_count;
+ int size;
+ int count;
+};
+
+/* struct aa_ns - namespace for a set of profiles
+ * @base: common policy
+ * @parent: parent of namespace
+ * @lock: lock for modifying the object
+ * @acct: accounting for the namespace
+ * @unconfined: special unconfined profile for the namespace
+ * @sub_ns: list of namespaces under the current namespace.
+ * @uniq_null: uniq value used for null learning profiles
+ * @uniq_id: a unique id count for the profiles in the namespace
+ * @level: level of ns within the tree hierarchy
+ * @dents: dentries for the namespaces file entries in apparmorfs
+ *
+ * An aa_ns defines the set profiles that are searched to determine which
+ * profile to attach to a task. Profiles can not be shared between aa_ns
+ * and profile names within a namespace are guaranteed to be unique. When
+ * profiles in separate namespaces have the same name they are NOT considered
+ * to be equivalent.
+ *
+ * Namespaces are hierarchical and only namespaces and profiles below the
+ * current namespace are visible.
+ *
+ * Namespace names must be unique and can not contain the characters :/\0
+ */
+struct aa_ns {
+ struct aa_policy base;
+ struct aa_ns *parent;
+ struct mutex lock;
+ struct aa_ns_acct acct;
+ struct aa_profile *unconfined;
+ struct list_head sub_ns;
+ atomic_t uniq_null;
+ long uniq_id;
+ int level;
+ long revision;
+ wait_queue_head_t wait;
+
+ struct aa_labelset labels;
+ struct list_head rawdata_list;
+
+ struct dentry *dents[AAFS_NS_SIZEOF];
+};
+
+extern struct aa_label *kernel_t;
+extern struct aa_ns *root_ns;
+
+extern const char *aa_hidden_ns_name;
+
+#define ns_unconfined(NS) (&(NS)->unconfined->label)
+
+bool aa_ns_visible(struct aa_ns *curr, struct aa_ns *view, bool subns);
+const char *aa_ns_name(struct aa_ns *parent, struct aa_ns *child, bool subns);
+void aa_free_ns(struct aa_ns *ns);
+int aa_alloc_root_ns(void);
+void aa_free_root_ns(void);
+void aa_free_ns_kref(struct kref *kref);
+
+struct aa_ns *aa_find_ns(struct aa_ns *root, const char *name);
+struct aa_ns *aa_findn_ns(struct aa_ns *root, const char *name, size_t n);
+struct aa_ns *__aa_lookupn_ns(struct aa_ns *view, const char *hname, size_t n);
+struct aa_ns *aa_lookupn_ns(struct aa_ns *view, const char *name, size_t n);
+struct aa_ns *__aa_find_or_create_ns(struct aa_ns *parent, const char *name,
+ struct dentry *dir);
+struct aa_ns *aa_prepare_ns(struct aa_ns *root, const char *name);
+void __aa_remove_ns(struct aa_ns *ns);
+
+static inline struct aa_profile *aa_deref_parent(struct aa_profile *p)
+{
+ return rcu_dereference_protected(p->parent,
+ mutex_is_locked(&p->ns->lock));
+}
+
+/**
+ * aa_get_ns - increment references count on @ns
+ * @ns: namespace to increment reference count of (MAYBE NULL)
+ *
+ * Returns: pointer to @ns, if @ns is NULL returns NULL
+ * Requires: @ns must be held with valid refcount when called
+ */
+static inline struct aa_ns *aa_get_ns(struct aa_ns *ns)
+{
+ if (ns)
+ aa_get_profile(ns->unconfined);
+
+ return ns;
+}
+
+/**
+ * aa_put_ns - decrement refcount on @ns
+ * @ns: namespace to put reference of
+ *
+ * Decrement reference count of @ns and if no longer in use free it
+ */
+static inline void aa_put_ns(struct aa_ns *ns)
+{
+ if (ns)
+ aa_put_profile(ns->unconfined);
+}
+
+/**
+ * __aa_findn_ns - find a namespace on a list by @name
+ * @head: list to search for namespace on (NOT NULL)
+ * @name: name of namespace to look for (NOT NULL)
+ * @n: length of @name
+ * Returns: unrefcounted namespace
+ *
+ * Requires: rcu_read_lock be held
+ */
+static inline struct aa_ns *__aa_findn_ns(struct list_head *head,
+ const char *name, size_t n)
+{
+ return (struct aa_ns *)__policy_strn_find(head, name, n);
+}
+
+static inline struct aa_ns *__aa_find_ns(struct list_head *head,
+ const char *name)
+{
+ return __aa_findn_ns(head, name, strlen(name));
+}
+
+static inline struct aa_ns *__aa_lookup_ns(struct aa_ns *base,
+ const char *hname)
+{
+ return __aa_lookupn_ns(base, hname, strlen(hname));
+}
+
+static inline struct aa_ns *aa_lookup_ns(struct aa_ns *view, const char *name)
+{
+ return aa_lookupn_ns(view, name, strlen(name));
+}
+
+#endif /* AA_NAMESPACE_H */
diff --git a/security/apparmor/include/policy_unpack.h b/security/apparmor/include/policy_unpack.h
new file mode 100644
index 000000000..e89b70144
--- /dev/null
+++ b/security/apparmor/include/policy_unpack.h
@@ -0,0 +1,179 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor policy loading interface function definitions.
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2010 Canonical Ltd.
+ */
+
+#ifndef __POLICY_INTERFACE_H
+#define __POLICY_INTERFACE_H
+
+#include <linux/list.h>
+#include <linux/kref.h>
+#include <linux/dcache.h>
+#include <linux/workqueue.h>
+
+struct aa_load_ent {
+ struct list_head list;
+ struct aa_profile *new;
+ struct aa_profile *old;
+ struct aa_profile *rename;
+ const char *ns_name;
+};
+
+void aa_load_ent_free(struct aa_load_ent *ent);
+struct aa_load_ent *aa_load_ent_alloc(void);
+
+#define PACKED_FLAG_HAT 1
+#define PACKED_FLAG_DEBUG1 2
+#define PACKED_FLAG_DEBUG2 4
+
+#define PACKED_MODE_ENFORCE 0
+#define PACKED_MODE_COMPLAIN 1
+#define PACKED_MODE_KILL 2
+#define PACKED_MODE_UNCONFINED 3
+
+struct aa_ns;
+
+enum {
+ AAFS_LOADDATA_ABI = 0,
+ AAFS_LOADDATA_REVISION,
+ AAFS_LOADDATA_HASH,
+ AAFS_LOADDATA_DATA,
+ AAFS_LOADDATA_COMPRESSED_SIZE,
+ AAFS_LOADDATA_DIR, /* must be last actual entry */
+ AAFS_LOADDATA_NDENTS /* count of entries */
+};
+
+/*
+ * The AppArmor interface treats data as a type byte followed by the
+ * actual data. The interface has the notion of a named entry
+ * which has a name (AA_NAME typecode followed by name string) followed by
+ * the entries typecode and data. Named types allow for optional
+ * elements and extensions to be added and tested for without breaking
+ * backwards compatibility.
+ */
+
+enum aa_code {
+ AA_U8,
+ AA_U16,
+ AA_U32,
+ AA_U64,
+ AA_NAME, /* same as string except it is items name */
+ AA_STRING,
+ AA_BLOB,
+ AA_STRUCT,
+ AA_STRUCTEND,
+ AA_LIST,
+ AA_LISTEND,
+ AA_ARRAY,
+ AA_ARRAYEND,
+};
+
+/*
+ * aa_ext is the read of the buffer containing the serialized profile. The
+ * data is copied into a kernel buffer in apparmorfs and then handed off to
+ * the unpack routines.
+ */
+struct aa_ext {
+ void *start;
+ void *end;
+ void *pos; /* pointer to current position in the buffer */
+ u32 version;
+};
+
+/*
+ * struct aa_loaddata - buffer of policy raw_data set
+ *
+ * there is no loaddata ref for being on ns list, nor a ref from
+ * d_inode(@dentry) when grab a ref from these, @ns->lock must be held
+ * && __aa_get_loaddata() needs to be used, and the return value
+ * checked, if NULL the loaddata is already being reaped and should be
+ * considered dead.
+ */
+struct aa_loaddata {
+ struct kref count;
+ struct list_head list;
+ struct work_struct work;
+ struct dentry *dents[AAFS_LOADDATA_NDENTS];
+ struct aa_ns *ns;
+ char *name;
+ size_t size; /* the original size of the payload */
+ size_t compressed_size; /* the compressed size of the payload */
+ long revision; /* the ns policy revision this caused */
+ int abi;
+ unsigned char *hash;
+
+ /* Pointer to payload. If @compressed_size > 0, then this is the
+ * compressed version of the payload, else it is the uncompressed
+ * version (with the size indicated by @size).
+ */
+ char *data;
+};
+
+int aa_unpack(struct aa_loaddata *udata, struct list_head *lh, const char **ns);
+
+/**
+ * __aa_get_loaddata - get a reference count to uncounted data reference
+ * @data: reference to get a count on
+ *
+ * Returns: pointer to reference OR NULL if race is lost and reference is
+ * being repeated.
+ * Requires: @data->ns->lock held, and the return code MUST be checked
+ *
+ * Use only from inode->i_private and @data->list found references
+ */
+static inline struct aa_loaddata *
+__aa_get_loaddata(struct aa_loaddata *data)
+{
+ if (data && kref_get_unless_zero(&(data->count)))
+ return data;
+
+ return NULL;
+}
+
+/**
+ * aa_get_loaddata - get a reference count from a counted data reference
+ * @data: reference to get a count on
+ *
+ * Returns: point to reference
+ * Requires: @data to have a valid reference count on it. It is a bug
+ * if the race to reap can be encountered when it is used.
+ */
+static inline struct aa_loaddata *
+aa_get_loaddata(struct aa_loaddata *data)
+{
+ struct aa_loaddata *tmp = __aa_get_loaddata(data);
+
+ AA_BUG(data && !tmp);
+
+ return tmp;
+}
+
+void __aa_loaddata_update(struct aa_loaddata *data, long revision);
+bool aa_rawdata_eq(struct aa_loaddata *l, struct aa_loaddata *r);
+void aa_loaddata_kref(struct kref *kref);
+struct aa_loaddata *aa_loaddata_alloc(size_t size);
+static inline void aa_put_loaddata(struct aa_loaddata *data)
+{
+ if (data)
+ kref_put(&data->count, aa_loaddata_kref);
+}
+
+#if IS_ENABLED(CONFIG_KUNIT)
+bool aa_inbounds(struct aa_ext *e, size_t size);
+size_t aa_unpack_u16_chunk(struct aa_ext *e, char **chunk);
+bool aa_unpack_X(struct aa_ext *e, enum aa_code code);
+bool aa_unpack_nameX(struct aa_ext *e, enum aa_code code, const char *name);
+bool aa_unpack_u32(struct aa_ext *e, u32 *data, const char *name);
+bool aa_unpack_u64(struct aa_ext *e, u64 *data, const char *name);
+size_t aa_unpack_array(struct aa_ext *e, const char *name);
+size_t aa_unpack_blob(struct aa_ext *e, char **blob, const char *name);
+int aa_unpack_str(struct aa_ext *e, const char **string, const char *name);
+int aa_unpack_strdup(struct aa_ext *e, char **string, const char *name);
+#endif
+
+#endif /* __POLICY_INTERFACE_H */
diff --git a/security/apparmor/include/procattr.h b/security/apparmor/include/procattr.h
new file mode 100644
index 000000000..31689437e
--- /dev/null
+++ b/security/apparmor/include/procattr.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor /proc/<pid>/attr/ interface function definitions.
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2010 Canonical Ltd.
+ */
+
+#ifndef __AA_PROCATTR_H
+#define __AA_PROCATTR_H
+
+int aa_getprocattr(struct aa_label *label, char **string);
+int aa_setprocattr_changehat(char *args, size_t size, int flags);
+
+#endif /* __AA_PROCATTR_H */
diff --git a/security/apparmor/include/resource.h b/security/apparmor/include/resource.h
new file mode 100644
index 000000000..961d85d32
--- /dev/null
+++ b/security/apparmor/include/resource.h
@@ -0,0 +1,46 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor resource limits function definitions.
+ *
+ * Copyright (C) 1998-2008 Novell/SUSE
+ * Copyright 2009-2010 Canonical Ltd.
+ */
+
+#ifndef __AA_RESOURCE_H
+#define __AA_RESOURCE_H
+
+#include <linux/resource.h>
+#include <linux/sched.h>
+
+#include "apparmorfs.h"
+
+struct aa_profile;
+
+/* struct aa_rlimit - rlimit settings for the profile
+ * @mask: which hard limits to set
+ * @limits: rlimit values that override task limits
+ *
+ * AppArmor rlimits are used to set confined task rlimits. Only the
+ * limits specified in @mask will be controlled by apparmor.
+ */
+struct aa_rlimit {
+ unsigned int mask;
+ struct rlimit limits[RLIM_NLIMITS];
+};
+
+extern struct aa_sfs_entry aa_sfs_entry_rlimit[];
+
+int aa_map_resource(int resource);
+int aa_task_setrlimit(struct aa_label *label, struct task_struct *task,
+ unsigned int resource, struct rlimit *new_rlim);
+
+void __aa_transition_rlimits(struct aa_label *old, struct aa_label *new);
+
+static inline void aa_free_rlimit_rules(struct aa_rlimit *rlims)
+{
+ /* NOP */
+}
+
+#endif /* __AA_RESOURCE_H */
diff --git a/security/apparmor/include/secid.h b/security/apparmor/include/secid.h
new file mode 100644
index 000000000..a912a5d5d
--- /dev/null
+++ b/security/apparmor/include/secid.h
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor security identifier (secid) definitions
+ *
+ * Copyright 2009-2018 Canonical Ltd.
+ */
+
+#ifndef __AA_SECID_H
+#define __AA_SECID_H
+
+#include <linux/slab.h>
+#include <linux/types.h>
+
+struct aa_label;
+
+/* secid value that will not be allocated */
+#define AA_SECID_INVALID 0
+
+/* secid value that matches any other secid */
+#define AA_SECID_WILDCARD 1
+
+/* sysctl to enable displaying mode when converting secid to secctx */
+extern int apparmor_display_secid_mode;
+
+struct aa_label *aa_secid_to_label(u32 secid);
+int apparmor_secid_to_secctx(u32 secid, char **secdata, u32 *seclen);
+int apparmor_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid);
+void apparmor_release_secctx(char *secdata, u32 seclen);
+
+
+int aa_alloc_secid(struct aa_label *label, gfp_t gfp);
+void aa_free_secid(u32 secid);
+void aa_secid_update(u32 secid, struct aa_label *label);
+
+#endif /* __AA_SECID_H */
diff --git a/security/apparmor/include/sig_names.h b/security/apparmor/include/sig_names.h
new file mode 100644
index 000000000..cbf7a997e
--- /dev/null
+++ b/security/apparmor/include/sig_names.h
@@ -0,0 +1,101 @@
+#include <linux/signal.h>
+
+#define SIGUNKNOWN 0
+#define MAXMAPPED_SIG 35
+#define MAXMAPPED_SIGNAME (MAXMAPPED_SIG + 1)
+#define SIGRT_BASE 128
+
+/* provide a mapping of arch signal to internal signal # for mediation
+ * those that are always an alias SIGCLD for SIGCLHD and SIGPOLL for SIGIO
+ * map to the same entry those that may/or may not get a separate entry
+ */
+static const int sig_map[MAXMAPPED_SIG] = {
+ [0] = MAXMAPPED_SIG, /* existence test */
+ [SIGHUP] = 1,
+ [SIGINT] = 2,
+ [SIGQUIT] = 3,
+ [SIGILL] = 4,
+ [SIGTRAP] = 5, /* -, 5, - */
+ [SIGABRT] = 6, /* SIGIOT: -, 6, - */
+ [SIGBUS] = 7, /* 10, 7, 10 */
+ [SIGFPE] = 8,
+ [SIGKILL] = 9,
+ [SIGUSR1] = 10, /* 30, 10, 16 */
+ [SIGSEGV] = 11,
+ [SIGUSR2] = 12, /* 31, 12, 17 */
+ [SIGPIPE] = 13,
+ [SIGALRM] = 14,
+ [SIGTERM] = 15,
+#ifdef SIGSTKFLT
+ [SIGSTKFLT] = 16, /* -, 16, - */
+#endif
+ [SIGCHLD] = 17, /* 20, 17, 18. SIGCHLD -, -, 18 */
+ [SIGCONT] = 18, /* 19, 18, 25 */
+ [SIGSTOP] = 19, /* 17, 19, 23 */
+ [SIGTSTP] = 20, /* 18, 20, 24 */
+ [SIGTTIN] = 21, /* 21, 21, 26 */
+ [SIGTTOU] = 22, /* 22, 22, 27 */
+ [SIGURG] = 23, /* 16, 23, 21 */
+ [SIGXCPU] = 24, /* 24, 24, 30 */
+ [SIGXFSZ] = 25, /* 25, 25, 31 */
+ [SIGVTALRM] = 26, /* 26, 26, 28 */
+ [SIGPROF] = 27, /* 27, 27, 29 */
+ [SIGWINCH] = 28, /* 28, 28, 20 */
+ [SIGIO] = 29, /* SIGPOLL: 23, 29, 22 */
+ [SIGPWR] = 30, /* 29, 30, 19. SIGINFO 29, -, - */
+#ifdef SIGSYS
+ [SIGSYS] = 31, /* 12, 31, 12. often SIG LOST/UNUSED */
+#endif
+#ifdef SIGEMT
+ [SIGEMT] = 32, /* 7, - , 7 */
+#endif
+#if defined(SIGLOST) && SIGPWR != SIGLOST /* sparc */
+ [SIGLOST] = 33, /* unused on Linux */
+#endif
+#if defined(SIGUNUSED) && \
+ defined(SIGLOST) && defined(SIGSYS) && SIGLOST != SIGSYS
+ [SIGUNUSED] = 34, /* -, 31, - */
+#endif
+};
+
+/* this table is ordered post sig_map[sig] mapping */
+static const char *const sig_names[MAXMAPPED_SIGNAME] = {
+ "unknown",
+ "hup",
+ "int",
+ "quit",
+ "ill",
+ "trap",
+ "abrt",
+ "bus",
+ "fpe",
+ "kill",
+ "usr1",
+ "segv",
+ "usr2",
+ "pipe",
+ "alrm",
+ "term",
+ "stkflt",
+ "chld",
+ "cont",
+ "stop",
+ "stp",
+ "ttin",
+ "ttou",
+ "urg",
+ "xcpu",
+ "xfsz",
+ "vtalrm",
+ "prof",
+ "winch",
+ "io",
+ "pwr",
+ "sys",
+ "emt",
+ "lost",
+ "unused",
+
+ "exists", /* always last existence test mapped to MAXMAPPED_SIG */
+};
+
diff --git a/security/apparmor/include/task.h b/security/apparmor/include/task.h
new file mode 100644
index 000000000..13437d62c
--- /dev/null
+++ b/security/apparmor/include/task.h
@@ -0,0 +1,98 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * AppArmor security module
+ *
+ * This file contains AppArmor task related definitions and mediation
+ *
+ * Copyright 2017 Canonical Ltd.
+ */
+
+#ifndef __AA_TASK_H
+#define __AA_TASK_H
+
+static inline struct aa_task_ctx *task_ctx(struct task_struct *task)
+{
+ return task->security + apparmor_blob_sizes.lbs_task;
+}
+
+/*
+ * struct aa_task_ctx - information for current task label change
+ * @nnp: snapshot of label at time of no_new_privs
+ * @onexec: profile to transition to on next exec (MAY BE NULL)
+ * @previous: profile the task may return to (MAY BE NULL)
+ * @token: magic value the task must know for returning to @previous_profile
+ */
+struct aa_task_ctx {
+ struct aa_label *nnp;
+ struct aa_label *onexec;
+ struct aa_label *previous;
+ u64 token;
+};
+
+int aa_replace_current_label(struct aa_label *label);
+int aa_set_current_onexec(struct aa_label *label, bool stack);
+int aa_set_current_hat(struct aa_label *label, u64 token);
+int aa_restore_previous_label(u64 cookie);
+struct aa_label *aa_get_task_label(struct task_struct *task);
+
+/**
+ * aa_free_task_ctx - free a task_ctx
+ * @ctx: task_ctx to free (MAYBE NULL)
+ */
+static inline void aa_free_task_ctx(struct aa_task_ctx *ctx)
+{
+ if (ctx) {
+ aa_put_label(ctx->nnp);
+ aa_put_label(ctx->previous);
+ aa_put_label(ctx->onexec);
+ }
+}
+
+/**
+ * aa_dup_task_ctx - duplicate a task context, incrementing reference counts
+ * @new: a blank task context (NOT NULL)
+ * @old: the task context to copy (NOT NULL)
+ */
+static inline void aa_dup_task_ctx(struct aa_task_ctx *new,
+ const struct aa_task_ctx *old)
+{
+ *new = *old;
+ aa_get_label(new->nnp);
+ aa_get_label(new->previous);
+ aa_get_label(new->onexec);
+}
+
+/**
+ * aa_clear_task_ctx_trans - clear transition tracking info from the ctx
+ * @ctx: task context to clear (NOT NULL)
+ */
+static inline void aa_clear_task_ctx_trans(struct aa_task_ctx *ctx)
+{
+ AA_BUG(!ctx);
+
+ aa_put_label(ctx->previous);
+ aa_put_label(ctx->onexec);
+ ctx->previous = NULL;
+ ctx->onexec = NULL;
+ ctx->token = 0;
+}
+
+#define AA_PTRACE_TRACE MAY_WRITE
+#define AA_PTRACE_READ MAY_READ
+#define AA_MAY_BE_TRACED AA_MAY_APPEND
+#define AA_MAY_BE_READ AA_MAY_CREATE
+#define PTRACE_PERM_SHIFT 2
+
+#define AA_PTRACE_PERM_MASK (AA_PTRACE_READ | AA_PTRACE_TRACE | \
+ AA_MAY_BE_READ | AA_MAY_BE_TRACED)
+#define AA_SIGNAL_PERM_MASK (MAY_READ | MAY_WRITE)
+
+#define AA_SFS_SIG_MASK "hup int quit ill trap abrt bus fpe kill usr1 " \
+ "segv usr2 pipe alrm term stkflt chld cont stop stp ttin ttou urg " \
+ "xcpu xfsz vtalrm prof winch io pwr sys emt lost"
+
+int aa_may_ptrace(struct aa_label *tracer, struct aa_label *tracee,
+ u32 request);
+
+
+#endif /* __AA_TASK_H */