diff --git a/patches.apparmor/0001-apparmor-Fix-shadowed-local-variable-in-unpack_trans.patch b/patches.apparmor/0001-apparmor-Fix-shadowed-local-variable-in-unpack_trans.patch deleted file mode 100644 index 95d1970..0000000 --- a/patches.apparmor/0001-apparmor-Fix-shadowed-local-variable-in-unpack_trans.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 9dcf6985ceb2d46bec2ce7fd602f1cede3cce04d Mon Sep 17 00:00:00 2001 -From: Geert Uytterhoeven -Date: Thu, 6 Jul 2017 10:56:21 +0200 -Subject: [PATCH 01/17] apparmor: Fix shadowed local variable in unpack_trans_table() -References: FATE#323500 -Patch-mainline: v4.14-rc2 -Git-commit: 19fe43a54fb67b6cc8857e65c78e1dc8aa2e97a3 - -with W=2: - - security/apparmor/policy_unpack.c: In function ‘unpack_trans_table’: - security/apparmor/policy_unpack.c:469: warning: declaration of ‘pos’ shadows a previous local - security/apparmor/policy_unpack.c:451: warning: shadowed declaration is here - -Rename the old "pos" to "saved_pos" to fix this. - -Fixes: 5379a3312024a8be ("apparmor: support v7 transition format compatible with label_parse") -Signed-off-by: Geert Uytterhoeven -Reviewed-by: Serge Hallyn -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/policy_unpack.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c -index c600f4dd1783..2d5a1a007b06 100644 ---- a/security/apparmor/policy_unpack.c -+++ b/security/apparmor/policy_unpack.c -@@ -448,7 +448,7 @@ static struct aa_dfa *unpack_dfa(struct aa_ext *e) - */ - static bool unpack_trans_table(struct aa_ext *e, struct aa_profile *profile) - { -- void *pos = e->pos; -+ void *saved_pos = e->pos; - - /* exec table is optional */ - if (unpack_nameX(e, AA_STRUCT, "xtable")) { -@@ -511,7 +511,7 @@ static bool unpack_trans_table(struct aa_ext *e, struct aa_profile *profile) - - fail: - aa_free_domain_entries(&profile->file.trans); -- e->pos = pos; -+ e->pos = saved_pos; - return 0; - } - --- -2.14.1 - diff --git a/patches.apparmor/0001-apparmor-fix-profile-attachment-for-special-unconfin.patch b/patches.apparmor/0001-apparmor-fix-profile-attachment-for-special-unconfin.patch deleted file mode 100644 index 44417e2..0000000 --- a/patches.apparmor/0001-apparmor-fix-profile-attachment-for-special-unconfin.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 4eaafeb72be65caaee2a742f5bb2e9bfa279405f Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Fri, 17 Nov 2017 18:04:37 -0800 -Subject: [PATCH] apparmor: fix profile attachment for special unconfined profiles -References: bsc#1071035 -Git-commit: 06d426d113fe0b3107939e81db920ca7b097e97c -Patch-mainline: v4.15-rc1 - -It used to be that unconfined would never attach. However that is not -the case anymore as some special profiles can be marked as unconfined, -that are not the namespaces unconfined profile, and may have an -attachment. - -Fixes: f1bd904175e8 ("apparmor: add the base fns() for domain labels") -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/domain.c | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - ---- a/security/apparmor/domain.c -+++ b/security/apparmor/domain.c -@@ -325,8 +325,10 @@ static struct aa_profile *__attach_match - struct aa_profile *profile, *candidate = NULL; - - list_for_each_entry_rcu(profile, head, base.list) { -- if (profile->label.flags & FLAG_NULL) -+ if (profile->label.flags & FLAG_NULL && -+ &profile->label == ns_unconfined(profile->ns)) - continue; -+ - if (profile->xmatch) { - if (profile->xmatch_len == len) { - conflict = true; diff --git a/patches.apparmor/0001-securityfs-add-the-ability-to-support-symlinks.patch b/patches.apparmor/0001-securityfs-add-the-ability-to-support-symlinks.patch deleted file mode 100644 index 7de0519..0000000 --- a/patches.apparmor/0001-securityfs-add-the-ability-to-support-symlinks.patch +++ /dev/null @@ -1,267 +0,0 @@ -From 93aa5f375b29a18ae7c8a6d1971c1998cc448380 Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Sun, 7 May 2017 05:53:37 -0700 -Subject: [PATCH 01/65] securityfs: add the ability to support symlinks -Git-commit: 6623ec7c4dbe18a5a2878e2d888be70d08a91826 -Patch-mainline: v4.13-rc1 -References: FATE#323500 - -apparmor: 4.13 dependency - -Signed-off-by: John Johansen -Reviewed-by: Seth Arnold -Acked-by: Kees Cook -Acked-by: Goldwyn Rodrigues ---- - include/linux/security.h | 12 ++++ - security/inode.c | 144 ++++++++++++++++++++++++++++++++++++++++------- - 2 files changed, 135 insertions(+), 21 deletions(-) - -diff --git a/include/linux/security.h b/include/linux/security.h -index af675b576645..caf8b64d8b5c 100644 ---- a/include/linux/security.h -+++ b/include/linux/security.h -@@ -1651,6 +1651,10 @@ extern struct dentry *securityfs_create_file(const char *name, umode_t mode, - struct dentry *parent, void *data, - const struct file_operations *fops); - extern struct dentry *securityfs_create_dir(const char *name, struct dentry *parent); -+struct dentry *securityfs_create_symlink(const char *name, -+ struct dentry *parent, -+ const char *target, -+ const struct inode_operations *iops); - extern void securityfs_remove(struct dentry *dentry); - - #else /* CONFIG_SECURITYFS */ -@@ -1670,6 +1674,14 @@ static inline struct dentry *securityfs_create_file(const char *name, - return ERR_PTR(-ENODEV); - } - -+static inline struct dentry *securityfs_create_symlink(const char *name, -+ struct dentry *parent, -+ const char *target, -+ const struct inode_operations *iops) -+{ -+ return ERR_PTR(-ENODEV); -+} -+ - static inline void securityfs_remove(struct dentry *dentry) - {} - -diff --git a/security/inode.c b/security/inode.c -index eccd58ef2ae8..8dd9ca8848e4 100644 ---- a/security/inode.c -+++ b/security/inode.c -@@ -26,11 +26,31 @@ - static struct vfsmount *mount; - static int mount_count; - -+static void securityfs_evict_inode(struct inode *inode) -+{ -+ truncate_inode_pages_final(&inode->i_data); -+ clear_inode(inode); -+ if (S_ISLNK(inode->i_mode)) -+ kfree(inode->i_link); -+} -+ -+static const struct super_operations securityfs_super_operations = { -+ .statfs = simple_statfs, -+ .evict_inode = securityfs_evict_inode, -+}; -+ - static int fill_super(struct super_block *sb, void *data, int silent) - { - static const struct tree_descr files[] = {{""}}; -+ int error; -+ -+ error = simple_fill_super(sb, SECURITYFS_MAGIC, files); -+ if (error) -+ return error; -+ -+ sb->s_op = &securityfs_super_operations; - -- return simple_fill_super(sb, SECURITYFS_MAGIC, files); -+ return 0; - } - - static struct dentry *get_sb(struct file_system_type *fs_type, -@@ -48,7 +68,7 @@ static struct file_system_type fs_type = { - }; - - /** -- * securityfs_create_file - create a file in the securityfs filesystem -+ * securityfs_create_dentry - create a dentry in the securityfs filesystem - * - * @name: a pointer to a string containing the name of the file to create. - * @mode: the permission that the file should have -@@ -60,34 +80,35 @@ static struct file_system_type fs_type = { - * the open() call. - * @fops: a pointer to a struct file_operations that should be used for - * this file. -+ * @iops: a point to a struct of inode_operations that should be used for -+ * this file/dir - * -- * This is the basic "create a file" function for securityfs. It allows for a -- * wide range of flexibility in creating a file, or a directory (if you -- * want to create a directory, the securityfs_create_dir() function is -- * recommended to be used instead). -+ * This is the basic "create a file/dir/symlink" function for -+ * securityfs. It allows for a wide range of flexibility in creating -+ * a file, or a directory (if you want to create a directory, the -+ * securityfs_create_dir() function is recommended to be used -+ * instead). - * - * This function returns a pointer to a dentry if it succeeds. This -- * pointer must be passed to the securityfs_remove() function when the file is -- * to be removed (no automatic cleanup happens if your module is unloaded, -- * you are responsible here). If an error occurs, the function will return -- * the error value (via ERR_PTR). -+ * pointer must be passed to the securityfs_remove() function when the -+ * file is to be removed (no automatic cleanup happens if your module -+ * is unloaded, you are responsible here). If an error occurs, the -+ * function will return the error value (via ERR_PTR). - * - * If securityfs is not enabled in the kernel, the value %-ENODEV is - * returned. - */ --struct dentry *securityfs_create_file(const char *name, umode_t mode, -- struct dentry *parent, void *data, -- const struct file_operations *fops) -+static struct dentry *securityfs_create_dentry(const char *name, umode_t mode, -+ struct dentry *parent, void *data, -+ const struct file_operations *fops, -+ const struct inode_operations *iops) - { - struct dentry *dentry; -- int is_dir = S_ISDIR(mode); - struct inode *dir, *inode; - int error; - -- if (!is_dir) { -- BUG_ON(!fops); -+ if (!(mode & S_IFMT)) - mode = (mode & S_IALLUGO) | S_IFREG; -- } - - pr_debug("securityfs: creating file '%s'\n",name); - -@@ -120,11 +141,14 @@ struct dentry *securityfs_create_file(const char *name, umode_t mode, - inode->i_mode = mode; - inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode); - inode->i_private = data; -- if (is_dir) { -+ if (S_ISDIR(mode)) { - inode->i_op = &simple_dir_inode_operations; - inode->i_fop = &simple_dir_operations; - inc_nlink(inode); - inc_nlink(dir); -+ } else if (S_ISLNK(mode)) { -+ inode->i_op = iops ? iops : &simple_symlink_inode_operations; -+ inode->i_link = data; - } else { - inode->i_fop = fops; - } -@@ -141,6 +165,38 @@ struct dentry *securityfs_create_file(const char *name, umode_t mode, - simple_release_fs(&mount, &mount_count); - return dentry; - } -+ -+/** -+ * securityfs_create_file - create a file in the securityfs filesystem -+ * -+ * @name: a pointer to a string containing the name of the file to create. -+ * @mode: the permission that the file should have -+ * @parent: a pointer to the parent dentry for this file. This should be a -+ * directory dentry if set. If this parameter is %NULL, then the -+ * file will be created in the root of the securityfs filesystem. -+ * @data: a pointer to something that the caller will want to get to later -+ * on. The inode.i_private pointer will point to this value on -+ * the open() call. -+ * @fops: a pointer to a struct file_operations that should be used for -+ * this file. -+ * -+ * This function creates a file in securityfs with the given @name. -+ * -+ * This function returns a pointer to a dentry if it succeeds. This -+ * pointer must be passed to the securityfs_remove() function when the file is -+ * to be removed (no automatic cleanup happens if your module is unloaded, -+ * you are responsible here). If an error occurs, the function will return -+ * the error value (via ERR_PTR). -+ * -+ * If securityfs is not enabled in the kernel, the value %-ENODEV is -+ * returned. -+ */ -+struct dentry *securityfs_create_file(const char *name, umode_t mode, -+ struct dentry *parent, void *data, -+ const struct file_operations *fops) -+{ -+ return securityfs_create_dentry(name, mode, parent, data, fops, NULL); -+} - EXPORT_SYMBOL_GPL(securityfs_create_file); - - /** -@@ -165,13 +221,59 @@ EXPORT_SYMBOL_GPL(securityfs_create_file); - */ - struct dentry *securityfs_create_dir(const char *name, struct dentry *parent) - { -- return securityfs_create_file(name, -- S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO, -- parent, NULL, NULL); -+ return securityfs_create_file(name, S_IFDIR | 0755, parent, NULL, NULL); - } - EXPORT_SYMBOL_GPL(securityfs_create_dir); - - /** -+ * securityfs_create_symlink - create a symlink in the securityfs filesystem -+ * -+ * @name: a pointer to a string containing the name of the symlink to -+ * create. -+ * @parent: a pointer to the parent dentry for the symlink. This should be a -+ * directory dentry if set. If this parameter is %NULL, then the -+ * directory will be created in the root of the securityfs filesystem. -+ * @target: a pointer to a string containing the name of the symlink's target. -+ * If this parameter is %NULL, then the @iops parameter needs to be -+ * setup to handle .readlink and .get_link inode_operations. -+ * @iops: a pointer to the struct inode_operations to use for the symlink. If -+ * this parameter is %NULL, then the default simple_symlink_inode -+ * operations will be used. -+ * -+ * This function creates a symlink in securityfs with the given @name. -+ * -+ * This function returns a pointer to a dentry if it succeeds. This -+ * pointer must be passed to the securityfs_remove() function when the file is -+ * to be removed (no automatic cleanup happens if your module is unloaded, -+ * you are responsible here). If an error occurs, the function will return -+ * the error value (via ERR_PTR). -+ * -+ * If securityfs is not enabled in the kernel, the value %-ENODEV is -+ * returned. -+ */ -+struct dentry *securityfs_create_symlink(const char *name, -+ struct dentry *parent, -+ const char *target, -+ const struct inode_operations *iops) -+{ -+ struct dentry *dent; -+ char *link = NULL; -+ -+ if (target) { -+ link = kstrdup(target, GFP_KERNEL); -+ if (!link) -+ return ERR_PTR(-ENOMEM); -+ } -+ dent = securityfs_create_dentry(name, S_IFLNK | 0444, parent, -+ link, NULL, iops); -+ if (IS_ERR(dent)) -+ kfree(link); -+ -+ return dent; -+} -+EXPORT_SYMBOL_GPL(securityfs_create_symlink); -+ -+/** - * securityfs_remove - removes a file or directory from the securityfs filesystem - * - * @dentry: a pointer to a the dentry of the file or directory to be removed. --- -2.12.3 - diff --git a/patches.apparmor/0002-apparmor-Fix-logical-error-in-verify_header.patch b/patches.apparmor/0002-apparmor-Fix-logical-error-in-verify_header.patch deleted file mode 100644 index f3d7c04..0000000 --- a/patches.apparmor/0002-apparmor-Fix-logical-error-in-verify_header.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 85d1b984ba65c0424d57ec24027fa3ffa899eb86 Mon Sep 17 00:00:00 2001 -From: Christos Gkekas -Date: Sat, 8 Jul 2017 20:50:21 +0100 -Subject: [PATCH 02/17] apparmor: Fix logical error in verify_header() -References: FATE#323500 -Patch-mainline: v4.14-rc2 -Git-commit: 86aea56f14929ff1c05eca1776e9068e907429d5 - -verify_header() is currently checking whether interface version is less -than 5 *and* greater than 7, which always evaluates to false. Instead it -should check whether it is less than 5 *or* greater than 7. - -Signed-off-by: Christos Gkekas -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/policy_unpack.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c -index 2d5a1a007b06..bda0dce3b582 100644 ---- a/security/apparmor/policy_unpack.c -+++ b/security/apparmor/policy_unpack.c -@@ -832,7 +832,7 @@ static int verify_header(struct aa_ext *e, int required, const char **ns) - * if not specified use previous version - * Mask off everything that is not kernel abi version - */ -- if (VERSION_LT(e->version, v5) && VERSION_GT(e->version, v7)) { -+ if (VERSION_LT(e->version, v5) || VERSION_GT(e->version, v7)) { - audit_iface(NULL, NULL, NULL, "unsupported interface version", - e, error); - return error; --- -2.14.1 - diff --git a/patches.apparmor/0002-apparmor-fix-leak-of-null-profile-name-if-profile-al.patch b/patches.apparmor/0002-apparmor-fix-leak-of-null-profile-name-if-profile-al.patch deleted file mode 100644 index 130dc67..0000000 --- a/patches.apparmor/0002-apparmor-fix-leak-of-null-profile-name-if-profile-al.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 3218a24ad0b4787055aa665e3a33004e506d2402 Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Wed, 15 Nov 2017 15:25:30 -0800 -Subject: [PATCH] apparmor: fix leak of null profile name if profile allocation fails -References: bsc#1071057 -Git-commit: 4633307e5ed6128975595df43f796a10c41d11c1 -Patch-mainline: v4.15-rc1 - -Fixes: d07881d2edb0 ("apparmor: move new_null_profile to after profile lookup fns()") -Reported-by: Seth Arnold -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/policy.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c -index ea8acc9fcfda..877983014b5b 100644 ---- a/security/apparmor/policy.c -+++ b/security/apparmor/policy.c -@@ -503,7 +503,7 @@ struct aa_profile *aa_new_null_profile(struct aa_profile *parent, bool hat, - { - struct aa_profile *p, *profile; - const char *bname; -- char *name; -+ char *name = NULL; - - AA_BUG(!parent); - -@@ -563,6 +563,7 @@ struct aa_profile *aa_new_null_profile(struct aa_profile *parent, bool hat, - return profile; - - fail: -+ kfree(name); - aa_free_profile(profile); - return NULL; - } --- -2.14.2 - diff --git a/patches.apparmor/0002-apparmorfs-Combine-two-function-calls-into-one-in-aa.patch b/patches.apparmor/0002-apparmorfs-Combine-two-function-calls-into-one-in-aa.patch deleted file mode 100644 index c253bc1..0000000 --- a/patches.apparmor/0002-apparmorfs-Combine-two-function-calls-into-one-in-aa.patch +++ /dev/null @@ -1,40 +0,0 @@ -From d952bc9966116ab5dba22d4a0c6d646e3b37235e Mon Sep 17 00:00:00 2001 -From: Markus Elfring -Date: Sun, 7 May 2017 13:43:50 +0200 -Subject: [PATCH 02/65] apparmorfs: Combine two function calls into one in - aa_fs_seq_raw_abi_show() -References: FATE#323500 -Patch-mainline: v4.13-rc1 -Acked-by: Goldwyn Rodrigues -Git-commit: 0ff3d97f7676d9f513288a2d30582dcd2b34d238 - -A bit of data was put into a sequence by two separate function calls. -Print the same data by a single function call instead. - -Signed-off-by: Markus Elfring -Signed-off-by: John Johansen ---- - security/apparmor/apparmorfs.c | 7 +++---- - 1 file changed, 3 insertions(+), 4 deletions(-) - -diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c -index 4f6ac9dbc65d..b4d83e0bc651 100644 ---- a/security/apparmor/apparmorfs.c -+++ b/security/apparmor/apparmorfs.c -@@ -572,10 +572,9 @@ static int aa_fs_seq_raw_abi_show(struct seq_file *seq, void *v) - struct aa_proxy *proxy = seq->private; - struct aa_profile *profile = aa_get_profile_rcu(&proxy->profile); - -- if (profile->rawdata->abi) { -- seq_printf(seq, "v%d", profile->rawdata->abi); -- seq_puts(seq, "\n"); -- } -+ if (profile->rawdata->abi) -+ seq_printf(seq, "v%d\n", profile->rawdata->abi); -+ - aa_put_profile(profile); - - return 0; --- -2.12.3 - diff --git a/patches.apparmor/0003-apparmor-Fix-an-error-code-in-aafs_create.patch b/patches.apparmor/0003-apparmor-Fix-an-error-code-in-aafs_create.patch deleted file mode 100644 index 7b0ee75..0000000 --- a/patches.apparmor/0003-apparmor-Fix-an-error-code-in-aafs_create.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 19ea40c85443af3d34e33a5660eb2c7da0e85857 Mon Sep 17 00:00:00 2001 -From: Dan Carpenter -Date: Thu, 13 Jul 2017 10:39:20 +0300 -Subject: [PATCH 03/17] apparmor: Fix an error code in aafs_create() -References: FATE#323500 -Patch-mainline: v4.14-rc2 -Git-commit: 5d314a81eca29b01939930c1c596dfa44937e970 - -We accidentally forgot to set the error code on this path. It means we -return NULL instead of an error pointer. I looked through a bunch of -callers and I don't think it really causes a big issue, but the -documentation says we're supposed to return error pointers here. - -Signed-off-by: Dan Carpenter -Acked-by: Serge Hallyn -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/apparmorfs.c | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c -index 853c2ec8e0c9..2caeb748070c 100644 ---- a/security/apparmor/apparmorfs.c -+++ b/security/apparmor/apparmorfs.c -@@ -248,8 +248,10 @@ static struct dentry *aafs_create(const char *name, umode_t mode, - - inode_lock(dir); - dentry = lookup_one_len(name, parent, strlen(name)); -- if (IS_ERR(dentry)) -+ if (IS_ERR(dentry)) { -+ error = PTR_ERR(dentry); - goto fail_lock; -+ } - - if (d_really_is_positive(dentry)) { - error = -EEXIST; --- -2.14.1 - diff --git a/patches.apparmor/0003-apparmor-fix-locking-when-creating-a-new-complain-pr.patch b/patches.apparmor/0003-apparmor-fix-locking-when-creating-a-new-complain-pr.patch deleted file mode 100644 index 8e10bb6..0000000 --- a/patches.apparmor/0003-apparmor-fix-locking-when-creating-a-new-complain-pr.patch +++ /dev/null @@ -1,182 +0,0 @@ -From d88c0461174a1afcc9aad91ee2b50dbbe2c0791c Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Mon, 20 Nov 2017 22:26:12 -0800 -Subject: [PATCH] apparmor: fix locking when creating a new complain profile. -References: bsc#1071061 -Git-commit: 5d7c44ef5e4f0149c9fb99faeae41e930485a1ec -Patch-mainline: v4.15-rc1 - -Break the per cpu buffer atomic section when creating a new null -complain profile. In learning mode this won't matter and we can -safely re-aquire the buffer. - -This fixes the following lockdep BUG trace - nov. 14 14:09:09 cyclope audit[7152]: AVC apparmor="ALLOWED" operation="exec" profile="/usr/sbin/sssd" name="/usr/sbin/adcli" pid=7152 comm="sssd_be" requested_mask="x" denied_mask="x" fsuid=0 ouid=0 target="/usr/sbin/sssd//null-/usr/sbin/adcli" - nov. 14 14:09:09 cyclope kernel: BUG: sleeping function called from invalid context at kernel/locking/mutex.c:747 - nov. 14 14:09:09 cyclope kernel: in_atomic(): 1, irqs_disabled(): 0, pid: 7152, name: sssd_be - nov. 14 14:09:09 cyclope kernel: 1 lock held by sssd_be/7152: - nov. 14 14:09:09 cyclope kernel: #0: (&sig->cred_guard_mutex){....}, at: [] prepare_bprm_creds+0x4e/0x100 - nov. 14 14:09:09 cyclope kernel: CPU: 3 PID: 7152 Comm: sssd_be Not tainted 4.14.0prahal+intel #150 - nov. 14 14:09:09 cyclope kernel: Hardware name: LENOVO 20CDCTO1WW/20CDCTO1WW, BIOS GQET53WW (1.33 ) 09/15/2017 - nov. 14 14:09:09 cyclope kernel: Call Trace: - nov. 14 14:09:09 cyclope kernel: dump_stack+0xb0/0x135 - nov. 14 14:09:09 cyclope kernel: ? _atomic_dec_and_lock+0x15b/0x15b - nov. 14 14:09:09 cyclope kernel: ? lockdep_print_held_locks+0xc4/0x130 - nov. 14 14:09:09 cyclope kernel: ___might_sleep+0x29c/0x320 - nov. 14 14:09:09 cyclope kernel: ? rq_clock+0xf0/0xf0 - nov. 14 14:09:09 cyclope kernel: ? __kernel_text_address+0xd/0x40 - nov. 14 14:09:09 cyclope kernel: __might_sleep+0x95/0x190 - nov. 14 14:09:09 cyclope kernel: ? aa_new_null_profile+0x50a/0x960 - nov. 14 14:09:09 cyclope kernel: __mutex_lock+0x13e/0x1a20 - nov. 14 14:09:09 cyclope kernel: ? aa_new_null_profile+0x50a/0x960 - nov. 14 14:09:09 cyclope kernel: ? save_stack+0x43/0xd0 - nov. 14 14:09:09 cyclope kernel: ? kmem_cache_alloc_trace+0x13f/0x290 - nov. 14 14:09:09 cyclope kernel: ? mutex_lock_io_nested+0x1880/0x1880 - nov. 14 14:09:09 cyclope kernel: ? profile_transition+0x932/0x2d40 - nov. 14 14:09:09 cyclope kernel: ? apparmor_bprm_set_creds+0x1479/0x1f70 - nov. 14 14:09:09 cyclope kernel: ? security_bprm_set_creds+0x5a/0x80 - nov. 14 14:09:09 cyclope kernel: ? prepare_binprm+0x366/0x980 - nov. 14 14:09:09 cyclope kernel: ? do_execveat_common.isra.30+0x12a9/0x2350 - nov. 14 14:09:09 cyclope kernel: ? SyS_execve+0x2c/0x40 - nov. 14 14:09:09 cyclope kernel: ? do_syscall_64+0x228/0x650 - nov. 14 14:09:09 cyclope kernel: ? entry_SYSCALL64_slow_path+0x25/0x25 - nov. 14 14:09:09 cyclope kernel: ? deactivate_slab.isra.62+0x49d/0x5e0 - nov. 14 14:09:09 cyclope kernel: ? save_stack_trace+0x16/0x20 - nov. 14 14:09:09 cyclope kernel: ? init_object+0x88/0x90 - nov. 14 14:09:09 cyclope kernel: ? ___slab_alloc+0x520/0x590 - nov. 14 14:09:09 cyclope kernel: ? ___slab_alloc+0x520/0x590 - nov. 14 14:09:09 cyclope kernel: ? aa_alloc_proxy+0xab/0x200 - nov. 14 14:09:09 cyclope kernel: ? lock_downgrade+0x7e0/0x7e0 - nov. 14 14:09:09 cyclope kernel: ? memcg_kmem_get_cache+0x970/0x970 - nov. 14 14:09:09 cyclope kernel: ? kasan_unpoison_shadow+0x35/0x50 - nov. 14 14:09:09 cyclope kernel: ? kasan_unpoison_shadow+0x35/0x50 - nov. 14 14:09:09 cyclope kernel: ? kasan_kmalloc+0xad/0xe0 - nov. 14 14:09:09 cyclope kernel: ? aa_alloc_proxy+0xab/0x200 - nov. 14 14:09:09 cyclope kernel: ? kmem_cache_alloc_trace+0x13f/0x290 - nov. 14 14:09:09 cyclope kernel: ? aa_alloc_proxy+0xab/0x200 - nov. 14 14:09:09 cyclope kernel: ? aa_alloc_proxy+0xab/0x200 - nov. 14 14:09:09 cyclope kernel: ? _raw_spin_unlock+0x22/0x30 - nov. 14 14:09:09 cyclope kernel: ? vec_find+0xa0/0xa0 - nov. 14 14:09:09 cyclope kernel: ? aa_label_init+0x6f/0x230 - nov. 14 14:09:09 cyclope kernel: ? __label_insert+0x3e0/0x3e0 - nov. 14 14:09:09 cyclope kernel: ? kmem_cache_alloc_trace+0x13f/0x290 - nov. 14 14:09:09 cyclope kernel: ? aa_alloc_profile+0x58/0x200 - nov. 14 14:09:09 cyclope kernel: mutex_lock_nested+0x16/0x20 - nov. 14 14:09:09 cyclope kernel: ? mutex_lock_nested+0x16/0x20 - nov. 14 14:09:09 cyclope kernel: aa_new_null_profile+0x50a/0x960 - nov. 14 14:09:09 cyclope kernel: ? aa_fqlookupn_profile+0xdc0/0xdc0 - nov. 14 14:09:09 cyclope kernel: ? aa_compute_fperms+0x4b5/0x640 - nov. 14 14:09:09 cyclope kernel: ? disconnect.isra.2+0x1b0/0x1b0 - nov. 14 14:09:09 cyclope kernel: ? aa_str_perms+0x8d/0xe0 - nov. 14 14:09:09 cyclope kernel: profile_transition+0x932/0x2d40 - nov. 14 14:09:09 cyclope kernel: ? up_read+0x1a/0x40 - nov. 14 14:09:09 cyclope kernel: ? ext4_xattr_get+0x15c/0xaf0 [ext4] - nov. 14 14:09:09 cyclope kernel: ? x_table_lookup+0x190/0x190 - nov. 14 14:09:09 cyclope kernel: ? ext4_xattr_ibody_get+0x590/0x590 [ext4] - nov. 14 14:09:09 cyclope kernel: ? sched_clock+0x9/0x10 - nov. 14 14:09:09 cyclope kernel: ? sched_clock+0x9/0x10 - nov. 14 14:09:09 cyclope kernel: ? ext4_xattr_security_get+0x1a/0x20 [ext4] - nov. 14 14:09:09 cyclope kernel: ? __vfs_getxattr+0x6d/0xa0 - nov. 14 14:09:09 cyclope kernel: ? get_vfs_caps_from_disk+0x114/0x720 - nov. 14 14:09:09 cyclope kernel: ? sched_clock+0x9/0x10 - nov. 14 14:09:09 cyclope kernel: ? sched_clock+0x9/0x10 - nov. 14 14:09:09 cyclope kernel: ? tsc_resume+0x10/0x10 - nov. 14 14:09:09 cyclope kernel: ? get_vfs_caps_from_disk+0x720/0x720 - nov. 14 14:09:09 cyclope kernel: ? native_sched_clock_from_tsc+0x201/0x2b0 - nov. 14 14:09:09 cyclope kernel: ? sched_clock+0x9/0x10 - nov. 14 14:09:09 cyclope kernel: ? sched_clock_cpu+0x1b/0x170 - nov. 14 14:09:09 cyclope kernel: ? find_held_lock+0x3c/0x1e0 - nov. 14 14:09:09 cyclope kernel: ? rb_insert_color_cached+0x1660/0x1660 - nov. 14 14:09:09 cyclope kernel: apparmor_bprm_set_creds+0x1479/0x1f70 - nov. 14 14:09:09 cyclope kernel: ? sched_clock+0x9/0x10 - nov. 14 14:09:09 cyclope kernel: ? handle_onexec+0x31d0/0x31d0 - nov. 14 14:09:09 cyclope kernel: ? tsc_resume+0x10/0x10 - nov. 14 14:09:09 cyclope kernel: ? graph_lock+0xd0/0xd0 - nov. 14 14:09:09 cyclope kernel: ? tsc_resume+0x10/0x10 - nov. 14 14:09:09 cyclope kernel: ? sched_clock_cpu+0x1b/0x170 - nov. 14 14:09:09 cyclope kernel: ? sched_clock+0x9/0x10 - nov. 14 14:09:09 cyclope kernel: ? sched_clock+0x9/0x10 - nov. 14 14:09:09 cyclope kernel: ? sched_clock_cpu+0x1b/0x170 - nov. 14 14:09:09 cyclope kernel: ? find_held_lock+0x3c/0x1e0 - nov. 14 14:09:09 cyclope kernel: security_bprm_set_creds+0x5a/0x80 - nov. 14 14:09:09 cyclope kernel: prepare_binprm+0x366/0x980 - nov. 14 14:09:09 cyclope kernel: ? install_exec_creds+0x150/0x150 - nov. 14 14:09:09 cyclope kernel: ? __might_fault+0x89/0xb0 - nov. 14 14:09:09 cyclope kernel: ? up_read+0x40/0x40 - nov. 14 14:09:09 cyclope kernel: ? get_user_arg_ptr.isra.18+0x2c/0x70 - nov. 14 14:09:09 cyclope kernel: ? count.isra.20.constprop.32+0x7c/0xf0 - nov. 14 14:09:09 cyclope kernel: do_execveat_common.isra.30+0x12a9/0x2350 - nov. 14 14:09:09 cyclope kernel: ? prepare_bprm_creds+0x100/0x100 - nov. 14 14:09:09 cyclope kernel: ? _raw_spin_unlock+0x22/0x30 - nov. 14 14:09:09 cyclope kernel: ? deactivate_slab.isra.62+0x49d/0x5e0 - nov. 14 14:09:09 cyclope kernel: ? save_stack_trace+0x16/0x20 - nov. 14 14:09:09 cyclope kernel: ? init_object+0x88/0x90 - nov. 14 14:09:09 cyclope kernel: ? ___slab_alloc+0x520/0x590 - nov. 14 14:09:09 cyclope kernel: ? ___slab_alloc+0x520/0x590 - nov. 14 14:09:09 cyclope kernel: ? kasan_check_write+0x14/0x20 - nov. 14 14:09:09 cyclope kernel: ? memcg_kmem_get_cache+0x970/0x970 - nov. 14 14:09:09 cyclope kernel: ? kasan_unpoison_shadow+0x35/0x50 - nov. 14 14:09:09 cyclope kernel: ? glob_match+0x730/0x730 - nov. 14 14:09:09 cyclope kernel: ? kmem_cache_alloc+0x225/0x280 - nov. 14 14:09:09 cyclope kernel: ? getname_flags+0xb8/0x510 - nov. 14 14:09:09 cyclope kernel: ? mm_fault_error+0x2e0/0x2e0 - nov. 14 14:09:09 cyclope kernel: ? getname_flags+0xf6/0x510 - nov. 14 14:09:09 cyclope kernel: ? ptregs_sys_vfork+0x10/0x10 - nov. 14 14:09:09 cyclope kernel: SyS_execve+0x2c/0x40 - nov. 14 14:09:09 cyclope kernel: do_syscall_64+0x228/0x650 - nov. 14 14:09:09 cyclope kernel: ? syscall_return_slowpath+0x2f0/0x2f0 - nov. 14 14:09:09 cyclope kernel: ? syscall_return_slowpath+0x167/0x2f0 - nov. 14 14:09:09 cyclope kernel: ? prepare_exit_to_usermode+0x220/0x220 - nov. 14 14:09:09 cyclope kernel: ? prepare_exit_to_usermode+0xda/0x220 - nov. 14 14:09:09 cyclope kernel: ? perf_trace_sys_enter+0x1060/0x1060 - nov. 14 14:09:09 cyclope kernel: ? __put_user_4+0x1c/0x30 - nov. 14 14:09:09 cyclope kernel: entry_SYSCALL64_slow_path+0x25/0x25 - nov. 14 14:09:09 cyclope kernel: RIP: 0033:0x7f9320f23637 - nov. 14 14:09:09 cyclope kernel: RSP: 002b:00007fff783be338 EFLAGS: 00000202 ORIG_RAX: 000000000000003b - nov. 14 14:09:09 cyclope kernel: RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007f9320f23637 - nov. 14 14:09:09 cyclope kernel: RDX: 0000558c35002a70 RSI: 0000558c3505bd10 RDI: 0000558c35018b90 - nov. 14 14:09:09 cyclope kernel: RBP: 0000558c34b63ae8 R08: 0000558c3505bd10 R09: 0000000000000080 - nov. 14 14:09:09 cyclope kernel: R10: 0000000000000095 R11: 0000000000000202 R12: 0000000000000001 - nov. 14 14:09:09 cyclope kernel: R13: 0000558c35018b90 R14: 0000558c3505bd18 R15: 0000558c3505bd10 - -Fixes: 4227c333f65c ("apparmor: Move path lookup to using preallocated buffers") -BugLink: http://bugs.launchpad.net/bugs/173228 -Reported-by: Alban Browaeys -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/domain.c | 18 +++++++++++++++--- - 1 file changed, 15 insertions(+), 3 deletions(-) - -diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c -index 61dbdcf15a64..d6e88b2231e4 100644 ---- a/security/apparmor/domain.c -+++ b/security/apparmor/domain.c -@@ -543,9 +543,21 @@ static struct aa_label *profile_transition(struct aa_profile *profile, - } - } else if (COMPLAIN_MODE(profile)) { - /* no exec permission - learning mode */ -- struct aa_profile *new_profile = aa_new_null_profile(profile, -- false, name, -- GFP_ATOMIC); -+ struct aa_profile *new_profile = NULL; -+ char *n = kstrdup(name, GFP_ATOMIC); -+ -+ if (n) { -+ /* name is ptr into buffer */ -+ long pos = name - buffer; -+ /* break per cpu buffer hold */ -+ put_buffers(buffer); -+ new_profile = aa_new_null_profile(profile, false, n, -+ GFP_KERNEL); -+ get_buffers(buffer); -+ name = buffer + pos; -+ strcpy((char *)name, n); -+ kfree(n); -+ } - if (!new_profile) { - error = -ENOMEM; - info = "could not create null profile"; --- -2.14.2 - diff --git a/patches.apparmor/0003-doc-ReSTify-apparmor.txt.patch b/patches.apparmor/0003-doc-ReSTify-apparmor.txt.patch deleted file mode 100644 index 11897aa..0000000 --- a/patches.apparmor/0003-doc-ReSTify-apparmor.txt.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0993c534c86a9019546af0e1f187ba989d25f606 Mon Sep 17 00:00:00 2001 -From: Kees Cook -Date: Sat, 13 May 2017 04:51:45 -0700 -Subject: [PATCH 03/65] doc: ReSTify apparmor.txt -Git-commit: 26fccd9ed2e283add2849858c28bd14f84d9c48e -Patch-mainline: v4.13-rc1 -References: FATE#323500 - -Adjusts for ReST markup and moves under LSM admin guide. - -Acked-by: John Johansen -Signed-off-by: Kees Cook -Signed-off-by: Jonathan Corbet -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/match.c | 2 +- - security/apparmor/policy_unpack.c | 2 +- - 2 files changed, 2 insertions(+), 2 deletions(-) - -diff --git a/security/apparmor/match.c b/security/apparmor/match.c -index 960c913381e2..72c604350e80 100644 ---- a/security/apparmor/match.c -+++ b/security/apparmor/match.c -@@ -226,7 +226,7 @@ void aa_dfa_free_kref(struct kref *kref) - * @flags: flags controlling what type of accept tables are acceptable - * - * Unpack a dfa that has been serialized. To find information on the dfa -- * format look in Documentation/security/apparmor.txt -+ * format look in Documentation/admin-guide/LSM/apparmor.rst - * Assumes the dfa @blob stream has been aligned on a 8 byte boundary - * - * Returns: an unpacked dfa ready for matching or ERR_PTR on failure -diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c -index f3422a91353c..981d570eebba 100644 ---- a/security/apparmor/policy_unpack.c -+++ b/security/apparmor/policy_unpack.c -@@ -13,7 +13,7 @@ - * License. - * - * AppArmor uses a serialized binary format for loading policy. To find -- * policy format documentation look in Documentation/security/apparmor.txt -+ * policy format documentation see Documentation/admin-guide/LSM/apparmor.rst - * All policy is validated before it is used. - */ - --- -2.12.3 - diff --git a/patches.apparmor/0004-apparmor-Redundant-condition-prev_ns.-in-label.c-149.patch b/patches.apparmor/0004-apparmor-Redundant-condition-prev_ns.-in-label.c-149.patch deleted file mode 100644 index 5c673e3..0000000 --- a/patches.apparmor/0004-apparmor-Redundant-condition-prev_ns.-in-label.c-149.patch +++ /dev/null @@ -1,31 +0,0 @@ -From e6ace4325d85f080ea107233e6ff26195ad117c7 Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Mon, 31 Jul 2017 23:44:37 -0700 -Subject: [PATCH 04/17] apparmor: Redundant condition: prev_ns. in [label.c:1498] -References: FATE#323500 -Patch-mainline: v4.14-rc2 -Git-commit: c5561700c9cb951ec3a33a0914c840423b09d7c9 - -Reported-by: David Binderman -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/label.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/security/apparmor/label.c b/security/apparmor/label.c -index e052eaba1cf6..e324f4df3e34 100644 ---- a/security/apparmor/label.c -+++ b/security/apparmor/label.c -@@ -1495,7 +1495,7 @@ static int aa_profile_snxprint(char *str, size_t size, struct aa_ns *view, - view = profiles_ns(profile); - - if (view != profile->ns && -- (!prev_ns || (prev_ns && *prev_ns != profile->ns))) { -+ (!prev_ns || (*prev_ns != profile->ns))) { - if (prev_ns) - *prev_ns = profile->ns; - ns_name = aa_ns_name(view, profile->ns, --- -2.14.1 - diff --git a/patches.apparmor/0004-apparmor-fix-off-by-one-comparison-on-MAXMAPPED_SIG.patch b/patches.apparmor/0004-apparmor-fix-off-by-one-comparison-on-MAXMAPPED_SIG.patch deleted file mode 100644 index 541385e..0000000 --- a/patches.apparmor/0004-apparmor-fix-off-by-one-comparison-on-MAXMAPPED_SIG.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 8731435ab7253baa9d92463a7d6e1d0c1e66d533 Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Wed, 8 Nov 2017 08:09:52 -0800 -Subject: [PATCH] apparmor: fix off-by-one comparison on MAXMAPPED_SIG -References: bsc#1071070 -Git-commit: f7dc4c9a855a13dbb33294c9fc94f17af03f6291 -Patch-mainline: v4.14 - -This came in yesterday, and I have verified our regression tests -were missing this and it can cause an oops. Please apply. - -There is a an off-by-one comparision on sig against MAXMAPPED_SIG -that can lead to a read outside the sig_map array if sig -is MAXMAPPED_SIG. Fix this. - -Verified that the check is an out of bounds case that can cause an oops. - -Revised: add comparison fix to second case -Fixes: cd1dbf76b23d ("apparmor: add the ability to mediate signals") -Signed-off-by: Colin Ian King -Signed-off-by: John Johansen -Signed-off-by: Linus Torvalds -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/ipc.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/security/apparmor/ipc.c b/security/apparmor/ipc.c -index 66fb9ede9447..7ca0032e7ba9 100644 ---- a/security/apparmor/ipc.c -+++ b/security/apparmor/ipc.c -@@ -128,7 +128,7 @@ static inline int map_signal_num(int sig) - return SIGUNKNOWN; - else if (sig >= SIGRTMIN) - return sig - SIGRTMIN + 128; /* rt sigs mapped to 128 */ -- else if (sig <= MAXMAPPED_SIG) -+ else if (sig < MAXMAPPED_SIG) - return sig_map[sig]; - return SIGUNKNOWN; - } -@@ -163,7 +163,7 @@ static void audit_signal_cb(struct audit_buffer *ab, void *va) - audit_signal_mask(ab, aad(sa)->denied); - } - } -- if (aad(sa)->signal <= MAXMAPPED_SIG) -+ if (aad(sa)->signal < MAXMAPPED_SIG) - audit_log_format(ab, " signal=%s", sig_names[aad(sa)->signal]); - else - audit_log_format(ab, " signal=rtmin+%d", --- -2.14.2 - diff --git a/patches.apparmor/0004-apparmorfs-Use-seq_putc-in-two-functions.patch b/patches.apparmor/0004-apparmorfs-Use-seq_putc-in-two-functions.patch deleted file mode 100644 index 46b7151..0000000 --- a/patches.apparmor/0004-apparmorfs-Use-seq_putc-in-two-functions.patch +++ /dev/null @@ -1,45 +0,0 @@ -From dba5a52fead7a98a0a13a98ca43000718321b3bd Mon Sep 17 00:00:00 2001 -From: Markus Elfring -Date: Sun, 7 May 2017 13:50:28 +0200 -Subject: [PATCH 04/65] apparmorfs: Use seq_putc() -Patch-mainline: v4.13-rc1 -References: FATE#323500 -Acked-by: Goldwyn Rodrigues in two functions -Git-commit: 47dbd1cdbb4e74d656e444deb6675ee38ca1b1f3 - -Two single characters (line breaks) should be put into a sequence. -Thus use the corresponding function "seq_putc". - -This issue was detected by using the Coccinelle software. - -Signed-off-by: Markus Elfring -Signed-off-by: John Johansen ---- - security/apparmor/apparmorfs.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c -index b4d83e0bc651..41e427a4f051 100644 ---- a/security/apparmor/apparmorfs.c -+++ b/security/apparmor/apparmorfs.c -@@ -494,7 +494,7 @@ static int aa_fs_seq_hash_show(struct seq_file *seq, void *v) - if (profile->hash) { - for (i = 0; i < size; i++) - seq_printf(seq, "%.2x", profile->hash[i]); -- seq_puts(seq, "\n"); -+ seq_putc(seq, '\n'); - } - aa_put_profile(profile); - -@@ -602,7 +602,7 @@ static int aa_fs_seq_raw_hash_show(struct seq_file *seq, void *v) - if (profile->rawdata->hash) { - for (i = 0; i < size; i++) - seq_printf(seq, "%.2x", profile->rawdata->hash[i]); -- seq_puts(seq, "\n"); -+ seq_putc(seq, '\n'); - } - aa_put_profile(profile); - --- -2.12.3 - diff --git a/patches.apparmor/0005-apparmor-Fix-error-cod-in-__aa_fs_profile_mkdir.patch b/patches.apparmor/0005-apparmor-Fix-error-cod-in-__aa_fs_profile_mkdir.patch deleted file mode 100644 index 9508bec..0000000 --- a/patches.apparmor/0005-apparmor-Fix-error-cod-in-__aa_fs_profile_mkdir.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 71197508dc73905a2a7e6edc3e1e5b053bdd39c6 Mon Sep 17 00:00:00 2001 -From: Dan Carpenter -Date: Tue, 23 May 2017 17:33:46 +0300 -Subject: [PATCH 05/65] apparmor: Fix error cod in __aa_fs_profile_mkdir() -Git-commit: ffac1de6cf6f84e47cdb6d6de0629bc534f60961 -Patch-mainline: v4.13-rc1 -References: FATE#323500 -Acked-by: Goldwyn Rodrigues - -We can either return PTR_ERR(NULL) or a PTR_ERR(a valid pointer) here. -Returning NULL is probably not good, but since this happens at boot -then we are probably already toasted if we were to hit this bug in real -life. In other words, it seems like a very low severity bug to me. - -Signed-off-by: Dan Carpenter -Signed-off-by: John Johansen ---- - security/apparmor/apparmorfs.c | 6 ++++-- - 1 file changed, 4 insertions(+), 2 deletions(-) - -diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c -index 41e427a4f051..26ad1a370632 100644 ---- a/security/apparmor/apparmorfs.c -+++ b/security/apparmor/apparmorfs.c -@@ -727,8 +727,10 @@ int __aa_fs_profile_mkdir(struct aa_profile *profile, struct dentry *parent) - id_len = snprintf(NULL, 0, ".%ld", profile->ns->uniq_id); - - profile->dirname = kmalloc(len + id_len + 1, GFP_KERNEL); -- if (!profile->dirname) -- goto fail; -+ if (!profile->dirname) { -+ error = -ENOMEM; -+ goto fail2; -+ } - - mangle_name(profile->base.name, profile->dirname); - sprintf(profile->dirname + len, ".%ld", profile->ns->uniq_id++); --- -2.12.3 - diff --git a/patches.apparmor/0005-apparmor-add-the-ability-to-mediate-signals.patch b/patches.apparmor/0005-apparmor-add-the-ability-to-mediate-signals.patch deleted file mode 100644 index 46f374c..0000000 --- a/patches.apparmor/0005-apparmor-add-the-ability-to-mediate-signals.patch +++ /dev/null @@ -1,400 +0,0 @@ -From 5f840316deac0e4c2d6226c48c1c513412cd2112 Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Tue, 18 Jul 2017 22:56:22 -0700 -Subject: [PATCH 05/17] apparmor: add the ability to mediate signals -References: FATE#323500 -Patch-mainline: v4.14-rc2 -Git-commit: cd1dbf76b23d5ab2cba5e657fe20b1e236a408cc - -Add signal mediation where the signal can be mediated based on the -signal, direction, or the label or the peer/target. The signal perms -are verified on a cross check to ensure policy consistency in the case -of incremental policy load/replacement. - -The optimization of skipping the cross check when policy is guaranteed -to be consistent (single compile unit) remains to be done. - -policy rules have the form of - SIGNAL_RULE = [ QUALIFIERS ] 'signal' [ SIGNAL ACCESS PERMISSIONS ] - [ SIGNAL SET ] [ SIGNAL PEER ] - - SIGNAL ACCESS PERMISSIONS = SIGNAL ACCESS | SIGNAL ACCESS LIST - - SIGNAL ACCESS LIST = '(' Comma or space separated list of SIGNAL - ACCESS ')' - - SIGNAL ACCESS = ( 'r' | 'w' | 'rw' | 'read' | 'write' | 'send' | - 'receive' ) - - SIGNAL SET = 'set' '=' '(' SIGNAL LIST ')' - - SIGNAL LIST = Comma or space separated list of SIGNALS - - SIGNALS = ( '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' | 'exists' | 'rtmin+0' ... 'rtmin+32' - ) - - SIGNAL PEER = 'peer' '=' AARE - -eg. - signal, # allow all signals - signal send set=(hup, kill) peer=foo, - -Signed-off-by: John Johansen -Acked-by: Seth Arnold -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/apparmorfs.c | 7 +++ - security/apparmor/include/apparmor.h | 1 + - security/apparmor/include/audit.h | 2 + - security/apparmor/include/ipc.h | 6 +++ - security/apparmor/include/sig_names.h | 95 +++++++++++++++++++++++++++++++++ - security/apparmor/ipc.c | 99 +++++++++++++++++++++++++++++++++++ - security/apparmor/lsm.c | 21 ++++++++ - 7 files changed, 231 insertions(+) - create mode 100644 security/apparmor/include/sig_names.h - -diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c -index 2caeb748070c..a5f9e1aa51f7 100644 ---- a/security/apparmor/apparmorfs.c -+++ b/security/apparmor/apparmorfs.c -@@ -32,6 +32,7 @@ - #include "include/audit.h" - #include "include/context.h" - #include "include/crypto.h" -+#include "include/ipc.h" - #include "include/policy_ns.h" - #include "include/label.h" - #include "include/policy.h" -@@ -2129,6 +2130,11 @@ static struct aa_sfs_entry aa_sfs_entry_ptrace[] = { - { } - }; - -+static struct aa_sfs_entry aa_sfs_entry_signal[] = { -+ AA_SFS_FILE_STRING("mask", AA_SFS_SIG_MASK), -+ { } -+}; -+ - static struct aa_sfs_entry aa_sfs_entry_domain[] = { - AA_SFS_FILE_BOOLEAN("change_hat", 1), - AA_SFS_FILE_BOOLEAN("change_hatv", 1), -@@ -2179,6 +2185,7 @@ static struct aa_sfs_entry aa_sfs_entry_features[] = { - AA_SFS_DIR("rlimit", aa_sfs_entry_rlimit), - AA_SFS_DIR("caps", aa_sfs_entry_caps), - AA_SFS_DIR("ptrace", aa_sfs_entry_ptrace), -+ AA_SFS_DIR("signal", aa_sfs_entry_signal), - AA_SFS_DIR("query", aa_sfs_entry_query), - { } - }; -diff --git a/security/apparmor/include/apparmor.h b/security/apparmor/include/apparmor.h -index aaf893f4e4f5..962a20a75e01 100644 ---- a/security/apparmor/include/apparmor.h -+++ b/security/apparmor/include/apparmor.h -@@ -28,6 +28,7 @@ - #define AA_CLASS_RLIMITS 5 - #define AA_CLASS_DOMAIN 6 - #define AA_CLASS_PTRACE 9 -+#define AA_CLASS_SIGNAL 10 - #define AA_CLASS_LABEL 16 - - #define AA_CLASS_LAST AA_CLASS_LABEL -diff --git a/security/apparmor/include/audit.h b/security/apparmor/include/audit.h -index c68839a44351..d9a156ae11b9 100644 ---- a/security/apparmor/include/audit.h -+++ b/security/apparmor/include/audit.h -@@ -86,6 +86,7 @@ enum audit_type { - #define OP_SHUTDOWN "socket_shutdown" - - #define OP_PTRACE "ptrace" -+#define OP_SIGNAL "signal" - - #define OP_EXEC "exec" - -@@ -126,6 +127,7 @@ struct apparmor_audit_data { - long pos; - const char *ns; - } iface; -+ int signal; - struct { - int rlim; - unsigned long max; -diff --git a/security/apparmor/include/ipc.h b/security/apparmor/include/ipc.h -index 656fdb81c8a0..5ffc218d1e74 100644 ---- a/security/apparmor/include/ipc.h -+++ b/security/apparmor/include/ipc.h -@@ -27,8 +27,14 @@ struct aa_profile; - - #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); -+int aa_may_signal(struct aa_label *sender, struct aa_label *target, int sig); - - #endif /* __AA_IPC_H */ -diff --git a/security/apparmor/include/sig_names.h b/security/apparmor/include/sig_names.h -new file mode 100644 -index 000000000000..0d4395f231ca ---- /dev/null -+++ b/security/apparmor/include/sig_names.h -@@ -0,0 +1,95 @@ -+#include -+ -+#define SIGUNKNOWN 0 -+#define MAXMAPPED_SIG 35 -+/* 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, -+ [SIGSTKFLT] = 16, /* -, 16, - */ -+ [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(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_SIG + 1] = { -+ "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/ipc.c b/security/apparmor/ipc.c -index 11e66b5bbc42..66fb9ede9447 100644 ---- a/security/apparmor/ipc.c -+++ b/security/apparmor/ipc.c -@@ -20,6 +20,7 @@ - #include "include/context.h" - #include "include/policy.h" - #include "include/ipc.h" -+#include "include/sig_names.h" - - /** - * audit_ptrace_mask - convert mask to permission string -@@ -121,3 +122,101 @@ int aa_may_ptrace(struct aa_label *tracer, struct aa_label *tracee, - } - - -+static inline int map_signal_num(int sig) -+{ -+ if (sig > SIGRTMAX) -+ return SIGUNKNOWN; -+ else if (sig >= SIGRTMIN) -+ return sig - SIGRTMIN + 128; /* rt sigs mapped to 128 */ -+ else if (sig <= MAXMAPPED_SIG) -+ return sig_map[sig]; -+ return SIGUNKNOWN; -+} -+ -+/** -+ * audit_file_mask - convert mask to permission string -+ * @buffer: buffer to write string to (NOT NULL) -+ * @mask: permission mask to convert -+ */ -+static void audit_signal_mask(struct audit_buffer *ab, u32 mask) -+{ -+ if (mask & MAY_READ) -+ audit_log_string(ab, "receive"); -+ if (mask & MAY_WRITE) -+ audit_log_string(ab, "send"); -+} -+ -+/** -+ * audit_cb - call back for signal specific audit fields -+ * @ab: audit_buffer (NOT NULL) -+ * @va: audit struct to audit values of (NOT NULL) -+ */ -+static void audit_signal_cb(struct audit_buffer *ab, void *va) -+{ -+ struct common_audit_data *sa = va; -+ -+ if (aad(sa)->request & AA_SIGNAL_PERM_MASK) { -+ audit_log_format(ab, " requested_mask="); -+ audit_signal_mask(ab, aad(sa)->request); -+ if (aad(sa)->denied & AA_SIGNAL_PERM_MASK) { -+ audit_log_format(ab, " denied_mask="); -+ audit_signal_mask(ab, aad(sa)->denied); -+ } -+ } -+ if (aad(sa)->signal <= MAXMAPPED_SIG) -+ audit_log_format(ab, " signal=%s", sig_names[aad(sa)->signal]); -+ else -+ audit_log_format(ab, " signal=rtmin+%d", -+ aad(sa)->signal - 128); -+ audit_log_format(ab, " peer="); -+ aa_label_xaudit(ab, labels_ns(aad(sa)->label), aad(sa)->peer, -+ FLAGS_NONE, GFP_ATOMIC); -+} -+ -+/* TODO: update to handle compound name&name2, conditionals */ -+static void profile_match_signal(struct aa_profile *profile, const char *label, -+ int signal, struct aa_perms *perms) -+{ -+ unsigned int state; -+ -+ /* TODO: secondary cache check */ -+ state = aa_dfa_next(profile->policy.dfa, -+ profile->policy.start[AA_CLASS_SIGNAL], -+ signal); -+ state = aa_dfa_match(profile->policy.dfa, state, label); -+ aa_compute_perms(profile->policy.dfa, state, perms); -+} -+ -+static int profile_signal_perm(struct aa_profile *profile, -+ struct aa_profile *peer, u32 request, -+ struct common_audit_data *sa) -+{ -+ struct aa_perms perms; -+ -+ if (profile_unconfined(profile) || -+ !PROFILE_MEDIATES(profile, AA_CLASS_SIGNAL)) -+ return 0; -+ -+ aad(sa)->peer = &peer->label; -+ profile_match_signal(profile, peer->base.hname, aad(sa)->signal, -+ &perms); -+ aa_apply_modes_to_perms(profile, &perms); -+ return aa_check_perms(profile, &perms, request, sa, audit_signal_cb); -+} -+ -+static int aa_signal_cross_perm(struct aa_profile *sender, -+ struct aa_profile *target, -+ struct common_audit_data *sa) -+{ -+ return xcheck(profile_signal_perm(sender, target, MAY_WRITE, sa), -+ profile_signal_perm(target, sender, MAY_READ, sa)); -+} -+ -+int aa_may_signal(struct aa_label *sender, struct aa_label *target, int sig) -+{ -+ DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, OP_SIGNAL); -+ -+ aad(&sa)->signal = map_signal_num(sig); -+ return xcheck_labels_profiles(sender, target, aa_signal_cross_perm, -+ &sa); -+} -diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c -index 867bcd154c7e..af22f3dfbcce 100644 ---- a/security/apparmor/lsm.c -+++ b/security/apparmor/lsm.c -@@ -656,6 +656,26 @@ static int apparmor_task_setrlimit(struct task_struct *task, - return error; - } - -+static int apparmor_task_kill(struct task_struct *target, struct siginfo *info, -+ int sig, u32 secid) -+{ -+ struct aa_label *cl, *tl; -+ int error; -+ -+ if (secid) -+ /* TODO: after secid to label mapping is done. -+ * Dealing with USB IO specific behavior -+ */ -+ return 0; -+ cl = __begin_current_label_crit_section(); -+ tl = aa_get_task_label(target); -+ error = aa_may_signal(cl, tl, sig); -+ aa_put_label(tl); -+ __end_current_label_crit_section(cl); -+ -+ return error; -+} -+ - static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = { - LSM_HOOK_INIT(ptrace_access_check, apparmor_ptrace_access_check), - LSM_HOOK_INIT(ptrace_traceme, apparmor_ptrace_traceme), -@@ -697,6 +717,7 @@ static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = { - LSM_HOOK_INIT(bprm_secureexec, apparmor_bprm_secureexec), - - LSM_HOOK_INIT(task_setrlimit, apparmor_task_setrlimit), -+ LSM_HOOK_INIT(task_kill, apparmor_task_kill), - }; - - /* --- -2.14.1 - diff --git a/patches.apparmor/0006-apparmor-add-mount-mediation.patch b/patches.apparmor/0006-apparmor-add-mount-mediation.patch deleted file mode 100644 index 7446f46..0000000 --- a/patches.apparmor/0006-apparmor-add-mount-mediation.patch +++ /dev/null @@ -1,1054 +0,0 @@ -From 644d641569e060735a06232b53f321c6c62c0947 Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Tue, 18 Jul 2017 23:04:47 -0700 -Subject: [PATCH 06/17] apparmor: add mount mediation -References: FATE#323500 -Patch-mainline: v4.14-rc2 -Git-commit: 2ea3ffb7782a84da33a8382f13ebd016da50079b - -Add basic mount mediation. That allows controlling based on basic -mount parameters. It does not include special mount parameters for -apparmor, super block labeling, or any triggers for apparmor namespace -parameter modifications on pivot root. - -default userspace policy rules have the form of - MOUNT RULE = ( MOUNT | REMOUNT | UMOUNT ) - - MOUNT = [ QUALIFIERS ] 'mount' [ MOUNT CONDITIONS ] [ SOURCE FILEGLOB ] - [ '->' MOUNTPOINT FILEGLOB ] - - REMOUNT = [ QUALIFIERS ] 'remount' [ MOUNT CONDITIONS ] - MOUNTPOINT FILEGLOB - - UMOUNT = [ QUALIFIERS ] 'umount' [ MOUNT CONDITIONS ] MOUNTPOINT FILEGLOB - - MOUNT CONDITIONS = [ ( 'fstype' | 'vfstype' ) ( '=' | 'in' ) - MOUNT FSTYPE EXPRESSION ] - [ 'options' ( '=' | 'in' ) MOUNT FLAGS EXPRESSION ] - - MOUNT FSTYPE EXPRESSION = ( MOUNT FSTYPE LIST | MOUNT EXPRESSION ) - - MOUNT FSTYPE LIST = Comma separated list of valid filesystem and - virtual filesystem types (eg ext4, debugfs, etc) - - MOUNT FLAGS EXPRESSION = ( MOUNT FLAGS LIST | MOUNT EXPRESSION ) - - MOUNT FLAGS LIST = Comma separated list of MOUNT FLAGS. - - MOUNT FLAGS = ( 'ro' | 'rw' | 'nosuid' | 'suid' | 'nodev' | 'dev' | - 'noexec' | 'exec' | 'sync' | 'async' | 'remount' | - 'mand' | 'nomand' | 'dirsync' | 'noatime' | 'atime' | - 'nodiratime' | 'diratime' | 'bind' | 'rbind' | 'move' | - 'verbose' | 'silent' | 'loud' | 'acl' | 'noacl' | - 'unbindable' | 'runbindable' | 'private' | 'rprivate' | - 'slave' | 'rslave' | 'shared' | 'rshared' | - 'relatime' | 'norelatime' | 'iversion' | 'noiversion' | - 'strictatime' | 'nouser' | 'user' ) - - MOUNT EXPRESSION = ( ALPHANUMERIC | AARE ) ... - - PIVOT ROOT RULE = [ QUALIFIERS ] pivot_root [ oldroot=OLD PUT FILEGLOB ] - [ NEW ROOT FILEGLOB ] - - SOURCE FILEGLOB = FILEGLOB - - MOUNTPOINT FILEGLOB = FILEGLOB - -eg. - mount, - mount /dev/foo, - mount options=ro /dev/foo -> /mnt/, - mount options in (ro,atime) /dev/foo -> /mnt/, - mount options=ro options=atime, - -Signed-off-by: John Johansen -Acked-by: Seth Arnold -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/Makefile | 2 +- - security/apparmor/apparmorfs.c | 8 +- - security/apparmor/domain.c | 4 +- - security/apparmor/include/apparmor.h | 1 + - security/apparmor/include/audit.h | 11 + - security/apparmor/include/domain.h | 5 + - security/apparmor/include/mount.h | 54 +++ - security/apparmor/lsm.c | 64 ++++ - security/apparmor/mount.c | 696 +++++++++++++++++++++++++++++++++++ - 9 files changed, 841 insertions(+), 4 deletions(-) - create mode 100644 security/apparmor/include/mount.h - create mode 100644 security/apparmor/mount.c - -diff --git a/security/apparmor/Makefile b/security/apparmor/Makefile -index a16b195274de..81a34426d024 100644 ---- a/security/apparmor/Makefile -+++ b/security/apparmor/Makefile -@@ -4,7 +4,7 @@ obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o - - apparmor-y := apparmorfs.o audit.o capability.o context.o ipc.o lib.o match.o \ - path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \ -- resource.o secid.o file.o policy_ns.o label.o -+ resource.o secid.o file.o policy_ns.o label.o mount.o - apparmor-$(CONFIG_SECURITY_APPARMOR_HASH) += crypto.o - - clean-files := capability_names.h rlim_names.h -diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c -index a5f9e1aa51f7..8fa6c898c44b 100644 ---- a/security/apparmor/apparmorfs.c -+++ b/security/apparmor/apparmorfs.c -@@ -2159,9 +2159,14 @@ static struct aa_sfs_entry aa_sfs_entry_policy[] = { - { } - }; - -+static struct aa_sfs_entry aa_sfs_entry_mount[] = { -+ AA_SFS_FILE_STRING("mask", "mount umount pivot_root"), -+ { } -+}; -+ - static struct aa_sfs_entry aa_sfs_entry_ns[] = { - AA_SFS_FILE_BOOLEAN("profile", 1), -- AA_SFS_FILE_BOOLEAN("pivot_root", 1), -+ AA_SFS_FILE_BOOLEAN("pivot_root", 0), - { } - }; - -@@ -2180,6 +2185,7 @@ static struct aa_sfs_entry aa_sfs_entry_features[] = { - AA_SFS_DIR("policy", aa_sfs_entry_policy), - AA_SFS_DIR("domain", aa_sfs_entry_domain), - AA_SFS_DIR("file", aa_sfs_entry_file), -+ AA_SFS_DIR("mount", aa_sfs_entry_mount), - AA_SFS_DIR("namespaces", aa_sfs_entry_ns), - AA_SFS_FILE_U64("capability", VFS_CAP_FLAGS_MASK), - AA_SFS_DIR("rlimit", aa_sfs_entry_rlimit), -diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c -index d0594446ae3f..ffc8c75a6785 100644 ---- a/security/apparmor/domain.c -+++ b/security/apparmor/domain.c -@@ -374,8 +374,8 @@ static const char *next_name(int xtype, const char *name) - * - * Returns: refcounted label, or NULL on failure (MAYBE NULL) - */ --static struct aa_label *x_table_lookup(struct aa_profile *profile, u32 xindex, -- const char **name) -+struct aa_label *x_table_lookup(struct aa_profile *profile, u32 xindex, -+ const char **name) - { - struct aa_label *label = NULL; - u32 xtype = xindex & AA_X_TYPE_MASK; -diff --git a/security/apparmor/include/apparmor.h b/security/apparmor/include/apparmor.h -index 962a20a75e01..829082c35faa 100644 ---- a/security/apparmor/include/apparmor.h -+++ b/security/apparmor/include/apparmor.h -@@ -27,6 +27,7 @@ - #define AA_CLASS_NET 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_LABEL 16 -diff --git a/security/apparmor/include/audit.h b/security/apparmor/include/audit.h -index d9a156ae11b9..c3fe1c5ef3bc 100644 ---- a/security/apparmor/include/audit.h -+++ b/security/apparmor/include/audit.h -@@ -71,6 +71,10 @@ enum audit_type { - #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" -@@ -132,6 +136,13 @@ struct apparmor_audit_data { - int rlim; - unsigned long max; - } rlim; -+ struct { -+ const char *src_name; -+ const char *type; -+ const char *trans; -+ const char *data; -+ unsigned long flags; -+ } mnt; - }; - }; - -diff --git a/security/apparmor/include/domain.h b/security/apparmor/include/domain.h -index bab5810b6e9a..db27403346c5 100644 ---- a/security/apparmor/include/domain.h -+++ b/security/apparmor/include/domain.h -@@ -15,6 +15,8 @@ - #include - #include - -+#include "label.h" -+ - #ifndef __AA_DOMAIN_H - #define __AA_DOMAIN_H - -@@ -29,6 +31,9 @@ struct aa_domain { - #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_set_creds(struct linux_binprm *bprm); - int apparmor_bprm_secureexec(struct linux_binprm *bprm); - -diff --git a/security/apparmor/include/mount.h b/security/apparmor/include/mount.h -new file mode 100644 -index 000000000000..25d6067fa6ef ---- /dev/null -+++ b/security/apparmor/include/mount.h -@@ -0,0 +1,54 @@ -+/* -+ * AppArmor security module -+ * -+ * This file contains AppArmor file mediation function definitions. -+ * -+ * Copyright 2017 Canonical Ltd. -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License as -+ * published by the Free Software Foundation, version 2 of the -+ * License. -+ */ -+ -+#ifndef __AA_MOUNT_H -+#define __AA_MOUNT_H -+ -+#include -+#include -+ -+#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/lsm.c b/security/apparmor/lsm.c -index af22f3dfbcce..4ad0b3a45142 100644 ---- a/security/apparmor/lsm.c -+++ b/security/apparmor/lsm.c -@@ -38,6 +38,7 @@ - #include "include/policy.h" - #include "include/policy_ns.h" - #include "include/procattr.h" -+#include "include/mount.h" - - /* Flag indicating whether initialization completed */ - int apparmor_initialized; -@@ -511,6 +512,65 @@ static int apparmor_file_mprotect(struct vm_area_struct *vma, - !(vma->vm_flags & VM_SHARED) ? MAP_PRIVATE : 0); - } - -+static int apparmor_sb_mount(const char *dev_name, const struct path *path, -+ const char *type, unsigned long flags, void *data) -+{ -+ struct aa_label *label; -+ int error = 0; -+ -+ /* Discard magic */ -+ if ((flags & MS_MGC_MSK) == MS_MGC_VAL) -+ flags &= ~MS_MGC_MSK; -+ -+ flags &= ~AA_MS_IGNORE_MASK; -+ -+ label = __begin_current_label_crit_section(); -+ if (!unconfined(label)) { -+ if (flags & MS_REMOUNT) -+ error = aa_remount(label, path, flags, data); -+ else if (flags & MS_BIND) -+ error = aa_bind_mount(label, path, dev_name, flags); -+ else if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE | -+ MS_UNBINDABLE)) -+ error = aa_mount_change_type(label, path, flags); -+ else if (flags & MS_MOVE) -+ error = aa_move_mount(label, path, dev_name); -+ else -+ error = aa_new_mount(label, dev_name, path, type, -+ flags, data); -+ } -+ __end_current_label_crit_section(label); -+ -+ return error; -+} -+ -+static int apparmor_sb_umount(struct vfsmount *mnt, int flags) -+{ -+ struct aa_label *label; -+ int error = 0; -+ -+ label = __begin_current_label_crit_section(); -+ if (!unconfined(label)) -+ error = aa_umount(label, mnt, flags); -+ __end_current_label_crit_section(label); -+ -+ return error; -+} -+ -+static int apparmor_sb_pivotroot(const struct path *old_path, -+ const struct path *new_path) -+{ -+ struct aa_label *label; -+ int error = 0; -+ -+ label = aa_get_current_label(); -+ if (!unconfined(label)) -+ error = aa_pivotroot(label, old_path, new_path); -+ aa_put_label(label); -+ -+ return error; -+} -+ - static int apparmor_getprocattr(struct task_struct *task, char *name, - char **value) - { -@@ -682,6 +742,10 @@ static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = { - LSM_HOOK_INIT(capget, apparmor_capget), - LSM_HOOK_INIT(capable, apparmor_capable), - -+ LSM_HOOK_INIT(sb_mount, apparmor_sb_mount), -+ LSM_HOOK_INIT(sb_umount, apparmor_sb_umount), -+ LSM_HOOK_INIT(sb_pivotroot, apparmor_sb_pivotroot), -+ - LSM_HOOK_INIT(path_link, apparmor_path_link), - LSM_HOOK_INIT(path_unlink, apparmor_path_unlink), - LSM_HOOK_INIT(path_symlink, apparmor_path_symlink), -diff --git a/security/apparmor/mount.c b/security/apparmor/mount.c -new file mode 100644 -index 000000000000..82a64b58041d ---- /dev/null -+++ b/security/apparmor/mount.c -@@ -0,0 +1,696 @@ -+/* -+ * AppArmor security module -+ * -+ * This file contains AppArmor mediation of files -+ * -+ * Copyright (C) 1998-2008 Novell/SUSE -+ * Copyright 2009-2017 Canonical Ltd. -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License as -+ * published by the Free Software Foundation, version 2 of the -+ * License. -+ */ -+ -+#include -+#include -+#include -+ -+#include "include/apparmor.h" -+#include "include/audit.h" -+#include "include/context.h" -+#include "include/domain.h" -+#include "include/file.h" -+#include "include/match.h" -+#include "include/mount.h" -+#include "include/path.h" -+#include "include/policy.h" -+ -+ -+static void audit_mnt_flags(struct audit_buffer *ab, unsigned long flags) -+{ -+ if (flags & MS_RDONLY) -+ audit_log_format(ab, "ro"); -+ else -+ audit_log_format(ab, "rw"); -+ if (flags & MS_NOSUID) -+ audit_log_format(ab, ", nosuid"); -+ if (flags & MS_NODEV) -+ audit_log_format(ab, ", nodev"); -+ if (flags & MS_NOEXEC) -+ audit_log_format(ab, ", noexec"); -+ if (flags & MS_SYNCHRONOUS) -+ audit_log_format(ab, ", sync"); -+ if (flags & MS_REMOUNT) -+ audit_log_format(ab, ", remount"); -+ if (flags & MS_MANDLOCK) -+ audit_log_format(ab, ", mand"); -+ if (flags & MS_DIRSYNC) -+ audit_log_format(ab, ", dirsync"); -+ if (flags & MS_NOATIME) -+ audit_log_format(ab, ", noatime"); -+ if (flags & MS_NODIRATIME) -+ audit_log_format(ab, ", nodiratime"); -+ if (flags & MS_BIND) -+ audit_log_format(ab, flags & MS_REC ? ", rbind" : ", bind"); -+ if (flags & MS_MOVE) -+ audit_log_format(ab, ", move"); -+ if (flags & MS_SILENT) -+ audit_log_format(ab, ", silent"); -+ if (flags & MS_POSIXACL) -+ audit_log_format(ab, ", acl"); -+ if (flags & MS_UNBINDABLE) -+ audit_log_format(ab, flags & MS_REC ? ", runbindable" : -+ ", unbindable"); -+ if (flags & MS_PRIVATE) -+ audit_log_format(ab, flags & MS_REC ? ", rprivate" : -+ ", private"); -+ if (flags & MS_SLAVE) -+ audit_log_format(ab, flags & MS_REC ? ", rslave" : -+ ", slave"); -+ if (flags & MS_SHARED) -+ audit_log_format(ab, flags & MS_REC ? ", rshared" : -+ ", shared"); -+ if (flags & MS_RELATIME) -+ audit_log_format(ab, ", relatime"); -+ if (flags & MS_I_VERSION) -+ audit_log_format(ab, ", iversion"); -+ if (flags & MS_STRICTATIME) -+ audit_log_format(ab, ", strictatime"); -+ if (flags & MS_NOUSER) -+ audit_log_format(ab, ", nouser"); -+} -+ -+/** -+ * audit_cb - call back for mount specific audit fields -+ * @ab: audit_buffer (NOT NULL) -+ * @va: audit struct to audit values of (NOT NULL) -+ */ -+static void audit_cb(struct audit_buffer *ab, void *va) -+{ -+ struct common_audit_data *sa = va; -+ -+ if (aad(sa)->mnt.type) { -+ audit_log_format(ab, " fstype="); -+ audit_log_untrustedstring(ab, aad(sa)->mnt.type); -+ } -+ if (aad(sa)->mnt.src_name) { -+ audit_log_format(ab, " srcname="); -+ audit_log_untrustedstring(ab, aad(sa)->mnt.src_name); -+ } -+ if (aad(sa)->mnt.trans) { -+ audit_log_format(ab, " trans="); -+ audit_log_untrustedstring(ab, aad(sa)->mnt.trans); -+ } -+ if (aad(sa)->mnt.flags) { -+ audit_log_format(ab, " flags=\""); -+ audit_mnt_flags(ab, aad(sa)->mnt.flags); -+ audit_log_format(ab, "\""); -+ } -+ if (aad(sa)->mnt.data) { -+ audit_log_format(ab, " options="); -+ audit_log_untrustedstring(ab, aad(sa)->mnt.data); -+ } -+} -+ -+/** -+ * audit_mount - handle the auditing of mount operations -+ * @profile: the profile being enforced (NOT NULL) -+ * @op: operation being mediated (NOT NULL) -+ * @name: name of object being mediated (MAYBE NULL) -+ * @src_name: src_name of object being mediated (MAYBE_NULL) -+ * @type: type of filesystem (MAYBE_NULL) -+ * @trans: name of trans (MAYBE NULL) -+ * @flags: filesystem idependent mount flags -+ * @data: filesystem mount flags -+ * @request: permissions requested -+ * @perms: the permissions computed for the request (NOT NULL) -+ * @info: extra information message (MAYBE NULL) -+ * @error: 0 if operation allowed else failure error code -+ * -+ * Returns: %0 or error on failure -+ */ -+static int audit_mount(struct aa_profile *profile, const char *op, -+ const char *name, const char *src_name, -+ const char *type, const char *trans, -+ unsigned long flags, const void *data, u32 request, -+ struct aa_perms *perms, const char *info, int error) -+{ -+ int audit_type = AUDIT_APPARMOR_AUTO; -+ DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, op); -+ -+ if (likely(!error)) { -+ u32 mask = perms->audit; -+ -+ if (unlikely(AUDIT_MODE(profile) == AUDIT_ALL)) -+ mask = 0xffff; -+ -+ /* mask off perms that are not being force audited */ -+ request &= mask; -+ -+ if (likely(!request)) -+ return 0; -+ audit_type = AUDIT_APPARMOR_AUDIT; -+ } else { -+ /* only report permissions that were denied */ -+ request = request & ~perms->allow; -+ -+ if (request & perms->kill) -+ audit_type = AUDIT_APPARMOR_KILL; -+ -+ /* quiet known rejects, assumes quiet and kill do not overlap */ -+ if ((request & perms->quiet) && -+ AUDIT_MODE(profile) != AUDIT_NOQUIET && -+ AUDIT_MODE(profile) != AUDIT_ALL) -+ request &= ~perms->quiet; -+ -+ if (!request) -+ return error; -+ } -+ -+ aad(&sa)->name = name; -+ aad(&sa)->mnt.src_name = src_name; -+ aad(&sa)->mnt.type = type; -+ aad(&sa)->mnt.trans = trans; -+ aad(&sa)->mnt.flags = flags; -+ if (data && (perms->audit & AA_AUDIT_DATA)) -+ aad(&sa)->mnt.data = data; -+ aad(&sa)->info = info; -+ aad(&sa)->error = error; -+ -+ return aa_audit(audit_type, profile, &sa, audit_cb); -+} -+ -+/** -+ * match_mnt_flags - Do an ordered match on mount flags -+ * @dfa: dfa to match against -+ * @state: state to start in -+ * @flags: mount flags to match against -+ * -+ * Mount flags are encoded as an ordered match. This is done instead of -+ * checking against a simple bitmask, to allow for logical operations -+ * on the flags. -+ * -+ * Returns: next state after flags match -+ */ -+static unsigned int match_mnt_flags(struct aa_dfa *dfa, unsigned int state, -+ unsigned long flags) -+{ -+ unsigned int i; -+ -+ for (i = 0; i <= 31 ; ++i) { -+ if ((1 << i) & flags) -+ state = aa_dfa_next(dfa, state, i + 1); -+ } -+ -+ return state; -+} -+ -+/** -+ * compute_mnt_perms - compute mount permission associated with @state -+ * @dfa: dfa to match against (NOT NULL) -+ * @state: state match finished in -+ * -+ * Returns: mount permissions -+ */ -+static struct aa_perms compute_mnt_perms(struct aa_dfa *dfa, -+ unsigned int state) -+{ -+ struct aa_perms perms; -+ -+ perms.kill = 0; -+ perms.allow = dfa_user_allow(dfa, state); -+ perms.audit = dfa_user_audit(dfa, state); -+ perms.quiet = dfa_user_quiet(dfa, state); -+ perms.xindex = dfa_user_xindex(dfa, state); -+ -+ return perms; -+} -+ -+static const char * const mnt_info_table[] = { -+ "match succeeded", -+ "failed mntpnt match", -+ "failed srcname match", -+ "failed type match", -+ "failed flags match", -+ "failed data match" -+}; -+ -+/* -+ * Returns 0 on success else element that match failed in, this is the -+ * index into the mnt_info_table above -+ */ -+static int do_match_mnt(struct aa_dfa *dfa, unsigned int start, -+ const char *mntpnt, const char *devname, -+ const char *type, unsigned long flags, -+ void *data, bool binary, struct aa_perms *perms) -+{ -+ unsigned int state; -+ -+ AA_BUG(!dfa); -+ AA_BUG(!perms); -+ -+ state = aa_dfa_match(dfa, start, mntpnt); -+ state = aa_dfa_null_transition(dfa, state); -+ if (!state) -+ return 1; -+ -+ if (devname) -+ state = aa_dfa_match(dfa, state, devname); -+ state = aa_dfa_null_transition(dfa, state); -+ if (!state) -+ return 2; -+ -+ if (type) -+ state = aa_dfa_match(dfa, state, type); -+ state = aa_dfa_null_transition(dfa, state); -+ if (!state) -+ return 3; -+ -+ state = match_mnt_flags(dfa, state, flags); -+ if (!state) -+ return 4; -+ *perms = compute_mnt_perms(dfa, state); -+ if (perms->allow & AA_MAY_MOUNT) -+ return 0; -+ -+ /* only match data if not binary and the DFA flags data is expected */ -+ if (data && !binary && (perms->allow & AA_MNT_CONT_MATCH)) { -+ state = aa_dfa_null_transition(dfa, state); -+ if (!state) -+ return 4; -+ -+ state = aa_dfa_match(dfa, state, data); -+ if (!state) -+ return 5; -+ *perms = compute_mnt_perms(dfa, state); -+ if (perms->allow & AA_MAY_MOUNT) -+ return 0; -+ } -+ -+ /* failed at end of flags match */ -+ return 4; -+} -+ -+ -+static int path_flags(struct aa_profile *profile, const struct path *path) -+{ -+ AA_BUG(!profile); -+ AA_BUG(!path); -+ -+ return profile->path_flags | -+ (S_ISDIR(path->dentry->d_inode->i_mode) ? PATH_IS_DIR : 0); -+} -+ -+/** -+ * match_mnt_path_str - handle path matching for mount -+ * @profile: the confining profile -+ * @mntpath: for the mntpnt (NOT NULL) -+ * @buffer: buffer to be used to lookup mntpath -+ * @devnme: string for the devname/src_name (MAY BE NULL OR ERRPTR) -+ * @type: string for the dev type (MAYBE NULL) -+ * @flags: mount flags to match -+ * @data: fs mount data (MAYBE NULL) -+ * @binary: whether @data is binary -+ * @devinfo: error str if (IS_ERR(@devname)) -+ * -+ * Returns: 0 on success else error -+ */ -+static int match_mnt_path_str(struct aa_profile *profile, -+ const struct path *mntpath, char *buffer, -+ const char *devname, const char *type, -+ unsigned long flags, void *data, bool binary, -+ const char *devinfo) -+{ -+ struct aa_perms perms = { }; -+ const char *mntpnt = NULL, *info = NULL; -+ int pos, error; -+ -+ AA_BUG(!profile); -+ AA_BUG(!mntpath); -+ AA_BUG(!buffer); -+ -+ error = aa_path_name(mntpath, path_flags(profile, mntpath), buffer, -+ &mntpnt, &info, profile->disconnected); -+ if (error) -+ goto audit; -+ if (IS_ERR(devname)) { -+ error = PTR_ERR(devname); -+ devname = NULL; -+ info = devinfo; -+ goto audit; -+ } -+ -+ error = -EACCES; -+ pos = do_match_mnt(profile->policy.dfa, -+ profile->policy.start[AA_CLASS_MOUNT], -+ mntpnt, devname, type, flags, data, binary, &perms); -+ if (pos) { -+ info = mnt_info_table[pos]; -+ goto audit; -+ } -+ error = 0; -+ -+audit: -+ return audit_mount(profile, OP_MOUNT, mntpnt, devname, type, NULL, -+ flags, data, AA_MAY_MOUNT, &perms, info, error); -+} -+ -+/** -+ * match_mnt - handle path matching for mount -+ * @profile: the confining profile -+ * @mntpath: for the mntpnt (NOT NULL) -+ * @buffer: buffer to be used to lookup mntpath -+ * @devpath: path devname/src_name (MAYBE NULL) -+ * @devbuffer: buffer to be used to lookup devname/src_name -+ * @type: string for the dev type (MAYBE NULL) -+ * @flags: mount flags to match -+ * @data: fs mount data (MAYBE NULL) -+ * @binary: whether @data is binary -+ * -+ * Returns: 0 on success else error -+ */ -+static int match_mnt(struct aa_profile *profile, const struct path *path, -+ char *buffer, struct path *devpath, char *devbuffer, -+ const char *type, unsigned long flags, void *data, -+ bool binary) -+{ -+ const char *devname = NULL, *info = NULL; -+ int error = -EACCES; -+ -+ AA_BUG(!profile); -+ AA_BUG(devpath && !devbuffer); -+ -+ if (devpath) { -+ error = aa_path_name(devpath, path_flags(profile, devpath), -+ devbuffer, &devname, &info, -+ profile->disconnected); -+ if (error) -+ devname = ERR_PTR(error); -+ } -+ -+ return match_mnt_path_str(profile, path, buffer, devname, type, flags, -+ data, binary, info); -+} -+ -+int aa_remount(struct aa_label *label, const struct path *path, -+ unsigned long flags, void *data) -+{ -+ struct aa_profile *profile; -+ char *buffer = NULL; -+ bool binary; -+ int error; -+ -+ AA_BUG(!label); -+ AA_BUG(!path); -+ -+ binary = path->dentry->d_sb->s_type->fs_flags & FS_BINARY_MOUNTDATA; -+ -+ get_buffers(buffer); -+ error = fn_for_each_confined(label, profile, -+ match_mnt(profile, path, buffer, NULL, NULL, NULL, -+ flags, data, binary)); -+ put_buffers(buffer); -+ -+ return error; -+} -+ -+int aa_bind_mount(struct aa_label *label, const struct path *path, -+ const char *dev_name, unsigned long flags) -+{ -+ struct aa_profile *profile; -+ char *buffer = NULL, *old_buffer = NULL; -+ struct path old_path; -+ int error; -+ -+ AA_BUG(!label); -+ AA_BUG(!path); -+ -+ if (!dev_name || !*dev_name) -+ return -EINVAL; -+ -+ flags &= MS_REC | MS_BIND; -+ -+ error = kern_path(dev_name, LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT, &old_path); -+ if (error) -+ return error; -+ -+ get_buffers(buffer, old_buffer); -+ error = fn_for_each_confined(label, profile, -+ match_mnt(profile, path, buffer, &old_path, old_buffer, -+ NULL, flags, NULL, false)); -+ put_buffers(buffer, old_buffer); -+ path_put(&old_path); -+ -+ return error; -+} -+ -+int aa_mount_change_type(struct aa_label *label, const struct path *path, -+ unsigned long flags) -+{ -+ struct aa_profile *profile; -+ char *buffer = NULL; -+ int error; -+ -+ AA_BUG(!label); -+ AA_BUG(!path); -+ -+ /* These are the flags allowed by do_change_type() */ -+ flags &= (MS_REC | MS_SILENT | MS_SHARED | MS_PRIVATE | MS_SLAVE | -+ MS_UNBINDABLE); -+ -+ get_buffers(buffer); -+ error = fn_for_each_confined(label, profile, -+ match_mnt(profile, path, buffer, NULL, NULL, NULL, -+ flags, NULL, false)); -+ put_buffers(buffer); -+ -+ return error; -+} -+ -+int aa_move_mount(struct aa_label *label, const struct path *path, -+ const char *orig_name) -+{ -+ struct aa_profile *profile; -+ char *buffer = NULL, *old_buffer = NULL; -+ struct path old_path; -+ int error; -+ -+ AA_BUG(!label); -+ AA_BUG(!path); -+ -+ if (!orig_name || !*orig_name) -+ return -EINVAL; -+ -+ error = kern_path(orig_name, LOOKUP_FOLLOW, &old_path); -+ if (error) -+ return error; -+ -+ get_buffers(buffer, old_buffer); -+ error = fn_for_each_confined(label, profile, -+ match_mnt(profile, path, buffer, &old_path, old_buffer, -+ NULL, MS_MOVE, NULL, false)); -+ put_buffers(buffer, old_buffer); -+ path_put(&old_path); -+ -+ return error; -+} -+ -+int aa_new_mount(struct aa_label *label, const char *dev_name, -+ const struct path *path, const char *type, unsigned long flags, -+ void *data) -+{ -+ struct aa_profile *profile; -+ char *buffer = NULL, *dev_buffer = NULL; -+ bool binary = true; -+ int error; -+ int requires_dev = 0; -+ struct path tmp_path, *dev_path = NULL; -+ -+ AA_BUG(!label); -+ AA_BUG(!path); -+ -+ if (type) { -+ struct file_system_type *fstype; -+ -+ fstype = get_fs_type(type); -+ if (!fstype) -+ return -ENODEV; -+ binary = fstype->fs_flags & FS_BINARY_MOUNTDATA; -+ requires_dev = fstype->fs_flags & FS_REQUIRES_DEV; -+ put_filesystem(fstype); -+ -+ if (requires_dev) { -+ if (!dev_name || !*dev_name) -+ return -ENOENT; -+ -+ error = kern_path(dev_name, LOOKUP_FOLLOW, &tmp_path); -+ if (error) -+ return error; -+ dev_path = &tmp_path; -+ } -+ } -+ -+ get_buffers(buffer, dev_buffer); -+ if (dev_path) { -+ error = fn_for_each_confined(label, profile, -+ match_mnt(profile, path, buffer, dev_path, dev_buffer, -+ type, flags, data, binary)); -+ } else { -+ error = fn_for_each_confined(label, profile, -+ match_mnt_path_str(profile, path, buffer, dev_name, -+ type, flags, data, binary, NULL)); -+ } -+ put_buffers(buffer, dev_buffer); -+ if (dev_path) -+ path_put(dev_path); -+ -+ return error; -+} -+ -+static int profile_umount(struct aa_profile *profile, struct path *path, -+ char *buffer) -+{ -+ struct aa_perms perms = { }; -+ const char *name = NULL, *info = NULL; -+ unsigned int state; -+ int error; -+ -+ AA_BUG(!profile); -+ AA_BUG(!path); -+ -+ error = aa_path_name(path, path_flags(profile, path), buffer, &name, -+ &info, profile->disconnected); -+ if (error) -+ goto audit; -+ -+ state = aa_dfa_match(profile->policy.dfa, -+ profile->policy.start[AA_CLASS_MOUNT], -+ name); -+ perms = compute_mnt_perms(profile->policy.dfa, state); -+ if (AA_MAY_UMOUNT & ~perms.allow) -+ error = -EACCES; -+ -+audit: -+ return audit_mount(profile, OP_UMOUNT, name, NULL, NULL, NULL, 0, NULL, -+ AA_MAY_UMOUNT, &perms, info, error); -+} -+ -+int aa_umount(struct aa_label *label, struct vfsmount *mnt, int flags) -+{ -+ struct aa_profile *profile; -+ char *buffer = NULL; -+ int error; -+ struct path path = { .mnt = mnt, .dentry = mnt->mnt_root }; -+ -+ AA_BUG(!label); -+ AA_BUG(!mnt); -+ -+ get_buffers(buffer); -+ error = fn_for_each_confined(label, profile, -+ profile_umount(profile, &path, buffer)); -+ put_buffers(buffer); -+ -+ return error; -+} -+ -+/* helper fn for transition on pivotroot -+ * -+ * Returns: label for transition or ERR_PTR. Does not return NULL -+ */ -+static struct aa_label *build_pivotroot(struct aa_profile *profile, -+ const struct path *new_path, -+ char *new_buffer, -+ const struct path *old_path, -+ char *old_buffer) -+{ -+ const char *old_name, *new_name = NULL, *info = NULL; -+ const char *trans_name = NULL; -+ struct aa_perms perms = { }; -+ unsigned int state; -+ int error; -+ -+ AA_BUG(!profile); -+ AA_BUG(!new_path); -+ AA_BUG(!old_path); -+ -+ if (profile_unconfined(profile)) -+ return aa_get_newest_label(&profile->label); -+ -+ error = aa_path_name(old_path, path_flags(profile, old_path), -+ old_buffer, &old_name, &info, -+ profile->disconnected); -+ if (error) -+ goto audit; -+ error = aa_path_name(new_path, path_flags(profile, new_path), -+ new_buffer, &new_name, &info, -+ profile->disconnected); -+ if (error) -+ goto audit; -+ -+ error = -EACCES; -+ state = aa_dfa_match(profile->policy.dfa, -+ profile->policy.start[AA_CLASS_MOUNT], -+ new_name); -+ state = aa_dfa_null_transition(profile->policy.dfa, state); -+ state = aa_dfa_match(profile->policy.dfa, state, old_name); -+ perms = compute_mnt_perms(profile->policy.dfa, state); -+ -+ if (AA_MAY_PIVOTROOT & perms.allow) -+ error = 0; -+ -+audit: -+ error = audit_mount(profile, OP_PIVOTROOT, new_name, old_name, -+ NULL, trans_name, 0, NULL, AA_MAY_PIVOTROOT, -+ &perms, info, error); -+ if (error) -+ return ERR_PTR(error); -+ -+ return aa_get_newest_label(&profile->label); -+} -+ -+int aa_pivotroot(struct aa_label *label, const struct path *old_path, -+ const struct path *new_path) -+{ -+ struct aa_profile *profile; -+ struct aa_label *target = NULL; -+ char *old_buffer = NULL, *new_buffer = NULL, *info = NULL; -+ int error; -+ -+ AA_BUG(!label); -+ AA_BUG(!old_path); -+ AA_BUG(!new_path); -+ -+ get_buffers(old_buffer, new_buffer); -+ target = fn_label_build(label, profile, GFP_ATOMIC, -+ build_pivotroot(profile, new_path, new_buffer, -+ old_path, old_buffer)); -+ if (!target) { -+ info = "label build failed"; -+ error = -ENOMEM; -+ goto fail; -+ } else if (!IS_ERR(target)) { -+ error = aa_replace_current_label(target); -+ if (error) { -+ /* TODO: audit target */ -+ aa_put_label(target); -+ goto out; -+ } -+ } else -+ /* already audited error */ -+ error = PTR_ERR(target); -+out: -+ put_buffers(old_buffer, new_buffer); -+ -+ return error; -+ -+fail: -+ /* TODO: add back in auditing of new_name and old_name */ -+ error = fn_for_each(label, profile, -+ audit_mount(profile, OP_PIVOTROOT, NULL /*new_name */, -+ NULL /* old_name */, -+ NULL, NULL, -+ 0, NULL, AA_MAY_PIVOTROOT, &nullperms, info, -+ error)); -+ goto out; -+} --- -2.14.1 - diff --git a/patches.apparmor/0006-security-apparmor-Use-POSIX-compatible-printf-s.patch b/patches.apparmor/0006-security-apparmor-Use-POSIX-compatible-printf-s.patch deleted file mode 100644 index 9f16fa6..0000000 --- a/patches.apparmor/0006-security-apparmor-Use-POSIX-compatible-printf-s.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 80e3c5c516a4d9b6653456399fa13a46a66fd3c9 Mon Sep 17 00:00:00 2001 -From: Thomas Schneider -Date: Fri, 14 Oct 2016 21:29:49 +0200 -Subject: [PATCH 06/65] security/apparmor: Use POSIX-compatible "printf '%s'" -Git-commit: 651e54953b5d4ad103f0efa54fc6b380807fca3a -Patch-mainline: v4.13-rc1 -References: FATE#323500 - -When using a strictly POSIX-compliant shell, "-n #define ..." gets -written into the file. Use "printf '%s'" to avoid this. - -Signed-off-by: Thomas Schneider -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/Makefile | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/security/apparmor/Makefile b/security/apparmor/Makefile -index ad369a7aac24..2ded2f1be98b 100644 ---- a/security/apparmor/Makefile -+++ b/security/apparmor/Makefile -@@ -20,7 +20,7 @@ cmd_make-caps = echo "static const char *const capability_names[] = {" > $@ ;\ - sed $< >>$@ -r -n -e '/CAP_FS_MASK/d' \ - -e 's/^\#define[ \t]+CAP_([A-Z0-9_]+)[ \t]+([0-9]+)/[\2] = "\L\1",/p';\ - echo "};" >> $@ ;\ -- echo -n '\#define AA_FS_CAPS_MASK "' >> $@ ;\ -+ printf '%s' '\#define AA_FS_CAPS_MASK "' >> $@ ;\ - sed $< -r -n -e '/CAP_FS_MASK/d' \ - -e 's/^\#define[ \t]+CAP_([A-Z0-9_]+)[ \t]+([0-9]+)/\L\1/p' | \ - tr '\n' ' ' | sed -e 's/ $$/"\n/' >> $@ -@@ -56,7 +56,7 @@ cmd_make-rlim = echo "static const char *const rlim_names[RLIM_NLIMITS] = {" \ - echo "static const int rlim_map[RLIM_NLIMITS] = {" >> $@ ;\ - sed -r -n "s/^\# ?define[ \t]+(RLIMIT_[A-Z0-9_]+).*/\1,/p" $< >> $@ ;\ - echo "};" >> $@ ; \ -- echo -n '\#define AA_FS_RLIMIT_MASK "' >> $@ ;\ -+ printf '%s' '\#define AA_FS_RLIMIT_MASK "' >> $@ ;\ - sed -r -n 's/^\# ?define[ \t]+RLIMIT_([A-Z0-9_]+).*/\L\1/p' $< | \ - tr '\n' ' ' | sed -e 's/ $$/"\n/' >> $@ - --- -2.12.3 - diff --git a/patches.apparmor/0007-apparmor-cleanup-conditional-check-for-label-in-labe.patch b/patches.apparmor/0007-apparmor-cleanup-conditional-check-for-label-in-labe.patch deleted file mode 100644 index da05031..0000000 --- a/patches.apparmor/0007-apparmor-cleanup-conditional-check-for-label-in-labe.patch +++ /dev/null @@ -1,73 +0,0 @@ -From 05842051f418debd2a3ed633a93da96bd4c39ff7 Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Sun, 6 Aug 2017 05:36:40 -0700 -Subject: [PATCH 07/17] apparmor: cleanup conditional check for label in label_print -References: FATE#323500 -Patch-mainline: v4.14-rc2 -Git-commit: f872af75d325cc449b6621a0d30a4f2ba77dd092 - -Signed-off-by: John Johansen -Acked-by: Seth Arnold -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/label.c | 22 ++++++++-------------- - 1 file changed, 8 insertions(+), 14 deletions(-) - -diff --git a/security/apparmor/label.c b/security/apparmor/label.c -index e324f4df3e34..38be7a89cc31 100644 ---- a/security/apparmor/label.c -+++ b/security/apparmor/label.c -@@ -1450,9 +1450,11 @@ bool aa_update_label_name(struct aa_ns *ns, struct aa_label *label, gfp_t gfp) - * cached label name is present and visible - * @label->hname only exists if label is namespace hierachical - */ --static inline bool use_label_hname(struct aa_ns *ns, struct aa_label *label) -+static inline bool use_label_hname(struct aa_ns *ns, struct aa_label *label, -+ int flags) - { -- if (label->hname && labels_ns(label) == ns) -+ if (label->hname && (!ns || labels_ns(label) == ns) && -+ !(flags & ~FLAG_SHOW_MODE)) - return true; - - return false; -@@ -1710,10 +1712,8 @@ void aa_label_xaudit(struct audit_buffer *ab, struct aa_ns *ns, - AA_BUG(!ab); - AA_BUG(!label); - -- if (!ns) -- ns = labels_ns(label); -- -- if (!use_label_hname(ns, label) || display_mode(ns, label, flags)) { -+ if (!use_label_hname(ns, label, flags) || -+ display_mode(ns, label, flags)) { - len = aa_label_asxprint(&name, ns, label, flags, gfp); - if (len == -1) { - AA_DEBUG("label print error"); -@@ -1738,10 +1738,7 @@ void aa_label_seq_xprint(struct seq_file *f, struct aa_ns *ns, - AA_BUG(!f); - AA_BUG(!label); - -- if (!ns) -- ns = labels_ns(label); -- -- if (!use_label_hname(ns, label)) { -+ if (!use_label_hname(ns, label, flags)) { - char *str; - int len; - -@@ -1764,10 +1761,7 @@ void aa_label_xprintk(struct aa_ns *ns, struct aa_label *label, int flags, - { - AA_BUG(!label); - -- if (!ns) -- ns = labels_ns(label); -- -- if (!use_label_hname(ns, label)) { -+ if (!use_label_hname(ns, label, flags)) { - char *str; - int len; - --- -2.14.1 - diff --git a/patches.apparmor/0007-apparmor-move-file-context-into-file.h.patch b/patches.apparmor/0007-apparmor-move-file-context-into-file.h.patch deleted file mode 100644 index bb44154..0000000 --- a/patches.apparmor/0007-apparmor-move-file-context-into-file.h.patch +++ /dev/null @@ -1,104 +0,0 @@ -From ebb6be0172b361652679954159484f966675db5f Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Sun, 21 May 2017 17:15:28 -0700 -Subject: [PATCH 07/65] apparmor: move file context into file.h -Git-commit: af7caa8f8dd1b45e38a3653a69ed4d708286bc83 -Patch-mainline: v4.13-rc1 -References: FATE#323500 - -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/include/context.h | 32 -------------------------------- - security/apparmor/include/file.h | 32 ++++++++++++++++++++++++++++++++ - 2 files changed, 32 insertions(+), 32 deletions(-) - -diff --git a/security/apparmor/include/context.h b/security/apparmor/include/context.h -index 5b18fedab4c8..420cfd041218 100644 ---- a/security/apparmor/include/context.h -+++ b/security/apparmor/include/context.h -@@ -25,38 +25,6 @@ - #define cred_ctx(X) ((X)->security) - #define current_ctx() cred_ctx(current_cred()) - --/* struct aa_file_ctx - the AppArmor context the file was opened in -- * @perms: the permission the file was opened with -- * -- * The file_ctx could currently be directly stored in file->f_security -- * as the profile reference is now stored in the f_cred. However the -- * ctx struct will expand in the future so we keep the struct. -- */ --struct aa_file_ctx { -- u16 allow; --}; -- --/** -- * aa_alloc_file_context - allocate file_ctx -- * @gfp: gfp flags for allocation -- * -- * Returns: file_ctx or NULL on failure -- */ --static inline struct aa_file_ctx *aa_alloc_file_context(gfp_t gfp) --{ -- return kzalloc(sizeof(struct aa_file_ctx), gfp); --} -- --/** -- * aa_free_file_context - free a file_ctx -- * @ctx: file_ctx to free (MAYBE_NULL) -- */ --static inline void aa_free_file_context(struct aa_file_ctx *ctx) --{ -- if (ctx) -- kzfree(ctx); --} -- - /** - * struct aa_task_ctx - primary label for confined tasks - * @profile: the current profile (NOT NULL) -diff --git a/security/apparmor/include/file.h b/security/apparmor/include/file.h -index 38f821bf49b6..eba39cb25f02 100644 ---- a/security/apparmor/include/file.h -+++ b/security/apparmor/include/file.h -@@ -47,6 +47,38 @@ struct path; - AA_MAY_CHMOD | AA_MAY_CHOWN | AA_MAY_LOCK | \ - AA_EXEC_MMAP | AA_MAY_LINK) - -+/* struct aa_file_ctx - the AppArmor context the file was opened in -+ * @perms: the permission the file was opened with -+ * -+ * The file_ctx could currently be directly stored in file->f_security -+ * as the profile reference is now stored in the f_cred. However the -+ * ctx struct will expand in the future so we keep the struct. -+ */ -+struct aa_file_ctx { -+ u16 allow; -+}; -+ -+/** -+ * aa_alloc_file_context - allocate file_ctx -+ * @gfp: gfp flags for allocation -+ * -+ * Returns: file_ctx or NULL on failure -+ */ -+static inline struct aa_file_ctx *aa_alloc_file_context(gfp_t gfp) -+{ -+ return kzalloc(sizeof(struct aa_file_ctx), gfp); -+} -+ -+/** -+ * aa_free_file_context - free a file_ctx -+ * @ctx: file_ctx to free (MAYBE_NULL) -+ */ -+static inline void aa_free_file_context(struct aa_file_ctx *ctx) -+{ -+ if (ctx) -+ kzfree(ctx); -+} -+ - /* - * The xindex is broken into 3 parts - * - index - an index into either the exec name table or the variable table --- -2.12.3 - diff --git a/patches.apparmor/0008-apparmor-add-support-for-absolute-root-view-based-la.patch b/patches.apparmor/0008-apparmor-add-support-for-absolute-root-view-based-la.patch deleted file mode 100644 index 1f24326..0000000 --- a/patches.apparmor/0008-apparmor-add-support-for-absolute-root-view-based-la.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 0d09c5b5363e1e4a506352dd6eec63d48858d9af Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Sun, 6 Aug 2017 05:39:08 -0700 -Subject: [PATCH 08/17] apparmor: add support for absolute root view based labels -References: FATE#323500 -Patch-mainline: v4.14-rc2 -Git-commit: 26b7899510ae243e392960704ebdba52d05fbb13 - -With apparmor policy virtualization based on policy namespace View's -we don't generally want/need absolute root based views, however there -are cases like debugging and some secid based conversions where -using a root based view is important. - -Signed-off-by: John Johansen -Acked-by: Seth Arnold -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/include/label.h | 1 + - security/apparmor/label.c | 10 +++++++++- - 2 files changed, 10 insertions(+), 1 deletion(-) - -diff --git a/security/apparmor/include/label.h b/security/apparmor/include/label.h -index 9a283b722755..af22dcbbcb8a 100644 ---- a/security/apparmor/include/label.h -+++ b/security/apparmor/include/label.h -@@ -310,6 +310,7 @@ bool aa_update_label_name(struct aa_ns *ns, struct aa_label *label, gfp_t gfp); - #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, -diff --git a/security/apparmor/label.c b/security/apparmor/label.c -index 38be7a89cc31..52b4ef14840d 100644 ---- a/security/apparmor/label.c -+++ b/security/apparmor/label.c -@@ -1607,8 +1607,13 @@ int aa_label_snxprint(char *str, size_t size, struct aa_ns *ns, - AA_BUG(!str && size != 0); - AA_BUG(!label); - -- if (!ns) -+ if (flags & FLAG_ABS_ROOT) { -+ ns = root_ns; -+ len = snprintf(str, size, "="); -+ update_for_len(total, len, size, str); -+ } else if (!ns) { - ns = labels_ns(label); -+ } - - label_for_each(i, label, profile) { - if (aa_ns_visible(ns, profile->ns, flags & FLAG_VIEW_SUBNS)) { -@@ -1868,6 +1873,9 @@ struct aa_label *aa_label_parse(struct aa_label *base, const char *str, - if (*str == '&') - str++; - } -+ if (*str == '=') -+ base = &root_ns->unconfined->label; -+ - error = vec_setup(profile, vec, len, gfp); - if (error) - return ERR_PTR(error); --- -2.14.1 - diff --git a/patches.apparmor/0008-apparmor-make-internal-lib-fn-skipn_spaces-available.patch b/patches.apparmor/0008-apparmor-make-internal-lib-fn-skipn_spaces-available.patch deleted file mode 100644 index d2fc2ae..0000000 --- a/patches.apparmor/0008-apparmor-make-internal-lib-fn-skipn_spaces-available.patch +++ /dev/null @@ -1,44 +0,0 @@ -From d65673a60608bb3222416ae16d2533ee5679d9a4 Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Mon, 22 May 2017 02:47:22 -0700 -Subject: [PATCH 08/65] apparmor: make internal lib fn skipn_spaces available - to the rest of apparmor -Git-commit: b91deb9db12851c18ccb55719f1cd55c2400aca1 -Patch-mainline: v4.13-rc1 -References: FATE#323500 - -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/include/lib.h | 1 + - security/apparmor/lib.c | 2 +- - 2 files changed, 2 insertions(+), 1 deletion(-) - -diff --git a/security/apparmor/include/lib.h b/security/apparmor/include/lib.h -index 550a700563b4..89524aade657 100644 ---- a/security/apparmor/include/lib.h -+++ b/security/apparmor/include/lib.h -@@ -60,6 +60,7 @@ - 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); -diff --git a/security/apparmor/lib.c b/security/apparmor/lib.c -index 7cd788a9445b..864b2fa45852 100644 ---- a/security/apparmor/lib.c -+++ b/security/apparmor/lib.c -@@ -69,7 +69,7 @@ char *aa_split_fqname(char *fqname, char **ns_name) - * if all whitespace will return NULL - */ - --static const char *skipn_spaces(const char *str, size_t n) -+const char *skipn_spaces(const char *str, size_t n) - { - for (; n && isspace(*str); --n) - ++str; --- -2.12.3 - diff --git a/patches.apparmor/0009-apparmor-allow-profiles-to-provide-info-to-disconnec.patch b/patches.apparmor/0009-apparmor-allow-profiles-to-provide-info-to-disconnec.patch deleted file mode 100644 index de666ec..0000000 --- a/patches.apparmor/0009-apparmor-allow-profiles-to-provide-info-to-disconnec.patch +++ /dev/null @@ -1,224 +0,0 @@ -From 2b1d572f01ffd76a23967d5ffead7036c82dc8da Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Mon, 22 May 2017 03:06:52 -0700 -Subject: [PATCH 09/65] apparmor: allow profiles to provide info to - disconnected paths -Git-commit: 72c8a768641dc6ee8d1d9dcebd51bbec2817459b -Patch-mainline: v4.13-rc1 -References: FATE#323500 - -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/domain.c | 2 +- - security/apparmor/file.c | 7 ++++--- - security/apparmor/include/path.h | 3 ++- - security/apparmor/include/policy.h | 2 ++ - security/apparmor/path.c | 34 ++++++++++++++++++++++------------ - security/apparmor/policy_unpack.c | 3 +++ - 6 files changed, 34 insertions(+), 17 deletions(-) - -diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c -index 001e133a3c8c..c92fd0e7b33c 100644 ---- a/security/apparmor/domain.c -+++ b/security/apparmor/domain.c -@@ -366,7 +366,7 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm) - - /* buffer freed below, name is pointer into buffer */ - error = aa_path_name(&bprm->file->f_path, profile->path_flags, &buffer, -- &name, &info); -+ &name, &info, profile->disconnected); - if (error) { - if (unconfined(profile) || - (profile->flags & PFLAG_IX_ON_NAME_ERROR)) -diff --git a/security/apparmor/file.c b/security/apparmor/file.c -index 750564c3ab71..83d43ac72134 100644 ---- a/security/apparmor/file.c -+++ b/security/apparmor/file.c -@@ -285,7 +285,8 @@ int aa_path_perm(const char *op, struct aa_profile *profile, - int error; - - flags |= profile->path_flags | (S_ISDIR(cond->mode) ? PATH_IS_DIR : 0); -- error = aa_path_name(path, flags, &buffer, &name, &info); -+ error = aa_path_name(path, flags, &buffer, &name, &info, -+ profile->disconnected); - if (error) { - if (error == -ENOENT && is_deleted(path->dentry)) { - /* Access to open files that are deleted are -@@ -366,13 +367,13 @@ int aa_path_link(struct aa_profile *profile, struct dentry *old_dentry, - - /* buffer freed below, lname is pointer in buffer */ - error = aa_path_name(&link, profile->path_flags, &buffer, &lname, -- &info); -+ &info, profile->disconnected); - if (error) - goto audit; - - /* buffer2 freed below, tname is pointer in buffer2 */ - error = aa_path_name(&target, profile->path_flags, &buffer2, &tname, -- &info); -+ &info, profile->disconnected); - if (error) - goto audit; - -diff --git a/security/apparmor/include/path.h b/security/apparmor/include/path.h -index 0444fdde3918..78e4909dcc6a 100644 ---- a/security/apparmor/include/path.h -+++ b/security/apparmor/include/path.h -@@ -27,7 +27,8 @@ enum path_flags { - }; - - int aa_path_name(const struct path *path, int flags, char **buffer, -- const char **name, const char **info); -+ const char **name, const char **info, -+ const char *disconnected); - - #define MAX_PATH_BUFFERS 2 - -diff --git a/security/apparmor/include/policy.h b/security/apparmor/include/policy.h -index 67bc96afe541..dffa01c018c8 100644 ---- a/security/apparmor/include/policy.h -+++ b/security/apparmor/include/policy.h -@@ -128,6 +128,7 @@ struct aa_data { - * @mode: the enforcement mode of the profile - * @flags: flags controlling profile behavior - * @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 -@@ -169,6 +170,7 @@ struct aa_profile { - long mode; - long flags; - u32 path_flags; -+ const char *disconnected; - int size; - - struct aa_policydb policy; -diff --git a/security/apparmor/path.c b/security/apparmor/path.c -index a8fc7d08c144..9490f8e89630 100644 ---- a/security/apparmor/path.c -+++ b/security/apparmor/path.c -@@ -50,7 +50,7 @@ static int prepend(char **buffer, int buflen, const char *str, int namelen) - * namespace root. - */ - static int disconnect(const struct path *path, char *buf, char **name, -- int flags) -+ int flags, const char *disconnected) - { - int error = 0; - -@@ -63,9 +63,14 @@ static int disconnect(const struct path *path, char *buf, char **name, - error = -EACCES; - if (**name == '/') - *name = *name + 1; -- } else if (**name != '/') -- /* CONNECT_PATH with missing root */ -- error = prepend(name, *name - buf, "/", 1); -+ } else { -+ if (**name != '/') -+ /* CONNECT_PATH with missing root */ -+ error = prepend(name, *name - buf, "/", 1); -+ if (!error && disconnected) -+ error = prepend(name, *name - buf, disconnected, -+ strlen(disconnected)); -+ } - - return error; - } -@@ -77,6 +82,7 @@ static int disconnect(const struct path *path, char *buf, char **name, - * @buflen: length of @buf - * @name: Returns - pointer for start of path name with in @buf (NOT NULL) - * @flags: flags controlling path lookup -+ * @disconnected: string to prefix to disconnected paths - * - * Handle path name lookup. - * -@@ -85,7 +91,7 @@ static int disconnect(const struct path *path, char *buf, char **name, - * to a position in @buf - */ - static int d_namespace_path(const struct path *path, char *buf, int buflen, -- char **name, int flags) -+ char **name, int flags, const char *disconnected) - { - char *res; - int error = 0; -@@ -106,8 +112,8 @@ static int d_namespace_path(const struct path *path, char *buf, int buflen, - */ - return prepend(name, *name - buf, "/proc", 5); - } else -- return disconnect(path, buf, name, flags); -- return 0; -+ return disconnect(path, buf, name, flags, -+ disconnected); - } - - /* resolve paths relative to chroot?*/ -@@ -153,7 +159,7 @@ static int d_namespace_path(const struct path *path, char *buf, int buflen, - } - - if (!connected) -- error = disconnect(path, buf, name, flags); -+ error = disconnect(path, buf, name, flags, disconnected); - - out: - return error; -@@ -170,10 +176,12 @@ static int d_namespace_path(const struct path *path, char *buf, int buflen, - * Returns: %0 else error on failure - */ - static int get_name_to_buffer(const struct path *path, int flags, char *buffer, -- int size, char **name, const char **info) -+ int size, char **name, const char **info, -+ const char *disconnected) - { - int adjust = (flags & PATH_IS_DIR) ? 1 : 0; -- int error = d_namespace_path(path, buffer, size - adjust, name, flags); -+ int error = d_namespace_path(path, buffer, size - adjust, name, flags, -+ disconnected); - - if (!error && (flags & PATH_IS_DIR) && (*name)[1] != '\0') - /* -@@ -203,6 +211,7 @@ static int get_name_to_buffer(const struct path *path, int flags, char *buffer, - * @buffer: buffer that aa_get_name() allocated (NOT NULL) - * @name: Returns - the generated path name if !error (NOT NULL) - * @info: Returns - information on why the path lookup failed (MAYBE NULL) -+ * @disconnected: string to prepend to disconnected paths - * - * @name is a pointer to the beginning of the pathname (which usually differs - * from the beginning of the buffer), or NULL. If there is an error @name -@@ -216,7 +225,7 @@ static int get_name_to_buffer(const struct path *path, int flags, char *buffer, - * Returns: %0 else error code if could retrieve name - */ - int aa_path_name(const struct path *path, int flags, char **buffer, -- const char **name, const char **info) -+ const char **name, const char **info, const char *disconnected) - { - char *buf, *str = NULL; - int size = 256; -@@ -230,7 +239,8 @@ int aa_path_name(const struct path *path, int flags, char **buffer, - if (!buf) - return -ENOMEM; - -- error = get_name_to_buffer(path, flags, buf, size, &str, info); -+ error = get_name_to_buffer(path, flags, buf, size, &str, info, -+ disconnected); - if (error != -ENAMETOOLONG) - break; - -diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c -index 981d570eebba..182bbfeb4b2c 100644 ---- a/security/apparmor/policy_unpack.c -+++ b/security/apparmor/policy_unpack.c -@@ -569,6 +569,9 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name) - profile->xmatch_len = tmp; - } - -+ /* disconnected attachment string is optional */ -+ (void) unpack_str(e, &profile->disconnected, "disconnected"); -+ - /* per profile debug flags (complain, audit) */ - if (!unpack_nameX(e, AA_STRUCT, "flags")) - goto fail; --- -2.12.3 - diff --git a/patches.apparmor/0009-apparmor-make-policy_unpack-able-to-audit-different-.patch b/patches.apparmor/0009-apparmor-make-policy_unpack-able-to-audit-different-.patch deleted file mode 100644 index c2ec8c0..0000000 --- a/patches.apparmor/0009-apparmor-make-policy_unpack-able-to-audit-different-.patch +++ /dev/null @@ -1,221 +0,0 @@ -From 483939f63449d291a2d62661d405da17b52e5e08 Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Tue, 18 Jul 2017 23:37:18 -0700 -Subject: [PATCH 09/17] apparmor: make policy_unpack able to audit different info messages -References: FATE#323500 -Patch-mainline: v4.14-rc2 -Git-commit: 2410aa96d6b4930ed25fd02c3d173f14b962e0f4 - -Switch unpack auditing to using the generic name field in the audit -struct and make it so we can start adding new info messages about -why an unpack failed. - -Signed-off-by: John Johansen -Acked-by: Seth Arnold -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/include/audit.h | 4 +-- - security/apparmor/policy_unpack.c | 52 ++++++++++++++++++++++++++++----------- - 2 files changed, 40 insertions(+), 16 deletions(-) - -diff --git a/security/apparmor/include/audit.h b/security/apparmor/include/audit.h -index c3fe1c5ef3bc..620e81169659 100644 ---- a/security/apparmor/include/audit.h -+++ b/security/apparmor/include/audit.h -@@ -127,9 +127,9 @@ struct apparmor_audit_data { - } fs; - }; - struct { -- const char *name; -- long pos; -+ struct aa_profile *profile; - const char *ns; -+ long pos; - } iface; - int signal; - struct { -diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c -index bda0dce3b582..4ede87c30f8b 100644 ---- a/security/apparmor/policy_unpack.c -+++ b/security/apparmor/policy_unpack.c -@@ -85,9 +85,9 @@ static void audit_cb(struct audit_buffer *ab, void *va) - audit_log_format(ab, " ns="); - audit_log_untrustedstring(ab, aad(sa)->iface.ns); - } -- if (aad(sa)->iface.name) { -+ if (aad(sa)->name) { - audit_log_format(ab, " name="); -- audit_log_untrustedstring(ab, aad(sa)->iface.name); -+ audit_log_untrustedstring(ab, aad(sa)->name); - } - if (aad(sa)->iface.pos) - audit_log_format(ab, " offset=%ld", aad(sa)->iface.pos); -@@ -114,9 +114,9 @@ static int audit_iface(struct aa_profile *new, const char *ns_name, - aad(&sa)->iface.pos = e->pos - e->start; - aad(&sa)->iface.ns = ns_name; - if (new) -- aad(&sa)->iface.name = new->base.hname; -+ aad(&sa)->name = new->base.hname; - else -- aad(&sa)->iface.name = name; -+ aad(&sa)->name = name; - aad(&sa)->info = info; - aad(&sa)->error = error; - -@@ -583,6 +583,7 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name) - { - struct aa_profile *profile = NULL; - const char *tmpname, *tmpns = NULL, *name = NULL; -+ const char *info = "failed to unpack profile"; - size_t ns_len; - struct rhashtable_params params = { 0 }; - char *key = NULL; -@@ -604,8 +605,10 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name) - tmpname = aa_splitn_fqname(name, strlen(name), &tmpns, &ns_len); - if (tmpns) { - *ns_name = kstrndup(tmpns, ns_len, GFP_KERNEL); -- if (!*ns_name) -+ if (!*ns_name) { -+ info = "out of memory"; - goto fail; -+ } - name = tmpname; - } - -@@ -624,12 +627,15 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name) - if (IS_ERR(profile->xmatch)) { - error = PTR_ERR(profile->xmatch); - profile->xmatch = NULL; -+ info = "bad xmatch"; - goto fail; - } - /* xmatch_len is not optional if xmatch is set */ - if (profile->xmatch) { -- if (!unpack_u32(e, &tmp, NULL)) -+ if (!unpack_u32(e, &tmp, NULL)) { -+ info = "missing xmatch len"; - goto fail; -+ } - profile->xmatch_len = tmp; - } - -@@ -637,8 +643,11 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name) - (void) unpack_str(e, &profile->disconnected, "disconnected"); - - /* per profile debug flags (complain, audit) */ -- if (!unpack_nameX(e, AA_STRUCT, "flags")) -+ if (!unpack_nameX(e, AA_STRUCT, "flags")) { -+ info = "profile missing flags"; - goto fail; -+ } -+ info = "failed to unpack profile flags"; - if (!unpack_u32(e, &tmp, NULL)) - goto fail; - if (tmp & PACKED_FLAG_HAT) -@@ -667,6 +676,7 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name) - /* set a default value if path_flags field is not present */ - profile->path_flags = PATH_MEDIATE_DELETED; - -+ info = "failed to unpack profile capabilities"; - if (!unpack_u32(e, &(profile->caps.allow.cap[0]), NULL)) - goto fail; - if (!unpack_u32(e, &(profile->caps.audit.cap[0]), NULL)) -@@ -676,6 +686,7 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name) - if (!unpack_u32(e, &tmpcap.cap[0], NULL)) - goto fail; - -+ info = "failed to unpack upper profile capabilities"; - if (unpack_nameX(e, AA_STRUCT, "caps64")) { - /* optional upper half of 64 bit caps */ - if (!unpack_u32(e, &(profile->caps.allow.cap[1]), NULL)) -@@ -690,6 +701,7 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name) - goto fail; - } - -+ info = "failed to unpack extended profile capabilities"; - if (unpack_nameX(e, AA_STRUCT, "capsx")) { - /* optional extended caps mediation mask */ - if (!unpack_u32(e, &(profile->caps.extended.cap[0]), NULL)) -@@ -700,11 +712,14 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name) - goto fail; - } - -- if (!unpack_rlimits(e, profile)) -+ if (!unpack_rlimits(e, profile)) { -+ info = "failed to unpack profile rlimits"; - goto fail; -+ } - - if (unpack_nameX(e, AA_STRUCT, "policydb")) { - /* generic policy dfa - optional and may be NULL */ -+ info = "failed to unpack policydb"; - profile->policy.dfa = unpack_dfa(e); - if (IS_ERR(profile->policy.dfa)) { - error = PTR_ERR(profile->policy.dfa); -@@ -734,6 +749,7 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name) - if (IS_ERR(profile->file.dfa)) { - error = PTR_ERR(profile->file.dfa); - profile->file.dfa = NULL; -+ info = "failed to unpack profile file rules"; - goto fail; - } else if (profile->file.dfa) { - if (!unpack_u32(e, &profile->file.start, "dfa_start")) -@@ -746,10 +762,13 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name) - } else - profile->file.dfa = aa_get_dfa(nulldfa); - -- if (!unpack_trans_table(e, profile)) -+ if (!unpack_trans_table(e, profile)) { -+ info = "failed to unpack profile transition table"; - goto fail; -+ } - - if (unpack_nameX(e, AA_STRUCT, "data")) { -+ info = "out of memory"; - profile->data = kzalloc(sizeof(*profile->data), GFP_KERNEL); - if (!profile->data) - goto fail; -@@ -761,8 +780,10 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name) - params.hashfn = strhash; - params.obj_cmpfn = datacmp; - -- if (rhashtable_init(profile->data, ¶ms)) -+ if (rhashtable_init(profile->data, ¶ms)) { -+ info = "failed to init key, value hash table"; - goto fail; -+ } - - while (unpack_strdup(e, &key, NULL)) { - data = kzalloc(sizeof(*data), GFP_KERNEL); -@@ -784,12 +805,16 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name) - profile->data->p); - } - -- if (!unpack_nameX(e, AA_STRUCTEND, NULL)) -+ if (!unpack_nameX(e, AA_STRUCTEND, NULL)) { -+ info = "failed to unpack end of key, value data table"; - goto fail; -+ } - } - -- if (!unpack_nameX(e, AA_STRUCTEND, NULL)) -+ if (!unpack_nameX(e, AA_STRUCTEND, NULL)) { -+ info = "failed to unpack end of profile"; - goto fail; -+ } - - return profile; - -@@ -798,8 +823,7 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name) - name = NULL; - else if (!name) - name = "unknown"; -- audit_iface(profile, NULL, name, "failed to unpack profile", e, -- error); -+ audit_iface(profile, NULL, name, info, e, error); - aa_free_profile(profile); - - return ERR_PTR(error); --- -2.14.1 - diff --git a/patches.apparmor/0010-apparmor-Move-path-lookup-to-using-preallocated-buff.patch b/patches.apparmor/0010-apparmor-Move-path-lookup-to-using-preallocated-buff.patch deleted file mode 100644 index 075ecf0..0000000 --- a/patches.apparmor/0010-apparmor-Move-path-lookup-to-using-preallocated-buff.patch +++ /dev/null @@ -1,316 +0,0 @@ -From 7ead53fe15ab016eeff34fac68c7c90f4bd5c6c1 Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Tue, 23 May 2017 03:25:14 -0700 -Subject: [PATCH 10/65] apparmor: Move path lookup to using preallocated - buffers -Git-commit: 4227c333f65cddc6c2f048e5b67cfe796b9df9a6 -Patch-mainline: v4.13-rc1 -References: FATE#323500 - -Dynamically allocating buffers is problematic and is an extra layer -that is a potntial point of failure and can slow down mediation. -Change path lookup to use the preallocated per cpu buffers. - -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/domain.c | 8 +-- - security/apparmor/file.c | 13 ++--- - security/apparmor/include/path.h | 4 +- - security/apparmor/path.c | 114 ++++++++++++++------------------------- - 4 files changed, 53 insertions(+), 86 deletions(-) - -diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c -index c92fd0e7b33c..ab8f23cdccff 100644 ---- a/security/apparmor/domain.c -+++ b/security/apparmor/domain.c -@@ -357,6 +357,9 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm) - AA_BUG(!ctx); - - profile = aa_get_newest_profile(ctx->profile); -+ -+ /* buffer freed below, name is pointer into buffer */ -+ get_buffers(buffer); - /* - * get the namespace from the replacement profile as replacement - * can change the namespace -@@ -364,8 +367,7 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm) - ns = profile->ns; - state = profile->file.start; - -- /* buffer freed below, name is pointer into buffer */ -- error = aa_path_name(&bprm->file->f_path, profile->path_flags, &buffer, -+ error = aa_path_name(&bprm->file->f_path, profile->path_flags, buffer, - &name, &info, profile->disconnected); - if (error) { - if (unconfined(profile) || -@@ -515,7 +517,7 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm) - cleanup: - aa_put_profile(new_profile); - aa_put_profile(profile); -- kfree(buffer); -+ put_buffers(buffer); - - return error; - } -diff --git a/security/apparmor/file.c b/security/apparmor/file.c -index 83d43ac72134..22be62f0fc73 100644 ---- a/security/apparmor/file.c -+++ b/security/apparmor/file.c -@@ -285,7 +285,8 @@ int aa_path_perm(const char *op, struct aa_profile *profile, - int error; - - flags |= profile->path_flags | (S_ISDIR(cond->mode) ? PATH_IS_DIR : 0); -- error = aa_path_name(path, flags, &buffer, &name, &info, -+ get_buffers(buffer); -+ error = aa_path_name(path, flags, buffer, &name, &info, - profile->disconnected); - if (error) { - if (error == -ENOENT && is_deleted(path->dentry)) { -@@ -304,7 +305,7 @@ int aa_path_perm(const char *op, struct aa_profile *profile, - } - error = aa_audit_file(profile, &perms, op, request, name, NULL, - cond->uid, info, error); -- kfree(buffer); -+ put_buffers(buffer); - - return error; - } -@@ -363,16 +364,17 @@ int aa_path_link(struct aa_profile *profile, struct dentry *old_dentry, - unsigned int state; - int error; - -+ get_buffers(buffer, buffer2); - lperms = nullperms; - - /* buffer freed below, lname is pointer in buffer */ -- error = aa_path_name(&link, profile->path_flags, &buffer, &lname, -+ error = aa_path_name(&link, profile->path_flags, buffer, &lname, - &info, profile->disconnected); - if (error) - goto audit; - - /* buffer2 freed below, tname is pointer in buffer2 */ -- error = aa_path_name(&target, profile->path_flags, &buffer2, &tname, -+ error = aa_path_name(&target, profile->path_flags, buffer2, &tname, - &info, profile->disconnected); - if (error) - goto audit; -@@ -432,8 +434,7 @@ int aa_path_link(struct aa_profile *profile, struct dentry *old_dentry, - audit: - error = aa_audit_file(profile, &lperms, OP_LINK, request, - lname, tname, cond.uid, info, error); -- kfree(buffer); -- kfree(buffer2); -+ put_buffers(buffer, buffer2); - - return error; - } -diff --git a/security/apparmor/include/path.h b/security/apparmor/include/path.h -index 78e4909dcc6a..05fb3305671e 100644 ---- a/security/apparmor/include/path.h -+++ b/security/apparmor/include/path.h -@@ -23,10 +23,10 @@ enum path_flags { - PATH_CHROOT_NSCONNECT = 0x10, /* connect paths that are at ns root */ - - PATH_DELEGATE_DELETED = 0x08000, /* delegate deleted files */ -- PATH_MEDIATE_DELETED = 0x10000, /* mediate deleted paths */ -+ PATH_MEDIATE_DELETED = 0x10000, /* mediate deleted paths */ - }; - --int aa_path_name(const struct path *path, int flags, char **buffer, -+int aa_path_name(const struct path *path, int flags, char *buffer, - const char **name, const char **info, - const char *disconnected); - -diff --git a/security/apparmor/path.c b/security/apparmor/path.c -index 9490f8e89630..9d5de1d05be4 100644 ---- a/security/apparmor/path.c -+++ b/security/apparmor/path.c -@@ -79,7 +79,6 @@ static int disconnect(const struct path *path, char *buf, char **name, - * d_namespace_path - lookup a name associated with a given path - * @path: path to lookup (NOT NULL) - * @buf: buffer to store path to (NOT NULL) -- * @buflen: length of @buf - * @name: Returns - pointer for start of path name with in @buf (NOT NULL) - * @flags: flags controlling path lookup - * @disconnected: string to prefix to disconnected paths -@@ -90,12 +89,14 @@ static int disconnect(const struct path *path, char *buf, char **name, - * When no error the path name is returned in @name which points to - * to a position in @buf - */ --static int d_namespace_path(const struct path *path, char *buf, int buflen, -- char **name, int flags, const char *disconnected) -+static int d_namespace_path(const struct path *path, char *buf, char **name, -+ int flags, const char *disconnected) - { - char *res; - int error = 0; - int connected = 1; -+ int isdir = (flags & PATH_IS_DIR) ? 1 : 0; -+ int buflen = aa_g_path_max - isdir; - - if (path->mnt->mnt_flags & MNT_INTERNAL) { - /* it's not mounted anywhere */ -@@ -110,10 +111,12 @@ static int d_namespace_path(const struct path *path, char *buf, int buflen, - /* TODO: convert over to using a per namespace - * control instead of hard coded /proc - */ -- return prepend(name, *name - buf, "/proc", 5); -+ error = prepend(name, *name - buf, "/proc", 5); -+ goto out; - } else -- return disconnect(path, buf, name, flags, -- disconnected); -+ error = disconnect(path, buf, name, flags, -+ disconnected); -+ goto out; - } - - /* resolve paths relative to chroot?*/ -@@ -132,8 +135,11 @@ static int d_namespace_path(const struct path *path, char *buf, int buflen, - * be returned. - */ - if (!res || IS_ERR(res)) { -- if (PTR_ERR(res) == -ENAMETOOLONG) -- return -ENAMETOOLONG; -+ if (PTR_ERR(res) == -ENAMETOOLONG) { -+ error = -ENAMETOOLONG; -+ *name = buf; -+ goto out; -+ } - connected = 0; - res = dentry_path_raw(path->dentry, buf, buflen); - if (IS_ERR(res)) { -@@ -146,6 +152,9 @@ static int d_namespace_path(const struct path *path, char *buf, int buflen, - - *name = res; - -+ if (!connected) -+ error = disconnect(path, buf, name, flags, disconnected); -+ - /* Handle two cases: - * 1. A deleted dentry && profile is not allowing mediation of deleted - * 2. On some filesystems, newly allocated dentries appear to the -@@ -153,62 +162,27 @@ static int d_namespace_path(const struct path *path, char *buf, int buflen, - * allocated. - */ - if (d_unlinked(path->dentry) && d_is_positive(path->dentry) && -- !(flags & PATH_MEDIATE_DELETED)) { -+ !(flags & (PATH_MEDIATE_DELETED | PATH_DELEGATE_DELETED))) { - error = -ENOENT; - goto out; - } - -- if (!connected) -- error = disconnect(path, buf, name, flags, disconnected); -- - out: -- return error; --} -- --/** -- * get_name_to_buffer - get the pathname to a buffer ensure dir / is appended -- * @path: path to get name for (NOT NULL) -- * @flags: flags controlling path lookup -- * @buffer: buffer to put name in (NOT NULL) -- * @size: size of buffer -- * @name: Returns - contains position of path name in @buffer (NOT NULL) -- * -- * Returns: %0 else error on failure -- */ --static int get_name_to_buffer(const struct path *path, int flags, char *buffer, -- int size, char **name, const char **info, -- const char *disconnected) --{ -- int adjust = (flags & PATH_IS_DIR) ? 1 : 0; -- int error = d_namespace_path(path, buffer, size - adjust, name, flags, -- disconnected); -- -- if (!error && (flags & PATH_IS_DIR) && (*name)[1] != '\0') -- /* -- * Append "/" to the pathname. The root directory is a special -- * case; it already ends in slash. -- */ -- strcpy(&buffer[size - 2], "/"); -- -- if (info && error) { -- if (error == -ENOENT) -- *info = "Failed name lookup - deleted entry"; -- else if (error == -EACCES) -- *info = "Failed name lookup - disconnected path"; -- else if (error == -ENAMETOOLONG) -- *info = "Failed name lookup - name too long"; -- else -- *info = "Failed name lookup"; -- } -+ /* -+ * Append "/" to the pathname. The root directory is a special -+ * case; it already ends in slash. -+ */ -+ if (!error && isdir && ((*name)[1] != '\0' || (*name)[0] != '/')) -+ strcpy(&buf[aa_g_path_max - 2], "/"); - - return error; - } - - /** -- * aa_path_name - compute the pathname of a file -+ * aa_path_name - get the pathname to a buffer ensure dir / is appended - * @path: path the file (NOT NULL) - * @flags: flags controlling path name generation -- * @buffer: buffer that aa_get_name() allocated (NOT NULL) -+ * @buffer: buffer to put name in (NOT NULL) - * @name: Returns - the generated path name if !error (NOT NULL) - * @info: Returns - information on why the path lookup failed (MAYBE NULL) - * @disconnected: string to prepend to disconnected paths -@@ -224,33 +198,23 @@ static int get_name_to_buffer(const struct path *path, int flags, char *buffer, - * - * Returns: %0 else error code if could retrieve name - */ --int aa_path_name(const struct path *path, int flags, char **buffer, -+int aa_path_name(const struct path *path, int flags, char *buffer, - const char **name, const char **info, const char *disconnected) - { -- char *buf, *str = NULL; -- int size = 256; -- int error; -- -- *name = NULL; -- *buffer = NULL; -- for (;;) { -- /* freed by caller */ -- buf = kmalloc(size, GFP_KERNEL); -- if (!buf) -- return -ENOMEM; -+ char *str = NULL; -+ int error = d_namespace_path(path, buffer, &str, flags, disconnected); - -- error = get_name_to_buffer(path, flags, buf, size, &str, info, -- disconnected); -- if (error != -ENAMETOOLONG) -- break; -- -- kfree(buf); -- size <<= 1; -- if (size > aa_g_path_max) -- return -ENAMETOOLONG; -- *info = NULL; -+ if (info && error) { -+ if (error == -ENOENT) -+ *info = "Failed name lookup - deleted entry"; -+ else if (error == -EACCES) -+ *info = "Failed name lookup - disconnected path"; -+ else if (error == -ENAMETOOLONG) -+ *info = "Failed name lookup - name too long"; -+ else -+ *info = "Failed name lookup"; - } -- *buffer = buf; -+ - *name = str; - - return error; --- -2.12.3 - diff --git a/patches.apparmor/0010-apparmor-add-more-debug-asserts-to-apparmorfs.patch b/patches.apparmor/0010-apparmor-add-more-debug-asserts-to-apparmorfs.patch deleted file mode 100644 index 6ebde32..0000000 --- a/patches.apparmor/0010-apparmor-add-more-debug-asserts-to-apparmorfs.patch +++ /dev/null @@ -1,81 +0,0 @@ -From 55ba3bb63b78e3a5ae74c19507abfa2be6cdb69f Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Tue, 18 Jul 2017 23:41:13 -0700 -Subject: [PATCH 10/17] apparmor: add more debug asserts to apparmorfs -References: FATE#323500 -Patch-mainline: v4.14-rc2 -Git-commit: cbf2d0e1a9e4876046a628e0e036a7545a3a4c40 - -Signed-off-by: John Johansen -Acked-by: Seth Arnold -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/apparmorfs.c | 17 +++++++++++++++++ - 1 file changed, 17 insertions(+) - -diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c -index 8fa6c898c44b..7acea14c850b 100644 ---- a/security/apparmor/apparmorfs.c -+++ b/security/apparmor/apparmorfs.c -@@ -1446,6 +1446,10 @@ void __aafs_profile_migrate_dents(struct aa_profile *old, - { - int i; - -+ AA_BUG(!old); -+ AA_BUG(!new); -+ AA_BUG(!mutex_is_locked(&profiles_ns(old)->lock)); -+ - for (i = 0; i < AAFS_PROF_SIZEOF; i++) { - new->dents[i] = old->dents[i]; - if (new->dents[i]) -@@ -1509,6 +1513,9 @@ int __aafs_profile_mkdir(struct aa_profile *profile, struct dentry *parent) - struct dentry *dent = NULL, *dir; - int error; - -+ AA_BUG(!profile); -+ AA_BUG(!mutex_is_locked(&profiles_ns(profile)->lock)); -+ - if (!parent) { - struct aa_profile *p; - p = aa_deref_parent(profile); -@@ -1734,6 +1741,7 @@ void __aafs_ns_rmdir(struct aa_ns *ns) - - if (!ns) - return; -+ AA_BUG(!mutex_is_locked(&ns->lock)); - - list_for_each_entry(child, &ns->base.profiles, base.list) - __aafs_profile_rmdir(child); -@@ -1906,6 +1914,10 @@ static struct aa_ns *__next_ns(struct aa_ns *root, struct aa_ns *ns) - { - struct aa_ns *parent, *next; - -+ AA_BUG(!root); -+ AA_BUG(!ns); -+ AA_BUG(ns != root && !mutex_is_locked(&ns->parent->lock)); -+ - /* is next namespace a child */ - if (!list_empty(&ns->sub_ns)) { - next = list_first_entry(&ns->sub_ns, typeof(*ns), base.list); -@@ -1940,6 +1952,9 @@ static struct aa_ns *__next_ns(struct aa_ns *root, struct aa_ns *ns) - static struct aa_profile *__first_profile(struct aa_ns *root, - struct aa_ns *ns) - { -+ AA_BUG(!root); -+ AA_BUG(ns && !mutex_is_locked(&ns->lock)); -+ - for (; ns; ns = __next_ns(root, ns)) { - if (!list_empty(&ns->base.profiles)) - return list_first_entry(&ns->base.profiles, -@@ -1962,6 +1977,8 @@ static struct aa_profile *__next_profile(struct aa_profile *p) - struct aa_profile *parent; - struct aa_ns *ns = p->ns; - -+ AA_BUG(!mutex_is_locked(&profiles_ns(p)->lock)); -+ - /* is next profile a child */ - if (!list_empty(&p->base.profiles)) - return list_first_entry(&p->base.profiles, typeof(*p), --- -2.14.1 - diff --git a/patches.apparmor/0011-apparmor-move-to-per-loaddata-files-instead-of-repli.patch b/patches.apparmor/0011-apparmor-move-to-per-loaddata-files-instead-of-repli.patch deleted file mode 100644 index 5afe292..0000000 --- a/patches.apparmor/0011-apparmor-move-to-per-loaddata-files-instead-of-repli.patch +++ /dev/null @@ -1,786 +0,0 @@ -From 3ca09e527d11e352a5d562a717ef84bc7089f4fc Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Tue, 9 May 2017 00:08:41 -0700 -Subject: [PATCH 11/65] apparmor: move to per loaddata files, instead of - replicating in profiles -Git-commit: 5d5182cae40115c03933989473288e54afb39c7c -Patch-mainline: v4.13-rc1 -References: FATE#323500 - -The loaddata sets cover more than just a single profile and should -be tracked at the ns level. Move the load data files under the namespace -and reference the files from the profiles via a symlink. - -Signed-off-by: John Johansen -Reviewed-by: Seth Arnold -Reviewed-by: Kees Cook -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/apparmorfs.c | 294 +++++++++++++++++++++++------- - security/apparmor/include/apparmorfs.h | 5 + - security/apparmor/include/policy_ns.h | 3 + - security/apparmor/include/policy_unpack.h | 68 ++++++- - security/apparmor/policy.c | 46 ++++- - security/apparmor/policy_ns.c | 1 + - security/apparmor/policy_unpack.c | 61 ++++++- - 7 files changed, 409 insertions(+), 69 deletions(-) - -diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c -index 26ad1a370632..d3dafd4ed144 100644 ---- a/security/apparmor/apparmorfs.c -+++ b/security/apparmor/apparmorfs.c -@@ -98,14 +98,11 @@ static struct aa_loaddata *aa_simple_write_to_buffer(const char __user *userbuf, - return ERR_PTR(-ESPIPE); - - /* freed by caller to simple_write_to_buffer */ -- data = kvmalloc(sizeof(*data) + alloc_size, GFP_KERNEL); -- if (data == NULL) -- return ERR_PTR(-ENOMEM); -- kref_init(&data->count); -- data->size = copy_size; -- data->hash = NULL; -- data->abi = 0; -+ data = aa_loaddata_alloc(alloc_size); -+ if (IS_ERR(data)) -+ return data; - -+ data->size = copy_size; - if (copy_from_user(data->data, userbuf, copy_size)) { - kvfree(data); - return ERR_PTR(-EFAULT); -@@ -213,6 +210,11 @@ static const struct file_operations aa_fs_profile_remove = { - .llseek = default_llseek, - }; - -+void __aa_bump_ns_revision(struct aa_ns *ns) -+{ -+ ns->revision++; -+} -+ - /** - * query_data - queries a policy and writes its data to buf - * @buf: the resulting data is stored here (NOT NULL) -@@ -559,68 +561,88 @@ static const struct file_operations aa_fs_ns_name = { - .release = single_release, - }; - --static int rawdata_release(struct inode *inode, struct file *file) -+ -+/* policy/raw_data/ * file ops */ -+ -+#define SEQ_RAWDATA_FOPS(NAME) \ -+static int seq_rawdata_ ##NAME ##_open(struct inode *inode, struct file *file)\ -+{ \ -+ return seq_rawdata_open(inode, file, seq_rawdata_ ##NAME ##_show); \ -+} \ -+ \ -+static const struct file_operations seq_rawdata_ ##NAME ##_fops = { \ -+ .owner = THIS_MODULE, \ -+ .open = seq_rawdata_ ##NAME ##_open, \ -+ .read = seq_read, \ -+ .llseek = seq_lseek, \ -+ .release = seq_rawdata_release, \ -+} \ -+ -+static int seq_rawdata_open(struct inode *inode, struct file *file, -+ int (*show)(struct seq_file *, void *)) - { -- /* TODO: switch to loaddata when profile switched to symlink */ -- aa_put_loaddata(file->private_data); -+ struct aa_loaddata *data = __aa_get_loaddata(inode->i_private); -+ int error; - -- return 0; -+ if (!data) -+ /* lost race this ent is being reaped */ -+ return -ENOENT; -+ -+ error = single_open(file, show, data); -+ if (error) { -+ AA_BUG(file->private_data && -+ ((struct seq_file *)file->private_data)->private); -+ aa_put_loaddata(data); -+ } -+ -+ return error; - } - --static int aa_fs_seq_raw_abi_show(struct seq_file *seq, void *v) -+static int seq_rawdata_release(struct inode *inode, struct file *file) - { -- struct aa_proxy *proxy = seq->private; -- struct aa_profile *profile = aa_get_profile_rcu(&proxy->profile); -+ struct seq_file *seq = (struct seq_file *) file->private_data; -+ -+ if (seq) -+ aa_put_loaddata(seq->private); - -- if (profile->rawdata->abi) -- seq_printf(seq, "v%d\n", profile->rawdata->abi); -+ return single_release(inode, file); -+} - -- aa_put_profile(profile); -+static int seq_rawdata_abi_show(struct seq_file *seq, void *v) -+{ -+ struct aa_loaddata *data = seq->private; -+ -+ seq_printf(seq, "v%d\n", data->abi); - - return 0; - } - --static int aa_fs_seq_raw_abi_open(struct inode *inode, struct file *file) -+static int seq_rawdata_revision_show(struct seq_file *seq, void *v) - { -- return aa_fs_seq_profile_open(inode, file, aa_fs_seq_raw_abi_show); --} -+ struct aa_loaddata *data = seq->private; - --static const struct file_operations aa_fs_seq_raw_abi_fops = { -- .owner = THIS_MODULE, -- .open = aa_fs_seq_raw_abi_open, -- .read = seq_read, -- .llseek = seq_lseek, -- .release = aa_fs_seq_profile_release, --}; -+ seq_printf(seq, "%ld\n", data->revision); - --static int aa_fs_seq_raw_hash_show(struct seq_file *seq, void *v) -+ return 0; -+} -+ -+static int seq_rawdata_hash_show(struct seq_file *seq, void *v) - { -- struct aa_proxy *proxy = seq->private; -- struct aa_profile *profile = aa_get_profile_rcu(&proxy->profile); -+ struct aa_loaddata *data = seq->private; - unsigned int i, size = aa_hash_size(); - -- if (profile->rawdata->hash) { -+ if (data->hash) { - for (i = 0; i < size; i++) -- seq_printf(seq, "%.2x", profile->rawdata->hash[i]); -+ seq_printf(seq, "%.2x", data->hash[i]); - seq_putc(seq, '\n'); - } -- aa_put_profile(profile); - - return 0; - } - --static int aa_fs_seq_raw_hash_open(struct inode *inode, struct file *file) --{ -- return aa_fs_seq_profile_open(inode, file, aa_fs_seq_raw_hash_show); --} -- --static const struct file_operations aa_fs_seq_raw_hash_fops = { -- .owner = THIS_MODULE, -- .open = aa_fs_seq_raw_hash_open, -- .read = seq_read, -- .llseek = seq_lseek, -- .release = aa_fs_seq_profile_release, --}; -+SEQ_RAWDATA_FOPS(abi); -+SEQ_RAWDATA_FOPS(revision); -+SEQ_RAWDATA_FOPS(hash); - - static ssize_t rawdata_read(struct file *file, char __user *buf, size_t size, - loff_t *ppos) -@@ -631,27 +653,120 @@ static ssize_t rawdata_read(struct file *file, char __user *buf, size_t size, - rawdata->size); - } - --static int rawdata_open(struct inode *inode, struct file *file) -+static int rawdata_release(struct inode *inode, struct file *file) - { -- struct aa_proxy *proxy = inode->i_private; -- struct aa_profile *profile; -+ aa_put_loaddata(file->private_data); -+ -+ return 0; -+} - -+static int rawdata_open(struct inode *inode, struct file *file) -+{ - if (!policy_view_capable(NULL)) - return -EACCES; -- profile = aa_get_profile_rcu(&proxy->profile); -- file->private_data = aa_get_loaddata(profile->rawdata); -- aa_put_profile(profile); -+ file->private_data = __aa_get_loaddata(inode->i_private); -+ if (!file->private_data) -+ /* lost race: this entry is being reaped */ -+ return -ENOENT; - - return 0; - } - --static const struct file_operations aa_fs_rawdata_fops = { -+static const struct file_operations rawdata_fops = { - .open = rawdata_open, - .read = rawdata_read, - .llseek = generic_file_llseek, - .release = rawdata_release, - }; - -+static void remove_rawdata_dents(struct aa_loaddata *rawdata) -+{ -+ int i; -+ -+ for (i = 0; i < AAFS_LOADDATA_NDENTS; i++) { -+ if (!IS_ERR_OR_NULL(rawdata->dents[i])) { -+ /* no refcounts on i_private */ -+ securityfs_remove(rawdata->dents[i]); -+ rawdata->dents[i] = NULL; -+ } -+ } -+} -+ -+void __aa_fs_remove_rawdata(struct aa_loaddata *rawdata) -+{ -+ AA_BUG(rawdata->ns && !mutex_is_locked(&rawdata->ns->lock)); -+ -+ if (rawdata->ns) { -+ remove_rawdata_dents(rawdata); -+ list_del_init(&rawdata->list); -+ aa_put_ns(rawdata->ns); -+ rawdata->ns = NULL; -+ } -+} -+ -+int __aa_fs_create_rawdata(struct aa_ns *ns, struct aa_loaddata *rawdata) -+{ -+ struct dentry *dent, *dir; -+ -+ AA_BUG(!ns); -+ AA_BUG(!rawdata); -+ AA_BUG(!mutex_is_locked(&ns->lock)); -+ AA_BUG(!ns_subdata_dir(ns)); -+ -+ /* -+ * just use ns revision dir was originally created at. This is -+ * under ns->lock and if load is successful revision will be -+ * bumped and is guaranteed to be unique -+ */ -+ rawdata->name = kasprintf(GFP_KERNEL, "%ld", ns->revision); -+ if (!rawdata->name) -+ return -ENOMEM; -+ -+ dir = securityfs_create_dir(rawdata->name, ns_subdata_dir(ns)); -+ if (IS_ERR(dir)) -+ /* ->name freed when rawdata freed */ -+ return PTR_ERR(dir); -+ rawdata->dents[AAFS_LOADDATA_DIR] = dir; -+ -+ dent = securityfs_create_file("abi", S_IFREG | 0444, dir, rawdata, -+ &seq_rawdata_abi_fops); -+ if (IS_ERR(dent)) -+ goto fail; -+ rawdata->dents[AAFS_LOADDATA_ABI] = dent; -+ -+ dent = securityfs_create_file("revision", S_IFREG | 0444, dir, rawdata, -+ &seq_rawdata_revision_fops); -+ if (IS_ERR(dent)) -+ goto fail; -+ rawdata->dents[AAFS_LOADDATA_REVISION] = dent; -+ -+ if (aa_g_hash_policy) { -+ dent = securityfs_create_file("sha1", S_IFREG | 0444, dir, -+ rawdata, &seq_rawdata_hash_fops); -+ if (IS_ERR(dent)) -+ goto fail; -+ rawdata->dents[AAFS_LOADDATA_HASH] = dent; -+ } -+ -+ dent = securityfs_create_file("raw_data", S_IFREG | 0444, -+ dir, rawdata, &rawdata_fops); -+ if (IS_ERR(dent)) -+ goto fail; -+ rawdata->dents[AAFS_LOADDATA_DATA] = dent; -+ d_inode(dent)->i_size = rawdata->size; -+ -+ rawdata->ns = aa_get_ns(ns); -+ list_add(&rawdata->list, &ns->rawdata_list); -+ /* no refcount on inode rawdata */ -+ -+ return 0; -+ -+fail: -+ remove_rawdata_dents(rawdata); -+ -+ return PTR_ERR(dent); -+} -+ - /** fns to setup dynamic per profile/namespace files **/ - void __aa_fs_profile_rmdir(struct aa_profile *profile) - { -@@ -703,7 +818,41 @@ static struct dentry *create_profile_file(struct dentry *dir, const char *name, - return dent; - } - --/* requires lock be held */ -+static int profile_depth(struct aa_profile *profile) -+{ -+ int depth = 0; -+ -+ rcu_read_lock(); -+ for (depth = 0; profile; profile = rcu_access_pointer(profile->parent)) -+ depth++; -+ rcu_read_unlock(); -+ -+ return depth; -+} -+ -+static int gen_symlink_name(char *buffer, size_t bsize, int depth, -+ const char *dirname, const char *fname) -+{ -+ int error; -+ -+ for (; depth > 0; depth--) { -+ if (bsize < 7) -+ return -ENAMETOOLONG; -+ strcpy(buffer, "../../"); -+ buffer += 6; -+ bsize -= 6; -+ } -+ -+ error = snprintf(buffer, bsize, "raw_data/%s/%s", dirname, fname); -+ if (error >= bsize || error < 0) -+ return -ENAMETOOLONG; -+ -+ return 0; -+} -+ -+/* -+ * Requires: @profile->ns->lock held -+ */ - int __aa_fs_profile_mkdir(struct aa_profile *profile, struct dentry *parent) - { - struct aa_profile *child; -@@ -766,26 +915,35 @@ int __aa_fs_profile_mkdir(struct aa_profile *profile, struct dentry *parent) - } - - if (profile->rawdata) { -- dent = create_profile_file(dir, "raw_sha1", profile, -- &aa_fs_seq_raw_hash_fops); -+ char target[64]; -+ int depth = profile_depth(profile); -+ -+ error = gen_symlink_name(target, sizeof(target), depth, -+ profile->rawdata->name, "sha1"); -+ if (error < 0) -+ goto fail2; -+ dent = securityfs_create_symlink("raw_sha1", dir, target, NULL); - if (IS_ERR(dent)) - goto fail; - profile->dents[AAFS_PROF_RAW_HASH] = dent; - -- dent = create_profile_file(dir, "raw_abi", profile, -- &aa_fs_seq_raw_abi_fops); -+ error = gen_symlink_name(target, sizeof(target), depth, -+ profile->rawdata->name, "abi"); -+ if (error < 0) -+ goto fail2; -+ dent = securityfs_create_symlink("raw_abi", dir, target, NULL); - if (IS_ERR(dent)) - goto fail; - profile->dents[AAFS_PROF_RAW_ABI] = dent; - -- dent = securityfs_create_file("raw_data", S_IFREG | 0444, dir, -- profile->proxy, -- &aa_fs_rawdata_fops); -+ error = gen_symlink_name(target, sizeof(target), depth, -+ profile->rawdata->name, "raw_data"); -+ if (error < 0) -+ goto fail2; -+ dent = securityfs_create_symlink("raw_data", dir, target, NULL); - if (IS_ERR(dent)) - goto fail; - profile->dents[AAFS_PROF_RAW_DATA] = dent; -- d_inode(dent)->i_size = profile->rawdata->size; -- aa_get_proxy(profile->proxy); - } - - list_for_each_entry(child, &profile->base.profiles, base.list) { -@@ -805,6 +963,16 @@ int __aa_fs_profile_mkdir(struct aa_profile *profile, struct dentry *parent) - return error; - } - -+static void __aa_fs_list_remove_rawdata(struct aa_ns *ns) -+{ -+ struct aa_loaddata *ent, *tmp; -+ -+ AA_BUG(!mutex_is_locked(&ns->lock)); -+ -+ list_for_each_entry_safe(ent, tmp, &ns->rawdata_list, list) -+ __aa_fs_remove_rawdata(ent); -+} -+ - void __aa_fs_ns_rmdir(struct aa_ns *ns) - { - struct aa_ns *sub; -@@ -823,6 +991,8 @@ void __aa_fs_ns_rmdir(struct aa_ns *ns) - mutex_unlock(&sub->lock); - } - -+ __aa_fs_list_remove_rawdata(ns); -+ - if (ns_subns_dir(ns)) { - sub = d_inode(ns_subns_dir(ns))->i_private; - aa_put_ns(sub); -diff --git a/security/apparmor/include/apparmorfs.h b/security/apparmor/include/apparmorfs.h -index 120a798b5bb0..0b6d32b3f05e 100644 ---- a/security/apparmor/include/apparmorfs.h -+++ b/security/apparmor/include/apparmorfs.h -@@ -106,6 +106,7 @@ enum aafs_prof_type { - #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 __aa_fs_profile_rmdir(struct aa_profile *profile); - void __aa_fs_profile_migrate_dents(struct aa_profile *old, - struct aa_profile *new); -@@ -114,4 +115,8 @@ void __aa_fs_ns_rmdir(struct aa_ns *ns); - int __aa_fs_ns_mkdir(struct aa_ns *ns, struct dentry *parent, - const char *name); - -+struct aa_loaddata; -+void __aa_fs_remove_rawdata(struct aa_loaddata *rawdata); -+int __aa_fs_create_rawdata(struct aa_ns *ns, struct aa_loaddata *rawdata); -+ - #endif /* __AA_APPARMORFS_H */ -diff --git a/security/apparmor/include/policy_ns.h b/security/apparmor/include/policy_ns.h -index 89cffddd7e75..d7a07ac96168 100644 ---- a/security/apparmor/include/policy_ns.h -+++ b/security/apparmor/include/policy_ns.h -@@ -68,6 +68,9 @@ struct aa_ns { - atomic_t uniq_null; - long uniq_id; - int level; -+ long revision; -+ -+ struct list_head rawdata_list; - - struct dentry *dents[AAFS_NS_SIZEOF]; - }; -diff --git a/security/apparmor/include/policy_unpack.h b/security/apparmor/include/policy_unpack.h -index 4c1319eebc42..be6cd69ac319 100644 ---- a/security/apparmor/include/policy_unpack.h -+++ b/security/apparmor/include/policy_unpack.h -@@ -17,6 +17,8 @@ - - #include - #include -+#include -+#include - - struct aa_load_ent { - struct list_head list; -@@ -36,26 +38,84 @@ struct aa_load_ent *aa_load_ent_alloc(void); - #define PACKED_MODE_KILL 2 - #define PACKED_MODE_UNCONFINED 3 - --/* struct aa_loaddata - buffer of policy load data set */ -+struct aa_ns; -+ -+enum { -+ AAFS_LOADDATA_ABI = 0, -+ AAFS_LOADDATA_REVISION, -+ AAFS_LOADDATA_HASH, -+ AAFS_LOADDATA_DATA, -+ AAFS_LOADDATA_DIR, /* must be last actual entry */ -+ AAFS_LOADDATA_NDENTS /* count of entries */ -+}; -+ -+/* -+ * 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; -+ long revision; /* the ns policy revision this caused */ - int abi; - unsigned char *hash; -+ - 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) - { -- if (data) -- kref_get(&(data->count)); -- return 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) -diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c -index cf9d670dca94..5968914247a4 100644 ---- a/security/apparmor/policy.c -+++ b/security/apparmor/policy.c -@@ -840,10 +840,13 @@ ssize_t aa_replace_profiles(struct aa_ns *view, struct aa_profile *profile, - const char *ns_name, *info = NULL; - struct aa_ns *ns = NULL; - struct aa_load_ent *ent, *tmp; -+ struct aa_loaddata *rawdata_ent; - const char *op = OP_PROF_REPL; - ssize_t count, error; -+ - LIST_HEAD(lh); - -+ aa_get_loaddata(udata); - /* released below */ - error = aa_unpack(udata, &lh, &ns_name); - if (error) -@@ -887,9 +890,24 @@ ssize_t aa_replace_profiles(struct aa_ns *view, struct aa_profile *profile, - ns = aa_get_ns(view); - - mutex_lock(&ns->lock); -+ /* check for duplicate rawdata blobs: space and file dedup */ -+ list_for_each_entry(rawdata_ent, &ns->rawdata_list, list) { -+ if (aa_rawdata_eq(rawdata_ent, udata)) { -+ struct aa_loaddata *tmp; -+ -+ tmp = __aa_get_loaddata(rawdata_ent); -+ /* check we didn't fail the race */ -+ if (tmp) { -+ aa_put_loaddata(udata); -+ udata = tmp; -+ break; -+ } -+ } -+ } - /* setup parent and ns info */ - list_for_each_entry(ent, &lh, list) { - struct aa_policy *policy; -+ - ent->new->rawdata = aa_get_loaddata(udata); - error = __lookup_replace(ns, ent->new->base.hname, noreplace, - &ent->old, &info); -@@ -929,6 +947,14 @@ ssize_t aa_replace_profiles(struct aa_ns *view, struct aa_profile *profile, - } - - /* create new fs entries for introspection if needed */ -+ if (!udata->dents[AAFS_LOADDATA_DIR]) { -+ error = __aa_fs_create_rawdata(ns, udata); -+ if (error) { -+ info = "failed to create raw_data dir and files"; -+ ent = NULL; -+ goto fail_lock; -+ } -+ } - list_for_each_entry(ent, &lh, list) { - if (ent->old) { - /* inherit old interface files */ -@@ -955,10 +981,24 @@ ssize_t aa_replace_profiles(struct aa_ns *view, struct aa_profile *profile, - } - - /* Done with checks that may fail - do actual replacement */ -+ __aa_bump_ns_revision(ns); -+ __aa_loaddata_update(udata, ns->revision); - list_for_each_entry_safe(ent, tmp, &lh, list) { - list_del_init(&ent->list); - op = (!ent->old && !ent->rename) ? OP_PROF_LOAD : OP_PROF_REPL; - -+ if (ent->old && ent->old->rawdata == ent->new->rawdata) { -+ /* dedup actual profile replacement */ -+ audit_policy(profile, op, ns_name, ent->new->base.hname, -+ "same as current profile, skipping", -+ error); -+ goto skip; -+ } -+ -+ /* -+ * TODO: finer dedup based on profile range in data. Load set -+ * can differ but profile may remain unchanged -+ */ - audit_policy(profile, op, NULL, ent->new->base.hname, - NULL, error); - -@@ -998,12 +1038,14 @@ ssize_t aa_replace_profiles(struct aa_ns *view, struct aa_profile *profile, - aa_get_profile(ent->new)); - __list_add_profile(&ns->base.profiles, ent->new); - } -+ skip: - aa_load_ent_free(ent); - } - mutex_unlock(&ns->lock); - - out: - aa_put_ns(ns); -+ aa_put_loaddata(udata); - - if (error) - return error; -@@ -1013,7 +1055,7 @@ ssize_t aa_replace_profiles(struct aa_ns *view, struct aa_profile *profile, - mutex_unlock(&ns->lock); - - /* audit cause of failure */ -- op = (!ent->old) ? OP_PROF_LOAD : OP_PROF_REPL; -+ op = (ent && !ent->old) ? OP_PROF_LOAD : OP_PROF_REPL; - fail: - audit_policy(profile, op, ns_name, ent ? ent->new->base.hname : NULL, - info, error); -@@ -1085,6 +1127,7 @@ ssize_t aa_remove_profiles(struct aa_ns *view, struct aa_profile *subj, - /* remove namespace - can only happen if fqname[0] == ':' */ - mutex_lock(&ns->parent->lock); - __aa_remove_ns(ns); -+ __aa_bump_ns_revision(ns); - mutex_unlock(&ns->parent->lock); - } else { - /* remove profile */ -@@ -1097,6 +1140,7 @@ ssize_t aa_remove_profiles(struct aa_ns *view, struct aa_profile *subj, - } - name = profile->base.hname; - __remove_profile(profile); -+ __aa_bump_ns_revision(ns); - mutex_unlock(&ns->lock); - } - -diff --git a/security/apparmor/policy_ns.c b/security/apparmor/policy_ns.c -index 93d1826c4b09..c94ec6ef9e35 100644 ---- a/security/apparmor/policy_ns.c -+++ b/security/apparmor/policy_ns.c -@@ -99,6 +99,7 @@ static struct aa_ns *alloc_ns(const char *prefix, const char *name) - goto fail_ns; - - INIT_LIST_HEAD(&ns->sub_ns); -+ INIT_LIST_HEAD(&ns->rawdata_list); - mutex_init(&ns->lock); - - /* released by aa_free_ns() */ -diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c -index 182bbfeb4b2c..5ea6a7cb0212 100644 ---- a/security/apparmor/policy_unpack.c -+++ b/security/apparmor/policy_unpack.c -@@ -122,16 +122,73 @@ static int audit_iface(struct aa_profile *new, const char *ns_name, - return aa_audit(AUDIT_APPARMOR_STATUS, profile, &sa, audit_cb); - } - -+void __aa_loaddata_update(struct aa_loaddata *data, long revision) -+{ -+ AA_BUG(!data); -+ AA_BUG(!data->ns); -+ AA_BUG(!data->dents[AAFS_LOADDATA_REVISION]); -+ AA_BUG(!mutex_is_locked(&data->ns->lock)); -+ AA_BUG(data->revision > revision); -+ -+ data->revision = revision; -+ d_inode(data->dents[AAFS_LOADDATA_DIR])->i_mtime = -+ current_time(d_inode(data->dents[AAFS_LOADDATA_DIR])); -+ d_inode(data->dents[AAFS_LOADDATA_REVISION])->i_mtime = -+ current_time(d_inode(data->dents[AAFS_LOADDATA_REVISION])); -+} -+ -+bool aa_rawdata_eq(struct aa_loaddata *l, struct aa_loaddata *r) -+{ -+ if (l->size != r->size) -+ return false; -+ if (aa_g_hash_policy && memcmp(l->hash, r->hash, aa_hash_size()) != 0) -+ return false; -+ return memcmp(l->data, r->data, r->size) == 0; -+} -+ -+/* -+ * need to take the ns mutex lock which is NOT safe most places that -+ * put_loaddata is called, so we have to delay freeing it -+ */ -+static void do_loaddata_free(struct work_struct *work) -+{ -+ struct aa_loaddata *d = container_of(work, struct aa_loaddata, work); -+ struct aa_ns *ns = aa_get_ns(d->ns); -+ -+ if (ns) { -+ mutex_lock(&ns->lock); -+ __aa_fs_remove_rawdata(d); -+ mutex_unlock(&ns->lock); -+ aa_put_ns(ns); -+ } -+ -+ kzfree(d->hash); -+ kfree(d->name); -+ kvfree(d); -+} -+ - void aa_loaddata_kref(struct kref *kref) - { - struct aa_loaddata *d = container_of(kref, struct aa_loaddata, count); - - if (d) { -- kzfree(d->hash); -- kvfree(d); -+ INIT_WORK(&d->work, do_loaddata_free); -+ schedule_work(&d->work); - } - } - -+struct aa_loaddata *aa_loaddata_alloc(size_t size) -+{ -+ struct aa_loaddata *d = kvzalloc(sizeof(*d) + size, GFP_KERNEL); -+ -+ if (d == NULL) -+ return ERR_PTR(-ENOMEM); -+ kref_init(&d->count); -+ INIT_LIST_HEAD(&d->list); -+ -+ return d; -+} -+ - /* test if read will be in packed data bounds */ - static bool inbounds(struct aa_ext *e, size_t size) - { --- -2.12.3 - diff --git a/patches.apparmor/0012-apparmor-move-new_null_profile-to-after-profile-look.patch b/patches.apparmor/0012-apparmor-move-new_null_profile-to-after-profile-look.patch deleted file mode 100644 index af08f7e..0000000 --- a/patches.apparmor/0012-apparmor-move-new_null_profile-to-after-profile-look.patch +++ /dev/null @@ -1,196 +0,0 @@ -From 86352938e152537a8e7dc7ab204f518b90eb7e39 Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Wed, 16 Aug 2017 08:59:57 -0700 -Subject: [PATCH 12/17] apparmor: move new_null_profile to after profile lookup fns() -References: FATE#323500 -Patch-mainline: v4.14-rc2 -Git-commit: d07881d2edb0ab783846730629ac2faeaafdf4f1 - -new_null_profile will need to use some of the profile lookup fns() -so move instead of doing forward fn declarations. - -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/policy.c | 158 ++++++++++++++++++++++----------------------- - 1 file changed, 79 insertions(+), 79 deletions(-) - -diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c -index 244ea4a4a8f0..a81a384a63b1 100644 ---- a/security/apparmor/policy.c -+++ b/security/apparmor/policy.c -@@ -289,85 +289,6 @@ struct aa_profile *aa_alloc_profile(const char *hname, struct aa_proxy *proxy, - return NULL; - } - --/** -- * aa_new_null_profile - create or find a null-X learning profile -- * @parent: profile that caused this profile to be created (NOT NULL) -- * @hat: true if the null- learning profile is a hat -- * @base: name to base the null profile off of -- * @gfp: type of allocation -- * -- * Find/Create a null- complain mode profile used in learning mode. The -- * name of the profile is unique and follows the format of parent//null-XXX. -- * where XXX is based on the @name or if that fails or is not supplied -- * a unique number -- * -- * null profiles are added to the profile list but the list does not -- * hold a count on them so that they are automatically released when -- * not in use. -- * -- * Returns: new refcounted profile else NULL on failure -- */ --struct aa_profile *aa_new_null_profile(struct aa_profile *parent, bool hat, -- const char *base, gfp_t gfp) --{ -- struct aa_profile *profile; -- char *name; -- -- AA_BUG(!parent); -- -- if (base) { -- name = kmalloc(strlen(parent->base.hname) + 8 + strlen(base), -- gfp); -- if (name) { -- sprintf(name, "%s//null-%s", parent->base.hname, base); -- goto name; -- } -- /* fall through to try shorter uniq */ -- } -- -- name = kmalloc(strlen(parent->base.hname) + 2 + 7 + 8, gfp); -- if (!name) -- return NULL; -- sprintf(name, "%s//null-%x", parent->base.hname, -- atomic_inc_return(&parent->ns->uniq_null)); -- --name: -- /* lookup to see if this is a dup creation */ -- profile = aa_find_child(parent, basename(name)); -- if (profile) -- goto out; -- -- profile = aa_alloc_profile(name, NULL, gfp); -- if (!profile) -- goto fail; -- -- profile->mode = APPARMOR_COMPLAIN; -- profile->label.flags |= FLAG_NULL; -- if (hat) -- profile->label.flags |= FLAG_HAT; -- profile->path_flags = parent->path_flags; -- -- /* released on free_profile */ -- rcu_assign_pointer(profile->parent, aa_get_profile(parent)); -- profile->ns = aa_get_ns(parent->ns); -- profile->file.dfa = aa_get_dfa(nulldfa); -- profile->policy.dfa = aa_get_dfa(nulldfa); -- -- mutex_lock(&profile->ns->lock); -- __add_profile(&parent->base.profiles, profile); -- mutex_unlock(&profile->ns->lock); -- -- /* refcount released by caller */ --out: -- kfree(name); -- -- return profile; -- --fail: -- aa_free_profile(profile); -- return NULL; --} -- - /* TODO: profile accounting - setup in remove */ - - /** -@@ -558,6 +479,85 @@ struct aa_profile *aa_fqlookupn_profile(struct aa_label *base, - return profile; - } - -+/** -+ * aa_new_null_profile - create or find a null-X learning profile -+ * @parent: profile that caused this profile to be created (NOT NULL) -+ * @hat: true if the null- learning profile is a hat -+ * @base: name to base the null profile off of -+ * @gfp: type of allocation -+ * -+ * Find/Create a null- complain mode profile used in learning mode. The -+ * name of the profile is unique and follows the format of parent//null-XXX. -+ * where XXX is based on the @name or if that fails or is not supplied -+ * a unique number -+ * -+ * null profiles are added to the profile list but the list does not -+ * hold a count on them so that they are automatically released when -+ * not in use. -+ * -+ * Returns: new refcounted profile else NULL on failure -+ */ -+struct aa_profile *aa_new_null_profile(struct aa_profile *parent, bool hat, -+ const char *base, gfp_t gfp) -+{ -+ struct aa_profile *profile; -+ char *name; -+ -+ AA_BUG(!parent); -+ -+ if (base) { -+ name = kmalloc(strlen(parent->base.hname) + 8 + strlen(base), -+ gfp); -+ if (name) { -+ sprintf(name, "%s//null-%s", parent->base.hname, base); -+ goto name; -+ } -+ /* fall through to try shorter uniq */ -+ } -+ -+ name = kmalloc(strlen(parent->base.hname) + 2 + 7 + 8, gfp); -+ if (!name) -+ return NULL; -+ sprintf(name, "%s//null-%x", parent->base.hname, -+ atomic_inc_return(&parent->ns->uniq_null)); -+ -+name: -+ /* lookup to see if this is a dup creation */ -+ profile = aa_find_child(parent, basename(name)); -+ if (profile) -+ goto out; -+ -+ profile = aa_alloc_profile(name, NULL, gfp); -+ if (!profile) -+ goto fail; -+ -+ profile->mode = APPARMOR_COMPLAIN; -+ profile->label.flags |= FLAG_NULL; -+ if (hat) -+ profile->label.flags |= FLAG_HAT; -+ profile->path_flags = parent->path_flags; -+ -+ /* released on free_profile */ -+ rcu_assign_pointer(profile->parent, aa_get_profile(parent)); -+ profile->ns = aa_get_ns(parent->ns); -+ profile->file.dfa = aa_get_dfa(nulldfa); -+ profile->policy.dfa = aa_get_dfa(nulldfa); -+ -+ mutex_lock(&profile->ns->lock); -+ __add_profile(&parent->base.profiles, profile); -+ mutex_unlock(&profile->ns->lock); -+ -+ /* refcount released by caller */ -+out: -+ kfree(name); -+ -+ return profile; -+ -+fail: -+ aa_free_profile(profile); -+ return NULL; -+} -+ - /** - * replacement_allowed - test to see if replacement is allowed - * @profile: profile to test if it can be replaced (MAYBE NULL) --- -2.14.1 - diff --git a/patches.apparmor/0012-apparmor-use-macro-template-to-simplify-profile-seq_.patch b/patches.apparmor/0012-apparmor-use-macro-template-to-simplify-profile-seq_.patch deleted file mode 100644 index 04aaa2a..0000000 --- a/patches.apparmor/0012-apparmor-use-macro-template-to-simplify-profile-seq_.patch +++ /dev/null @@ -1,193 +0,0 @@ -From 88bc035bead1b6a6f7356b654591333b6b795d17 Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Thu, 25 May 2017 04:35:09 -0700 -Subject: [PATCH 12/65] apparmor: use macro template to simplify profile - seq_files -Git-commit: 52b97de32236d4cc9b302ae9259e70bb2f1fa2a5 -Patch-mainline: v4.13-rc1 -References: FATE#323500 - -Signed-off-by: John Johansen -Reviewed-by: Seth Arnold -Reviewed-by: Kees Cook -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/apparmorfs.c | 97 ++++++++++++++++-------------------------- - 1 file changed, 36 insertions(+), 61 deletions(-) - -diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c -index d3dafd4ed144..750431b0ec4e 100644 ---- a/security/apparmor/apparmorfs.c -+++ b/security/apparmor/apparmorfs.c -@@ -391,8 +391,27 @@ const struct file_operations aa_fs_seq_file_ops = { - .release = single_release, - }; - --static int aa_fs_seq_profile_open(struct inode *inode, struct file *file, -- int (*show)(struct seq_file *, void *)) -+/* -+ * profile based file operations -+ * policy/profiles/XXXX/profiles/ * -+ */ -+ -+#define SEQ_PROFILE_FOPS(NAME) \ -+static int seq_profile_ ##NAME ##_open(struct inode *inode, struct file *file)\ -+{ \ -+ return seq_profile_open(inode, file, seq_profile_ ##NAME ##_show); \ -+} \ -+ \ -+static const struct file_operations seq_profile_ ##NAME ##_fops = { \ -+ .owner = THIS_MODULE, \ -+ .open = seq_profile_ ##NAME ##_open, \ -+ .read = seq_read, \ -+ .llseek = seq_lseek, \ -+ .release = seq_profile_release, \ -+} \ -+ -+static int seq_profile_open(struct inode *inode, struct file *file, -+ int (*show)(struct seq_file *, void *)) - { - struct aa_proxy *proxy = aa_get_proxy(inode->i_private); - int error = single_open(file, show, proxy); -@@ -405,7 +424,7 @@ static int aa_fs_seq_profile_open(struct inode *inode, struct file *file, - return error; - } - --static int aa_fs_seq_profile_release(struct inode *inode, struct file *file) -+static int seq_profile_release(struct inode *inode, struct file *file) - { - struct seq_file *seq = (struct seq_file *) file->private_data; - if (seq) -@@ -413,7 +432,7 @@ static int aa_fs_seq_profile_release(struct inode *inode, struct file *file) - return single_release(inode, file); - } - --static int aa_fs_seq_profname_show(struct seq_file *seq, void *v) -+static int seq_profile_name_show(struct seq_file *seq, void *v) - { - struct aa_proxy *proxy = seq->private; - struct aa_profile *profile = aa_get_profile_rcu(&proxy->profile); -@@ -423,20 +442,7 @@ static int aa_fs_seq_profname_show(struct seq_file *seq, void *v) - return 0; - } - --static int aa_fs_seq_profname_open(struct inode *inode, struct file *file) --{ -- return aa_fs_seq_profile_open(inode, file, aa_fs_seq_profname_show); --} -- --static const struct file_operations aa_fs_profname_fops = { -- .owner = THIS_MODULE, -- .open = aa_fs_seq_profname_open, -- .read = seq_read, -- .llseek = seq_lseek, -- .release = aa_fs_seq_profile_release, --}; -- --static int aa_fs_seq_profmode_show(struct seq_file *seq, void *v) -+static int seq_profile_mode_show(struct seq_file *seq, void *v) - { - struct aa_proxy *proxy = seq->private; - struct aa_profile *profile = aa_get_profile_rcu(&proxy->profile); -@@ -446,20 +452,7 @@ static int aa_fs_seq_profmode_show(struct seq_file *seq, void *v) - return 0; - } - --static int aa_fs_seq_profmode_open(struct inode *inode, struct file *file) --{ -- return aa_fs_seq_profile_open(inode, file, aa_fs_seq_profmode_show); --} -- --static const struct file_operations aa_fs_profmode_fops = { -- .owner = THIS_MODULE, -- .open = aa_fs_seq_profmode_open, -- .read = seq_read, -- .llseek = seq_lseek, -- .release = aa_fs_seq_profile_release, --}; -- --static int aa_fs_seq_profattach_show(struct seq_file *seq, void *v) -+static int seq_profile_attach_show(struct seq_file *seq, void *v) - { - struct aa_proxy *proxy = seq->private; - struct aa_profile *profile = aa_get_profile_rcu(&proxy->profile); -@@ -474,20 +467,7 @@ static int aa_fs_seq_profattach_show(struct seq_file *seq, void *v) - return 0; - } - --static int aa_fs_seq_profattach_open(struct inode *inode, struct file *file) --{ -- return aa_fs_seq_profile_open(inode, file, aa_fs_seq_profattach_show); --} -- --static const struct file_operations aa_fs_profattach_fops = { -- .owner = THIS_MODULE, -- .open = aa_fs_seq_profattach_open, -- .read = seq_read, -- .llseek = seq_lseek, -- .release = aa_fs_seq_profile_release, --}; -- --static int aa_fs_seq_hash_show(struct seq_file *seq, void *v) -+static int seq_profile_hash_show(struct seq_file *seq, void *v) - { - struct aa_proxy *proxy = seq->private; - struct aa_profile *profile = aa_get_profile_rcu(&proxy->profile); -@@ -503,18 +483,11 @@ static int aa_fs_seq_hash_show(struct seq_file *seq, void *v) - return 0; - } - --static int aa_fs_seq_hash_open(struct inode *inode, struct file *file) --{ -- return single_open(file, aa_fs_seq_hash_show, inode->i_private); --} -+SEQ_PROFILE_FOPS(name); -+SEQ_PROFILE_FOPS(mode); -+SEQ_PROFILE_FOPS(attach); -+SEQ_PROFILE_FOPS(hash); - --static const struct file_operations aa_fs_seq_hash_fops = { -- .owner = THIS_MODULE, -- .open = aa_fs_seq_hash_open, -- .read = seq_read, -- .llseek = seq_lseek, -- .release = single_release, --}; - - - static int aa_fs_seq_show_ns_level(struct seq_file *seq, void *v) -@@ -890,25 +863,27 @@ int __aa_fs_profile_mkdir(struct aa_profile *profile, struct dentry *parent) - goto fail; - prof_dir(profile) = dir = dent; - -- dent = create_profile_file(dir, "name", profile, &aa_fs_profname_fops); -+ dent = create_profile_file(dir, "name", profile, -+ &seq_profile_name_fops); - if (IS_ERR(dent)) - goto fail; - profile->dents[AAFS_PROF_NAME] = dent; - -- dent = create_profile_file(dir, "mode", profile, &aa_fs_profmode_fops); -+ dent = create_profile_file(dir, "mode", profile, -+ &seq_profile_mode_fops); - if (IS_ERR(dent)) - goto fail; - profile->dents[AAFS_PROF_MODE] = dent; - - dent = create_profile_file(dir, "attach", profile, -- &aa_fs_profattach_fops); -+ &seq_profile_attach_fops); - if (IS_ERR(dent)) - goto fail; - profile->dents[AAFS_PROF_ATTACH] = dent; - - if (profile->hash) { - dent = create_profile_file(dir, "sha1", profile, -- &aa_fs_seq_hash_fops); -+ &seq_profile_hash_fops); - if (IS_ERR(dent)) - goto fail; - profile->dents[AAFS_PROF_HASH] = dent; --- -2.12.3 - diff --git a/patches.apparmor/0013-apparmor-fix-race-condition-in-null-profile-creation.patch b/patches.apparmor/0013-apparmor-fix-race-condition-in-null-profile-creation.patch deleted file mode 100644 index 2061fe1..0000000 --- a/patches.apparmor/0013-apparmor-fix-race-condition-in-null-profile-creation.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 29ec50aa3815bddeee97a224e917a310b677ca15 Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Wed, 16 Aug 2017 05:40:49 -0700 -Subject: [PATCH 13/17] apparmor: fix race condition in null profile creation -References: FATE#323500 -Patch-mainline: v4.14-rc2 -Git-commit: 290638a52a808d658bd04b746b3ca46886c157e0 - -There is a race when null- profile is being created between the -initial lookup/creation of the profile and lock/addition of the -profile. This could result in multiple version of a profile being -added to the list which need to be removed/replaced. - -Since these are learning profile their is no affect on mediation. - -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/policy.c | 14 +++++++++++--- - 1 file changed, 11 insertions(+), 3 deletions(-) - -diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c -index a81a384a63b1..4243b0c3f0e4 100644 ---- a/security/apparmor/policy.c -+++ b/security/apparmor/policy.c -@@ -500,7 +500,8 @@ struct aa_profile *aa_fqlookupn_profile(struct aa_label *base, - struct aa_profile *aa_new_null_profile(struct aa_profile *parent, bool hat, - const char *base, gfp_t gfp) - { -- struct aa_profile *profile; -+ struct aa_profile *p, *profile; -+ const char *bname; - char *name; - - AA_BUG(!parent); -@@ -523,7 +524,8 @@ struct aa_profile *aa_new_null_profile(struct aa_profile *parent, bool hat, - - name: - /* lookup to see if this is a dup creation */ -- profile = aa_find_child(parent, basename(name)); -+ bname = basename(name); -+ profile = aa_find_child(parent, bname); - if (profile) - goto out; - -@@ -544,7 +546,13 @@ struct aa_profile *aa_new_null_profile(struct aa_profile *parent, bool hat, - profile->policy.dfa = aa_get_dfa(nulldfa); - - mutex_lock(&profile->ns->lock); -- __add_profile(&parent->base.profiles, profile); -+ p = __find_child(&parent->base.profiles, bname); -+ if (p) { -+ aa_free_profile(profile); -+ profile = aa_get_profile(p); -+ } else { -+ __add_profile(&parent->base.profiles, profile); -+ } - mutex_unlock(&profile->ns->lock); - - /* refcount released by caller */ --- -2.14.1 - diff --git a/patches.apparmor/0013-apparmor-use-macro-template-to-simplify-namespace-se.patch b/patches.apparmor/0013-apparmor-use-macro-template-to-simplify-namespace-se.patch deleted file mode 100644 index 4f82675..0000000 --- a/patches.apparmor/0013-apparmor-use-macro-template-to-simplify-namespace-se.patch +++ /dev/null @@ -1,107 +0,0 @@ -From 6926a160746d360ad9067b49d252f667930c066c Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Thu, 25 May 2017 07:27:35 -0700 -Subject: [PATCH 13/65] apparmor: use macro template to simplify namespace - seq_files -Git-commit: 64c8697045f87713f0648e8429fcc3a0c4c61ffd -Patch-mainline: v4.13-rc1 -References: FATE#323500 - -Signed-off-by: John Johansen -Reviewed-by: Seth Arnold -Reviewed-by: Kees Cook -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/apparmorfs.c | 53 +++++++++++++++++++----------------------- - 1 file changed, 24 insertions(+), 29 deletions(-) - -diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c -index 750431b0ec4e..16680d15d43e 100644 ---- a/security/apparmor/apparmorfs.c -+++ b/security/apparmor/apparmorfs.c -@@ -488,9 +488,27 @@ SEQ_PROFILE_FOPS(mode); - SEQ_PROFILE_FOPS(attach); - SEQ_PROFILE_FOPS(hash); - -+/* -+ * namespace based files -+ * several root files and -+ * policy/ * -+ */ - -+#define SEQ_NS_FOPS(NAME) \ -+static int seq_ns_ ##NAME ##_open(struct inode *inode, struct file *file) \ -+{ \ -+ return single_open(file, seq_ns_ ##NAME ##_show, inode->i_private); \ -+} \ -+ \ -+static const struct file_operations seq_ns_ ##NAME ##_fops = { \ -+ .owner = THIS_MODULE, \ -+ .open = seq_ns_ ##NAME ##_open, \ -+ .read = seq_read, \ -+ .llseek = seq_lseek, \ -+ .release = single_release, \ -+} \ - --static int aa_fs_seq_show_ns_level(struct seq_file *seq, void *v) -+static int seq_ns_level_show(struct seq_file *seq, void *v) - { - struct aa_ns *ns = aa_current_profile()->ns; - -@@ -499,20 +517,7 @@ static int aa_fs_seq_show_ns_level(struct seq_file *seq, void *v) - return 0; - } - --static int aa_fs_seq_open_ns_level(struct inode *inode, struct file *file) --{ -- return single_open(file, aa_fs_seq_show_ns_level, inode->i_private); --} -- --static const struct file_operations aa_fs_ns_level = { -- .owner = THIS_MODULE, -- .open = aa_fs_seq_open_ns_level, -- .read = seq_read, -- .llseek = seq_lseek, -- .release = single_release, --}; -- --static int aa_fs_seq_show_ns_name(struct seq_file *seq, void *v) -+static int seq_ns_name_show(struct seq_file *seq, void *v) - { - struct aa_ns *ns = aa_current_profile()->ns; - -@@ -521,18 +526,8 @@ static int aa_fs_seq_show_ns_name(struct seq_file *seq, void *v) - return 0; - } - --static int aa_fs_seq_open_ns_name(struct inode *inode, struct file *file) --{ -- return single_open(file, aa_fs_seq_show_ns_name, inode->i_private); --} -- --static const struct file_operations aa_fs_ns_name = { -- .owner = THIS_MODULE, -- .open = aa_fs_seq_open_ns_name, -- .read = seq_read, -- .llseek = seq_lseek, -- .release = single_release, --}; -+SEQ_NS_FOPS(level); -+SEQ_NS_FOPS(name); - - - /* policy/raw_data/ * file ops */ -@@ -1363,8 +1358,8 @@ static struct aa_fs_entry aa_fs_entry_features[] = { - - static struct aa_fs_entry aa_fs_entry_apparmor[] = { - AA_FS_FILE_FOPS(".access", 0640, &aa_fs_access), -- AA_FS_FILE_FOPS(".ns_level", 0666, &aa_fs_ns_level), -- AA_FS_FILE_FOPS(".ns_name", 0640, &aa_fs_ns_name), -+ AA_FS_FILE_FOPS(".ns_level", 0666, &seq_ns_level_fops), -+ AA_FS_FILE_FOPS(".ns_name", 0640, &seq_ns_name_fops), - AA_FS_FILE_FOPS("profiles", 0440, &aa_fs_profiles_fops), - AA_FS_DIR("features", aa_fs_entry_features), - { } --- -2.12.3 - diff --git a/patches.apparmor/0014-apparmor-add-custom-apparmorfs-that-will-be-used-by-.patch b/patches.apparmor/0014-apparmor-add-custom-apparmorfs-that-will-be-used-by-.patch deleted file mode 100644 index f0f99be..0000000 --- a/patches.apparmor/0014-apparmor-add-custom-apparmorfs-that-will-be-used-by-.patch +++ /dev/null @@ -1,487 +0,0 @@ -From de1c3c809dd096b96bb0eca649fd5895c304b03f Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Thu, 25 May 2017 05:52:56 -0700 -Subject: [PATCH 14/65] apparmor: add custom apparmorfs that will be used by - policy namespace files -Git-commit: a481f4d917835cad86701fc0d1e620c74bb5cd5f -Patch-mainline: v4.13-rc1 -References: FATE#323500 -Acked-by: Goldwyn Rodrigues - -AppArmor policy needs to be able to be resolved based on the policy -namespace a task is confined by. Add a base apparmorfs filesystem that -(like nsfs) will exist as a kern mount and be accessed via jump_link -through a securityfs file. - -Setup the base apparmorfs fns and data, but don't use it yet. - -Signed-off-by: John Johansen -Reviewed-by: Seth Arnold -Reviewed-by: Kees Cook ---- - include/uapi/linux/magic.h | 2 + - security/apparmor/apparmorfs.c | 353 +++++++++++++++++++++++++++++++++++++++-- - 2 files changed, 338 insertions(+), 17 deletions(-) - -diff --git a/include/uapi/linux/magic.h b/include/uapi/linux/magic.h -index e230af2e6855..a0908f1d2760 100644 ---- a/include/uapi/linux/magic.h -+++ b/include/uapi/linux/magic.h -@@ -80,6 +80,8 @@ - #define BTRFS_TEST_MAGIC 0x73727279 - #define NSFS_MAGIC 0x6e736673 - #define BPF_FS_MAGIC 0xcafe4a11 -+#define AAFS_MAGIC 0x5a3c69f0 -+ - /* Since UDF 2.01 is ISO 13346 based... */ - #define UDF_SUPER_MAGIC 0x15013346 - #define BALLOON_KVM_MAGIC 0x13661366 -diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c -index 16680d15d43e..7e4b7f28ee20 100644 ---- a/security/apparmor/apparmorfs.c -+++ b/security/apparmor/apparmorfs.c -@@ -22,8 +22,9 @@ - #include - #include - #include --#include - #include -+#include -+#include - - #include "include/apparmor.h" - #include "include/apparmorfs.h" -@@ -74,6 +75,265 @@ static int mangle_name(const char *name, char *target) - return t - target; - } - -+ -+/* -+ * aafs - core fns and data for the policy tree -+ */ -+ -+#define AAFS_NAME "apparmorfs" -+static struct vfsmount *aafs_mnt; -+static int aafs_count; -+ -+ -+static int aafs_show_path(struct seq_file *seq, struct dentry *dentry) -+{ -+ struct inode *inode = d_inode(dentry); -+ -+ seq_printf(seq, "%s:[%lu]", AAFS_NAME, inode->i_ino); -+ return 0; -+} -+ -+static void aafs_evict_inode(struct inode *inode) -+{ -+ truncate_inode_pages_final(&inode->i_data); -+ clear_inode(inode); -+ if (S_ISLNK(inode->i_mode)) -+ kfree(inode->i_link); -+} -+ -+static const struct super_operations aafs_super_ops = { -+ .statfs = simple_statfs, -+ .evict_inode = aafs_evict_inode, -+ .show_path = aafs_show_path, -+}; -+ -+static int fill_super(struct super_block *sb, void *data, int silent) -+{ -+ static struct tree_descr files[] = { {""} }; -+ int error; -+ -+ error = simple_fill_super(sb, AAFS_MAGIC, files); -+ if (error) -+ return error; -+ sb->s_op = &aafs_super_ops; -+ -+ return 0; -+} -+ -+static struct dentry *aafs_mount(struct file_system_type *fs_type, -+ int flags, const char *dev_name, void *data) -+{ -+ return mount_single(fs_type, flags, data, fill_super); -+} -+ -+static struct file_system_type aafs_ops = { -+ .owner = THIS_MODULE, -+ .name = AAFS_NAME, -+ .mount = aafs_mount, -+ .kill_sb = kill_anon_super, -+}; -+ -+/** -+ * __aafs_setup_d_inode - basic inode setup for apparmorfs -+ * @dir: parent directory for the dentry -+ * @dentry: dentry we are seting the inode up for -+ * @mode: permissions the file should have -+ * @data: data to store on inode.i_private, available in open() -+ * @link: if symlink, symlink target string -+ * @fops: struct file_operations that should be used -+ * @iops: struct of inode_operations that should be used -+ */ -+static int __aafs_setup_d_inode(struct inode *dir, struct dentry *dentry, -+ umode_t mode, void *data, char *link, -+ const struct file_operations *fops, -+ const struct inode_operations *iops) -+{ -+ struct inode *inode = new_inode(dir->i_sb); -+ -+ AA_BUG(!dir); -+ AA_BUG(!dentry); -+ -+ if (!inode) -+ return -ENOMEM; -+ -+ inode->i_ino = get_next_ino(); -+ inode->i_mode = mode; -+ inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode); -+ inode->i_private = data; -+ if (S_ISDIR(mode)) { -+ inode->i_op = iops ? iops : &simple_dir_inode_operations; -+ inode->i_fop = &simple_dir_operations; -+ inc_nlink(inode); -+ inc_nlink(dir); -+ } else if (S_ISLNK(mode)) { -+ inode->i_op = iops ? iops : &simple_symlink_inode_operations; -+ inode->i_link = link; -+ } else { -+ inode->i_fop = fops; -+ } -+ d_instantiate(dentry, inode); -+ dget(dentry); -+ -+ return 0; -+} -+ -+/** -+ * aafs_create - create a dentry in the apparmorfs filesystem -+ * -+ * @name: name of dentry to create -+ * @mode: permissions the file should have -+ * @parent: parent directory for this dentry -+ * @data: data to store on inode.i_private, available in open() -+ * @link: if symlink, symlink target string -+ * @fops: struct file_operations that should be used for -+ * @iops: struct of inode_operations that should be used -+ * -+ * This is the basic "create a xxx" function for apparmorfs. -+ * -+ * Returns a pointer to a dentry if it succeeds, that must be free with -+ * aafs_remove(). Will return ERR_PTR on failure. -+ */ -+static struct dentry *aafs_create(const char *name, umode_t mode, -+ struct dentry *parent, void *data, void *link, -+ const struct file_operations *fops, -+ const struct inode_operations *iops) -+{ -+ struct dentry *dentry; -+ struct inode *dir; -+ int error; -+ -+ AA_BUG(!name); -+ AA_BUG(!parent); -+ -+ if (!(mode & S_IFMT)) -+ mode = (mode & S_IALLUGO) | S_IFREG; -+ -+ error = simple_pin_fs(&aafs_ops, &aafs_mnt, &aafs_count); -+ if (error) -+ return ERR_PTR(error); -+ -+ dir = d_inode(parent); -+ -+ inode_lock(dir); -+ dentry = lookup_one_len(name, parent, strlen(name)); -+ if (IS_ERR(dentry)) -+ goto fail_lock; -+ -+ if (d_really_is_positive(dentry)) { -+ error = -EEXIST; -+ goto fail_dentry; -+ } -+ -+ error = __aafs_setup_d_inode(dir, dentry, mode, data, link, fops, iops); -+ if (error) -+ goto fail_dentry; -+ inode_unlock(dir); -+ -+ return dentry; -+ -+fail_dentry: -+ dput(dentry); -+ -+fail_lock: -+ inode_unlock(dir); -+ simple_release_fs(&aafs_mnt, &aafs_count); -+ -+ return ERR_PTR(error); -+} -+ -+/** -+ * aafs_create_file - create a file in the apparmorfs filesystem -+ * -+ * @name: name of dentry to create -+ * @mode: permissions the file should have -+ * @parent: parent directory for this dentry -+ * @data: data to store on inode.i_private, available in open() -+ * @fops: struct file_operations that should be used for -+ * -+ * see aafs_create -+ */ -+static struct dentry *aafs_create_file(const char *name, umode_t mode, -+ struct dentry *parent, void *data, -+ const struct file_operations *fops) -+{ -+ return aafs_create(name, mode, parent, data, NULL, fops, NULL); -+} -+ -+/** -+ * aafs_create_dir - create a directory in the apparmorfs filesystem -+ * -+ * @name: name of dentry to create -+ * @parent: parent directory for this dentry -+ * -+ * see aafs_create -+ */ -+static struct dentry *aafs_create_dir(const char *name, struct dentry *parent) -+{ -+ return aafs_create(name, S_IFDIR | 0755, parent, NULL, NULL, NULL, -+ NULL); -+} -+ -+/** -+ * aafs_create_symlink - create a symlink in the apparmorfs filesystem -+ * @name: name of dentry to create -+ * @parent: parent directory for this dentry -+ * @target: if symlink, symlink target string -+ * @iops: struct of inode_operations that should be used -+ * -+ * If @target parameter is %NULL, then the @iops parameter needs to be -+ * setup to handle .readlink and .get_link inode_operations. -+ */ -+static struct dentry *aafs_create_symlink(const char *name, -+ struct dentry *parent, -+ const char *target, -+ const struct inode_operations *iops) -+{ -+ struct dentry *dent; -+ char *link = NULL; -+ -+ if (target) { -+ link = kstrdup(target, GFP_KERNEL); -+ if (!link) -+ return ERR_PTR(-ENOMEM); -+ } -+ dent = aafs_create(name, S_IFLNK | 0444, parent, NULL, link, NULL, -+ iops); -+ if (IS_ERR(dent)) -+ kfree(link); -+ -+ return dent; -+} -+ -+/** -+ * aafs_remove - removes a file or directory from the apparmorfs filesystem -+ * -+ * @dentry: dentry of the file/directory/symlink to removed. -+ */ -+static void aafs_remove(struct dentry *dentry) -+{ -+ struct inode *dir; -+ -+ if (!dentry || IS_ERR(dentry)) -+ return; -+ -+ dir = d_inode(dentry->d_parent); -+ inode_lock(dir); -+ if (simple_positive(dentry)) { -+ if (d_is_dir(dentry)) -+ simple_rmdir(dir, dentry); -+ else -+ simple_unlink(dir, dentry); -+ dput(dentry); -+ } -+ inode_unlock(dir); -+ simple_release_fs(&aafs_mnt, &aafs_count); -+} -+ -+ -+/* -+ * aa_fs - policy load/replace/remove -+ */ -+ - /** - * aa_simple_write_to_buffer - common routine for getting policy from user - * @userbuf: user buffer to copy data from (NOT NULL) -@@ -1369,14 +1629,14 @@ static struct aa_fs_entry aa_fs_entry = - AA_FS_DIR("apparmor", aa_fs_entry_apparmor); - - /** -- * aafs_create_file - create a file entry in the apparmor securityfs -+ * entry_create_file - create a file entry in the apparmor securityfs - * @fs_file: aa_fs_entry to build an entry for (NOT NULL) - * @parent: the parent dentry in the securityfs - * -- * Use aafs_remove_file to remove entries created with this fn. -+ * Use entry_remove_file to remove entries created with this fn. - */ --static int __init aafs_create_file(struct aa_fs_entry *fs_file, -- struct dentry *parent) -+static int __init entry_create_file(struct aa_fs_entry *fs_file, -+ struct dentry *parent) - { - int error = 0; - -@@ -1391,15 +1651,15 @@ static int __init aafs_create_file(struct aa_fs_entry *fs_file, - return error; - } - --static void __init aafs_remove_dir(struct aa_fs_entry *fs_dir); -+static void __init entry_remove_dir(struct aa_fs_entry *fs_dir); - /** -- * aafs_create_dir - recursively create a directory entry in the securityfs -+ * entry_create_dir - recursively create a directory entry in the securityfs - * @fs_dir: aa_fs_entry (and all child entries) to build (NOT NULL) - * @parent: the parent dentry in the securityfs - * -- * Use aafs_remove_dir to remove entries created with this fn. -+ * Use entry_remove_dir to remove entries created with this fn. - */ --static int __init aafs_create_dir(struct aa_fs_entry *fs_dir, -+static int __init entry_create_dir(struct aa_fs_entry *fs_dir, - struct dentry *parent) - { - struct aa_fs_entry *fs_file; -@@ -1413,9 +1673,9 @@ static int __init aafs_create_dir(struct aa_fs_entry *fs_dir, - - for (fs_file = fs_dir->v.files; fs_file && fs_file->name; ++fs_file) { - if (fs_file->v_type == AA_FS_TYPE_DIR) -- error = aafs_create_dir(fs_file, fs_dir->dentry); -+ error = entry_create_dir(fs_file, fs_dir->dentry); - else -- error = aafs_create_file(fs_file, fs_dir->dentry); -+ error = entry_create_file(fs_file, fs_dir->dentry); - if (error) - goto failed; - } -@@ -1423,7 +1683,7 @@ static int __init aafs_create_dir(struct aa_fs_entry *fs_dir, - return 0; - - failed: -- aafs_remove_dir(fs_dir); -+ entry_remove_dir(fs_dir); - - return error; - } -@@ -1442,16 +1702,16 @@ static void __init aafs_remove_file(struct aa_fs_entry *fs_file) - } - - /** -- * aafs_remove_dir - recursively drop a directory entry from the securityfs -+ * entry_remove_dir - recursively drop a directory entry from the securityfs - * @fs_dir: aa_fs_entry (and all child entries) to detach (NOT NULL) - */ --static void __init aafs_remove_dir(struct aa_fs_entry *fs_dir) -+static void __init entry_remove_dir(struct aa_fs_entry *fs_dir) - { - struct aa_fs_entry *fs_file; - - for (fs_file = fs_dir->v.files; fs_file && fs_file->name; ++fs_file) { - if (fs_file->v_type == AA_FS_TYPE_DIR) -- aafs_remove_dir(fs_file); -+ entry_remove_dir(fs_file); - else - aafs_remove_file(fs_file); - } -@@ -1466,7 +1726,7 @@ static void __init aafs_remove_dir(struct aa_fs_entry *fs_dir) - */ - void __init aa_destroy_aafs(void) - { -- aafs_remove_dir(&aa_fs_entry); -+ entry_remove_dir(&aa_fs_entry); - } - - -@@ -1515,6 +1775,59 @@ static int aa_mk_null_file(struct dentry *parent) - return error; - } - -+ -+ -+static const char *policy_get_link(struct dentry *dentry, -+ struct inode *inode, -+ struct delayed_call *done) -+{ -+ struct aa_ns *ns; -+ struct path path; -+ -+ if (!dentry) -+ return ERR_PTR(-ECHILD); -+ ns = aa_get_current_ns(); -+ path.mnt = mntget(aafs_mnt); -+ path.dentry = dget(ns_dir(ns)); -+ nd_jump_link(&path); -+ aa_put_ns(ns); -+ -+ return NULL; -+} -+ -+static int ns_get_name(char *buf, size_t size, struct aa_ns *ns, -+ struct inode *inode) -+{ -+ int res = snprintf(buf, size, "%s:[%lu]", AAFS_NAME, inode->i_ino); -+ -+ if (res < 0 || res >= size) -+ res = -ENOENT; -+ -+ return res; -+} -+ -+static int policy_readlink(struct dentry *dentry, char __user *buffer, -+ int buflen) -+{ -+ struct aa_ns *ns; -+ char name[32]; -+ int res; -+ -+ ns = aa_get_current_ns(); -+ res = ns_get_name(name, sizeof(name), ns, d_inode(dentry)); -+ if (res >= 0) -+ res = readlink_copy(buffer, buflen, name); -+ aa_put_ns(ns); -+ -+ return res; -+} -+ -+static const struct inode_operations policy_link_iops = { -+ .readlink = policy_readlink, -+ .get_link = policy_get_link, -+}; -+ -+ - /** - * aa_create_aafs - create the apparmor security filesystem - * -@@ -1535,8 +1848,14 @@ static int __init aa_create_aafs(void) - return -EEXIST; - } - -+ /* setup apparmorfs used to virtualize policy/ */ -+ aafs_mnt = kern_mount(&aafs_ops); -+ if (IS_ERR(aafs_mnt)) -+ panic("can't set apparmorfs up\n"); -+ aafs_mnt->mnt_sb->s_flags &= ~MS_NOUSER; -+ - /* Populate fs tree. */ -- error = aafs_create_dir(&aa_fs_entry, NULL); -+ error = entry_create_dir(&aa_fs_entry, NULL); - if (error) - goto error; - --- -2.12.3 - diff --git a/patches.apparmor/0014-apparmor-ensure-unconfined-profiles-have-dfas-initia.patch b/patches.apparmor/0014-apparmor-ensure-unconfined-profiles-have-dfas-initia.patch deleted file mode 100644 index df260c8..0000000 --- a/patches.apparmor/0014-apparmor-ensure-unconfined-profiles-have-dfas-initia.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 970d4f158cab54cc90f649fa5ed1a4c5dcec001d Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Wed, 16 Aug 2017 05:48:06 -0700 -Subject: [PATCH 14/17] apparmor: ensure unconfined profiles have dfas initialized -References: FATE#323500 -Patch-mainline: v4.14-rc2 -Git-commit: 15372b97aa7593c6f5bc1afe69f42fd403c40685 - -Generally unconfined has early bailout tests and does not need the -dfas initialized, however if an early bailout test is ever missed -it will result in an oops. - -Be defensive and initialize the unconfined profile to have null dfas -(no permission) so if an early bailout test is missed we fail -closed (no perms granted) instead of oopsing. - -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/policy_ns.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/security/apparmor/policy_ns.c b/security/apparmor/policy_ns.c -index 351d3bab3a3d..62a3589c62ab 100644 ---- a/security/apparmor/policy_ns.c -+++ b/security/apparmor/policy_ns.c -@@ -112,6 +112,8 @@ static struct aa_ns *alloc_ns(const char *prefix, const char *name) - ns->unconfined->label.flags |= FLAG_IX_ON_NAME_ERROR | - FLAG_IMMUTIBLE | FLAG_NS_COUNT | FLAG_UNCONFINED; - ns->unconfined->mode = APPARMOR_UNCONFINED; -+ ns->unconfined->file.dfa = aa_get_dfa(nulldfa); -+ ns->unconfined->policy.dfa = aa_get_dfa(nulldfa); - - /* ns and ns->unconfined share ns->unconfined refcount */ - ns->unconfined->ns = ns; --- -2.14.1 - diff --git a/patches.apparmor/0015-apparmor-fix-incorrect-type-assignment-when-freeing-.patch b/patches.apparmor/0015-apparmor-fix-incorrect-type-assignment-when-freeing-.patch deleted file mode 100644 index 96286de..0000000 --- a/patches.apparmor/0015-apparmor-fix-incorrect-type-assignment-when-freeing-.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 3298c42b313d63d48b5f4e0fd9a942beca66d9d0 Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Wed, 16 Aug 2017 09:33:48 -0700 -Subject: [PATCH 15/17] apparmor: fix incorrect type assignment when freeing proxies -References: FATE#323500 -Patch-mainline: v4.14-rc2 -Git-commit: bc4d82fb946e7b471eab2a80e384227c4eb15652 - -sparse reports - -poisoning the proxy->label before freeing the struct is resulting in -a sparse build warning. -../security/apparmor/label.c:52:30: warning: incorrect type in assignment (different address spaces) -../security/apparmor/label.c:52:30: expected struct aa_label [noderef] *label -../security/apparmor/label.c:52:30: got struct aa_label * - -fix with RCU_INIT_POINTER as this is one of those cases where -rcu_assign_pointer() is not needed. - -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/label.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/security/apparmor/label.c b/security/apparmor/label.c -index 52b4ef14840d..c5b99b954580 100644 ---- a/security/apparmor/label.c -+++ b/security/apparmor/label.c -@@ -49,7 +49,7 @@ static void free_proxy(struct aa_proxy *proxy) - /* p->label will not updated any more as p is dead */ - aa_put_label(rcu_dereference_protected(proxy->label, true)); - memset(proxy, 0, sizeof(*proxy)); -- proxy->label = (struct aa_label *) PROXY_POISON; -+ RCU_INIT_POINTER(proxy->label, (struct aa_label *)PROXY_POISON); - kfree(proxy); - } - } --- -2.14.1 - diff --git a/patches.apparmor/0015-apparmor-rename-apparmor-file-fns-and-data-to-indica.patch b/patches.apparmor/0015-apparmor-rename-apparmor-file-fns-and-data-to-indica.patch deleted file mode 100644 index 542ec88..0000000 --- a/patches.apparmor/0015-apparmor-rename-apparmor-file-fns-and-data-to-indica.patch +++ /dev/null @@ -1,775 +0,0 @@ -From 0966d2dc636cd82765f02cfc14c4b4b9a7d9f28e Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Thu, 25 May 2017 06:23:42 -0700 -Subject: [PATCH 15/65] apparmor: rename apparmor file fns and data to indicate - use -Git-commit: c97204baf840bf850e14ef4f5f43251239ca43b6 -Patch-mainline: v4.13-rc1 -References: FATE#323500 - -prefixes are used for fns/data that are not static to apparmorfs.c -with the prefixes being - aafs - special magic apparmorfs for policy namespace data - aa_sfs - for fns/data that go into securityfs - aa_fs - for fns/data that may be used in the either of aafs or - securityfs - -Signed-off-by: John Johansen -Reviewed-by: Seth Arnold -Reviewed-by: Kees Cook -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/Makefile | 6 +- - security/apparmor/apparmorfs.c | 213 ++++++++++++++++++++------------- - security/apparmor/capability.c | 4 +- - security/apparmor/include/apparmorfs.h | 58 ++++----- - security/apparmor/include/capability.h | 2 +- - security/apparmor/include/resource.h | 2 +- - security/apparmor/policy.c | 6 +- - security/apparmor/policy_ns.c | 4 +- - security/apparmor/resource.c | 4 +- - 9 files changed, 172 insertions(+), 127 deletions(-) - -diff --git a/security/apparmor/Makefile b/security/apparmor/Makefile -index 2ded2f1be98b..b3e7c04b7e7b 100644 ---- a/security/apparmor/Makefile -+++ b/security/apparmor/Makefile -@@ -20,7 +20,7 @@ cmd_make-caps = echo "static const char *const capability_names[] = {" > $@ ;\ - sed $< >>$@ -r -n -e '/CAP_FS_MASK/d' \ - -e 's/^\#define[ \t]+CAP_([A-Z0-9_]+)[ \t]+([0-9]+)/[\2] = "\L\1",/p';\ - echo "};" >> $@ ;\ -- printf '%s' '\#define AA_FS_CAPS_MASK "' >> $@ ;\ -+ printf '%s' '\#define AA_SFS_CAPS_MASK "' >> $@ ;\ - sed $< -r -n -e '/CAP_FS_MASK/d' \ - -e 's/^\#define[ \t]+CAP_([A-Z0-9_]+)[ \t]+([0-9]+)/\L\1/p' | \ - tr '\n' ' ' | sed -e 's/ $$/"\n/' >> $@ -@@ -46,7 +46,7 @@ cmd_make-caps = echo "static const char *const capability_names[] = {" > $@ ;\ - # #define RLIMIT_FSIZE 1 /* Maximum filesize */ - # #define RLIMIT_STACK 3 /* max stack size */ - # to --# #define AA_FS_RLIMIT_MASK "fsize stack" -+# #define AA_SFS_RLIMIT_MASK "fsize stack" - quiet_cmd_make-rlim = GEN $@ - cmd_make-rlim = echo "static const char *const rlim_names[RLIM_NLIMITS] = {" \ - > $@ ;\ -@@ -56,7 +56,7 @@ cmd_make-rlim = echo "static const char *const rlim_names[RLIM_NLIMITS] = {" \ - echo "static const int rlim_map[RLIM_NLIMITS] = {" >> $@ ;\ - sed -r -n "s/^\# ?define[ \t]+(RLIMIT_[A-Z0-9_]+).*/\1,/p" $< >> $@ ;\ - echo "};" >> $@ ; \ -- printf '%s' '\#define AA_FS_RLIMIT_MASK "' >> $@ ;\ -+ printf '%s' '\#define AA_SFS_RLIMIT_MASK "' >> $@ ;\ - sed -r -n 's/^\# ?define[ \t]+RLIMIT_([A-Z0-9_]+).*/\L\1/p' $< | \ - tr '\n' ' ' | sed -e 's/ $$/"\n/' >> $@ - -diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c -index 7e4b7f28ee20..35b822c4a079 100644 ---- a/security/apparmor/apparmorfs.c -+++ b/security/apparmor/apparmorfs.c -@@ -36,6 +36,35 @@ - #include "include/resource.h" - #include "include/policy_unpack.h" - -+/* -+ * The apparmor filesystem interface used for policy load and introspection -+ * The interface is split into two main components based on their function -+ * a securityfs component: -+ * used for static files that are always available, and which allows -+ * userspace to specificy the location of the security filesystem. -+ * -+ * fns and data are prefixed with -+ * aa_sfs_ -+ * -+ * an apparmorfs component: -+ * used loaded policy content and introspection. It is not part of a -+ * regular mounted filesystem and is available only through the magic -+ * policy symlink in the root of the securityfs apparmor/ directory. -+ * Tasks queries will be magically redirected to the correct portion -+ * of the policy tree based on their confinement. -+ * -+ * fns and data are prefixed with -+ * aafs_ -+ * -+ * The aa_fs_ prefix is used to indicate the fn is used by both the -+ * securityfs and apparmorfs filesystems. -+ */ -+ -+ -+/* -+ * support fns -+ */ -+ - /** - * aa_mangle_name - mangle a profile name to std profile layout form - * @name: profile name to mangle (NOT NULL) -@@ -606,28 +635,28 @@ static ssize_t aa_write_access(struct file *file, const char __user *ubuf, - return count; - } - --static const struct file_operations aa_fs_access = { -+static const struct file_operations aa_sfs_access = { - .write = aa_write_access, - .read = simple_transaction_read, - .release = simple_transaction_release, - .llseek = generic_file_llseek, - }; - --static int aa_fs_seq_show(struct seq_file *seq, void *v) -+static int aa_sfs_seq_show(struct seq_file *seq, void *v) - { -- struct aa_fs_entry *fs_file = seq->private; -+ struct aa_sfs_entry *fs_file = seq->private; - - if (!fs_file) - return 0; - - switch (fs_file->v_type) { -- case AA_FS_TYPE_BOOLEAN: -+ case AA_SFS_TYPE_BOOLEAN: - seq_printf(seq, "%s\n", fs_file->v.boolean ? "yes" : "no"); - break; -- case AA_FS_TYPE_STRING: -+ case AA_SFS_TYPE_STRING: - seq_printf(seq, "%s\n", fs_file->v.string); - break; -- case AA_FS_TYPE_U64: -+ case AA_SFS_TYPE_U64: - seq_printf(seq, "%#08lx\n", fs_file->v.u64); - break; - default: -@@ -638,14 +667,14 @@ static int aa_fs_seq_show(struct seq_file *seq, void *v) - return 0; - } - --static int aa_fs_seq_open(struct inode *inode, struct file *file) -+static int aa_sfs_seq_open(struct inode *inode, struct file *file) - { -- return single_open(file, aa_fs_seq_show, inode->i_private); -+ return single_open(file, aa_sfs_seq_show, inode->i_private); - } - --const struct file_operations aa_fs_seq_file_ops = { -+const struct file_operations aa_sfs_seq_file_ops = { - .owner = THIS_MODULE, -- .open = aa_fs_seq_open, -+ .open = aa_sfs_seq_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -@@ -996,7 +1025,12 @@ int __aa_fs_create_rawdata(struct aa_ns *ns, struct aa_loaddata *rawdata) - } - - /** fns to setup dynamic per profile/namespace files **/ --void __aa_fs_profile_rmdir(struct aa_profile *profile) -+ -+/** -+ * -+ * Requires: @profile->ns->lock held -+ */ -+void __aafs_profile_rmdir(struct aa_profile *profile) - { - struct aa_profile *child; - int i; -@@ -1005,7 +1039,7 @@ void __aa_fs_profile_rmdir(struct aa_profile *profile) - return; - - list_for_each_entry(child, &profile->base.profiles, base.list) -- __aa_fs_profile_rmdir(child); -+ __aafs_profile_rmdir(child); - - for (i = AAFS_PROF_SIZEOF - 1; i >= 0; --i) { - struct aa_proxy *proxy; -@@ -1019,8 +1053,12 @@ void __aa_fs_profile_rmdir(struct aa_profile *profile) - } - } - --void __aa_fs_profile_migrate_dents(struct aa_profile *old, -- struct aa_profile *new) -+/** -+ * -+ * Requires: @old->ns->lock held -+ */ -+void __aafs_profile_migrate_dents(struct aa_profile *old, -+ struct aa_profile *new) - { - int i; - -@@ -1081,7 +1119,7 @@ static int gen_symlink_name(char *buffer, size_t bsize, int depth, - /* - * Requires: @profile->ns->lock held - */ --int __aa_fs_profile_mkdir(struct aa_profile *profile, struct dentry *parent) -+int __aafs_profile_mkdir(struct aa_profile *profile, struct dentry *parent) - { - struct aa_profile *child; - struct dentry *dent = NULL, *dir; -@@ -1177,7 +1215,7 @@ int __aa_fs_profile_mkdir(struct aa_profile *profile, struct dentry *parent) - } - - list_for_each_entry(child, &profile->base.profiles, base.list) { -- error = __aa_fs_profile_mkdir(child, prof_child_dir(profile)); -+ error = __aafs_profile_mkdir(child, prof_child_dir(profile)); - if (error) - goto fail2; - } -@@ -1188,7 +1226,7 @@ int __aa_fs_profile_mkdir(struct aa_profile *profile, struct dentry *parent) - error = PTR_ERR(dent); - - fail2: -- __aa_fs_profile_rmdir(profile); -+ __aafs_profile_rmdir(profile); - - return error; - } -@@ -1203,7 +1241,11 @@ static void __aa_fs_list_remove_rawdata(struct aa_ns *ns) - __aa_fs_remove_rawdata(ent); - } - --void __aa_fs_ns_rmdir(struct aa_ns *ns) -+/** -+ * -+ * Requires: @ns->lock held -+ */ -+void __aafs_ns_rmdir(struct aa_ns *ns) - { - struct aa_ns *sub; - struct aa_profile *child; -@@ -1213,11 +1255,11 @@ void __aa_fs_ns_rmdir(struct aa_ns *ns) - return; - - list_for_each_entry(child, &ns->base.profiles, base.list) -- __aa_fs_profile_rmdir(child); -+ __aafs_profile_rmdir(child); - - list_for_each_entry(sub, &ns->sub_ns, base.list) { - mutex_lock(&sub->lock); -- __aa_fs_ns_rmdir(sub); -+ __aafs_ns_rmdir(sub); - mutex_unlock(&sub->lock); - } - -@@ -1247,7 +1289,7 @@ void __aa_fs_ns_rmdir(struct aa_ns *ns) - } - - /* assumes cleanup in caller */ --static int __aa_fs_ns_mkdir_entries(struct aa_ns *ns, struct dentry *dir) -+static int __aafs_ns_mkdir_entries(struct aa_ns *ns, struct dentry *dir) - { - struct dentry *dent; - -@@ -1294,7 +1336,10 @@ static int __aa_fs_ns_mkdir_entries(struct aa_ns *ns, struct dentry *dir) - return 0; - } - --int __aa_fs_ns_mkdir(struct aa_ns *ns, struct dentry *parent, const char *name) -+/* -+ * Requires: @ns->lock held -+ */ -+int __aafs_ns_mkdir(struct aa_ns *ns, struct dentry *parent, const char *name) - { - struct aa_ns *sub; - struct aa_profile *child; -@@ -1314,13 +1359,13 @@ int __aa_fs_ns_mkdir(struct aa_ns *ns, struct dentry *parent, const char *name) - goto fail; - - ns_dir(ns) = dir = dent; -- error = __aa_fs_ns_mkdir_entries(ns, dir); -+ error = __aafs_ns_mkdir_entries(ns, dir); - if (error) - goto fail2; - - /* profiles */ - list_for_each_entry(child, &ns->base.profiles, base.list) { -- error = __aa_fs_profile_mkdir(child, ns_subprofs_dir(ns)); -+ error = __aafs_profile_mkdir(child, ns_subprofs_dir(ns)); - if (error) - goto fail2; - } -@@ -1328,7 +1373,7 @@ int __aa_fs_ns_mkdir(struct aa_ns *ns, struct dentry *parent, const char *name) - /* subnamespaces */ - list_for_each_entry(sub, &ns->sub_ns, base.list) { - mutex_lock(&sub->lock); -- error = __aa_fs_ns_mkdir(sub, ns_subns_dir(ns), NULL); -+ error = __aafs_ns_mkdir(sub, ns_subns_dir(ns), NULL); - mutex_unlock(&sub->lock); - if (error) - goto fail2; -@@ -1340,7 +1385,7 @@ int __aa_fs_ns_mkdir(struct aa_ns *ns, struct dentry *parent, const char *name) - error = PTR_ERR(dent); - - fail2: -- __aa_fs_ns_rmdir(ns); -+ __aafs_ns_rmdir(ns); - - return error; - } -@@ -1550,7 +1595,7 @@ static int seq_show_profile(struct seq_file *f, void *p) - return 0; - } - --static const struct seq_operations aa_fs_profiles_op = { -+static const struct seq_operations aa_sfs_profiles_op = { - .start = p_start, - .next = p_next, - .stop = p_stop, -@@ -1562,7 +1607,7 @@ static int profiles_open(struct inode *inode, struct file *file) - if (!policy_view_capable(NULL)) - return -EACCES; - -- return seq_open(file, &aa_fs_profiles_op); -+ return seq_open(file, &aa_sfs_profiles_op); - } - - static int profiles_release(struct inode *inode, struct file *file) -@@ -1570,7 +1615,7 @@ static int profiles_release(struct inode *inode, struct file *file) - return seq_release(inode, file); - } - --static const struct file_operations aa_fs_profiles_fops = { -+static const struct file_operations aa_sfs_profiles_fops = { - .open = profiles_open, - .read = seq_read, - .llseek = seq_lseek, -@@ -1579,63 +1624,63 @@ static const struct file_operations aa_fs_profiles_fops = { - - - /** Base file system setup **/ --static struct aa_fs_entry aa_fs_entry_file[] = { -- AA_FS_FILE_STRING("mask", "create read write exec append mmap_exec " \ -- "link lock"), -+static struct aa_sfs_entry aa_sfs_entry_file[] = { -+ AA_SFS_FILE_STRING("mask", -+ "create read write exec append mmap_exec link lock"), - { } - }; - --static struct aa_fs_entry aa_fs_entry_domain[] = { -- AA_FS_FILE_BOOLEAN("change_hat", 1), -- AA_FS_FILE_BOOLEAN("change_hatv", 1), -- AA_FS_FILE_BOOLEAN("change_onexec", 1), -- AA_FS_FILE_BOOLEAN("change_profile", 1), -- AA_FS_FILE_BOOLEAN("fix_binfmt_elf_mmap", 1), -- AA_FS_FILE_STRING("version", "1.2"), -+static struct aa_sfs_entry aa_sfs_entry_domain[] = { -+ AA_SFS_FILE_BOOLEAN("change_hat", 1), -+ AA_SFS_FILE_BOOLEAN("change_hatv", 1), -+ AA_SFS_FILE_BOOLEAN("change_onexec", 1), -+ AA_SFS_FILE_BOOLEAN("change_profile", 1), -+ AA_SFS_FILE_BOOLEAN("fix_binfmt_elf_mmap", 1), -+ AA_SFS_FILE_STRING("version", "1.2"), - { } - }; - --static struct aa_fs_entry aa_fs_entry_versions[] = { -- AA_FS_FILE_BOOLEAN("v5", 1), -+static struct aa_sfs_entry aa_sfs_entry_versions[] = { -+ AA_SFS_FILE_BOOLEAN("v5", 1), - { } - }; - --static struct aa_fs_entry aa_fs_entry_policy[] = { -- AA_FS_DIR("versions", aa_fs_entry_versions), -- AA_FS_FILE_BOOLEAN("set_load", 1), -+static struct aa_sfs_entry aa_sfs_entry_policy[] = { -+ AA_SFS_DIR("versions", aa_sfs_entry_versions), -+ AA_SFS_FILE_BOOLEAN("set_load", 1), - { } - }; - --static struct aa_fs_entry aa_fs_entry_features[] = { -- AA_FS_DIR("policy", aa_fs_entry_policy), -- AA_FS_DIR("domain", aa_fs_entry_domain), -- AA_FS_DIR("file", aa_fs_entry_file), -- AA_FS_FILE_U64("capability", VFS_CAP_FLAGS_MASK), -- AA_FS_DIR("rlimit", aa_fs_entry_rlimit), -- AA_FS_DIR("caps", aa_fs_entry_caps), -+static struct aa_sfs_entry aa_sfs_entry_features[] = { -+ AA_SFS_DIR("policy", aa_sfs_entry_policy), -+ AA_SFS_DIR("domain", aa_sfs_entry_domain), -+ AA_SFS_DIR("file", aa_sfs_entry_file), -+ AA_SFS_FILE_U64("capability", VFS_CAP_FLAGS_MASK), -+ AA_SFS_DIR("rlimit", aa_sfs_entry_rlimit), -+ AA_SFS_DIR("caps", aa_sfs_entry_caps), - { } - }; - --static struct aa_fs_entry aa_fs_entry_apparmor[] = { -- AA_FS_FILE_FOPS(".access", 0640, &aa_fs_access), -- AA_FS_FILE_FOPS(".ns_level", 0666, &seq_ns_level_fops), -- AA_FS_FILE_FOPS(".ns_name", 0640, &seq_ns_name_fops), -- AA_FS_FILE_FOPS("profiles", 0440, &aa_fs_profiles_fops), -- AA_FS_DIR("features", aa_fs_entry_features), -+static struct aa_sfs_entry aa_sfs_entry_apparmor[] = { -+ AA_SFS_FILE_FOPS(".access", 0640, &aa_sfs_access), -+ AA_SFS_FILE_FOPS(".ns_level", 0666, &seq_ns_level_fops), -+ AA_SFS_FILE_FOPS(".ns_name", 0640, &seq_ns_name_fops), -+ AA_SFS_FILE_FOPS("profiles", 0440, &aa_sfs_profiles_fops), -+ AA_SFS_DIR("features", aa_sfs_entry_features), - { } - }; - --static struct aa_fs_entry aa_fs_entry = -- AA_FS_DIR("apparmor", aa_fs_entry_apparmor); -+static struct aa_sfs_entry aa_sfs_entry = -+ AA_SFS_DIR("apparmor", aa_sfs_entry_apparmor); - - /** - * entry_create_file - create a file entry in the apparmor securityfs -- * @fs_file: aa_fs_entry to build an entry for (NOT NULL) -+ * @fs_file: aa_sfs_entry to build an entry for (NOT NULL) - * @parent: the parent dentry in the securityfs - * - * Use entry_remove_file to remove entries created with this fn. - */ --static int __init entry_create_file(struct aa_fs_entry *fs_file, -+static int __init entry_create_file(struct aa_sfs_entry *fs_file, - struct dentry *parent) - { - int error = 0; -@@ -1651,18 +1696,18 @@ static int __init entry_create_file(struct aa_fs_entry *fs_file, - return error; - } - --static void __init entry_remove_dir(struct aa_fs_entry *fs_dir); -+static void __init entry_remove_dir(struct aa_sfs_entry *fs_dir); - /** - * entry_create_dir - recursively create a directory entry in the securityfs -- * @fs_dir: aa_fs_entry (and all child entries) to build (NOT NULL) -+ * @fs_dir: aa_sfs_entry (and all child entries) to build (NOT NULL) - * @parent: the parent dentry in the securityfs - * - * Use entry_remove_dir to remove entries created with this fn. - */ --static int __init entry_create_dir(struct aa_fs_entry *fs_dir, -- struct dentry *parent) -+static int __init entry_create_dir(struct aa_sfs_entry *fs_dir, -+ struct dentry *parent) - { -- struct aa_fs_entry *fs_file; -+ struct aa_sfs_entry *fs_file; - struct dentry *dir; - int error; - -@@ -1672,7 +1717,7 @@ static int __init entry_create_dir(struct aa_fs_entry *fs_dir, - fs_dir->dentry = dir; - - for (fs_file = fs_dir->v.files; fs_file && fs_file->name; ++fs_file) { -- if (fs_file->v_type == AA_FS_TYPE_DIR) -+ if (fs_file->v_type == AA_SFS_TYPE_DIR) - error = entry_create_dir(fs_file, fs_dir->dentry); - else - error = entry_create_file(fs_file, fs_dir->dentry); -@@ -1689,10 +1734,10 @@ static int __init entry_create_dir(struct aa_fs_entry *fs_dir, - } - - /** -- * aafs_remove_file - drop a single file entry in the apparmor securityfs -- * @fs_file: aa_fs_entry to detach from the securityfs (NOT NULL) -+ * entry_remove_file - drop a single file entry in the apparmor securityfs -+ * @fs_file: aa_sfs_entry to detach from the securityfs (NOT NULL) - */ --static void __init aafs_remove_file(struct aa_fs_entry *fs_file) -+static void __init entry_remove_file(struct aa_sfs_entry *fs_file) - { - if (!fs_file->dentry) - return; -@@ -1703,20 +1748,20 @@ static void __init aafs_remove_file(struct aa_fs_entry *fs_file) - - /** - * entry_remove_dir - recursively drop a directory entry from the securityfs -- * @fs_dir: aa_fs_entry (and all child entries) to detach (NOT NULL) -+ * @fs_dir: aa_sfs_entry (and all child entries) to detach (NOT NULL) - */ --static void __init entry_remove_dir(struct aa_fs_entry *fs_dir) -+static void __init entry_remove_dir(struct aa_sfs_entry *fs_dir) - { -- struct aa_fs_entry *fs_file; -+ struct aa_sfs_entry *fs_file; - - for (fs_file = fs_dir->v.files; fs_file && fs_file->name; ++fs_file) { -- if (fs_file->v_type == AA_FS_TYPE_DIR) -+ if (fs_file->v_type == AA_SFS_TYPE_DIR) - entry_remove_dir(fs_file); - else -- aafs_remove_file(fs_file); -+ entry_remove_file(fs_file); - } - -- aafs_remove_file(fs_dir); -+ entry_remove_file(fs_dir); - } - - /** -@@ -1726,7 +1771,7 @@ static void __init entry_remove_dir(struct aa_fs_entry *fs_dir) - */ - void __init aa_destroy_aafs(void) - { -- entry_remove_dir(&aa_fs_entry); -+ entry_remove_dir(&aa_sfs_entry); - } - - -@@ -1843,7 +1888,7 @@ static int __init aa_create_aafs(void) - if (!apparmor_initialized) - return 0; - -- if (aa_fs_entry.dentry) { -+ if (aa_sfs_entry.dentry) { - AA_ERROR("%s: AppArmor securityfs already exists\n", __func__); - return -EEXIST; - } -@@ -1855,11 +1900,11 @@ static int __init aa_create_aafs(void) - aafs_mnt->mnt_sb->s_flags &= ~MS_NOUSER; - - /* Populate fs tree. */ -- error = entry_create_dir(&aa_fs_entry, NULL); -+ error = entry_create_dir(&aa_sfs_entry, NULL); - if (error) - goto error; - -- dent = securityfs_create_file(".load", 0666, aa_fs_entry.dentry, -+ dent = securityfs_create_file(".load", 0666, aa_sfs_entry.dentry, - NULL, &aa_fs_profile_load); - if (IS_ERR(dent)) { - error = PTR_ERR(dent); -@@ -1867,7 +1912,7 @@ static int __init aa_create_aafs(void) - } - ns_subload(root_ns) = dent; - -- dent = securityfs_create_file(".replace", 0666, aa_fs_entry.dentry, -+ dent = securityfs_create_file(".replace", 0666, aa_sfs_entry.dentry, - NULL, &aa_fs_profile_replace); - if (IS_ERR(dent)) { - error = PTR_ERR(dent); -@@ -1875,7 +1920,7 @@ static int __init aa_create_aafs(void) - } - ns_subreplace(root_ns) = dent; - -- dent = securityfs_create_file(".remove", 0666, aa_fs_entry.dentry, -+ dent = securityfs_create_file(".remove", 0666, aa_sfs_entry.dentry, - NULL, &aa_fs_profile_remove); - if (IS_ERR(dent)) { - error = PTR_ERR(dent); -@@ -1884,13 +1929,13 @@ static int __init aa_create_aafs(void) - ns_subremove(root_ns) = dent; - - mutex_lock(&root_ns->lock); -- error = __aa_fs_ns_mkdir(root_ns, aa_fs_entry.dentry, "policy"); -+ error = __aafs_ns_mkdir(root_ns, aa_sfs_entry.dentry, "policy"); - mutex_unlock(&root_ns->lock); - - if (error) - goto error; - -- error = aa_mk_null_file(aa_fs_entry.dentry); -+ error = aa_mk_null_file(aa_sfs_entry.dentry); - if (error) - goto error; - -diff --git a/security/apparmor/capability.c b/security/apparmor/capability.c -index ed0a3e6b8022..3bc19843d8df 100644 ---- a/security/apparmor/capability.c -+++ b/security/apparmor/capability.c -@@ -28,8 +28,8 @@ - */ - #include "capability_names.h" - --struct aa_fs_entry aa_fs_entry_caps[] = { -- AA_FS_FILE_STRING("mask", AA_FS_CAPS_MASK), -+struct aa_sfs_entry aa_sfs_entry_caps[] = { -+ AA_SFS_FILE_STRING("mask", AA_SFS_CAPS_MASK), - { } - }; - -diff --git a/security/apparmor/include/apparmorfs.h b/security/apparmor/include/apparmorfs.h -index 0b6d32b3f05e..bcad87740cb6 100644 ---- a/security/apparmor/include/apparmorfs.h -+++ b/security/apparmor/include/apparmorfs.h -@@ -17,49 +17,49 @@ - - extern struct path aa_null; - --enum aa_fs_type { -- AA_FS_TYPE_BOOLEAN, -- AA_FS_TYPE_STRING, -- AA_FS_TYPE_U64, -- AA_FS_TYPE_FOPS, -- AA_FS_TYPE_DIR, -+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_fs_entry; -+struct aa_sfs_entry; - --struct aa_fs_entry { -+struct aa_sfs_entry { - const char *name; - struct dentry *dentry; - umode_t mode; -- enum aa_fs_type v_type; -+ enum aa_sfs_type v_type; - union { - bool boolean; - char *string; - unsigned long u64; -- struct aa_fs_entry *files; -+ struct aa_sfs_entry *files; - } v; - const struct file_operations *file_ops; - }; - --extern const struct file_operations aa_fs_seq_file_ops; -+extern const struct file_operations aa_sfs_seq_file_ops; - --#define AA_FS_FILE_BOOLEAN(_name, _value) \ -+#define AA_SFS_FILE_BOOLEAN(_name, _value) \ - { .name = (_name), .mode = 0444, \ -- .v_type = AA_FS_TYPE_BOOLEAN, .v.boolean = (_value), \ -- .file_ops = &aa_fs_seq_file_ops } --#define AA_FS_FILE_STRING(_name, _value) \ -+ .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_FS_TYPE_STRING, .v.string = (_value), \ -- .file_ops = &aa_fs_seq_file_ops } --#define AA_FS_FILE_U64(_name, _value) \ -+ .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_FS_TYPE_U64, .v.u64 = (_value), \ -- .file_ops = &aa_fs_seq_file_ops } --#define AA_FS_FILE_FOPS(_name, _mode, _fops) \ -- { .name = (_name), .v_type = AA_FS_TYPE_FOPS, \ -+ .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_FS_DIR(_name, _value) \ -- { .name = (_name), .v_type = AA_FS_TYPE_DIR, .v.files = (_value) } -+#define AA_SFS_DIR(_name, _value) \ -+ { .name = (_name), .v_type = AA_SFS_TYPE_DIR, .v.files = (_value) } - - extern void __init aa_destroy_aafs(void); - -@@ -107,12 +107,12 @@ enum aafs_prof_type { - #define prof_child_dir(X) ((X)->dents[AAFS_PROF_PROFS]) - - void __aa_bump_ns_revision(struct aa_ns *ns); --void __aa_fs_profile_rmdir(struct aa_profile *profile); --void __aa_fs_profile_migrate_dents(struct aa_profile *old, -+void __aafs_profile_rmdir(struct aa_profile *profile); -+void __aafs_profile_migrate_dents(struct aa_profile *old, - struct aa_profile *new); --int __aa_fs_profile_mkdir(struct aa_profile *profile, struct dentry *parent); --void __aa_fs_ns_rmdir(struct aa_ns *ns); --int __aa_fs_ns_mkdir(struct aa_ns *ns, struct dentry *parent, -+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 aa_loaddata; -diff --git a/security/apparmor/include/capability.h b/security/apparmor/include/capability.h -index fc3fa381d850..1218e95ebe49 100644 ---- a/security/apparmor/include/capability.h -+++ b/security/apparmor/include/capability.h -@@ -36,7 +36,7 @@ struct aa_caps { - kernel_cap_t extended; - }; - --extern struct aa_fs_entry aa_fs_entry_caps[]; -+extern struct aa_sfs_entry aa_sfs_entry_caps[]; - - int aa_capable(struct aa_profile *profile, int cap, int audit); - -diff --git a/security/apparmor/include/resource.h b/security/apparmor/include/resource.h -index d3f4cf027957..f6289f335c4d 100644 ---- a/security/apparmor/include/resource.h -+++ b/security/apparmor/include/resource.h -@@ -34,7 +34,7 @@ struct aa_rlimit { - struct rlimit limits[RLIM_NLIMITS]; - }; - --extern struct aa_fs_entry aa_fs_entry_rlimit[]; -+extern struct aa_sfs_entry aa_sfs_entry_rlimit[]; - - int aa_map_resource(int resource); - int aa_task_setrlimit(struct aa_profile *profile, struct task_struct *, -diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c -index 5968914247a4..a5e8559e4dec 100644 ---- a/security/apparmor/policy.c -+++ b/security/apparmor/policy.c -@@ -160,7 +160,7 @@ static void __remove_profile(struct aa_profile *profile) - __aa_profile_list_release(&profile->base.profiles); - /* released by free_profile */ - __aa_update_proxy(profile, profile->ns->unconfined); -- __aa_fs_profile_rmdir(profile); -+ __aafs_profile_rmdir(profile); - __list_remove_profile(profile); - } - -@@ -784,7 +784,7 @@ static void __replace_profile(struct aa_profile *old, struct aa_profile *new, - /* aafs interface uses proxy */ - rcu_assign_pointer(new->proxy->profile, - aa_get_profile(new)); -- __aa_fs_profile_migrate_dents(old, new); -+ __aafs_profile_migrate_dents(old, new); - - if (list_empty(&new->base.list)) { - /* new is not on a list already */ -@@ -971,7 +971,7 @@ ssize_t aa_replace_profiles(struct aa_ns *view, struct aa_profile *profile, - parent = prof_child_dir(p); - } else - parent = ns_subprofs_dir(ent->new->ns); -- error = __aa_fs_profile_mkdir(ent->new, parent); -+ error = __aafs_profile_mkdir(ent->new, parent); - } - - if (error) { -diff --git a/security/apparmor/policy_ns.c b/security/apparmor/policy_ns.c -index c94ec6ef9e35..0a8bc4e887ef 100644 ---- a/security/apparmor/policy_ns.c -+++ b/security/apparmor/policy_ns.c -@@ -196,7 +196,7 @@ static struct aa_ns *__aa_create_ns(struct aa_ns *parent, const char *name, - if (!ns) - return NULL; - mutex_lock(&ns->lock); -- error = __aa_fs_ns_mkdir(ns, ns_subns_dir(parent), name); -+ error = __aafs_ns_mkdir(ns, ns_subns_dir(parent), name); - if (error) { - AA_ERROR("Failed to create interface for ns %s\n", - ns->base.name); -@@ -284,7 +284,7 @@ static void destroy_ns(struct aa_ns *ns) - - if (ns->parent) - __aa_update_proxy(ns->unconfined, ns->parent->unconfined); -- __aa_fs_ns_rmdir(ns); -+ __aafs_ns_rmdir(ns); - mutex_unlock(&ns->lock); - } - -diff --git a/security/apparmor/resource.c b/security/apparmor/resource.c -index 86a941afd956..ae66151fdc38 100644 ---- a/security/apparmor/resource.c -+++ b/security/apparmor/resource.c -@@ -24,8 +24,8 @@ - */ - #include "rlim_names.h" - --struct aa_fs_entry aa_fs_entry_rlimit[] = { -- AA_FS_FILE_STRING("mask", AA_FS_RLIMIT_MASK), -+struct aa_sfs_entry aa_sfs_entry_rlimit[] = { -+ AA_SFS_FILE_STRING("mask", AA_SFS_RLIMIT_MASK), - { } - }; - --- -2.12.3 - diff --git a/patches.apparmor/0016-apparmor-allow-specifying-an-already-created-dir-to-.patch b/patches.apparmor/0016-apparmor-allow-specifying-an-already-created-dir-to-.patch deleted file mode 100644 index c009d83..0000000 --- a/patches.apparmor/0016-apparmor-allow-specifying-an-already-created-dir-to-.patch +++ /dev/null @@ -1,87 +0,0 @@ -From b30c67c46e1e7c4966bc2a3ffd350767541f3ed1 Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Thu, 25 May 2017 06:31:46 -0700 -Subject: [PATCH 16/65] apparmor: allow specifying an already created dir to - create ns entries in -Git-commit: 98407f0a0d378df27bfea79301a3aba42d7cea1c -Patch-mainline: v4.13-rc1 -References: FATE#323500 - -Signed-off-by: John Johansen -Reviewed-by: Seth Arnold -Reviewed-by: Kees Cook -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/apparmorfs.c | 9 +++++---- - security/apparmor/include/apparmorfs.h | 4 ++-- - security/apparmor/policy_ns.c | 2 +- - 3 files changed, 8 insertions(+), 7 deletions(-) - -diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c -index 35b822c4a079..a18f14ab7a8b 100644 ---- a/security/apparmor/apparmorfs.c -+++ b/security/apparmor/apparmorfs.c -@@ -1339,11 +1339,12 @@ static int __aafs_ns_mkdir_entries(struct aa_ns *ns, struct dentry *dir) - /* - * Requires: @ns->lock held - */ --int __aafs_ns_mkdir(struct aa_ns *ns, struct dentry *parent, const char *name) -+int __aafs_ns_mkdir(struct aa_ns *ns, struct dentry *parent, const char *name, -+ struct dentry *dent) - { - struct aa_ns *sub; - struct aa_profile *child; -- struct dentry *dent, *dir; -+ struct dentry *dir; - int error; - - AA_BUG(!ns); -@@ -1373,7 +1374,7 @@ int __aafs_ns_mkdir(struct aa_ns *ns, struct dentry *parent, const char *name) - /* subnamespaces */ - list_for_each_entry(sub, &ns->sub_ns, base.list) { - mutex_lock(&sub->lock); -- error = __aafs_ns_mkdir(sub, ns_subns_dir(ns), NULL); -+ error = __aafs_ns_mkdir(sub, ns_subns_dir(ns), NULL, NULL); - mutex_unlock(&sub->lock); - if (error) - goto fail2; -@@ -1929,7 +1930,7 @@ static int __init aa_create_aafs(void) - ns_subremove(root_ns) = dent; - - mutex_lock(&root_ns->lock); -- error = __aafs_ns_mkdir(root_ns, aa_sfs_entry.dentry, "policy"); -+ error = __aafs_ns_mkdir(root_ns, aa_sfs_entry.dentry, "policy", NULL); - mutex_unlock(&root_ns->lock); - - if (error) -diff --git a/security/apparmor/include/apparmorfs.h b/security/apparmor/include/apparmorfs.h -index bcad87740cb6..071a59a1f056 100644 ---- a/security/apparmor/include/apparmorfs.h -+++ b/security/apparmor/include/apparmorfs.h -@@ -112,8 +112,8 @@ 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); -+int __aafs_ns_mkdir(struct aa_ns *ns, struct dentry *parent, const char *name, -+ struct dentry *dent); - - struct aa_loaddata; - void __aa_fs_remove_rawdata(struct aa_loaddata *rawdata); -diff --git a/security/apparmor/policy_ns.c b/security/apparmor/policy_ns.c -index 0a8bc4e887ef..7d7c23705be2 100644 ---- a/security/apparmor/policy_ns.c -+++ b/security/apparmor/policy_ns.c -@@ -196,7 +196,7 @@ static struct aa_ns *__aa_create_ns(struct aa_ns *parent, const char *name, - if (!ns) - return NULL; - mutex_lock(&ns->lock); -- error = __aafs_ns_mkdir(ns, ns_subns_dir(parent), name); -+ error = __aafs_ns_mkdir(ns, ns_subns_dir(parent), name, dir); - if (error) { - AA_ERROR("Failed to create interface for ns %s\n", - ns->base.name); --- -2.12.3 - diff --git a/patches.apparmor/0016-apparmor-fix-build-failure-on-sparc-caused-by-undecl.patch b/patches.apparmor/0016-apparmor-fix-build-failure-on-sparc-caused-by-undecl.patch deleted file mode 100644 index fd85d39..0000000 --- a/patches.apparmor/0016-apparmor-fix-build-failure-on-sparc-caused-by-undecl.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 58c09ef9a59cd58d2900b910c27e50f10b1c2e23 Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Wed, 23 Aug 2017 12:10:39 -0700 -Subject: [PATCH 16/17] apparmor: fix build failure on sparc caused by undeclared signals -Acked-by: Goldwyn Rodrigues -References: FATE#323500 -Patch-mainline: v4.14-rc2 -Git-commit: b1545dba092ba543eab1f7b5ed757a4988e267c8 - - In file included from security/apparmor/ipc.c:23:0: - security/apparmor/include/sig_names.h:26:3: error: 'SIGSTKFLT' undeclared here (not in a function) - [SIGSTKFLT] = 16, /* -, 16, - */ - ^ - security/apparmor/include/sig_names.h:26:3: error: array index in initializer not of integer type - security/apparmor/include/sig_names.h:26:3: note: (near initialization for 'sig_map') - security/apparmor/include/sig_names.h:51:3: error: 'SIGUNUSED' undeclared here (not in a function) - [SIGUNUSED] = 34, /* -, 31, - */ - ^ - security/apparmor/include/sig_names.h:51:3: error: array index in initializer not of integer type - security/apparmor/include/sig_names.h:51:3: note: (near initialization for 'sig_map') - -Reported-by: Stephen Rothwell -Fixes: c6bf1adaecaa ("apparmor: add the ability to mediate signals") -Signed-off-by: John Johansen ---- - security/apparmor/include/sig_names.h | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -diff --git a/security/apparmor/include/sig_names.h b/security/apparmor/include/sig_names.h -index 0d4395f231ca..92e62fe95292 100644 ---- a/security/apparmor/include/sig_names.h -+++ b/security/apparmor/include/sig_names.h -@@ -23,7 +23,9 @@ static const int sig_map[MAXMAPPED_SIG] = { - [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 */ -@@ -47,7 +49,8 @@ static const int sig_map[MAXMAPPED_SIG] = { - #if defined(SIGLOST) && SIGPWR != SIGLOST /* sparc */ - [SIGLOST] = 33, /* unused on Linux */ - #endif --#if defined(SIGLOST) && defined(SIGSYS) && SIGLOST != SIGSYS -+#if defined(SIGUNUSED) && \ -+ defined(SIGLOST) && defined(SIGSYS) && SIGLOST != SIGSYS - [SIGUNUSED] = 34, /* -, 31, - */ - #endif - }; --- -2.14.1 - diff --git a/patches.apparmor/0017-apparmor-convert-from-securityfs-to-apparmorfs-for-p.patch b/patches.apparmor/0017-apparmor-convert-from-securityfs-to-apparmorfs-for-p.patch deleted file mode 100644 index 6e23097..0000000 --- a/patches.apparmor/0017-apparmor-convert-from-securityfs-to-apparmorfs-for-p.patch +++ /dev/null @@ -1,236 +0,0 @@ -From de0b29caff196166ce6b58e700ba5dcb75ff9936 Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Thu, 25 May 2017 06:35:38 -0700 -Subject: [PATCH 17/65] apparmor: convert from securityfs to apparmorfs for - policy ns files -Git-commit: c961ee5f21b202dea60b63eeef945730d92e46a6 -Patch-mainline: v4.13-rc1 -References: FATE#323500 - -Virtualize the apparmor policy/ directory so that the current -namespace affects what part of policy is seen. To do this convert to -using apparmorfs for policy namespace files and setup a magic symlink -in the securityfs apparmor dir to access those files. - -Signed-off-by: John Johansen -Reviewed-by: Seth Arnold -Reviewed-by: Kees Cook -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/apparmorfs.c | 63 +++++++++++++++++++++++++----------------- - 1 file changed, 37 insertions(+), 26 deletions(-) - -diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c -index a18f14ab7a8b..c847f601371d 100644 ---- a/security/apparmor/apparmorfs.c -+++ b/security/apparmor/apparmorfs.c -@@ -943,7 +943,7 @@ static void remove_rawdata_dents(struct aa_loaddata *rawdata) - for (i = 0; i < AAFS_LOADDATA_NDENTS; i++) { - if (!IS_ERR_OR_NULL(rawdata->dents[i])) { - /* no refcounts on i_private */ -- securityfs_remove(rawdata->dents[i]); -+ aafs_remove(rawdata->dents[i]); - rawdata->dents[i] = NULL; - } - } -@@ -979,33 +979,33 @@ int __aa_fs_create_rawdata(struct aa_ns *ns, struct aa_loaddata *rawdata) - if (!rawdata->name) - return -ENOMEM; - -- dir = securityfs_create_dir(rawdata->name, ns_subdata_dir(ns)); -+ dir = aafs_create_dir(rawdata->name, ns_subdata_dir(ns)); - if (IS_ERR(dir)) - /* ->name freed when rawdata freed */ - return PTR_ERR(dir); - rawdata->dents[AAFS_LOADDATA_DIR] = dir; - -- dent = securityfs_create_file("abi", S_IFREG | 0444, dir, rawdata, -+ dent = aafs_create_file("abi", S_IFREG | 0444, dir, rawdata, - &seq_rawdata_abi_fops); - if (IS_ERR(dent)) - goto fail; - rawdata->dents[AAFS_LOADDATA_ABI] = dent; - -- dent = securityfs_create_file("revision", S_IFREG | 0444, dir, rawdata, -+ dent = aafs_create_file("revision", S_IFREG | 0444, dir, rawdata, - &seq_rawdata_revision_fops); - if (IS_ERR(dent)) - goto fail; - rawdata->dents[AAFS_LOADDATA_REVISION] = dent; - - if (aa_g_hash_policy) { -- dent = securityfs_create_file("sha1", S_IFREG | 0444, dir, -+ dent = aafs_create_file("sha1", S_IFREG | 0444, dir, - rawdata, &seq_rawdata_hash_fops); - if (IS_ERR(dent)) - goto fail; - rawdata->dents[AAFS_LOADDATA_HASH] = dent; - } - -- dent = securityfs_create_file("raw_data", S_IFREG | 0444, -+ dent = aafs_create_file("raw_data", S_IFREG | 0444, - dir, rawdata, &rawdata_fops); - if (IS_ERR(dent)) - goto fail; -@@ -1047,7 +1047,7 @@ void __aafs_profile_rmdir(struct aa_profile *profile) - continue; - - proxy = d_inode(profile->dents[i])->i_private; -- securityfs_remove(profile->dents[i]); -+ aafs_remove(profile->dents[i]); - aa_put_proxy(proxy); - profile->dents[i] = NULL; - } -@@ -1077,7 +1077,7 @@ static struct dentry *create_profile_file(struct dentry *dir, const char *name, - struct aa_proxy *proxy = aa_get_proxy(profile->proxy); - struct dentry *dent; - -- dent = securityfs_create_file(name, S_IFREG | 0444, dir, proxy, fops); -+ dent = aafs_create_file(name, S_IFREG | 0444, dir, proxy, fops); - if (IS_ERR(dent)) - aa_put_proxy(proxy); - -@@ -1130,7 +1130,7 @@ int __aafs_profile_mkdir(struct aa_profile *profile, struct dentry *parent) - p = aa_deref_parent(profile); - dent = prof_dir(p); - /* adding to parent that previously didn't have children */ -- dent = securityfs_create_dir("profiles", dent); -+ dent = aafs_create_dir("profiles", dent); - if (IS_ERR(dent)) - goto fail; - prof_child_dir(p) = parent = dent; -@@ -1151,7 +1151,7 @@ int __aafs_profile_mkdir(struct aa_profile *profile, struct dentry *parent) - sprintf(profile->dirname + len, ".%ld", profile->ns->uniq_id++); - } - -- dent = securityfs_create_dir(profile->dirname, parent); -+ dent = aafs_create_dir(profile->dirname, parent); - if (IS_ERR(dent)) - goto fail; - prof_dir(profile) = dir = dent; -@@ -1190,7 +1190,7 @@ int __aafs_profile_mkdir(struct aa_profile *profile, struct dentry *parent) - profile->rawdata->name, "sha1"); - if (error < 0) - goto fail2; -- dent = securityfs_create_symlink("raw_sha1", dir, target, NULL); -+ dent = aafs_create_symlink("raw_sha1", dir, target, NULL); - if (IS_ERR(dent)) - goto fail; - profile->dents[AAFS_PROF_RAW_HASH] = dent; -@@ -1199,7 +1199,7 @@ int __aafs_profile_mkdir(struct aa_profile *profile, struct dentry *parent) - profile->rawdata->name, "abi"); - if (error < 0) - goto fail2; -- dent = securityfs_create_symlink("raw_abi", dir, target, NULL); -+ dent = aafs_create_symlink("raw_abi", dir, target, NULL); - if (IS_ERR(dent)) - goto fail; - profile->dents[AAFS_PROF_RAW_ABI] = dent; -@@ -1208,7 +1208,7 @@ int __aafs_profile_mkdir(struct aa_profile *profile, struct dentry *parent) - profile->rawdata->name, "raw_data"); - if (error < 0) - goto fail2; -- dent = securityfs_create_symlink("raw_data", dir, target, NULL); -+ dent = aafs_create_symlink("raw_data", dir, target, NULL); - if (IS_ERR(dent)) - goto fail; - profile->dents[AAFS_PROF_RAW_DATA] = dent; -@@ -1283,7 +1283,7 @@ void __aafs_ns_rmdir(struct aa_ns *ns) - } - - for (i = AAFS_NS_SIZEOF - 1; i >= 0; --i) { -- securityfs_remove(ns->dents[i]); -+ aafs_remove(ns->dents[i]); - ns->dents[i] = NULL; - } - } -@@ -1296,38 +1296,38 @@ static int __aafs_ns_mkdir_entries(struct aa_ns *ns, struct dentry *dir) - AA_BUG(!ns); - AA_BUG(!dir); - -- dent = securityfs_create_dir("profiles", dir); -+ dent = aafs_create_dir("profiles", dir); - if (IS_ERR(dent)) - return PTR_ERR(dent); - ns_subprofs_dir(ns) = dent; - -- dent = securityfs_create_dir("raw_data", dir); -+ dent = aafs_create_dir("raw_data", dir); - if (IS_ERR(dent)) - return PTR_ERR(dent); - ns_subdata_dir(ns) = dent; - -- dent = securityfs_create_file(".load", 0640, dir, ns, -+ dent = aafs_create_file(".load", 0640, dir, ns, - &aa_fs_profile_load); - if (IS_ERR(dent)) - return PTR_ERR(dent); - aa_get_ns(ns); - ns_subload(ns) = dent; - -- dent = securityfs_create_file(".replace", 0640, dir, ns, -+ dent = aafs_create_file(".replace", 0640, dir, ns, - &aa_fs_profile_replace); - if (IS_ERR(dent)) - return PTR_ERR(dent); - aa_get_ns(ns); - ns_subreplace(ns) = dent; - -- dent = securityfs_create_file(".remove", 0640, dir, ns, -+ dent = aafs_create_file(".remove", 0640, dir, ns, - &aa_fs_profile_remove); - if (IS_ERR(dent)) - return PTR_ERR(dent); - aa_get_ns(ns); - ns_subremove(ns) = dent; - -- dent = securityfs_create_dir("namespaces", dir); -+ dent = aafs_create_dir("namespaces", dir); - if (IS_ERR(dent)) - return PTR_ERR(dent); - aa_get_ns(ns); -@@ -1354,11 +1354,13 @@ int __aafs_ns_mkdir(struct aa_ns *ns, struct dentry *parent, const char *name, - if (!name) - name = ns->base.name; - -- /* create ns dir if it doesn't already exist */ -- dent = securityfs_create_dir(name, parent); -- if (IS_ERR(dent)) -- goto fail; -- -+ if (!dent) { -+ /* create ns dir if it doesn't already exist */ -+ dent = aafs_create_dir(name, parent); -+ if (IS_ERR(dent)) -+ goto fail; -+ } else -+ dget(dent); - ns_dir(ns) = dir = dent; - error = __aafs_ns_mkdir_entries(ns, dir); - if (error) -@@ -1930,12 +1932,21 @@ static int __init aa_create_aafs(void) - ns_subremove(root_ns) = dent; - - mutex_lock(&root_ns->lock); -- error = __aafs_ns_mkdir(root_ns, aa_sfs_entry.dentry, "policy", NULL); -+ error = __aafs_ns_mkdir(root_ns, aafs_mnt->mnt_root, ".policy", -+ aafs_mnt->mnt_root); - mutex_unlock(&root_ns->lock); - - if (error) - goto error; - -+ /* magic symlink similar to nsfs redirects based on task policy */ -+ dent = securityfs_create_symlink("policy", aa_sfs_entry.dentry, -+ NULL, &policy_link_iops); -+ if (IS_ERR(dent)) { -+ error = PTR_ERR(dent); -+ goto error; -+ } -+ - error = aa_mk_null_file(aa_sfs_entry.dentry); - if (error) - goto error; --- -2.12.3 - diff --git a/patches.apparmor/0017-apparmor-fix-apparmorfs-DAC-access-permissions.patch b/patches.apparmor/0017-apparmor-fix-apparmorfs-DAC-access-permissions.patch deleted file mode 100644 index ec27c15..0000000 --- a/patches.apparmor/0017-apparmor-fix-apparmorfs-DAC-access-permissions.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 287b1ee04780e6921eea4e427376c756ab314fab Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Thu, 31 Aug 2017 09:54:43 -0700 -Subject: [PATCH 17/17] apparmor: fix apparmorfs DAC access permissions -References: FATE#323500 -Patch-mainline: v4.14-rc2 -Git-commit: bf81100f63db7ea243d17b9d5008ba3af2fdf6b2 - -The DAC access permissions for several apparmorfs files are wrong. - -.access - needs to be writable by all tasks to perform queries -the others in the set only provide a read fn so should be read only. - -With policy namespace virtualization all apparmor needs to control -the permission and visibility checks directly which means DAC -access has to be allowed for all user, group, and other. - -BugLink: http://bugs.launchpad.net/bugs/1713103 -Fixes: c97204baf840b ("apparmor: rename apparmor file fns and data to indicate use") -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/apparmorfs.c | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - -diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c -index 125dad5c3fde..518d5928661b 100644 ---- a/security/apparmor/apparmorfs.c -+++ b/security/apparmor/apparmorfs.c -@@ -2215,12 +2215,12 @@ static struct aa_sfs_entry aa_sfs_entry_features[] = { - }; - - static struct aa_sfs_entry aa_sfs_entry_apparmor[] = { -- AA_SFS_FILE_FOPS(".access", 0640, &aa_sfs_access), -+ AA_SFS_FILE_FOPS(".access", 0666, &aa_sfs_access), - AA_SFS_FILE_FOPS(".stacked", 0444, &seq_ns_stacked_fops), - AA_SFS_FILE_FOPS(".ns_stacked", 0444, &seq_ns_nsstacked_fops), -- AA_SFS_FILE_FOPS(".ns_level", 0666, &seq_ns_level_fops), -- AA_SFS_FILE_FOPS(".ns_name", 0640, &seq_ns_name_fops), -- AA_SFS_FILE_FOPS("profiles", 0440, &aa_sfs_profiles_fops), -+ AA_SFS_FILE_FOPS(".ns_level", 0444, &seq_ns_level_fops), -+ AA_SFS_FILE_FOPS(".ns_name", 0444, &seq_ns_name_fops), -+ AA_SFS_FILE_FOPS("profiles", 0444, &aa_sfs_profiles_fops), - AA_SFS_DIR("features", aa_sfs_entry_features), - { } - }; --- -2.14.1 - diff --git a/patches.apparmor/0018-apparmor-move-permissions-into-their-own-file-to-be-.patch b/patches.apparmor/0018-apparmor-move-permissions-into-their-own-file-to-be-.patch deleted file mode 100644 index 30f4dbd..0000000 --- a/patches.apparmor/0018-apparmor-move-permissions-into-their-own-file-to-be-.patch +++ /dev/null @@ -1,127 +0,0 @@ -From 77116b1422c270acfeeefae235fc5400ed620b60 Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Fri, 26 May 2017 01:57:09 -0700 -Subject: [PATCH 18/65] apparmor: move permissions into their own file to be - more easily shared -Git-commit: fc7e0b26b8d26e680bb2f252e9521385e0092e4c -Patch-mainline: v4.13-rc1 -References: FATE#323500 - -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/include/file.h | 20 +------------------ - security/apparmor/include/perms.h | 40 ++++++++++++++++++++++++++++++++++++++ - security/apparmor/include/policy.h | 1 + - security/apparmor/lib.c | 1 + - 4 files changed, 43 insertions(+), 19 deletions(-) - create mode 100644 security/apparmor/include/perms.h - -diff --git a/security/apparmor/include/file.h b/security/apparmor/include/file.h -index eba39cb25f02..a75e4872053a 100644 ---- a/security/apparmor/include/file.h -+++ b/security/apparmor/include/file.h -@@ -17,29 +17,11 @@ - - #include "domain.h" - #include "match.h" -+#include "perms.h" - - struct aa_profile; - struct path; - --/* -- * We use MAY_EXEC, MAY_WRITE, MAY_READ, MAY_APPEND and the following flags -- * for profile permissions -- */ --#define AA_MAY_CREATE 0x0010 --#define AA_MAY_DELETE 0x0020 --#define AA_MAY_META_WRITE 0x0040 --#define AA_MAY_META_READ 0x0080 -- --#define AA_MAY_CHMOD 0x0100 --#define AA_MAY_CHOWN 0x0200 --#define AA_MAY_LOCK 0x0400 --#define AA_EXEC_MMAP 0x0800 -- --#define AA_MAY_LINK 0x1000 --#define AA_LINK_SUBSET AA_MAY_LOCK /* overlaid */ --#define AA_MAY_ONEXEC 0x40000000 /* exec allows onexec */ --#define AA_MAY_CHANGE_PROFILE 0x80000000 --#define AA_MAY_CHANGEHAT 0x80000000 /* ctrl auditing only */ - - #define AA_AUDIT_FILE_MASK (MAY_READ | MAY_WRITE | MAY_EXEC | MAY_APPEND |\ - AA_MAY_CREATE | AA_MAY_DELETE | \ -diff --git a/security/apparmor/include/perms.h b/security/apparmor/include/perms.h -new file mode 100644 -index 000000000000..4a65755a2dc0 ---- /dev/null -+++ b/security/apparmor/include/perms.h -@@ -0,0 +1,40 @@ -+/* -+ * AppArmor security module -+ * -+ * This file contains AppArmor basic permission sets definitions. -+ * -+ * Copyright 2017 Canonical Ltd. -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License as -+ * published by the Free Software Foundation, version 2 of the -+ * License. -+ */ -+ -+#ifndef __AA_PERM_H -+#define __AA_PERM_H -+ -+#include -+ -+/* -+ * We use MAY_EXEC, MAY_WRITE, MAY_READ, MAY_APPEND and the following flags -+ * for profile permissions -+ */ -+#define AA_MAY_CREATE 0x0010 -+#define AA_MAY_DELETE 0x0020 -+#define AA_MAY_META_WRITE 0x0040 -+#define AA_MAY_META_READ 0x0080 -+ -+#define AA_MAY_CHMOD 0x0100 -+#define AA_MAY_CHOWN 0x0200 -+#define AA_MAY_LOCK 0x0400 -+#define AA_EXEC_MMAP 0x0800 -+ -+#define AA_MAY_LINK 0x1000 -+#define AA_LINK_SUBSET AA_MAY_LOCK /* overlaid */ -+#define AA_MAY_ONEXEC 0x40000000 /* exec allows onexec */ -+#define AA_MAY_CHANGE_PROFILE 0x80000000 -+#define AA_MAY_CHANGEHAT 0x80000000 /* ctrl auditing only */ -+ -+ -+#endif /* __AA_PERM_H */ -diff --git a/security/apparmor/include/policy.h b/security/apparmor/include/policy.h -index dffa01c018c8..0f87f70287ad 100644 ---- a/security/apparmor/include/policy.h -+++ b/security/apparmor/include/policy.h -@@ -29,6 +29,7 @@ - #include "domain.h" - #include "file.h" - #include "lib.h" -+#include "perms.h" - #include "resource.h" - - -diff --git a/security/apparmor/lib.c b/security/apparmor/lib.c -index 864b2fa45852..90eb14c9e0cf 100644 ---- a/security/apparmor/lib.c -+++ b/security/apparmor/lib.c -@@ -21,6 +21,7 @@ - #include "include/audit.h" - #include "include/apparmor.h" - #include "include/lib.h" -+#include "include/perms.h" - #include "include/policy.h" - - /** --- -2.12.3 - diff --git a/patches.apparmor/0019-apparmor-rework-perm-mapping-to-a-slightly-broader-s.patch b/patches.apparmor/0019-apparmor-rework-perm-mapping-to-a-slightly-broader-s.patch deleted file mode 100644 index 5d0b929..0000000 --- a/patches.apparmor/0019-apparmor-rework-perm-mapping-to-a-slightly-broader-s.patch +++ /dev/null @@ -1,311 +0,0 @@ -From ba54ac8ab064ddb8bf082f6c71d28aa8d9b16af4 Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Fri, 26 May 2017 15:07:22 -0700 -Subject: [PATCH 19/65] apparmor: rework perm mapping to a slightly broader set -Git-commit: e53cfe6c7caa79ccdccce53e600dae522acb1c84 -Patch-mainline: v4.13-rc1 -References: FATE#323500 - -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/file.c | 43 +++++++++--------------- - security/apparmor/include/file.h | 5 +-- - security/apparmor/include/perms.h | 69 ++++++++++++++++++++++++++++----------- - security/apparmor/lib.c | 59 +++++++++++++++++++++++++++++++++ - security/apparmor/lsm.c | 10 +++--- - 5 files changed, 133 insertions(+), 53 deletions(-) - -diff --git a/security/apparmor/file.c b/security/apparmor/file.c -index 22be62f0fc73..44549db904b3 100644 ---- a/security/apparmor/file.c -+++ b/security/apparmor/file.c -@@ -21,6 +21,17 @@ - - struct file_perms nullperms; - -+static u32 map_mask_to_chr_mask(u32 mask) -+{ -+ u32 m = mask & PERMS_CHRS_MASK; -+ -+ if (mask & AA_MAY_GETATTR) -+ m |= MAY_READ; -+ if (mask & (AA_MAY_SETATTR | AA_MAY_CHMOD | AA_MAY_CHOWN)) -+ m |= MAY_WRITE; -+ -+ return m; -+} - - /** - * audit_file_mask - convert mask to permission string -@@ -31,29 +42,7 @@ static void audit_file_mask(struct audit_buffer *ab, u32 mask) - { - char str[10]; - -- char *m = str; -- -- if (mask & AA_EXEC_MMAP) -- *m++ = 'm'; -- if (mask & (MAY_READ | AA_MAY_META_READ)) -- *m++ = 'r'; -- if (mask & (MAY_WRITE | AA_MAY_META_WRITE | AA_MAY_CHMOD | -- AA_MAY_CHOWN)) -- *m++ = 'w'; -- else if (mask & MAY_APPEND) -- *m++ = 'a'; -- if (mask & AA_MAY_CREATE) -- *m++ = 'c'; -- if (mask & AA_MAY_DELETE) -- *m++ = 'd'; -- if (mask & AA_MAY_LINK) -- *m++ = 'l'; -- if (mask & AA_MAY_LOCK) -- *m++ = 'k'; -- if (mask & MAY_EXEC) -- *m++ = 'x'; -- *m = '\0'; -- -+ aa_perm_mask_to_str(str, aa_file_perm_chrs, map_mask_to_chr_mask(mask)); - audit_log_string(ab, str); - } - -@@ -163,10 +152,10 @@ static u32 map_old_perms(u32 old) - { - u32 new = old & 0xf; - if (old & MAY_READ) -- new |= AA_MAY_META_READ; -+ new |= AA_MAY_GETATTR | AA_MAY_OPEN; - if (old & MAY_WRITE) -- new |= AA_MAY_META_WRITE | AA_MAY_CREATE | AA_MAY_DELETE | -- AA_MAY_CHMOD | AA_MAY_CHOWN; -+ new |= AA_MAY_SETATTR | AA_MAY_CREATE | AA_MAY_DELETE | -+ AA_MAY_CHMOD | AA_MAY_CHOWN | AA_MAY_OPEN; - if (old & 0x10) - new |= AA_MAY_LINK; - /* the old mapping lock and link_subset flags where overlaid -@@ -214,7 +203,7 @@ static struct file_perms compute_perms(struct aa_dfa *dfa, unsigned int state, - perms.quiet = map_old_perms(dfa_other_quiet(dfa, state)); - perms.xindex = dfa_other_xindex(dfa, state); - } -- perms.allow |= AA_MAY_META_READ; -+ perms.allow |= AA_MAY_GETATTR; - - /* change_profile wasn't determined by ownership in old mapping */ - if (ACCEPT_TABLE(dfa)[state] & 0x80000000) -diff --git a/security/apparmor/include/file.h b/security/apparmor/include/file.h -index a75e4872053a..fb3642a94e3d 100644 ---- a/security/apparmor/include/file.h -+++ b/security/apparmor/include/file.h -@@ -22,10 +22,11 @@ - 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_META_READ | AA_MAY_META_WRITE | \ -+ AA_MAY_GETATTR | AA_MAY_SETATTR | \ - AA_MAY_CHMOD | AA_MAY_CHOWN | AA_MAY_LOCK | \ - AA_EXEC_MMAP | AA_MAY_LINK) - -@@ -37,7 +38,7 @@ struct path; - * ctx struct will expand in the future so we keep the struct. - */ - struct aa_file_ctx { -- u16 allow; -+ u32 allow; - }; - - /** -diff --git a/security/apparmor/include/perms.h b/security/apparmor/include/perms.h -index 4a65755a2dc0..35e365e7aa75 100644 ---- a/security/apparmor/include/perms.h -+++ b/security/apparmor/include/perms.h -@@ -16,25 +16,56 @@ - - #include - --/* -- * We use MAY_EXEC, MAY_WRITE, MAY_READ, MAY_APPEND and the following flags -- * for profile permissions -- */ --#define AA_MAY_CREATE 0x0010 --#define AA_MAY_DELETE 0x0020 --#define AA_MAY_META_WRITE 0x0040 --#define AA_MAY_META_READ 0x0080 -- --#define AA_MAY_CHMOD 0x0100 --#define AA_MAY_CHOWN 0x0200 --#define AA_MAY_LOCK 0x0400 --#define AA_EXEC_MMAP 0x0800 -- --#define AA_MAY_LINK 0x1000 --#define AA_LINK_SUBSET AA_MAY_LOCK /* overlaid */ --#define AA_MAY_ONEXEC 0x40000000 /* exec allows onexec */ --#define AA_MAY_CHANGE_PROFILE 0x80000000 --#define AA_MAY_CHANGEHAT 0x80000000 /* ctrl auditing only */ -+#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[]; - -+void aa_perm_mask_to_str(char *str, const char *chrs, u32 mask); - - #endif /* __AA_PERM_H */ -diff --git a/security/apparmor/lib.c b/security/apparmor/lib.c -index 90eb14c9e0cf..90d4631ddafe 100644 ---- a/security/apparmor/lib.c -+++ b/security/apparmor/lib.c -@@ -129,6 +129,65 @@ void aa_info_message(const char *str) - printk(KERN_INFO "AppArmor: %s\n", str); - } - -+const char aa_file_perm_chrs[] = "xwracd km l "; -+const char *aa_file_perm_names[] = { -+ "exec", -+ "write", -+ "read", -+ "append", -+ -+ "create", -+ "delete", -+ "open", -+ "rename", -+ -+ "setattr", -+ "getattr", -+ "setcred", -+ "getcred", -+ -+ "chmod", -+ "chown", -+ "chgrp", -+ "lock", -+ -+ "mmap", -+ "mprot", -+ "link", -+ "snapshot", -+ -+ "unknown", -+ "unknown", -+ "unknown", -+ "unknown", -+ -+ "unknown", -+ "unknown", -+ "unknown", -+ "unknown", -+ -+ "stack", -+ "change_onexec", -+ "change_profile", -+ "change_hat", -+}; -+ -+/** -+ * aa_perm_mask_to_str - convert a perm mask to its short string -+ * @str: character buffer to store string in (at least 10 characters) -+ * @mask: permission mask to convert -+ */ -+void aa_perm_mask_to_str(char *str, const char *chrs, u32 mask) -+{ -+ unsigned int i, perm = 1; -+ -+ for (i = 0; i < 32; perm <<= 1, i++) { -+ if (mask & perm) -+ *str++ = chrs[i]; -+ } -+ *str = '\0'; -+} -+ - /** - * aa_policy_init - initialize a policy structure - * @policy: policy to initialize (NOT NULL) -diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c -index 8f3c0f7aca5a..a128f1772135 100644 ---- a/security/apparmor/lsm.c -+++ b/security/apparmor/lsm.c -@@ -278,7 +278,7 @@ static int apparmor_path_mknod(const struct path *dir, struct dentry *dentry, - - static int apparmor_path_truncate(const struct path *path) - { -- return common_perm_cond(OP_TRUNC, path, MAY_WRITE | AA_MAY_META_WRITE); -+ return common_perm_cond(OP_TRUNC, path, MAY_WRITE | AA_MAY_SETATTR); - } - - static int apparmor_path_symlink(const struct path *dir, struct dentry *dentry, -@@ -323,12 +323,12 @@ static int apparmor_path_rename(const struct path *old_dir, struct dentry *old_d - }; - - error = aa_path_perm(OP_RENAME_SRC, profile, &old_path, 0, -- MAY_READ | AA_MAY_META_READ | MAY_WRITE | -- AA_MAY_META_WRITE | AA_MAY_DELETE, -+ MAY_READ | AA_MAY_GETATTR | MAY_WRITE | -+ AA_MAY_SETATTR | AA_MAY_DELETE, - &cond); - if (!error) - error = aa_path_perm(OP_RENAME_DEST, profile, &new_path, -- 0, MAY_WRITE | AA_MAY_META_WRITE | -+ 0, MAY_WRITE | AA_MAY_SETATTR | - AA_MAY_CREATE, &cond); - - } -@@ -347,7 +347,7 @@ static int apparmor_path_chown(const struct path *path, kuid_t uid, kgid_t gid) - - static int apparmor_inode_getattr(const struct path *path) - { -- return common_perm_cond(OP_GETATTR, path, AA_MAY_META_READ); -+ return common_perm_cond(OP_GETATTR, path, AA_MAY_GETATTR); - } - - static int apparmor_file_open(struct file *file, const struct cred *cred) --- -2.12.3 - diff --git a/patches.apparmor/0020-apparmor-provide-finer-control-over-policy-managemen.patch b/patches.apparmor/0020-apparmor-provide-finer-control-over-policy-managemen.patch deleted file mode 100644 index 71c8373..0000000 --- a/patches.apparmor/0020-apparmor-provide-finer-control-over-policy-managemen.patch +++ /dev/null @@ -1,199 +0,0 @@ -From 9926b19ca1fc029c30503cdf0c6afc7da4215534 Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Fri, 26 May 2017 01:45:08 -0700 -Subject: [PATCH 20/65] apparmor: provide finer control over policy management -Git-commit: 18e99f191a8e66ec8fd06e4820de44bd9faa296a -Patch-mainline: v4.13-rc1 -References: FATE#323500 - -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/apparmorfs.c | 15 +++++++-------- - security/apparmor/include/policy.h | 8 ++++++-- - security/apparmor/policy.c | 35 ++++++++++++++++++++++------------- - 3 files changed, 35 insertions(+), 23 deletions(-) - -diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c -index c847f601371d..570d6b58b159 100644 ---- a/security/apparmor/apparmorfs.c -+++ b/security/apparmor/apparmorfs.c -@@ -400,17 +400,16 @@ static struct aa_loaddata *aa_simple_write_to_buffer(const char __user *userbuf, - return data; - } - --static ssize_t policy_update(int binop, const char __user *buf, size_t size, -+static ssize_t policy_update(u32 mask, const char __user *buf, size_t size, - loff_t *pos, struct aa_ns *ns) - { - ssize_t error; - struct aa_loaddata *data; - struct aa_profile *profile = aa_current_profile(); -- const char *op = binop == PROF_ADD ? OP_PROF_LOAD : OP_PROF_REPL; - /* high level check about policy management - fine grained in - * below after unpack - */ -- error = aa_may_manage_policy(profile, ns, op); -+ error = aa_may_manage_policy(profile, ns, mask); - if (error) - return error; - -@@ -418,7 +417,7 @@ static ssize_t policy_update(int binop, const char __user *buf, size_t size, - error = PTR_ERR(data); - if (!IS_ERR(data)) { - error = aa_replace_profiles(ns ? ns : profile->ns, profile, -- binop, data); -+ mask, data); - aa_put_loaddata(data); - } - -@@ -430,7 +429,7 @@ static ssize_t profile_load(struct file *f, const char __user *buf, size_t size, - loff_t *pos) - { - struct aa_ns *ns = aa_get_ns(f->f_inode->i_private); -- int error = policy_update(PROF_ADD, buf, size, pos, ns); -+ int error = policy_update(AA_MAY_LOAD_POLICY, buf, size, pos, ns); - - aa_put_ns(ns); - -@@ -447,8 +446,8 @@ static ssize_t profile_replace(struct file *f, const char __user *buf, - size_t size, loff_t *pos) - { - struct aa_ns *ns = aa_get_ns(f->f_inode->i_private); -- int error = policy_update(PROF_REPLACE, buf, size, pos, ns); -- -+ int error = policy_update(AA_MAY_LOAD_POLICY | AA_MAY_REPLACE_POLICY, -+ buf, size, pos, ns); - aa_put_ns(ns); - - return error; -@@ -472,7 +471,7 @@ static ssize_t profile_remove(struct file *f, const char __user *buf, - /* high level check about policy management - fine grained in - * below after unpack - */ -- error = aa_may_manage_policy(profile, ns, OP_PROF_RM); -+ error = aa_may_manage_policy(profile, ns, AA_MAY_REMOVE_POLICY); - if (error) - goto out; - -diff --git a/security/apparmor/include/policy.h b/security/apparmor/include/policy.h -index 0f87f70287ad..97bfbddef7b2 100644 ---- a/security/apparmor/include/policy.h -+++ b/security/apparmor/include/policy.h -@@ -188,6 +188,10 @@ struct aa_profile { - - 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 -+ - void __aa_update_proxy(struct aa_profile *orig, struct aa_profile *new); - - void aa_add_profile(struct aa_policy *common, struct aa_profile *profile); -@@ -208,7 +212,7 @@ struct aa_profile *aa_fqlookupn_profile(struct aa_profile *base, - struct aa_profile *aa_match_profile(struct aa_ns *ns, const char *name); - - ssize_t aa_replace_profiles(struct aa_ns *view, struct aa_profile *profile, -- bool noreplace, struct aa_loaddata *udata); -+ u32 mask, struct aa_loaddata *udata); - ssize_t aa_remove_profiles(struct aa_ns *view, struct aa_profile *profile, - char *name, size_t size); - void __aa_profile_list_release(struct list_head *head); -@@ -323,6 +327,6 @@ static inline int AUDIT_MODE(struct aa_profile *profile) - bool policy_view_capable(struct aa_ns *ns); - bool policy_admin_capable(struct aa_ns *ns); - int aa_may_manage_policy(struct aa_profile *profile, struct aa_ns *ns, -- const char *op); -+ u32 mask); - - #endif /* __AA_POLICY_H */ -diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c -index a5e8559e4dec..65e98d0491f4 100644 ---- a/security/apparmor/policy.c -+++ b/security/apparmor/policy.c -@@ -690,17 +690,25 @@ bool policy_admin_capable(struct aa_ns *ns) - * - * Returns: 0 if the task is allowed to manipulate policy else error - */ --int aa_may_manage_policy(struct aa_profile *profile, struct aa_ns *ns, -- const char *op) -+int aa_may_manage_policy(struct aa_profile *profile, struct aa_ns *ns, u32 mask) - { -+ const char *op; -+ -+ if (mask & AA_MAY_REMOVE_POLICY) -+ op = OP_PROF_RM; -+ else if (mask & AA_MAY_REPLACE_POLICY) -+ op = OP_PROF_REPL; -+ else -+ op = OP_PROF_LOAD; -+ - /* check if loading policy is locked out */ - if (aa_g_lock_policy) -- return audit_policy(profile, op, NULL, NULL, -- "policy_locked", -EACCES); -+ return audit_policy(profile, op, NULL, NULL, "policy_locked", -+ -EACCES); - - if (!policy_admin_capable(ns)) -- return audit_policy(profile, op, NULL, NULL, -- "not policy admin", -EACCES); -+ return audit_policy(profile, op, NULL, NULL, "not policy admin", -+ -EACCES); - - /* TODO: add fine grained mediation of policy loads */ - return 0; -@@ -825,7 +833,7 @@ static int __lookup_replace(struct aa_ns *ns, const char *hname, - * aa_replace_profiles - replace profile(s) on the profile list - * @view: namespace load is viewed from - * @label: label that is attempting to load/replace policy -- * @noreplace: true if only doing addition, no replacement allowed -+ * @mask: permission mask - * @udata: serialized data stream (NOT NULL) - * - * unpack and replace a profile on the profile list and uses of that profile -@@ -835,17 +843,17 @@ static int __lookup_replace(struct aa_ns *ns, const char *hname, - * Returns: size of data consumed else error code on failure. - */ - ssize_t aa_replace_profiles(struct aa_ns *view, struct aa_profile *profile, -- bool noreplace, struct aa_loaddata *udata) -+ u32 mask, struct aa_loaddata *udata) - { - const char *ns_name, *info = NULL; - struct aa_ns *ns = NULL; - struct aa_load_ent *ent, *tmp; - struct aa_loaddata *rawdata_ent; -- const char *op = OP_PROF_REPL; -+ const char *op; - ssize_t count, error; -- - LIST_HEAD(lh); - -+ op = mask & AA_MAY_REPLACE_POLICY ? OP_PROF_REPL : OP_PROF_LOAD; - aa_get_loaddata(udata); - /* released below */ - error = aa_unpack(udata, &lh, &ns_name); -@@ -909,15 +917,16 @@ ssize_t aa_replace_profiles(struct aa_ns *view, struct aa_profile *profile, - struct aa_policy *policy; - - ent->new->rawdata = aa_get_loaddata(udata); -- error = __lookup_replace(ns, ent->new->base.hname, noreplace, -+ error = __lookup_replace(ns, ent->new->base.hname, -+ !(mask & AA_MAY_REPLACE_POLICY), - &ent->old, &info); - if (error) - goto fail_lock; - - if (ent->new->rename) { - error = __lookup_replace(ns, ent->new->rename, -- noreplace, &ent->rename, -- &info); -+ !(mask & AA_MAY_REPLACE_POLICY), -+ &ent->rename, &info); - if (error) - goto fail_lock; - } --- -2.12.3 - diff --git a/patches.apparmor/0021-apparmor-add-policy-revision-file-interface.patch b/patches.apparmor/0021-apparmor-add-policy-revision-file-interface.patch deleted file mode 100644 index e85b5c8..0000000 --- a/patches.apparmor/0021-apparmor-add-policy-revision-file-interface.patch +++ /dev/null @@ -1,242 +0,0 @@ -From 449b4c3612d117118108bc87b3978a966b1cc985 Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Fri, 26 May 2017 16:27:58 -0700 -Subject: [PATCH 21/65] apparmor: add policy revision file interface -Git-commit: d9bf2c268be6064ae0c9980e4c37fdd262c7effc -Patch-mainline: v4.13-rc1 -References: FATE#323500 - -Add a policy revision file to find the current revision of a ns's policy. -There is a revision file per ns, as well as a virtualized global revision -file in the base apparmor fs directory. The global revision file when -opened will provide the revision of the opening task namespace. - -The revision file can be waited on via select/poll to detect apparmor -policy changes from the last read revision of the opened file. This -means that the revision file must be read after the select/poll other -wise update data will remain ready for reading. - -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/apparmorfs.c | 113 ++++++++++++++++++++++++++++++++- - security/apparmor/include/apparmorfs.h | 2 + - security/apparmor/include/policy_ns.h | 1 + - security/apparmor/policy_ns.c | 1 + - 4 files changed, 116 insertions(+), 1 deletion(-) - -diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c -index 570d6b58b159..8c413333726b 100644 ---- a/security/apparmor/apparmorfs.c -+++ b/security/apparmor/apparmorfs.c -@@ -23,6 +23,7 @@ - #include - #include - #include -+#include - #include - #include - -@@ -31,6 +32,7 @@ - #include "include/audit.h" - #include "include/context.h" - #include "include/crypto.h" -+#include "include/policy_ns.h" - #include "include/policy.h" - #include "include/policy_ns.h" - #include "include/resource.h" -@@ -498,11 +500,101 @@ static const struct file_operations aa_fs_profile_remove = { - .llseek = default_llseek, - }; - -+struct aa_revision { -+ struct aa_ns *ns; -+ long last_read; -+}; -+ -+/* revision file hook fn for policy loads */ -+static int ns_revision_release(struct inode *inode, struct file *file) -+{ -+ struct aa_revision *rev = file->private_data; -+ -+ if (rev) { -+ aa_put_ns(rev->ns); -+ kfree(rev); -+ } -+ -+ return 0; -+} -+ -+static ssize_t ns_revision_read(struct file *file, char __user *buf, -+ size_t size, loff_t *ppos) -+{ -+ struct aa_revision *rev = file->private_data; -+ char buffer[32]; -+ long last_read; -+ int avail; -+ -+ mutex_lock(&rev->ns->lock); -+ last_read = rev->last_read; -+ if (last_read == rev->ns->revision) { -+ mutex_unlock(&rev->ns->lock); -+ if (file->f_flags & O_NONBLOCK) -+ return -EAGAIN; -+ if (wait_event_interruptible(rev->ns->wait, -+ last_read != -+ READ_ONCE(rev->ns->revision))) -+ return -ERESTARTSYS; -+ mutex_lock(&rev->ns->lock); -+ } -+ -+ avail = sprintf(buffer, "%ld\n", rev->ns->revision); -+ if (*ppos + size > avail) { -+ rev->last_read = rev->ns->revision; -+ *ppos = 0; -+ } -+ mutex_unlock(&rev->ns->lock); -+ -+ return simple_read_from_buffer(buf, size, ppos, buffer, avail); -+} -+ -+static int ns_revision_open(struct inode *inode, struct file *file) -+{ -+ struct aa_revision *rev = kzalloc(sizeof(*rev), GFP_KERNEL); -+ -+ if (!rev) -+ return -ENOMEM; -+ -+ rev->ns = aa_get_ns(inode->i_private); -+ if (!rev->ns) -+ rev->ns = aa_get_current_ns(); -+ file->private_data = rev; -+ -+ return 0; -+} -+ -+static unsigned int ns_revision_poll(struct file *file, poll_table *pt) -+{ -+ struct aa_revision *rev = file->private_data; -+ unsigned int mask = 0; -+ -+ if (rev) { -+ mutex_lock(&rev->ns->lock); -+ poll_wait(file, &rev->ns->wait, pt); -+ if (rev->last_read < rev->ns->revision) -+ mask |= POLLIN | POLLRDNORM; -+ mutex_unlock(&rev->ns->lock); -+ } -+ -+ return mask; -+} -+ - void __aa_bump_ns_revision(struct aa_ns *ns) - { - ns->revision++; -+ wake_up_interruptible(&ns->wait); - } - -+static const struct file_operations aa_fs_ns_revision_fops = { -+ .owner = THIS_MODULE, -+ .open = ns_revision_open, -+ .poll = ns_revision_poll, -+ .read = ns_revision_read, -+ .llseek = generic_file_llseek, -+ .release = ns_revision_release, -+}; -+ - /** - * query_data - queries a policy and writes its data to buf - * @buf: the resulting data is stored here (NOT NULL) -@@ -1280,6 +1372,10 @@ void __aafs_ns_rmdir(struct aa_ns *ns) - sub = d_inode(ns_subremove(ns))->i_private; - aa_put_ns(sub); - } -+ if (ns_subrevision(ns)) { -+ sub = d_inode(ns_subrevision(ns))->i_private; -+ aa_put_ns(sub); -+ } - - for (i = AAFS_NS_SIZEOF - 1; i >= 0; --i) { - aafs_remove(ns->dents[i]); -@@ -1305,6 +1401,13 @@ static int __aafs_ns_mkdir_entries(struct aa_ns *ns, struct dentry *dir) - return PTR_ERR(dent); - ns_subdata_dir(ns) = dent; - -+ dent = aafs_create_file("revision", 0444, dir, ns, -+ &aa_fs_ns_revision_fops); -+ if (IS_ERR(dent)) -+ return PTR_ERR(dent); -+ aa_get_ns(ns); -+ ns_subrevision(ns) = dent; -+ - dent = aafs_create_file(".load", 0640, dir, ns, - &aa_fs_profile_load); - if (IS_ERR(dent)) -@@ -1930,11 +2033,19 @@ static int __init aa_create_aafs(void) - } - ns_subremove(root_ns) = dent; - -+ dent = securityfs_create_file("revision", 0444, aa_sfs_entry.dentry, -+ NULL, &aa_fs_ns_revision_fops); -+ if (IS_ERR(dent)) { -+ error = PTR_ERR(dent); -+ goto error; -+ } -+ ns_subrevision(root_ns) = dent; -+ -+ /* policy tree referenced by magic policy symlink */ - mutex_lock(&root_ns->lock); - error = __aafs_ns_mkdir(root_ns, aafs_mnt->mnt_root, ".policy", - aafs_mnt->mnt_root); - mutex_unlock(&root_ns->lock); -- - if (error) - goto error; - -diff --git a/security/apparmor/include/apparmorfs.h b/security/apparmor/include/apparmorfs.h -index 071a59a1f056..bd689114bf93 100644 ---- a/security/apparmor/include/apparmorfs.h -+++ b/security/apparmor/include/apparmorfs.h -@@ -74,6 +74,7 @@ enum aafs_ns_type { - AAFS_NS_LOAD, - AAFS_NS_REPLACE, - AAFS_NS_REMOVE, -+ AAFS_NS_REVISION, - AAFS_NS_COUNT, - AAFS_NS_MAX_COUNT, - AAFS_NS_SIZE, -@@ -102,6 +103,7 @@ enum aafs_prof_type { - #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]) -diff --git a/security/apparmor/include/policy_ns.h b/security/apparmor/include/policy_ns.h -index d7a07ac96168..23e7cb770226 100644 ---- a/security/apparmor/include/policy_ns.h -+++ b/security/apparmor/include/policy_ns.h -@@ -69,6 +69,7 @@ struct aa_ns { - long uniq_id; - int level; - long revision; -+ wait_queue_head_t wait; - - struct list_head rawdata_list; - -diff --git a/security/apparmor/policy_ns.c b/security/apparmor/policy_ns.c -index 7d7c23705be2..f3418a9e59b1 100644 ---- a/security/apparmor/policy_ns.c -+++ b/security/apparmor/policy_ns.c -@@ -101,6 +101,7 @@ static struct aa_ns *alloc_ns(const char *prefix, const char *name) - INIT_LIST_HEAD(&ns->sub_ns); - INIT_LIST_HEAD(&ns->rawdata_list); - mutex_init(&ns->lock); -+ init_waitqueue_head(&ns->wait); - - /* released by aa_free_ns() */ - ns->unconfined = aa_alloc_profile("unconfined", GFP_KERNEL); --- -2.12.3 - diff --git a/patches.apparmor/0022-apparmor-add-mkdir-rmdir-interface-to-manage-policy-.patch b/patches.apparmor/0022-apparmor-add-mkdir-rmdir-interface-to-manage-policy-.patch deleted file mode 100644 index d3b7549..0000000 --- a/patches.apparmor/0022-apparmor-add-mkdir-rmdir-interface-to-manage-policy-.patch +++ /dev/null @@ -1,138 +0,0 @@ -From 45f06af64e6d81ed917df095f06baff6b4a80404 Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Fri, 26 May 2017 16:45:48 -0700 -Subject: [PATCH 22/65] apparmor: add mkdir/rmdir interface to manage policy - namespaces -Git-commit: 4ae47f33354a96efb4e4231dec0d72a586b3921c -Patch-mainline: v4.13-rc1 -References: FATE#323500 - -When setting up namespaces for containers its easier for them to use -an fs interface to create the namespace for the containers -policy. Allow mkdir/rmdir under the policy/namespaces/ dir to be used -to create and remove namespaces. - -BugLink: http://bugs.launchpad.net/bugs/1611078 - -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/apparmorfs.c | 95 +++++++++++++++++++++++++++++++++++++++++- - 1 file changed, 94 insertions(+), 1 deletion(-) - -diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c -index 8c413333726b..7f3049300ce3 100644 ---- a/security/apparmor/apparmorfs.c -+++ b/security/apparmor/apparmorfs.c -@@ -1322,6 +1322,97 @@ int __aafs_profile_mkdir(struct aa_profile *profile, struct dentry *parent) - return error; - } - -+static int ns_mkdir_op(struct inode *dir, struct dentry *dentry, umode_t mode) -+{ -+ struct aa_ns *ns, *parent; -+ /* TODO: improve permission check */ -+ struct aa_profile *profile = aa_current_profile(); -+ int error = aa_may_manage_policy(profile, NULL, AA_MAY_LOAD_POLICY); -+ -+ if (error) -+ return error; -+ -+ parent = aa_get_ns(dir->i_private); -+ AA_BUG(d_inode(ns_subns_dir(parent)) != dir); -+ -+ /* we have to unlock and then relock to get locking order right -+ * for pin_fs -+ */ -+ inode_unlock(dir); -+ error = simple_pin_fs(&aafs_ops, &aafs_mnt, &aafs_count); -+ mutex_lock(&parent->lock); -+ inode_lock_nested(dir, I_MUTEX_PARENT); -+ if (error) -+ goto out; -+ -+ error = __aafs_setup_d_inode(dir, dentry, mode | S_IFDIR, NULL, -+ NULL, NULL, NULL); -+ if (error) -+ goto out_pin; -+ -+ ns = __aa_find_or_create_ns(parent, READ_ONCE(dentry->d_name.name), -+ dentry); -+ if (IS_ERR(ns)) { -+ error = PTR_ERR(ns); -+ ns = NULL; -+ } -+ -+ aa_put_ns(ns); /* list ref remains */ -+out_pin: -+ if (error) -+ simple_release_fs(&aafs_mnt, &aafs_count); -+out: -+ mutex_unlock(&parent->lock); -+ aa_put_ns(parent); -+ -+ return error; -+} -+ -+static int ns_rmdir_op(struct inode *dir, struct dentry *dentry) -+{ -+ struct aa_ns *ns, *parent; -+ /* TODO: improve permission check */ -+ struct aa_profile *profile = aa_current_profile(); -+ int error = aa_may_manage_policy(profile, NULL, AA_MAY_LOAD_POLICY); -+ -+ if (error) -+ return error; -+ -+ parent = aa_get_ns(dir->i_private); -+ /* rmdir calls the generic securityfs functions to remove files -+ * from the apparmor dir. It is up to the apparmor ns locking -+ * to avoid races. -+ */ -+ inode_unlock(dir); -+ inode_unlock(dentry->d_inode); -+ -+ mutex_lock(&parent->lock); -+ ns = aa_get_ns(__aa_findn_ns(&parent->sub_ns, dentry->d_name.name, -+ dentry->d_name.len)); -+ if (!ns) { -+ error = -ENOENT; -+ goto out; -+ } -+ AA_BUG(ns_dir(ns) != dentry); -+ -+ __aa_remove_ns(ns); -+ aa_put_ns(ns); -+ -+out: -+ mutex_unlock(&parent->lock); -+ inode_lock_nested(dir, I_MUTEX_PARENT); -+ inode_lock(dentry->d_inode); -+ aa_put_ns(parent); -+ -+ return error; -+} -+ -+static const struct inode_operations ns_dir_inode_operations = { -+ .lookup = simple_lookup, -+ .mkdir = ns_mkdir_op, -+ .rmdir = ns_rmdir_op, -+}; -+ - static void __aa_fs_list_remove_rawdata(struct aa_ns *ns) - { - struct aa_loaddata *ent, *tmp; -@@ -1429,7 +1520,9 @@ static int __aafs_ns_mkdir_entries(struct aa_ns *ns, struct dentry *dir) - aa_get_ns(ns); - ns_subremove(ns) = dent; - -- dent = aafs_create_dir("namespaces", dir); -+ /* use create_dentry so we can supply private data */ -+ dent = aafs_create("namespaces", S_IFDIR | 0755, dir, ns, NULL, NULL, -+ &ns_dir_inode_operations); - if (IS_ERR(dent)) - return PTR_ERR(dent); - aa_get_ns(ns); --- -2.12.3 - diff --git a/patches.apparmor/0023-apparmor-add-label-data-availability-to-the-feature-.patch b/patches.apparmor/0023-apparmor-add-label-data-availability-to-the-feature-.patch deleted file mode 100644 index b7e23c6..0000000 --- a/patches.apparmor/0023-apparmor-add-label-data-availability-to-the-feature-.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 64aa0a3ce8246414908ab89edf90a432fa4fae30 Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Fri, 26 May 2017 18:49:04 -0700 -Subject: [PATCH 23/65] apparmor: add label data availability to the feature - set -Git-commit: a83bd86e833a5842ad033527ea9af589efa6dc84 -Patch-mainline: v4.13-rc1 -References: FATE#323500 - -gsettings mediation needs to be able to determine if apparmor supports -label data queries. A label data query can be done to test for support -but its failure is indistinguishable from other failures, making it an -unreliable indicator. - -Fix by making support of label data queries available as a flag in the -apparmorfs features dir tree. - -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/apparmorfs.c | 10 ++++++++++ - 1 file changed, 10 insertions(+) - -diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c -index 7f3049300ce3..a447c00a452c 100644 ---- a/security/apparmor/apparmorfs.c -+++ b/security/apparmor/apparmorfs.c -@@ -1849,6 +1849,15 @@ static struct aa_sfs_entry aa_sfs_entry_policy[] = { - { } - }; - -+static struct aa_sfs_entry aa_sfs_entry_query_label[] = { -+ AA_SFS_FILE_BOOLEAN("data", 1), -+ { } -+}; -+ -+static struct aa_sfs_entry aa_sfs_entry_query[] = { -+ AA_SFS_DIR("label", aa_sfs_entry_query_label), -+ { } -+}; - static struct aa_sfs_entry aa_sfs_entry_features[] = { - AA_SFS_DIR("policy", aa_sfs_entry_policy), - AA_SFS_DIR("domain", aa_sfs_entry_domain), -@@ -1856,6 +1865,7 @@ static struct aa_sfs_entry aa_sfs_entry_features[] = { - AA_SFS_FILE_U64("capability", VFS_CAP_FLAGS_MASK), - AA_SFS_DIR("rlimit", aa_sfs_entry_rlimit), - AA_SFS_DIR("caps", aa_sfs_entry_caps), -+ AA_SFS_DIR("query", aa_sfs_entry_query), - { } - }; - --- -2.12.3 - diff --git a/patches.apparmor/0024-apparmor-speed-up-transactional-queries.patch b/patches.apparmor/0024-apparmor-speed-up-transactional-queries.patch deleted file mode 100644 index 9709711..0000000 --- a/patches.apparmor/0024-apparmor-speed-up-transactional-queries.patch +++ /dev/null @@ -1,201 +0,0 @@ -From dd33af1c6dda5b2558918f5b6e638a5d58b85f06 Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Fri, 26 May 2017 17:23:23 -0700 -Subject: [PATCH 24/65] apparmor: speed up transactional queries -Git-commit: 1dea3b41e84c5923173fe654dcb758a5cb4a46e5 -Patch-mainline: v4.13-rc1 -References: FATE#323500 - -The simple_transaction interface is slow. It requires 4 syscalls -(open, write, read, close) per query and shares a single lock for each -queries. - -So replace its use with a compatible in multi_transaction interface. -It allows for a faster 2 syscall pattern per query. After an initial -open, an arbitrary number of writes and reads can be issued. Each -write will reset the query with new data that can be read. Reads do -not clear the data, and can be issued multiple times, and used with -seek, until a new write is performed which will reset the data -available and the seek position. - -Note: this keeps the single lock design, if needed moving to a per -file lock will have to come later. - -Acked-by: Goldwyn Rodrigues -Signed-off-by: John Johansen ---- - security/apparmor/apparmorfs.c | 125 +++++++++++++++++++++++++++++++++++++---- - 1 file changed, 114 insertions(+), 11 deletions(-) - -diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c -index a447c00a452c..e553de58f801 100644 ---- a/security/apparmor/apparmorfs.c -+++ b/security/apparmor/apparmorfs.c -@@ -673,6 +673,106 @@ static ssize_t query_data(char *buf, size_t buf_len, - return out - buf; - } - -+/* -+ * Transaction based IO. -+ * The file expects a write which triggers the transaction, and then -+ * possibly a read(s) which collects the result - which is stored in a -+ * file-local buffer. Once a new write is performed, a new set of results -+ * are stored in the file-local buffer. -+ */ -+struct multi_transaction { -+ struct kref count; -+ ssize_t size; -+ char data[0]; -+}; -+ -+#define MULTI_TRANSACTION_LIMIT (PAGE_SIZE - sizeof(struct multi_transaction)) -+/* TODO: replace with per file lock */ -+static DEFINE_SPINLOCK(multi_transaction_lock); -+ -+static void multi_transaction_kref(struct kref *kref) -+{ -+ struct multi_transaction *t; -+ -+ t = container_of(kref, struct multi_transaction, count); -+ free_page((unsigned long) t); -+} -+ -+static struct multi_transaction * -+get_multi_transaction(struct multi_transaction *t) -+{ -+ if (t) -+ kref_get(&(t->count)); -+ -+ return t; -+} -+ -+static void put_multi_transaction(struct multi_transaction *t) -+{ -+ if (t) -+ kref_put(&(t->count), multi_transaction_kref); -+} -+ -+/* does not increment @new's count */ -+static void multi_transaction_set(struct file *file, -+ struct multi_transaction *new, size_t n) -+{ -+ struct multi_transaction *old; -+ -+ AA_BUG(n > MULTI_TRANSACTION_LIMIT); -+ -+ new->size = n; -+ spin_lock(&multi_transaction_lock); -+ old = (struct multi_transaction *) file->private_data; -+ file->private_data = new; -+ spin_unlock(&multi_transaction_lock); -+ put_multi_transaction(old); -+} -+ -+static struct multi_transaction *multi_transaction_new(struct file *file, -+ const char __user *buf, -+ size_t size) -+{ -+ struct multi_transaction *t; -+ -+ if (size > MULTI_TRANSACTION_LIMIT - 1) -+ return ERR_PTR(-EFBIG); -+ -+ t = (struct multi_transaction *)get_zeroed_page(GFP_KERNEL); -+ if (!t) -+ return ERR_PTR(-ENOMEM); -+ kref_init(&t->count); -+ if (copy_from_user(t->data, buf, size)) -+ return ERR_PTR(-EFAULT); -+ -+ return t; -+} -+ -+static ssize_t multi_transaction_read(struct file *file, char __user *buf, -+ size_t size, loff_t *pos) -+{ -+ struct multi_transaction *t; -+ ssize_t ret; -+ -+ spin_lock(&multi_transaction_lock); -+ t = get_multi_transaction(file->private_data); -+ spin_unlock(&multi_transaction_lock); -+ if (!t) -+ return 0; -+ -+ ret = simple_read_from_buffer(buf, size, pos, t->data, t->size); -+ put_multi_transaction(t); -+ -+ return ret; -+} -+ -+static int multi_transaction_release(struct inode *inode, struct file *file) -+{ -+ put_multi_transaction(file->private_data); -+ -+ return 0; -+} -+ - #define QUERY_CMD_DATA "data\0" - #define QUERY_CMD_DATA_LEN 5 - -@@ -700,36 +800,38 @@ static ssize_t query_data(char *buf, size_t buf_len, - static ssize_t aa_write_access(struct file *file, const char __user *ubuf, - size_t count, loff_t *ppos) - { -- char *buf; -+ struct multi_transaction *t; - ssize_t len; - - if (*ppos) - return -ESPIPE; - -- buf = simple_transaction_get(file, ubuf, count); -- if (IS_ERR(buf)) -- return PTR_ERR(buf); -+ t = multi_transaction_new(file, ubuf, count); -+ if (IS_ERR(t)) -+ return PTR_ERR(t); - - if (count > QUERY_CMD_DATA_LEN && -- !memcmp(buf, QUERY_CMD_DATA, QUERY_CMD_DATA_LEN)) { -- len = query_data(buf, SIMPLE_TRANSACTION_LIMIT, -- buf + QUERY_CMD_DATA_LEN, -+ !memcmp(t->data, QUERY_CMD_DATA, QUERY_CMD_DATA_LEN)) { -+ len = query_data(t->data, MULTI_TRANSACTION_LIMIT, -+ t->data + QUERY_CMD_DATA_LEN, - count - QUERY_CMD_DATA_LEN); - } else - len = -EINVAL; - -- if (len < 0) -+ if (len < 0) { -+ put_multi_transaction(t); - return len; -+ } - -- simple_transaction_set(file, len); -+ multi_transaction_set(file, t, len); - - return count; - } - - static const struct file_operations aa_sfs_access = { - .write = aa_write_access, -- .read = simple_transaction_read, -- .release = simple_transaction_release, -+ .read = multi_transaction_read, -+ .release = multi_transaction_release, - .llseek = generic_file_llseek, - }; - -@@ -1851,6 +1953,7 @@ static struct aa_sfs_entry aa_sfs_entry_policy[] = { - - static struct aa_sfs_entry aa_sfs_entry_query_label[] = { - AA_SFS_FILE_BOOLEAN("data", 1), -+ AA_SFS_FILE_BOOLEAN("multi_transaction", 1), - { } - }; - --- -2.12.3 - diff --git a/patches.apparmor/0025-apparmor-add-fn-to-test-if-profile-supports-a-given-.patch b/patches.apparmor/0025-apparmor-add-fn-to-test-if-profile-supports-a-given-.patch deleted file mode 100644 index 0816031..0000000 --- a/patches.apparmor/0025-apparmor-add-fn-to-test-if-profile-supports-a-given-.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 38f2676cda498dc477a558ff0163b90b0bb7a9fe Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Mon, 29 May 2017 11:45:29 -0700 -Subject: [PATCH 25/65] apparmor: add fn to test if profile supports a given - mediation class -Git-commit: b5b2557c0aeca35b34c558fd09ad6da67b9f3557 -Patch-mainline: v4.13-rc1 -References: FATE#323500 - -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/include/policy.h | 10 ++++++++++ - 1 file changed, 10 insertions(+) - -diff --git a/security/apparmor/include/policy.h b/security/apparmor/include/policy.h -index 97bfbddef7b2..d93f475bfd8b 100644 ---- a/security/apparmor/include/policy.h -+++ b/security/apparmor/include/policy.h -@@ -222,6 +222,16 @@ void __aa_profile_list_release(struct list_head *head); - - #define unconfined(X) ((X)->mode == APPARMOR_UNCONFINED) - -+#define PROFILE_MEDIATES(P, T) ((P)->policy.start[(T)]) -+/* safe version of POLICY_MEDIATES for full range input */ -+static inline unsigned int PROFILE_MEDIATES_SAFE(struct aa_profile *profile, -+ unsigned char class) -+{ -+ if (profile->policy.dfa) -+ return aa_dfa_match_len(profile->policy.dfa, -+ profile->policy.start[0], &class, 1); -+ return 0; -+} - - /** - * aa_get_profile - increment refcount on profile @p --- -2.12.3 - diff --git a/patches.apparmor/0026-apparmor-add-gerneric-permissions-struct-and-support.patch b/patches.apparmor/0026-apparmor-add-gerneric-permissions-struct-and-support.patch deleted file mode 100644 index b2ec9f4..0000000 --- a/patches.apparmor/0026-apparmor-add-gerneric-permissions-struct-and-support.patch +++ /dev/null @@ -1,281 +0,0 @@ -From 9377e727c8045a58dee38ff817029e2a3627363e Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Mon, 29 May 2017 12:16:04 -0700 -Subject: [PATCH 26/65] apparmor: add gerneric permissions struct and support - fns -Git-commit: aa9aeea8d4c3dfb9297723c4340671ef88e372d3 -Patch-mainline: v4.13-rc1 -References: FATE#323500 - -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/file.c | 30 +++++------ - security/apparmor/include/audit.h | 4 +- - security/apparmor/include/perms.h | 34 +++++++++++++ - security/apparmor/lib.c | 102 ++++++++++++++++++++++++++++++++++++++ - 4 files changed, 153 insertions(+), 17 deletions(-) - -diff --git a/security/apparmor/file.c b/security/apparmor/file.c -index 44549db904b3..1ee656f66aa4 100644 ---- a/security/apparmor/file.c -+++ b/security/apparmor/file.c -@@ -56,15 +56,15 @@ static void file_audit_cb(struct audit_buffer *ab, void *va) - struct common_audit_data *sa = va; - kuid_t fsuid = current_fsuid(); - -- if (aad(sa)->fs.request & AA_AUDIT_FILE_MASK) { -+ if (aad(sa)->request & AA_AUDIT_FILE_MASK) { - audit_log_format(ab, " requested_mask="); -- audit_file_mask(ab, aad(sa)->fs.request); -+ audit_file_mask(ab, aad(sa)->request); - } -- if (aad(sa)->fs.denied & AA_AUDIT_FILE_MASK) { -+ if (aad(sa)->denied & AA_AUDIT_FILE_MASK) { - audit_log_format(ab, " denied_mask="); -- audit_file_mask(ab, aad(sa)->fs.denied); -+ audit_file_mask(ab, aad(sa)->denied); - } -- if (aad(sa)->fs.request & AA_AUDIT_FILE_MASK) { -+ if (aad(sa)->request & AA_AUDIT_FILE_MASK) { - audit_log_format(ab, " fsuid=%d", - from_kuid(&init_user_ns, fsuid)); - audit_log_format(ab, " ouid=%d", -@@ -100,7 +100,7 @@ int aa_audit_file(struct aa_profile *profile, struct file_perms *perms, - DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_TASK, op); - - sa.u.tsk = NULL; -- aad(&sa)->fs.request = request; -+ aad(&sa)->request = request; - aad(&sa)->name = name; - aad(&sa)->fs.target = target; - aad(&sa)->fs.ouid = ouid; -@@ -115,30 +115,30 @@ int aa_audit_file(struct aa_profile *profile, struct file_perms *perms, - mask = 0xffff; - - /* mask off perms that are not being force audited */ -- aad(&sa)->fs.request &= mask; -+ aad(&sa)->request &= mask; - -- if (likely(!aad(&sa)->fs.request)) -+ if (likely(!aad(&sa)->request)) - return 0; - type = AUDIT_APPARMOR_AUDIT; - } else { - /* only report permissions that were denied */ -- aad(&sa)->fs.request = aad(&sa)->fs.request & ~perms->allow; -- AA_BUG(!aad(&sa)->fs.request); -+ aad(&sa)->request = aad(&sa)->request & ~perms->allow; -+ AA_BUG(!aad(&sa)->request); - -- if (aad(&sa)->fs.request & perms->kill) -+ if (aad(&sa)->request & perms->kill) - type = AUDIT_APPARMOR_KILL; - - /* quiet known rejects, assumes quiet and kill do not overlap */ -- if ((aad(&sa)->fs.request & perms->quiet) && -+ if ((aad(&sa)->request & perms->quiet) && - AUDIT_MODE(profile) != AUDIT_NOQUIET && - AUDIT_MODE(profile) != AUDIT_ALL) -- aad(&sa)->fs.request &= ~perms->quiet; -+ aad(&sa)->request &= ~perms->quiet; - -- if (!aad(&sa)->fs.request) -+ if (!aad(&sa)->request) - return COMPLAIN_MODE(profile) ? 0 : aad(&sa)->error; - } - -- aad(&sa)->fs.denied = aad(&sa)->fs.request & ~perms->allow; -+ aad(&sa)->denied = aad(&sa)->request & ~perms->allow; - return aa_audit(type, profile, &sa, file_audit_cb); - } - -diff --git a/security/apparmor/include/audit.h b/security/apparmor/include/audit.h -index fdc4774318ba..1aeb8550fb82 100644 ---- a/security/apparmor/include/audit.h -+++ b/security/apparmor/include/audit.h -@@ -107,14 +107,14 @@ struct apparmor_audit_data { - void *profile; - const char *name; - const char *info; -+ u32 request; -+ u32 denied; - union { - /* these entries require a custom callback fn */ - struct { - struct aa_profile *peer; - struct { - const char *target; -- u32 request; -- u32 denied; - kuid_t ouid; - } fs; - }; -diff --git a/security/apparmor/include/perms.h b/security/apparmor/include/perms.h -index 35e365e7aa75..6ef23212bd66 100644 ---- a/security/apparmor/include/perms.h -+++ b/security/apparmor/include/perms.h -@@ -66,6 +66,40 @@ - 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 allperms; -+ -+struct aa_profile; -+ - void aa_perm_mask_to_str(char *str, const char *chrs, u32 mask); -+void aa_audit_perm_names(struct audit_buffer *ab, const char **names, u32 mask); -+void aa_audit_perm_mask(struct audit_buffer *ab, u32 mask, const char *chrs, -+ u32 chrsmask, const char **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); - - #endif /* __AA_PERM_H */ -diff --git a/security/apparmor/lib.c b/security/apparmor/lib.c -index 90d4631ddafe..a50913744823 100644 ---- a/security/apparmor/lib.c -+++ b/security/apparmor/lib.c -@@ -24,6 +24,10 @@ - #include "include/perms.h" - #include "include/policy.h" - -+struct aa_perms allperms = { .allow = ALL_PERMS_MASK, -+ .quiet = ALL_PERMS_MASK, -+ .hide = ALL_PERMS_MASK }; -+ - /** - * aa_split_fqname - split a fqname into a profile and namespace name - * @fqname: a full qualified name in namespace profile format (NOT NULL) -@@ -188,6 +192,104 @@ void aa_perm_mask_to_str(char *str, const char *chrs, u32 mask) - *str = '\0'; - } - -+void aa_audit_perm_names(struct audit_buffer *ab, const char **names, u32 mask) -+{ -+ const char *fmt = "%s"; -+ unsigned int i, perm = 1; -+ bool prev = false; -+ -+ for (i = 0; i < 32; perm <<= 1, i++) { -+ if (mask & perm) { -+ audit_log_format(ab, fmt, names[i]); -+ if (!prev) { -+ prev = true; -+ fmt = " %s"; -+ } -+ } -+ } -+} -+ -+void aa_audit_perm_mask(struct audit_buffer *ab, u32 mask, const char *chrs, -+ u32 chrsmask, const char **names, u32 namesmask) -+{ -+ char str[33]; -+ -+ audit_log_format(ab, "\""); -+ if ((mask & chrsmask) && chrs) { -+ aa_perm_mask_to_str(str, chrs, mask & chrsmask); -+ mask &= ~chrsmask; -+ audit_log_format(ab, "%s", str); -+ if (mask & namesmask) -+ audit_log_format(ab, " "); -+ } -+ if ((mask & namesmask) && names) -+ aa_audit_perm_names(ab, names, mask & namesmask); -+ audit_log_format(ab, "\""); -+} -+ -+/** -+ * aa_apply_modes_to_perms - apply namespace and profile flags to perms -+ * @profile: that perms where computed from -+ * @perms: perms to apply mode modifiers to -+ * -+ * TODO: split into profile and ns based flags for when accumulating perms -+ */ -+void aa_apply_modes_to_perms(struct aa_profile *profile, struct aa_perms *perms) -+{ -+ switch (AUDIT_MODE(profile)) { -+ case AUDIT_ALL: -+ perms->audit = ALL_PERMS_MASK; -+ /* fall through */ -+ case AUDIT_NOQUIET: -+ perms->quiet = 0; -+ break; -+ case AUDIT_QUIET: -+ perms->audit = 0; -+ /* fall through */ -+ case AUDIT_QUIET_DENIED: -+ perms->quiet = ALL_PERMS_MASK; -+ break; -+ } -+ -+ if (KILL_MODE(profile)) -+ perms->kill = ALL_PERMS_MASK; -+ else if (COMPLAIN_MODE(profile)) -+ perms->complain = ALL_PERMS_MASK; -+/* -+ * TODO: -+ * else if (PROMPT_MODE(profile)) -+ * perms->prompt = ALL_PERMS_MASK; -+ */ -+} -+ -+static u32 map_other(u32 x) -+{ -+ return ((x & 0x3) << 8) | /* SETATTR/GETATTR */ -+ ((x & 0x1c) << 18) | /* ACCEPT/BIND/LISTEN */ -+ ((x & 0x60) << 19); /* SETOPT/GETOPT */ -+} -+ -+void aa_compute_perms(struct aa_dfa *dfa, unsigned int state, -+ struct aa_perms *perms) -+{ -+ perms->deny = 0; -+ perms->kill = perms->stop = 0; -+ perms->complain = perms->cond = 0; -+ perms->hide = 0; -+ perms->prompt = 0; -+ perms->allow = dfa_user_allow(dfa, state); -+ perms->audit = dfa_user_audit(dfa, state); -+ perms->quiet = dfa_user_quiet(dfa, state); -+ -+ /* for v5 perm mapping in the policydb, the other set is used -+ * to extend the general perm set -+ */ -+ perms->allow |= map_other(dfa_other_allow(dfa, state)); -+ perms->audit |= map_other(dfa_other_audit(dfa, state)); -+ perms->quiet |= map_other(dfa_other_quiet(dfa, state)); -+// perms->xindex = dfa_user_xindex(dfa, state); -+} -+ - /** - * aa_policy_init - initialize a policy structure - * @policy: policy to initialize (NOT NULL) --- -2.12.3 - diff --git a/patches.apparmor/0027-apparmor-switch-from-file_perms-to-aa_perms.patch b/patches.apparmor/0027-apparmor-switch-from-file_perms-to-aa_perms.patch deleted file mode 100644 index b6ec604..0000000 --- a/patches.apparmor/0027-apparmor-switch-from-file_perms-to-aa_perms.patch +++ /dev/null @@ -1,250 +0,0 @@ -From 66f4781f467e03ad8c2896275ed747798f9ca02c Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Mon, 29 May 2017 12:19:39 -0700 -Subject: [PATCH 27/65] apparmor: switch from file_perms to aa_perms -Git-commit: 2d679f3cb0eaa6afa0dc97fe6ad3b797e1c1899a -Patch-mainline: v4.13-rc1 -References: FATE#323500 - -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/domain.c | 18 +++++++++--------- - security/apparmor/file.c | 31 ++++++++++++++----------------- - security/apparmor/include/file.h | 25 ++++--------------------- - security/apparmor/include/perms.h | 2 +- - security/apparmor/lib.c | 1 + - 5 files changed, 29 insertions(+), 48 deletions(-) - -diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c -index ab8f23cdccff..a0ba33454b8c 100644 ---- a/security/apparmor/domain.c -+++ b/security/apparmor/domain.c -@@ -93,12 +93,12 @@ static int may_change_ptraced_domain(struct aa_profile *to_profile) - * - * Returns: permission set - */ --static struct file_perms change_profile_perms(struct aa_profile *profile, -- struct aa_ns *ns, -- const char *name, u32 request, -- unsigned int start) -+static struct aa_perms change_profile_perms(struct aa_profile *profile, -+ struct aa_ns *ns, -+ const char *name, u32 request, -+ unsigned int start) - { -- struct file_perms perms; -+ struct aa_perms perms; - struct path_cond cond = { }; - unsigned int state; - -@@ -342,7 +342,7 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm) - struct aa_ns *ns; - char *buffer = NULL; - unsigned int state; -- struct file_perms perms = {}; -+ struct aa_perms perms = {}; - struct path_cond cond = { - file_inode(bprm->file)->i_uid, - file_inode(bprm->file)->i_mode -@@ -400,7 +400,7 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm) - /* find exec permissions for name */ - state = aa_str_perms(profile->file.dfa, state, name, &cond, &perms); - if (ctx->onexec) { -- struct file_perms cp; -+ struct aa_perms cp; - info = "change_profile onexec"; - new_profile = aa_get_newest_profile(ctx->onexec); - if (!(perms.allow & AA_MAY_ONEXEC)) -@@ -609,7 +609,7 @@ int aa_change_hat(const char *hats[], int count, u64 token, bool permtest) - struct aa_profile *profile, *previous_profile, *hat = NULL; - char *name = NULL; - int i; -- struct file_perms perms = {}; -+ struct aa_perms perms = {}; - const char *target = NULL, *info = NULL; - int error = 0; - -@@ -748,7 +748,7 @@ int aa_change_profile(const char *fqname, bool onexec, - { - const struct cred *cred; - struct aa_profile *profile, *target = NULL; -- struct file_perms perms = {}; -+ struct aa_perms perms = {}; - const char *info = NULL, *op; - int error = 0; - u32 request; -diff --git a/security/apparmor/file.c b/security/apparmor/file.c -index 1ee656f66aa4..2e128c2aa4dc 100644 ---- a/security/apparmor/file.c -+++ b/security/apparmor/file.c -@@ -19,8 +19,6 @@ - #include "include/path.h" - #include "include/policy.h" - --struct file_perms nullperms; -- - static u32 map_mask_to_chr_mask(u32 mask) - { - u32 m = mask & PERMS_CHRS_MASK; -@@ -92,7 +90,7 @@ static void file_audit_cb(struct audit_buffer *ab, void *va) - * - * Returns: %0 or error on failure - */ --int aa_audit_file(struct aa_profile *profile, struct file_perms *perms, -+int aa_audit_file(struct aa_profile *profile, struct aa_perms *perms, - const char *op, u32 request, const char *name, - const char *target, kuid_t ouid, const char *info, int error) - { -@@ -170,7 +168,7 @@ static u32 map_old_perms(u32 old) - } - - /** -- * compute_perms - convert dfa compressed perms to internal perms -+ * aa_compute_fperms - convert dfa compressed perms to internal perms - * @dfa: dfa to compute perms for (NOT NULL) - * @state: state in dfa - * @cond: conditions to consider (NOT NULL) -@@ -180,17 +178,21 @@ static u32 map_old_perms(u32 old) - * - * Returns: computed permission set - */ --static struct file_perms compute_perms(struct aa_dfa *dfa, unsigned int state, -- struct path_cond *cond) -+struct aa_perms aa_compute_fperms(struct aa_dfa *dfa, unsigned int state, -+ struct path_cond *cond) - { -- struct file_perms perms; -+ struct aa_perms perms; - - /* FIXME: change over to new dfa format - * currently file perms are encoded in the dfa, new format - * splits the permissions from the dfa. This mapping can be - * done at profile load - */ -- perms.kill = 0; -+ perms.deny = 0; -+ perms.kill = perms.stop = 0; -+ perms.complain = perms.cond = 0; -+ perms.hide = 0; -+ perms.prompt = 0; - - if (uid_eq(current_fsuid(), cond->uid)) { - perms.allow = map_old_perms(dfa_user_allow(dfa, state)); -@@ -226,16 +228,11 @@ static struct file_perms compute_perms(struct aa_dfa *dfa, unsigned int state, - */ - unsigned int aa_str_perms(struct aa_dfa *dfa, unsigned int start, - const char *name, struct path_cond *cond, -- struct file_perms *perms) -+ struct aa_perms *perms) - { - unsigned int state; -- if (!dfa) { -- *perms = nullperms; -- return DFA_NOMATCH; -- } -- - state = aa_dfa_match(dfa, start, name); -- *perms = compute_perms(dfa, state, cond); -+ *perms = aa_compute_fperms(dfa, state, cond); - - return state; - } -@@ -269,7 +266,7 @@ int aa_path_perm(const char *op, struct aa_profile *profile, - struct path_cond *cond) - { - char *buffer = NULL; -- struct file_perms perms = {}; -+ struct aa_perms perms = {}; - const char *name, *info = NULL; - int error; - -@@ -348,7 +345,7 @@ int aa_path_link(struct aa_profile *profile, struct dentry *old_dentry, - }; - char *buffer = NULL, *buffer2 = NULL; - const char *lname, *tname = NULL, *info = NULL; -- struct file_perms lperms, perms; -+ struct aa_perms lperms, perms; - u32 request = AA_MAY_LINK; - unsigned int state; - int error; -diff --git a/security/apparmor/include/file.h b/security/apparmor/include/file.h -index fb3642a94e3d..365ca7ead133 100644 ---- a/security/apparmor/include/file.h -+++ b/security/apparmor/include/file.h -@@ -90,25 +90,6 @@ struct path_cond { - umode_t mode; - }; - --/* struct file_perms - file permission -- * @allow: mask of permissions that are allowed -- * @audit: mask of permissions to force an audit message for -- * @quiet: mask of permissions to quiet audit messages for -- * @kill: mask of permissions that when matched will kill the task -- * @xindex: exec transition index if @allow contains MAY_EXEC -- * -- * The @audit and @queit mask should be mutually exclusive. -- */ --struct file_perms { -- u32 allow; -- u32 audit; -- u32 quiet; -- u32 kill; -- u16 xindex; --}; -- --extern struct file_perms nullperms; -- - #define COMBINED_PERM_MASK(X) ((X).allow | (X).audit | (X).quiet | (X).kill) - - /* FIXME: split perms from dfa and match this to description -@@ -159,7 +140,7 @@ static inline u16 dfa_map_xindex(u16 mask) - #define dfa_other_xindex(dfa, state) \ - dfa_map_xindex((ACCEPT_TABLE(dfa)[state] >> 14) & 0x3fff) - --int aa_audit_file(struct aa_profile *profile, struct file_perms *perms, -+int aa_audit_file(struct aa_profile *profile, struct aa_perms *perms, - const char *op, u32 request, const char *name, - const char *target, kuid_t ouid, const char *info, int error); - -@@ -182,9 +163,11 @@ struct aa_file_rules { - /* 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 file_perms *perms); -+ struct aa_perms *perms); - - int aa_path_perm(const char *op, struct aa_profile *profile, - const struct path *path, int flags, u32 request, -diff --git a/security/apparmor/include/perms.h b/security/apparmor/include/perms.h -index 6ef23212bd66..82946fb81f91 100644 ---- a/security/apparmor/include/perms.h -+++ b/security/apparmor/include/perms.h -@@ -88,7 +88,7 @@ struct aa_perms { - }; - - #define ALL_PERMS_MASK 0xffffffff -- -+extern struct aa_perms nullperms; - extern struct aa_perms allperms; - - struct aa_profile; -diff --git a/security/apparmor/lib.c b/security/apparmor/lib.c -index a50913744823..3e9146e68c4a 100644 ---- a/security/apparmor/lib.c -+++ b/security/apparmor/lib.c -@@ -24,6 +24,7 @@ - #include "include/perms.h" - #include "include/policy.h" - -+struct aa_perms nullperms; - struct aa_perms allperms = { .allow = ALL_PERMS_MASK, - .quiet = ALL_PERMS_MASK, - .hide = ALL_PERMS_MASK }; --- -2.12.3 - diff --git a/patches.apparmor/0028-apparmor-add-profile-permission-query-ability.patch b/patches.apparmor/0028-apparmor-add-profile-permission-query-ability.patch deleted file mode 100644 index 5513216..0000000 --- a/patches.apparmor/0028-apparmor-add-profile-permission-query-ability.patch +++ /dev/null @@ -1,163 +0,0 @@ -From 4d5bf455c74738444b82831b32594d291f28733f Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Fri, 26 May 2017 18:35:29 -0700 -Subject: [PATCH 28/65] apparmor: add profile permission query ability -Git-commit: 4f3b3f2d79a42e5094f55eca4f29d8f60f1190bd -Patch-mainline: v4.13-rc1 -References: FATE#323500 - -Allow userspace to query a profile about permissions, through the -transaction interface that is already used to allow userspace to -query about key,value data. - -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/apparmorfs.c | 103 ++++++++++++++++++++++++++++++++++++++++- - 1 file changed, 102 insertions(+), 1 deletion(-) - -diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c -index e553de58f801..105a1da57b8f 100644 ---- a/security/apparmor/apparmorfs.c -+++ b/security/apparmor/apparmorfs.c -@@ -595,6 +595,40 @@ static const struct file_operations aa_fs_ns_revision_fops = { - .release = ns_revision_release, - }; - -+static void profile_query_cb(struct aa_profile *profile, struct aa_perms *perms, -+ const char *match_str, size_t match_len) -+{ -+ struct aa_perms tmp; -+ struct aa_dfa *dfa; -+ unsigned int state = 0; -+ -+ if (unconfined(profile)) -+ return; -+ if (profile->file.dfa && *match_str == AA_CLASS_FILE) { -+ dfa = profile->file.dfa; -+ state = aa_dfa_match_len(dfa, profile->file.start, -+ match_str + 1, match_len - 1); -+ tmp = nullperms; -+ if (state) { -+ struct path_cond cond = { }; -+ -+ tmp = aa_compute_fperms(dfa, state, &cond); -+ } -+ } else if (profile->policy.dfa) { -+ if (!PROFILE_MEDIATES_SAFE(profile, *match_str)) -+ return; /* no change to current perms */ -+ dfa = profile->policy.dfa; -+ state = aa_dfa_match_len(dfa, profile->policy.start[0], -+ match_str, match_len); -+ if (state) -+ aa_compute_perms(dfa, state, &tmp); -+ else -+ tmp = nullperms; -+ } -+ aa_apply_modes_to_perms(profile, &tmp); -+} -+ -+ - /** - * query_data - queries a policy and writes its data to buf - * @buf: the resulting data is stored here (NOT NULL) -@@ -673,6 +707,64 @@ static ssize_t query_data(char *buf, size_t buf_len, - return out - buf; - } - -+/** -+ * query_label - queries a label and writes permissions to buf -+ * @buf: the resulting permissions string is stored here (NOT NULL) -+ * @buf_len: size of buf -+ * @query: binary query string to match against the dfa -+ * @query_len: size of query -+ * @view_only: only compute for querier's view -+ * -+ * The buffers pointed to by buf and query may overlap. The query buffer is -+ * parsed before buf is written to. -+ * -+ * The query should look like "LABEL_NAME\0DFA_STRING" where LABEL_NAME is -+ * the name of the label, in the current namespace, that is to be queried and -+ * DFA_STRING is a binary string to match against the label(s)'s DFA. -+ * -+ * LABEL_NAME must be NUL terminated. DFA_STRING may contain NUL characters -+ * but must *not* be NUL terminated. -+ * -+ * Returns: number of characters written to buf or -errno on failure -+ */ -+static ssize_t query_label(char *buf, size_t buf_len, -+ char *query, size_t query_len, bool view_only) -+{ -+ struct aa_profile *profile, *curr; -+ char *label_name, *match_str; -+ size_t label_name_len, match_len; -+ struct aa_perms perms; -+ -+ if (!query_len) -+ return -EINVAL; -+ -+ label_name = query; -+ label_name_len = strnlen(query, query_len); -+ if (!label_name_len || label_name_len == query_len) -+ return -EINVAL; -+ -+ /** -+ * The extra byte is to account for the null byte between the -+ * profile name and dfa string. profile_name_len is greater -+ * than zero and less than query_len, so a byte can be safely -+ * added or subtracted. -+ */ -+ match_str = label_name + label_name_len + 1; -+ match_len = query_len - label_name_len - 1; -+ -+ curr = aa_current_profile(); -+ profile = aa_fqlookupn_profile(curr, label_name, label_name_len); -+ if (!profile) -+ return -ENOENT; -+ -+ perms = allperms; -+ profile_query_cb(profile, &perms, match_str, match_len); -+ -+ return scnprintf(buf, buf_len, -+ "allow 0x%08x\ndeny 0x%08x\naudit 0x%08x\nquiet 0x%08x\n", -+ perms.allow, perms.deny, perms.audit, perms.quiet); -+} -+ - /* - * Transaction based IO. - * The file expects a write which triggers the transaction, and then -@@ -773,6 +865,9 @@ static int multi_transaction_release(struct inode *inode, struct file *file) - return 0; - } - -+#define QUERY_CMD_PROFILE "profile\0" -+#define QUERY_CMD_PROFILE_LEN 8 -+ - #define QUERY_CMD_DATA "data\0" - #define QUERY_CMD_DATA_LEN 5 - -@@ -810,7 +905,12 @@ static ssize_t aa_write_access(struct file *file, const char __user *ubuf, - if (IS_ERR(t)) - return PTR_ERR(t); - -- if (count > QUERY_CMD_DATA_LEN && -+ if (count > QUERY_CMD_PROFILE_LEN && -+ !memcmp(t->data, QUERY_CMD_PROFILE, QUERY_CMD_PROFILE_LEN)) { -+ len = query_label(t->data, MULTI_TRANSACTION_LIMIT, -+ t->data + QUERY_CMD_PROFILE_LEN, -+ count - QUERY_CMD_PROFILE_LEN, true); -+ } else if (count > QUERY_CMD_DATA_LEN && - !memcmp(t->data, QUERY_CMD_DATA, QUERY_CMD_DATA_LEN)) { - len = query_data(t->data, MULTI_TRANSACTION_LIMIT, - t->data + QUERY_CMD_DATA_LEN, -@@ -1952,6 +2052,7 @@ static struct aa_sfs_entry aa_sfs_entry_policy[] = { - }; - - static struct aa_sfs_entry aa_sfs_entry_query_label[] = { -+ AA_SFS_FILE_STRING("perms", "allow deny audit quiet"), - AA_SFS_FILE_BOOLEAN("data", 1), - AA_SFS_FILE_BOOLEAN("multi_transaction", 1), - { } --- -2.12.3 - diff --git a/patches.apparmor/0029-apparmor-provide-information-about-path-buffer-size-.patch b/patches.apparmor/0029-apparmor-provide-information-about-path-buffer-size-.patch deleted file mode 100644 index b4a3f3a..0000000 --- a/patches.apparmor/0029-apparmor-provide-information-about-path-buffer-size-.patch +++ /dev/null @@ -1,43 +0,0 @@ -From c4838ffabb2d671934b99ace0f09539c292fc57c Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Thu, 30 Mar 2017 05:25:23 -0700 -Subject: [PATCH 29/65] apparmor: provide information about path buffer size at - boot -Git-commit: 39d84824eae3b1348408237173c710473e726ca9 -Patch-mainline: v4.13-rc1 -References: FATE#323500 - -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/lsm.c | 11 +++++++++-- - 1 file changed, 9 insertions(+), 2 deletions(-) - -diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c -index a128f1772135..8ab00c98613f 100644 ---- a/security/apparmor/lsm.c -+++ b/security/apparmor/lsm.c -@@ -774,11 +774,18 @@ static int param_get_aabool(char *buffer, const struct kernel_param *kp) - - static int param_set_aauint(const char *val, const struct kernel_param *kp) - { -+ int error; -+ - if (!apparmor_enabled) - return -EINVAL; -- if (apparmor_initialized && !policy_admin_capable(NULL)) -+ /* file is ro but enforce 2nd line check */ -+ if (apparmor_initialized) - return -EPERM; -- return param_set_uint(val, kp); -+ -+ error = param_set_uint(val, kp); -+ pr_info("AppArmor: buffer size set to %d bytes\n", aa_g_path_max); -+ -+ return error; - } - - static int param_get_aauint(char *buffer, const struct kernel_param *kp) --- -2.12.3 - diff --git a/patches.apparmor/0030-apparmor-cleanup-__find_child.patch b/patches.apparmor/0030-apparmor-cleanup-__find_child.patch deleted file mode 100644 index 37cce74..0000000 --- a/patches.apparmor/0030-apparmor-cleanup-__find_child.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 00787f48b355f8942498c58edd474820723a4abc Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Fri, 2 Jun 2017 13:50:22 -0700 -Subject: [PATCH 30/65] apparmor: cleanup __find_child( -Patch-mainline: v4.13-rc1 -References: FATE#323500 -Git-commit: ae3b31653691b9c5b572b99596de3dfcc8f05006 - -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/policy.c | 16 ++++++++-------- - 1 file changed, 8 insertions(+), 8 deletions(-) - -diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c -index 65e98d0491f4..0a99e5324da0 100644 ---- a/security/apparmor/policy.c -+++ b/security/apparmor/policy.c -@@ -397,33 +397,33 @@ struct aa_profile *aa_new_null_profile(struct aa_profile *parent, bool hat, - /* TODO: profile accounting - setup in remove */ - - /** -- * __find_child - find a profile on @head list with a name matching @name -+ * __strn_find_child - find a profile on @head list using substring of @name - * @head: list to search (NOT NULL) - * @name: name of profile (NOT NULL) -+ * @len: length of @name substring to match - * - * Requires: rcu_read_lock be held - * - * Returns: unrefcounted profile ptr, or NULL if not found - */ --static struct aa_profile *__find_child(struct list_head *head, const char *name) -+static struct aa_profile *__strn_find_child(struct list_head *head, -+ const char *name, int len) - { -- return (struct aa_profile *)__policy_find(head, name); -+ return (struct aa_profile *)__policy_strn_find(head, name, len); - } - - /** -- * __strn_find_child - find a profile on @head list using substring of @name -+ * __find_child - find a profile on @head list with a name matching @name - * @head: list to search (NOT NULL) - * @name: name of profile (NOT NULL) -- * @len: length of @name substring to match - * - * Requires: rcu_read_lock be held - * - * Returns: unrefcounted profile ptr, or NULL if not found - */ --static struct aa_profile *__strn_find_child(struct list_head *head, -- const char *name, int len) -+static struct aa_profile *__find_child(struct list_head *head, const char *name) - { -- return (struct aa_profile *)__policy_strn_find(head, name, len); -+ return __strn_find_child(head, name, strlen(name)); - } - - /** --- -2.12.3 - diff --git a/patches.apparmor/0031-apparmor-add-namespace-lookup-fns.patch b/patches.apparmor/0031-apparmor-add-namespace-lookup-fns.patch deleted file mode 100644 index 3509544..0000000 --- a/patches.apparmor/0031-apparmor-add-namespace-lookup-fns.patch +++ /dev/null @@ -1,156 +0,0 @@ -From fbfdb53589eed33b3b4b61216de21bfdc1f1c5d6 Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Fri, 2 Jun 2017 17:44:27 -0700 -Subject: [PATCH 31/65] apparmor: add namespace lookup fns() -Patch-mainline: v4.13-rc1 -References: FATE#323500 -Git-commit: 3664268f19ea07bec55df92fe53ff9ed28968bcc - -Currently lookups are restricted to a single ns component in the -path. However when namespaces are allowed to have separate views, and -scopes this will not be sufficient, as it will be possible to have -a multiple component ns path in scope. - -Add some ns lookup fns() to allow this and use them. - -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/include/policy_ns.h | 13 +++++++++ - security/apparmor/policy.c | 10 ++++--- - security/apparmor/policy_ns.c | 54 +++++++++++++++++++++++++++++++++++ - 3 files changed, 73 insertions(+), 4 deletions(-) - -diff --git a/security/apparmor/include/policy_ns.h b/security/apparmor/include/policy_ns.h -index 23e7cb770226..2f7e480a34e0 100644 ---- a/security/apparmor/include/policy_ns.h -+++ b/security/apparmor/include/policy_ns.h -@@ -89,6 +89,8 @@ 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); -@@ -148,4 +150,15 @@ static inline struct aa_ns *__aa_find_ns(struct list_head *head, - 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/policy.c b/security/apparmor/policy.c -index 0a99e5324da0..d95aae6bf710 100644 ---- a/security/apparmor/policy.c -+++ b/security/apparmor/policy.c -@@ -566,7 +566,7 @@ struct aa_profile *aa_fqlookupn_profile(struct aa_profile *base, - - name = aa_splitn_fqname(fqname, n, &ns_name, &ns_len); - if (ns_name) { -- ns = aa_findn_ns(base->ns, ns_name, ns_len); -+ ns = aa_lookupn_ns(base->ns, ns_name, ns_len); - if (!ns) - return NULL; - } else -@@ -1108,7 +1108,7 @@ ssize_t aa_remove_profiles(struct aa_ns *view, struct aa_profile *subj, - struct aa_ns *root = NULL, *ns = NULL; - struct aa_profile *profile = NULL; - const char *name = fqname, *info = NULL; -- char *ns_name = NULL; -+ const char *ns_name = NULL; - ssize_t error = 0; - - if (*fqname == 0) { -@@ -1120,9 +1120,11 @@ ssize_t aa_remove_profiles(struct aa_ns *view, struct aa_profile *subj, - root = view; - - if (fqname[0] == ':') { -- name = aa_split_fqname(fqname, &ns_name); -+ size_t ns_len; -+ -+ name = aa_splitn_fqname(fqname, size, &ns_name, &ns_len); - /* released below */ -- ns = aa_find_ns(root, ns_name); -+ ns = aa_lookupn_ns(root, ns_name, ns_len); - if (!ns) { - info = "namespace does not exist"; - error = -ENOENT; -diff --git a/security/apparmor/policy_ns.c b/security/apparmor/policy_ns.c -index f3418a9e59b1..c05316809a5e 100644 ---- a/security/apparmor/policy_ns.c -+++ b/security/apparmor/policy_ns.c -@@ -183,6 +183,60 @@ struct aa_ns *aa_find_ns(struct aa_ns *root, const char *name) - return aa_findn_ns(root, name, strlen(name)); - } - -+/** -+ * __aa_lookupn_ns - lookup the namespace matching @hname -+ * @base: base list to start looking up profile name from (NOT NULL) -+ * @hname: hierarchical ns name (NOT NULL) -+ * @n: length of @hname -+ * -+ * Requires: rcu_read_lock be held -+ * -+ * Returns: unrefcounted ns pointer or NULL if not found -+ * -+ * Do a relative name lookup, recursing through profile tree. -+ */ -+struct aa_ns *__aa_lookupn_ns(struct aa_ns *view, const char *hname, size_t n) -+{ -+ struct aa_ns *ns = view; -+ const char *split; -+ -+ for (split = strnstr(hname, "//", n); split; -+ split = strnstr(hname, "//", n)) { -+ ns = __aa_findn_ns(&ns->sub_ns, hname, split - hname); -+ if (!ns) -+ return NULL; -+ -+ n -= split + 2 - hname; -+ hname = split + 2; -+ } -+ -+ if (n) -+ return __aa_findn_ns(&ns->sub_ns, hname, n); -+ return NULL; -+} -+ -+/** -+ * aa_lookupn_ns - look up a policy namespace relative to @view -+ * @view: namespace to search in (NOT NULL) -+ * @name: name of namespace to find (NOT NULL) -+ * @n: length of @name -+ * -+ * Returns: a refcounted namespace on the list, or NULL if no namespace -+ * called @name exists. -+ * -+ * refcount released by caller -+ */ -+struct aa_ns *aa_lookupn_ns(struct aa_ns *view, const char *name, size_t n) -+{ -+ struct aa_ns *ns = NULL; -+ -+ rcu_read_lock(); -+ ns = aa_get_ns(__aa_lookupn_ns(view, name, n)); -+ rcu_read_unlock(); -+ -+ return ns; -+} -+ - static struct aa_ns *__aa_create_ns(struct aa_ns *parent, const char *name, - struct dentry *dir) - { --- -2.12.3 - diff --git a/patches.apparmor/0032-apparmor-fix-policy-load-remove-semantics.patch b/patches.apparmor/0032-apparmor-fix-policy-load-remove-semantics.patch deleted file mode 100644 index 97fcb83..0000000 --- a/patches.apparmor/0032-apparmor-fix-policy-load-remove-semantics.patch +++ /dev/null @@ -1,136 +0,0 @@ -From 2d3f8f332ad3a4b2b7a8b468de082ebae4280d45 Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Sun, 4 Jun 2017 12:22:22 -0700 -Subject: [PATCH 32/65] apparmor: fix policy load/remove semantics -Git-commit: 60285eb3e7c8827e00e2f2b54561a8cca07d802f -Patch-mainline: v4.13-rc1 -References: FATE#323500 - -The namespace being passed into the replace/remove profiles fns() is -not the view, but the namespace specified by the inode from the -file hook (if present) or the loading tasks ns, if accessing the -top level virtualized load/replace file interface. - -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/apparmorfs.c | 6 ++---- - security/apparmor/policy.c | 22 +++++++++++----------- - 2 files changed, 13 insertions(+), 15 deletions(-) - -diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c -index 105a1da57b8f..4f4cd98d2b3b 100644 ---- a/security/apparmor/apparmorfs.c -+++ b/security/apparmor/apparmorfs.c -@@ -418,8 +418,7 @@ static ssize_t policy_update(u32 mask, const char __user *buf, size_t size, - data = aa_simple_write_to_buffer(buf, size, size, pos); - error = PTR_ERR(data); - if (!IS_ERR(data)) { -- error = aa_replace_profiles(ns ? ns : profile->ns, profile, -- mask, data); -+ error = aa_replace_profiles(ns, profile, mask, data); - aa_put_loaddata(data); - } - -@@ -486,8 +485,7 @@ static ssize_t profile_remove(struct file *f, const char __user *buf, - error = PTR_ERR(data); - if (!IS_ERR(data)) { - data->data[size] = 0; -- error = aa_remove_profiles(ns ? ns : profile->ns, profile, -- data->data, size); -+ error = aa_remove_profiles(ns, profile, data->data, size); - aa_put_loaddata(data); - } - out: -diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c -index d95aae6bf710..29e04638790f 100644 ---- a/security/apparmor/policy.c -+++ b/security/apparmor/policy.c -@@ -831,7 +831,7 @@ static int __lookup_replace(struct aa_ns *ns, const char *hname, - - /** - * aa_replace_profiles - replace profile(s) on the profile list -- * @view: namespace load is viewed from -+ * @policy_ns: namespace load is occurring on - * @label: label that is attempting to load/replace policy - * @mask: permission mask - * @udata: serialized data stream (NOT NULL) -@@ -842,7 +842,7 @@ static int __lookup_replace(struct aa_ns *ns, const char *hname, - * - * Returns: size of data consumed else error code on failure. - */ --ssize_t aa_replace_profiles(struct aa_ns *view, struct aa_profile *profile, -+ssize_t aa_replace_profiles(struct aa_ns *policy_ns, struct aa_profile *profile, - u32 mask, struct aa_loaddata *udata) - { - const char *ns_name, *info = NULL; -@@ -885,7 +885,8 @@ ssize_t aa_replace_profiles(struct aa_ns *view, struct aa_profile *profile, - count++; - } - if (ns_name) { -- ns = aa_prepare_ns(view, ns_name); -+ ns = aa_prepare_ns(policy_ns ? policy_ns : profile->ns, -+ ns_name); - if (IS_ERR(ns)) { - op = OP_PROF_LOAD; - info = "failed to prepare namespace"; -@@ -895,7 +896,7 @@ ssize_t aa_replace_profiles(struct aa_ns *view, struct aa_profile *profile, - goto fail; - } - } else -- ns = aa_get_ns(view); -+ ns = aa_get_ns(policy_ns ? policy_ns : profile->ns); - - mutex_lock(&ns->lock); - /* check for duplicate rawdata blobs: space and file dedup */ -@@ -1090,7 +1091,7 @@ ssize_t aa_replace_profiles(struct aa_ns *view, struct aa_profile *profile, - - /** - * aa_remove_profiles - remove profile(s) from the system -- * @view: namespace the remove is being done from -+ * @policy_ns: namespace the remove is being done from - * @subj: profile attempting to remove policy - * @fqname: name of the profile or namespace to remove (NOT NULL) - * @size: size of the name -@@ -1102,10 +1103,10 @@ ssize_t aa_replace_profiles(struct aa_ns *view, struct aa_profile *profile, - * - * Returns: size of data consume else error code if fails - */ --ssize_t aa_remove_profiles(struct aa_ns *view, struct aa_profile *subj, -+ssize_t aa_remove_profiles(struct aa_ns *policy_ns, struct aa_profile *subj, - char *fqname, size_t size) - { -- struct aa_ns *root = NULL, *ns = NULL; -+ struct aa_ns *ns = NULL; - struct aa_profile *profile = NULL; - const char *name = fqname, *info = NULL; - const char *ns_name = NULL; -@@ -1117,14 +1118,13 @@ ssize_t aa_remove_profiles(struct aa_ns *view, struct aa_profile *subj, - goto fail; - } - -- root = view; -- - if (fqname[0] == ':') { - size_t ns_len; - - name = aa_splitn_fqname(fqname, size, &ns_name, &ns_len); - /* released below */ -- ns = aa_lookupn_ns(root, ns_name, ns_len); -+ ns = aa_lookupn_ns(policy_ns ? policy_ns : subj->ns, ns_name, -+ ns_len); - if (!ns) { - info = "namespace does not exist"; - error = -ENOENT; -@@ -1132,7 +1132,7 @@ ssize_t aa_remove_profiles(struct aa_ns *view, struct aa_profile *subj, - } - } else - /* released below */ -- ns = aa_get_ns(root); -+ ns = aa_get_ns(policy_ns ? policy_ns : subj->ns); - - if (!name) { - /* remove namespace - can only happen if fqname[0] == ':' */ --- -2.12.3 - diff --git a/patches.apparmor/0033-apparmor-fix-apparmor_query-data.patch b/patches.apparmor/0033-apparmor-fix-apparmor_query-data.patch deleted file mode 100644 index eec3c30..0000000 --- a/patches.apparmor/0033-apparmor-fix-apparmor_query-data.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 3d7a7d44e402393f4e234c232809514520757a0a Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Fri, 9 Jun 2017 02:28:19 -0700 -Subject: [PATCH 33/65] apparmor: fix apparmor_query data -Git-commit: 5262ef60b1bcc40e17476fda53284621af9b0bab -Patch-mainline: v4.13-rc1 -References: FATE#323500 - -The data being queried isn't always the current profile and a lookup -relative to the current profile should be done. - -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/apparmorfs.c | 8 ++++++-- - 1 file changed, 6 insertions(+), 2 deletions(-) - -diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c -index 4f4cd98d2b3b..818b70130bae 100644 ---- a/security/apparmor/apparmorfs.c -+++ b/security/apparmor/apparmorfs.c -@@ -650,7 +650,7 @@ static ssize_t query_data(char *buf, size_t buf_len, - { - char *out; - const char *key; -- struct aa_profile *profile; -+ struct aa_profile *profile, *curr; - struct aa_data *data; - u32 bytes, blocks; - __le32 outle32; -@@ -667,7 +667,10 @@ static ssize_t query_data(char *buf, size_t buf_len, - if (buf_len < sizeof(bytes) + sizeof(blocks)) - return -EINVAL; /* not enough space */ - -- profile = aa_current_profile(); -+ curr = aa_current_profile(); -+ profile = aa_fqlookupn_profile(curr, query, strnlen(query, query_len)); -+ if (!profile) -+ return -ENOENT; - - /* We are going to leave space for two numbers. The first is the total - * number of bytes we are writing after the first number. This is so -@@ -696,6 +699,7 @@ static ssize_t query_data(char *buf, size_t buf_len, - blocks++; - } - } -+ aa_put_profile(profile); - - outle32 = __cpu_to_le32(out - buf - sizeof(bytes)); - memcpy(buf, &outle32, sizeof(outle32)); --- -2.12.3 - diff --git a/patches.apparmor/0034-apparmor-fix-display-of-ns-name.patch b/patches.apparmor/0034-apparmor-fix-display-of-ns-name.patch deleted file mode 100644 index d8131ea..0000000 --- a/patches.apparmor/0034-apparmor-fix-display-of-ns-name.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 6cd1d682d6e073a5e78fb006a9187febee802738 Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Fri, 9 Jun 2017 02:11:29 -0700 -Subject: [PATCH 34/65] apparmor: fix display of ns name -Git-commit: d9f02d9c237aa603d781fe5165ebe383c554376d -Patch-mainline: v4.13-rc1 -References: FATE#323500 - -The ns name being displayed should go through an ns view lookup. - -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/apparmorfs.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c -index 818b70130bae..b64ea21a42ad 100644 ---- a/security/apparmor/apparmorfs.c -+++ b/security/apparmor/apparmorfs.c -@@ -1105,7 +1105,7 @@ static int seq_ns_name_show(struct seq_file *seq, void *v) - { - struct aa_ns *ns = aa_current_profile()->ns; - -- seq_printf(seq, "%s\n", ns->base.name); -+ seq_printf(seq, "%s\n", aa_ns_name(ns, ns, true)); - - return 0; - } --- -2.12.3 - diff --git a/patches.apparmor/0035-apparmor-move-bprm_committing_creds-committed_creds-.patch b/patches.apparmor/0035-apparmor-move-bprm_committing_creds-committed_creds-.patch deleted file mode 100644 index 3a4d4ff..0000000 --- a/patches.apparmor/0035-apparmor-move-bprm_committing_creds-committed_creds-.patch +++ /dev/null @@ -1,119 +0,0 @@ -From e4a0c89bd117c66393761e3b96a5d03d97f0d0b2 Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Fri, 9 Jun 2017 05:27:50 -0700 -Subject: [PATCH 35/65] apparmor: move bprm_committing_creds/committed_creds to - lsm.c -Git-commit: fe864821d504f33f22b3ce2d5599ae95598db721 -Patch-mainline: v4.13-rc1 -References: FATE#323500 - -There is no reason to have the small stubs that don't use domain -private functions in domain.c, instead move them to lsm.c and make -them static. - -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/domain.c | 30 ------------------------------ - security/apparmor/include/domain.h | 2 -- - security/apparmor/lsm.c | 30 ++++++++++++++++++++++++++++++ - 3 files changed, 30 insertions(+), 32 deletions(-) - -diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c -index a0ba33454b8c..2b1524c79fb8 100644 ---- a/security/apparmor/domain.c -+++ b/security/apparmor/domain.c -@@ -539,36 +539,6 @@ int apparmor_bprm_secureexec(struct linux_binprm *bprm) - return 0; - } - --/** -- * apparmor_bprm_committing_creds - do task cleanup on committing new creds -- * @bprm: binprm for the exec (NOT NULL) -- */ --void apparmor_bprm_committing_creds(struct linux_binprm *bprm) --{ -- struct aa_profile *profile = __aa_current_profile(); -- struct aa_task_ctx *new_ctx = cred_ctx(bprm->cred); -- -- /* bail out if unconfined or not changing profile */ -- if ((new_ctx->profile == profile) || -- (unconfined(new_ctx->profile))) -- return; -- -- current->pdeath_signal = 0; -- -- /* reset soft limits and set hard limits for the new profile */ -- __aa_transition_rlimits(profile, new_ctx->profile); --} -- --/** -- * apparmor_bprm_commited_cred - do cleanup after new creds committed -- * @bprm: binprm for the exec (NOT NULL) -- */ --void apparmor_bprm_committed_creds(struct linux_binprm *bprm) --{ -- /* TODO: cleanup signals - ipc mediation */ -- return; --} -- - /* - * Functions for self directed profile change - */ -diff --git a/security/apparmor/include/domain.h b/security/apparmor/include/domain.h -index 30544729878a..6587c4abb7e8 100644 ---- a/security/apparmor/include/domain.h -+++ b/security/apparmor/include/domain.h -@@ -25,8 +25,6 @@ struct aa_domain { - - int apparmor_bprm_set_creds(struct linux_binprm *bprm); - int apparmor_bprm_secureexec(struct linux_binprm *bprm); --void apparmor_bprm_committing_creds(struct linux_binprm *bprm); --void apparmor_bprm_committed_creds(struct linux_binprm *bprm); - - void aa_free_domain_entries(struct aa_domain *domain); - int aa_change_hat(const char *hats[], int count, u64 token, bool permtest); -diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c -index 8ab00c98613f..35492008658f 100644 ---- a/security/apparmor/lsm.c -+++ b/security/apparmor/lsm.c -@@ -575,6 +575,36 @@ static int apparmor_setprocattr(const char *name, void *value, - goto out; - } - -+/** -+ * apparmor_bprm_committing_creds - do task cleanup on committing new creds -+ * @bprm: binprm for the exec (NOT NULL) -+ */ -+static void apparmor_bprm_committing_creds(struct linux_binprm *bprm) -+{ -+ struct aa_profile *profile = __aa_current_profile(); -+ struct aa_task_ctx *new_ctx = cred_ctx(bprm->cred); -+ -+ /* bail out if unconfined or not changing profile */ -+ if ((new_ctx->profile == profile) || -+ (unconfined(new_ctx->profile))) -+ return; -+ -+ current->pdeath_signal = 0; -+ -+ /* reset soft limits and set hard limits for the new profile */ -+ __aa_transition_rlimits(profile, new_ctx->profile); -+} -+ -+/** -+ * apparmor_bprm_committed_cred - do cleanup after new creds committed -+ * @bprm: binprm for the exec (NOT NULL) -+ */ -+static void apparmor_bprm_committed_creds(struct linux_binprm *bprm) -+{ -+ /* TODO: cleanup signals - ipc mediation */ -+ return; -+} -+ - static int apparmor_task_setrlimit(struct task_struct *task, - unsigned int resource, struct rlimit *new_rlim) - { --- -2.12.3 - diff --git a/patches.apparmor/0036-apparmor-convert-to-profile-block-critical-sections.patch b/patches.apparmor/0036-apparmor-convert-to-profile-block-critical-sections.patch deleted file mode 100644 index 28d2433..0000000 --- a/patches.apparmor/0036-apparmor-convert-to-profile-block-critical-sections.patch +++ /dev/null @@ -1,609 +0,0 @@ -From cdb759a09cb1ef90e882cbd93095c5d755de7f92 Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Fri, 9 Jun 2017 02:08:28 -0700 -Subject: [PATCH 36/65] apparmor: convert to profile block critical sections -Git-commit: cf797c0e5e312520b0b9f0367039fc0279a07a76 -Patch-mainline: v4.13-rc1 -References: FATE#323500 - -There are still a few places where profile replacement fails to update -and a stale profile is used for mediation. Fix this by moving to -accessing the current label through a critical section that will -always ensure mediation is using the current label regardless of -whether the tasks cred has been updated or not. - -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/apparmorfs.c | 40 +++++++----- - security/apparmor/context.c | 2 +- - security/apparmor/domain.c | 5 +- - security/apparmor/include/context.h | 123 +++++++++++++++++++++++++++++------- - security/apparmor/lsm.c | 41 ++++++++---- - security/apparmor/policy_unpack.c | 2 +- - security/apparmor/procattr.c | 3 +- - security/apparmor/resource.c | 2 +- - 8 files changed, 162 insertions(+), 56 deletions(-) - -diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c -index b64ea21a42ad..e2919a0766b0 100644 ---- a/security/apparmor/apparmorfs.c -+++ b/security/apparmor/apparmorfs.c -@@ -407,7 +407,10 @@ static ssize_t policy_update(u32 mask, const char __user *buf, size_t size, - { - ssize_t error; - struct aa_loaddata *data; -- struct aa_profile *profile = aa_current_profile(); -+ struct aa_profile *profile; -+ -+ profile = begin_current_profile_crit_section(); -+ - /* high level check about policy management - fine grained in - * below after unpack - */ -@@ -421,6 +424,7 @@ static ssize_t policy_update(u32 mask, const char __user *buf, size_t size, - error = aa_replace_profiles(ns, profile, mask, data); - aa_put_loaddata(data); - } -+ end_current_profile_crit_section(profile); - - return error; - } -@@ -468,7 +472,7 @@ static ssize_t profile_remove(struct file *f, const char __user *buf, - ssize_t error; - struct aa_ns *ns = aa_get_ns(f->f_inode->i_private); - -- profile = aa_current_profile(); -+ profile = begin_current_profile_crit_section(); - /* high level check about policy management - fine grained in - * below after unpack - */ -@@ -489,6 +493,7 @@ static ssize_t profile_remove(struct file *f, const char __user *buf, - aa_put_loaddata(data); - } - out: -+ end_current_profile_crit_section(profile); - aa_put_ns(ns); - return error; - } -@@ -667,8 +672,9 @@ static ssize_t query_data(char *buf, size_t buf_len, - if (buf_len < sizeof(bytes) + sizeof(blocks)) - return -EINVAL; /* not enough space */ - -- curr = aa_current_profile(); -+ curr = begin_current_profile_crit_section(); - profile = aa_fqlookupn_profile(curr, query, strnlen(query, query_len)); -+ end_current_profile_crit_section(curr); - if (!profile) - return -ENOENT; - -@@ -754,8 +760,9 @@ static ssize_t query_label(char *buf, size_t buf_len, - match_str = label_name + label_name_len + 1; - match_len = query_len - label_name_len - 1; - -- curr = aa_current_profile(); -+ curr = begin_current_profile_crit_section(); - profile = aa_fqlookupn_profile(curr, label_name, label_name_len); -+ end_current_profile_crit_section(curr); - if (!profile) - return -ENOENT; - -@@ -1094,18 +1101,22 @@ static const struct file_operations seq_ns_ ##NAME ##_fops = { \ - - static int seq_ns_level_show(struct seq_file *seq, void *v) - { -- struct aa_ns *ns = aa_current_profile()->ns; -+ struct aa_profile *profile; - -- seq_printf(seq, "%d\n", ns->level); -+ profile = begin_current_profile_crit_section(); -+ seq_printf(seq, "%d\n", profile->ns->level); -+ end_current_profile_crit_section(profile); - - return 0; - } - - static int seq_ns_name_show(struct seq_file *seq, void *v) - { -- struct aa_ns *ns = aa_current_profile()->ns; -+ struct aa_profile *profile; - -- seq_printf(seq, "%s\n", aa_ns_name(ns, ns, true)); -+ profile = begin_current_profile_crit_section(); -+ seq_printf(seq, "%s\n", aa_ns_name(profile->ns, profile->ns, true)); -+ end_current_profile_crit_section(profile); - - return 0; - } -@@ -1530,9 +1541,9 @@ static int ns_mkdir_op(struct inode *dir, struct dentry *dentry, umode_t mode) - { - struct aa_ns *ns, *parent; - /* TODO: improve permission check */ -- struct aa_profile *profile = aa_current_profile(); -+ struct aa_profile *profile = begin_current_profile_crit_section(); - int error = aa_may_manage_policy(profile, NULL, AA_MAY_LOAD_POLICY); -- -+ end_current_profile_crit_section(profile); - if (error) - return error; - -@@ -1576,9 +1587,9 @@ static int ns_rmdir_op(struct inode *dir, struct dentry *dentry) - { - struct aa_ns *ns, *parent; - /* TODO: improve permission check */ -- struct aa_profile *profile = aa_current_profile(); -+ struct aa_profile *profile = begin_current_profile_crit_section(); - int error = aa_may_manage_policy(profile, NULL, AA_MAY_LOAD_POLICY); -- -+ end_current_profile_crit_section(profile); - if (error) - return error; - -@@ -1922,10 +1933,9 @@ static struct aa_profile *next_profile(struct aa_ns *root, - static void *p_start(struct seq_file *f, loff_t *pos) - { - struct aa_profile *profile = NULL; -- struct aa_ns *root = aa_current_profile()->ns; -+ struct aa_ns *root = aa_get_current_ns(); - loff_t l = *pos; -- f->private = aa_get_ns(root); -- -+ f->private = root; - - /* find the first profile */ - mutex_lock(&root->lock); -diff --git a/security/apparmor/context.c b/security/apparmor/context.c -index 1fc16b88efbf..410b9f7f68a1 100644 ---- a/security/apparmor/context.c -+++ b/security/apparmor/context.c -@@ -79,7 +79,7 @@ struct aa_profile *aa_get_task_profile(struct task_struct *task) - struct aa_profile *p; - - rcu_read_lock(); -- p = aa_get_profile(__aa_task_profile(task)); -+ p = aa_get_newest_profile(__aa_task_raw_profile(task)); - rcu_read_unlock(); - - return p; -diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c -index 2b1524c79fb8..0c02eac33a45 100644 ---- a/security/apparmor/domain.c -+++ b/security/apparmor/domain.c -@@ -594,7 +594,7 @@ int aa_change_hat(const char *hats[], int count, u64 token, bool permtest) - /* released below */ - cred = get_current_cred(); - ctx = cred_ctx(cred); -- profile = aa_get_newest_profile(aa_cred_profile(cred)); -+ profile = aa_get_newest_cred_profile(cred); - previous_profile = aa_get_newest_profile(ctx->previous); - - if (unconfined(profile)) { -@@ -737,7 +737,7 @@ int aa_change_profile(const char *fqname, bool onexec, - } - - cred = get_current_cred(); -- profile = aa_cred_profile(cred); -+ profile = aa_get_newest_cred_profile(cred); - - /* - * Fail explicitly requested domain transitions if no_new_privs -@@ -795,6 +795,7 @@ int aa_change_profile(const char *fqname, bool onexec, - fqname, GLOBAL_ROOT_UID, info, error); - - aa_put_profile(target); -+ aa_put_profile(profile); - put_cred(cred); - - return error; -diff --git a/security/apparmor/include/context.h b/security/apparmor/include/context.h -index 420cfd041218..7665fae7131f 100644 ---- a/security/apparmor/include/context.h -+++ b/security/apparmor/include/context.h -@@ -56,14 +56,14 @@ struct aa_profile *aa_get_task_profile(struct task_struct *task); - - - /** -- * aa_cred_profile - obtain cred's profiles -+ * aa_cred_raw_profile - obtain cred's profiles - * @cred: cred to obtain profiles from (NOT NULL) - * - * Returns: confining profile - * - * does NOT increment reference count - */ --static inline struct aa_profile *aa_cred_profile(const struct cred *cred) -+static inline struct aa_profile *aa_cred_raw_profile(const struct cred *cred) - { - struct aa_task_ctx *ctx = cred_ctx(cred); - -@@ -72,16 +72,28 @@ static inline struct aa_profile *aa_cred_profile(const struct cred *cred) - } - - /** -- * __aa_task_profile - retrieve another task's profile -+ * aa_get_newest_cred_profile - obtain the newest profile on a cred -+ * @cred: cred to obtain profile from (NOT NULL) -+ * -+ * Returns: newest version of confining profile -+ */ -+static inline -+struct aa_profile *aa_get_newest_cred_profile(const struct cred *cred) -+{ -+ return aa_get_newest_profile(aa_cred_raw_profile(cred)); -+} -+ -+/** -+ * __aa_task_raw_profile - retrieve another task's profile - * @task: task to query (NOT NULL) - * - * Returns: @task's profile without incrementing its ref count - * - * If @task != current needs to be called in RCU safe critical section - */ --static inline struct aa_profile *__aa_task_profile(struct task_struct *task) -+static inline struct aa_profile *__aa_task_raw_profile(struct task_struct *task) - { -- return aa_cred_profile(__task_cred(task)); -+ return aa_cred_raw_profile(__task_cred(task)); - } - - /** -@@ -92,50 +104,115 @@ static inline struct aa_profile *__aa_task_profile(struct task_struct *task) - */ - static inline bool __aa_task_is_confined(struct task_struct *task) - { -- return !unconfined(__aa_task_profile(task)); -+ return !unconfined(__aa_task_raw_profile(task)); - } - - /** -- * __aa_current_profile - find the current tasks confining profile -+ * aa_current_raw_profile - find the current tasks confining profile - * - * Returns: up to date confining profile or the ns unconfined profile (NOT NULL) - * - * This fn will not update the tasks cred to the most up to date version - * of the profile so it is safe to call when inside of locks. - */ --static inline struct aa_profile *__aa_current_profile(void) -+static inline struct aa_profile *aa_current_raw_profile(void) - { -- return aa_cred_profile(current_cred()); -+ return aa_cred_raw_profile(current_cred()); - } - - /** -- * aa_current_profile - find the current tasks confining profile and do updates -+ * aa_get_current_profile - get the newest version of the current tasks profile - * -- * Returns: up to date confining profile or the ns unconfined profile (NOT NULL) -+ * Returns: newest version of confining profile (NOT NULL) -+ * -+ * This fn will not update the tasks cred, so it is safe inside of locks - * -- * This fn will update the tasks cred structure if the profile has been -- * replaced. Not safe to call inside locks -+ * The returned reference must be put with aa_put_profile() - */ --static inline struct aa_profile *aa_current_profile(void) -+static inline struct aa_profile *aa_get_current_profile(void) - { -- const struct aa_task_ctx *ctx = current_ctx(); -- struct aa_profile *profile; -+ struct aa_profile *p = aa_current_raw_profile(); - -- AA_BUG(!ctx || !ctx->profile); -+ if (profile_is_stale(p)) -+ return aa_get_newest_profile(p); -+ return aa_get_profile(p); -+} - -- if (profile_is_stale(ctx->profile)) { -- profile = aa_get_newest_profile(ctx->profile); -- aa_replace_current_profile(profile); -+#define __end_current_profile_crit_section(X) \ -+ end_current_profile_crit_section(X) -+ -+/** -+ * end_profile_crit_section - put a reference found with begin_current_profile.. -+ * @profile: profile reference to put -+ * -+ * Should only be used with a reference obtained with -+ * begin_current_profile_crit_section and never used in situations where the -+ * task cred may be updated -+ */ -+static inline void end_current_profile_crit_section(struct aa_profile *profile) -+{ -+ if (profile != aa_current_raw_profile()) - aa_put_profile(profile); -- ctx = current_ctx(); -+} -+ -+/** -+ * __begin_current_profile_crit_section - current's confining profile -+ * -+ * Returns: up to date confining profile or the ns unconfined profile (NOT NULL) -+ * -+ * safe to call inside locks -+ * -+ * The returned reference must be put with __end_current_profile_crit_section() -+ * This must NOT be used if the task cred could be updated within the -+ * critical section between __begin_current_profile_crit_section() .. -+ * __end_current_profile_crit_section() -+ */ -+static inline struct aa_profile *__begin_current_profile_crit_section(void) -+{ -+ struct aa_profile *profile = aa_current_raw_profile(); -+ -+ if (profile_is_stale(profile)) -+ profile = aa_get_newest_profile(profile); -+ -+ return profile; -+} -+ -+/** -+ * begin_current_profile_crit_section - current's profile and update if needed -+ * -+ * Returns: up to date confining profile or the ns unconfined profile (NOT NULL) -+ * -+ * Not safe to call inside locks -+ * -+ * The returned reference must be put with end_current_profile_crit_section() -+ * This must NOT be used if the task cred could be updated within the -+ * critical section between begin_current_profile_crit_section() .. -+ * end_current_profile_crit_section() -+ */ -+static inline struct aa_profile *begin_current_profile_crit_section(void) -+{ -+ struct aa_profile *profile = aa_current_raw_profile(); -+ -+ if (profile_is_stale(profile)) { -+ profile = aa_get_newest_profile(profile); -+ if (aa_replace_current_profile(profile) == 0) -+ /* task cred will keep the reference */ -+ aa_put_profile(profile); - } - -- return ctx->profile; -+ return profile; - } - - static inline struct aa_ns *aa_get_current_ns(void) - { -- return aa_get_ns(__aa_current_profile()->ns); -+ struct aa_profile *profile; -+ struct aa_ns *ns; -+ -+ profile = __begin_current_profile_crit_section(); -+ ns = aa_get_ns(profile->ns); -+ __end_current_profile_crit_section(profile); -+ -+ return ns; - } - - /** -diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c -index 35492008658f..49b780b4c53b 100644 ---- a/security/apparmor/lsm.c -+++ b/security/apparmor/lsm.c -@@ -120,7 +120,7 @@ static int apparmor_capget(struct task_struct *target, kernel_cap_t *effective, - - rcu_read_lock(); - cred = __task_cred(target); -- profile = aa_cred_profile(cred); -+ profile = aa_get_newest_cred_profile(cred); - - /* - * cap_capget is stacked ahead of this and will -@@ -131,6 +131,7 @@ static int apparmor_capget(struct task_struct *target, kernel_cap_t *effective, - *permitted = cap_intersect(*permitted, profile->caps.allow); - } - rcu_read_unlock(); -+ aa_put_profile(profile); - - return 0; - } -@@ -141,9 +142,11 @@ static int apparmor_capable(const struct cred *cred, struct user_namespace *ns, - struct aa_profile *profile; - int error = 0; - -- profile = aa_cred_profile(cred); -+ profile = aa_get_newest_cred_profile(cred); - if (!unconfined(profile)) - error = aa_capable(profile, cap, audit); -+ aa_put_profile(profile); -+ - return error; - } - -@@ -162,9 +165,10 @@ static int common_perm(const char *op, const struct path *path, u32 mask, - struct aa_profile *profile; - int error = 0; - -- profile = __aa_current_profile(); -+ profile = __begin_current_profile_crit_section(); - if (!unconfined(profile)) - error = aa_path_perm(op, profile, path, 0, mask, cond); -+ __end_current_profile_crit_section(profile); - - return error; - } -@@ -297,9 +301,11 @@ static int apparmor_path_link(struct dentry *old_dentry, const struct path *new_ - if (!path_mediated_fs(old_dentry)) - return 0; - -- profile = aa_current_profile(); -+ profile = begin_current_profile_crit_section(); - if (!unconfined(profile)) - error = aa_path_link(profile, old_dentry, new_dir, new_dentry); -+ end_current_profile_crit_section(profile); -+ - return error; - } - -@@ -312,7 +318,7 @@ static int apparmor_path_rename(const struct path *old_dir, struct dentry *old_d - if (!path_mediated_fs(old_dentry)) - return 0; - -- profile = aa_current_profile(); -+ profile = begin_current_profile_crit_section(); - if (!unconfined(profile)) { - struct path old_path = { .mnt = old_dir->mnt, - .dentry = old_dentry }; -@@ -332,6 +338,8 @@ static int apparmor_path_rename(const struct path *old_dir, struct dentry *old_d - AA_MAY_CREATE, &cond); - - } -+ end_current_profile_crit_section(profile); -+ - return error; - } - -@@ -369,7 +377,7 @@ static int apparmor_file_open(struct file *file, const struct cred *cred) - return 0; - } - -- profile = aa_cred_profile(cred); -+ profile = aa_get_newest_cred_profile(cred); - if (!unconfined(profile)) { - struct inode *inode = file_inode(file); - struct path_cond cond = { inode->i_uid, inode->i_mode }; -@@ -379,18 +387,23 @@ static int apparmor_file_open(struct file *file, const struct cred *cred) - /* todo cache full allowed permissions set and state */ - fctx->allow = aa_map_file_to_perms(file); - } -+ aa_put_profile(profile); - - return error; - } - - static int apparmor_file_alloc_security(struct file *file) - { -+ int error = 0; -+ - /* freed by apparmor_file_free_security */ -+ struct aa_profile *profile = begin_current_profile_crit_section(); - file->f_security = aa_alloc_file_context(GFP_KERNEL); - if (!file->f_security) - return -ENOMEM; -- return 0; -+ end_current_profile_crit_section(profile); - -+ return error; - } - - static void apparmor_file_free_security(struct file *file) -@@ -403,16 +416,17 @@ static void apparmor_file_free_security(struct file *file) - static int common_file_perm(const char *op, struct file *file, u32 mask) - { - struct aa_file_ctx *fctx = file->f_security; -- struct aa_profile *profile, *fprofile = aa_cred_profile(file->f_cred); -+ struct aa_profile *profile, *fprofile; - int error = 0; - -+ fprofile = aa_cred_raw_profile(file->f_cred); - AA_BUG(!fprofile); - - if (!file->f_path.mnt || - !path_mediated_fs(file->f_path.dentry)) - return 0; - -- profile = __aa_current_profile(); -+ profile = __begin_current_profile_crit_section(); - - /* revalidate access, if task is unconfined, or the cached cred - * doesn't match or if the request is for more permissions than -@@ -424,6 +438,7 @@ static int common_file_perm(const char *op, struct file *file, u32 mask) - if (!unconfined(profile) && !unconfined(fprofile) && - ((fprofile != profile) || (mask & ~fctx->allow))) - error = aa_file_perm(op, profile, file, mask); -+ __end_current_profile_crit_section(profile); - - return error; - } -@@ -568,10 +583,11 @@ static int apparmor_setprocattr(const char *name, void *value, - return error; - - fail: -- aad(&sa)->profile = aa_current_profile(); -+ aad(&sa)->profile = begin_current_profile_crit_section(); - aad(&sa)->info = name; - aad(&sa)->error = error = -EINVAL; - aa_audit_msg(AUDIT_APPARMOR_DENIED, &sa, NULL); -+ end_current_profile_crit_section(aad(&sa)->profile); - goto out; - } - -@@ -581,7 +597,7 @@ static int apparmor_setprocattr(const char *name, void *value, - */ - static void apparmor_bprm_committing_creds(struct linux_binprm *bprm) - { -- struct aa_profile *profile = __aa_current_profile(); -+ struct aa_profile *profile = aa_current_raw_profile(); - struct aa_task_ctx *new_ctx = cred_ctx(bprm->cred); - - /* bail out if unconfined or not changing profile */ -@@ -608,11 +624,12 @@ static void apparmor_bprm_committed_creds(struct linux_binprm *bprm) - static int apparmor_task_setrlimit(struct task_struct *task, - unsigned int resource, struct rlimit *new_rlim) - { -- struct aa_profile *profile = __aa_current_profile(); -+ struct aa_profile *profile = __begin_current_profile_crit_section(); - int error = 0; - - if (!unconfined(profile)) - error = aa_task_setrlimit(profile, task, resource, new_rlim); -+ __end_current_profile_crit_section(profile); - - return error; - } -diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c -index 5ea6a7cb0212..1db4746270ab 100644 ---- a/security/apparmor/policy_unpack.c -+++ b/security/apparmor/policy_unpack.c -@@ -107,7 +107,7 @@ static int audit_iface(struct aa_profile *new, const char *ns_name, - const char *name, const char *info, struct aa_ext *e, - int error) - { -- struct aa_profile *profile = __aa_current_profile(); -+ struct aa_profile *profile = aa_current_raw_profile(); - DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, NULL); - if (e) - aad(&sa)->iface.pos = e->pos - e->start; -diff --git a/security/apparmor/procattr.c b/security/apparmor/procattr.c -index 3466a27bca09..41b7b64a906b 100644 ---- a/security/apparmor/procattr.c -+++ b/security/apparmor/procattr.c -@@ -41,7 +41,7 @@ int aa_getprocattr(struct aa_profile *profile, char **string) - const char *mode_str = aa_profile_mode_names[profile->mode]; - const char *ns_name = NULL; - struct aa_ns *ns = profile->ns; -- struct aa_ns *current_ns = __aa_current_profile()->ns; -+ struct aa_ns *current_ns = aa_get_current_ns(); - char *s; - - if (!aa_ns_visible(current_ns, ns, true)) -@@ -75,6 +75,7 @@ int aa_getprocattr(struct aa_profile *profile, char **string) - else - sprintf(s, "%s (%s)\n", profile->base.hname, mode_str); - *string = str; -+ aa_put_ns(current_ns); - - /* NOTE: len does not include \0 of string, not saved as part of file */ - return len; -diff --git a/security/apparmor/resource.c b/security/apparmor/resource.c -index ae66151fdc38..b26f1dac5106 100644 ---- a/security/apparmor/resource.c -+++ b/security/apparmor/resource.c -@@ -90,7 +90,7 @@ int aa_task_setrlimit(struct aa_profile *profile, struct task_struct *task, - int error = 0; - - rcu_read_lock(); -- task_profile = aa_get_profile(aa_cred_profile(__task_cred(task))); -+ task_profile = aa_get_newest_cred_profile((__task_cred(task))); - rcu_read_unlock(); - - /* TODO: extend resource control to handle other (non current) --- -2.12.3 - diff --git a/patches.apparmor/0037-apparmor-share-profile-name-on-replacement.patch b/patches.apparmor/0037-apparmor-share-profile-name-on-replacement.patch deleted file mode 100644 index b58a22f..0000000 --- a/patches.apparmor/0037-apparmor-share-profile-name-on-replacement.patch +++ /dev/null @@ -1,171 +0,0 @@ -From 5b47a7e7a7b67297d6c8dbabe95b12567ebcfe62 Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Fri, 9 Jun 2017 07:09:05 -0700 -Subject: [PATCH 37/65] apparmor: share profile name on replacement -Git-commit: a1bd627b46d169268a0ee5960899fb5be960a317 -Patch-mainline: v4.13-rc1 -References: FATE#323500 - -The profile names are the same, leverage this. - -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/include/lib.h | 32 +++++++++++++++++++++++++++++++- - security/apparmor/lib.c | 40 ++++++++++++++++++++++++++++++++-------- - security/apparmor/policy.c | 9 +++++++++ - 3 files changed, 72 insertions(+), 9 deletions(-) - -diff --git a/security/apparmor/include/lib.h b/security/apparmor/include/lib.h -index 89524aade657..593877d38088 100644 ---- a/security/apparmor/include/lib.h -+++ b/security/apparmor/include/lib.h -@@ -100,6 +100,36 @@ static inline bool path_mediated_fs(struct dentry *dentry) - return !(dentry->d_sb->s_flags & MS_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 -@@ -108,7 +138,7 @@ static inline bool path_mediated_fs(struct dentry *dentry) - */ - struct aa_policy { - const char *name; -- const char *hname; -+ __counted char *hname; - struct list_head list; - struct list_head profiles; - }; -diff --git a/security/apparmor/lib.c b/security/apparmor/lib.c -index 3e9146e68c4a..0ceecdbb4658 100644 ---- a/security/apparmor/lib.c -+++ b/security/apparmor/lib.c -@@ -134,6 +134,24 @@ void aa_info_message(const char *str) - printk(KERN_INFO "AppArmor: %s\n", str); - } - -+__counted char *aa_str_alloc(int size, gfp_t gfp) -+{ -+ struct counted_str *str; -+ -+ str = kmalloc(sizeof(struct counted_str) + size, gfp); -+ if (!str) -+ return NULL; -+ -+ kref_init(&str->count); -+ return str->name; -+} -+ -+void aa_str_kref(struct kref *kref) -+{ -+ kfree(container_of(kref, struct counted_str, count)); -+} -+ -+ - const char aa_file_perm_chrs[] = "xwracd km l "; - const char *aa_file_perm_names[] = { - "exec", -@@ -296,6 +314,7 @@ void aa_compute_perms(struct aa_dfa *dfa, unsigned int state, - * @policy: policy to initialize (NOT NULL) - * @prefix: prefix name if any is required. (MAYBE NULL) - * @name: name of the policy, init will make a copy of it (NOT NULL) -+ * @gfp: allocation mode - * - * Note: this fn creates a copy of strings passed in - * -@@ -304,16 +323,21 @@ void aa_compute_perms(struct aa_dfa *dfa, unsigned int state, - bool aa_policy_init(struct aa_policy *policy, const char *prefix, - const char *name, gfp_t gfp) - { -+ char *hname; -+ - /* freed by policy_free */ - if (prefix) { -- policy->hname = kmalloc(strlen(prefix) + strlen(name) + 3, -- gfp); -- if (policy->hname) -- sprintf((char *)policy->hname, "%s//%s", prefix, name); -- } else -- policy->hname = kstrdup(name, gfp); -- if (!policy->hname) -+ hname = aa_str_alloc(strlen(prefix) + strlen(name) + 3, gfp); -+ if (hname) -+ sprintf(hname, "%s//%s", prefix, name); -+ } else { -+ hname = aa_str_alloc(strlen(name) + 1, gfp); -+ if (hname) -+ strcpy(hname, name); -+ } -+ if (!hname) - return false; -+ policy->hname = hname; - /* base.name is a substring of fqname */ - policy->name = basename(policy->hname); - INIT_LIST_HEAD(&policy->list); -@@ -332,5 +356,5 @@ void aa_policy_destroy(struct aa_policy *policy) - AA_BUG(on_list_rcu(&policy->list)); - - /* don't free name as its a subset of hname */ -- kzfree(policy->hname); -+ aa_put_str(policy->hname); - } -diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c -index 29e04638790f..af925c07ad4e 100644 ---- a/security/apparmor/policy.c -+++ b/security/apparmor/policy.c -@@ -829,6 +829,14 @@ static int __lookup_replace(struct aa_ns *ns, const char *hname, - return 0; - } - -+static void share_name(struct aa_profile *old, struct aa_profile *new) -+{ -+ aa_put_str(new->base.hname); -+ aa_get_str(old->base.hname); -+ new->base.hname = old->base.hname; -+ new->base.name = old->base.name; -+} -+ - /** - * aa_replace_profiles - replace profile(s) on the profile list - * @policy_ns: namespace load is occurring on -@@ -1013,6 +1021,7 @@ ssize_t aa_replace_profiles(struct aa_ns *policy_ns, struct aa_profile *profile, - NULL, error); - - if (ent->old) { -+ share_name(ent->old, ent->new); - __replace_profile(ent->old, ent->new, 1); - if (ent->rename) { - /* aafs interface uses proxy */ --- -2.12.3 - diff --git a/patches.apparmor/0038-apparmor-refactor-updating-profiles-to-the-newest-pa.patch b/patches.apparmor/0038-apparmor-refactor-updating-profiles-to-the-newest-pa.patch deleted file mode 100644 index f15b101..0000000 --- a/patches.apparmor/0038-apparmor-refactor-updating-profiles-to-the-newest-pa.patch +++ /dev/null @@ -1,71 +0,0 @@ -From b438d4cae742c0c10ca33227361d7aba4f5e8823 Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Fri, 9 Jun 2017 07:16:46 -0700 -Subject: [PATCH 38/65] apparmor: refactor updating profiles to the newest - parent -Git-commit: 435222bc1bcc11636f4159fd3ce9e481ab7f2c7c -Patch-mainline: v4.13-rc1 -References: FATE#323500 - -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/policy.c | 35 +++++++++++++++++++++++++++++++---- - 1 file changed, 31 insertions(+), 4 deletions(-) - -diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c -index af925c07ad4e..20613186b1d8 100644 ---- a/security/apparmor/policy.c -+++ b/security/apparmor/policy.c -@@ -837,6 +837,27 @@ static void share_name(struct aa_profile *old, struct aa_profile *new) - new->base.name = old->base.name; - } - -+/* Update to newest version of parent after previous replacements -+ * Returns: unrefcount newest version of parent -+ */ -+static struct aa_profile *update_to_newest_parent(struct aa_profile *new) -+{ -+ struct aa_profile *parent, *newest; -+ -+ parent = rcu_dereference_protected(new->parent, -+ mutex_is_locked(&new->ns->lock)); -+ newest = aa_get_newest_profile(parent); -+ -+ /* parent replaced in this atomic set? */ -+ if (newest != parent) { -+ aa_put_profile(parent); -+ rcu_assign_pointer(new->parent, newest); -+ } else -+ aa_put_profile(newest); -+ -+ return newest; -+} -+ - /** - * aa_replace_profiles - replace profile(s) on the profile list - * @policy_ns: namespace load is occurring on -@@ -1052,10 +1073,16 @@ ssize_t aa_replace_profiles(struct aa_ns *policy_ns, struct aa_profile *profile, - __list_add_profile(&newest->base.profiles, ent->new); - aa_put_profile(newest); - } else { -- /* aafs interface uses proxy */ -- rcu_assign_pointer(ent->new->proxy->profile, -- aa_get_profile(ent->new)); -- __list_add_profile(&ns->base.profiles, ent->new); -+ struct list_head *lh; -+ -+ if (rcu_access_pointer(ent->new->parent)) { -+ struct aa_profile *parent; -+ -+ parent = update_to_newest_parent(ent->new); -+ lh = &parent->base.profiles; -+ } else -+ lh = &ns->base.profiles; -+ __list_add_profile(lh, ent->new); - } - skip: - aa_load_ent_free(ent); --- -2.12.3 - diff --git a/patches.apparmor/0039-apparmor-cleanup-remove-unused-and-not-fully-impleme.patch b/patches.apparmor/0039-apparmor-cleanup-remove-unused-and-not-fully-impleme.patch deleted file mode 100644 index 3c473b5..0000000 --- a/patches.apparmor/0039-apparmor-cleanup-remove-unused-and-not-fully-impleme.patch +++ /dev/null @@ -1,85 +0,0 @@ -From b6b36b260a4ae8c7bb97fb46302d8fd8adff4787 Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Fri, 9 Jun 2017 07:24:18 -0700 -Subject: [PATCH 39/65] apparmor: cleanup remove unused and not fully - implemented profile rename -Git-commit: dca91402e999aa0824c4144ad216bd61dd4fe3ff -Patch-mainline: v4.13-rc1 -References: FATE#323500 - -Remove the partially implemented code, until this can be properly -implemented. - -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/policy.c | 39 ++------------------------------------- - 1 file changed, 2 insertions(+), 37 deletions(-) - -diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c -index 20613186b1d8..605cb5949c60 100644 ---- a/security/apparmor/policy.c -+++ b/security/apparmor/policy.c -@@ -995,14 +995,7 @@ ssize_t aa_replace_profiles(struct aa_ns *policy_ns, struct aa_profile *profile, - } - } - list_for_each_entry(ent, &lh, list) { -- if (ent->old) { -- /* inherit old interface files */ -- -- /* if (ent->rename) -- TODO: support rename */ -- /* } else if (ent->rename) { -- TODO: support rename */ -- } else { -+ if (!ent->old) { - struct dentry *parent; - if (rcu_access_pointer(ent->new->parent)) { - struct aa_profile *p; -@@ -1014,7 +1007,7 @@ ssize_t aa_replace_profiles(struct aa_ns *policy_ns, struct aa_profile *profile, - } - - if (error) { -- info = "failed to create "; -+ info = "failed to create"; - goto fail_lock; - } - } -@@ -1044,34 +1037,6 @@ ssize_t aa_replace_profiles(struct aa_ns *policy_ns, struct aa_profile *profile, - if (ent->old) { - share_name(ent->old, ent->new); - __replace_profile(ent->old, ent->new, 1); -- if (ent->rename) { -- /* aafs interface uses proxy */ -- struct aa_proxy *r = ent->new->proxy; -- rcu_assign_pointer(r->profile, -- aa_get_profile(ent->new)); -- __replace_profile(ent->rename, ent->new, 0); -- } -- } else if (ent->rename) { -- /* aafs interface uses proxy */ -- rcu_assign_pointer(ent->new->proxy->profile, -- aa_get_profile(ent->new)); -- __replace_profile(ent->rename, ent->new, 0); -- } else if (ent->new->parent) { -- struct aa_profile *parent, *newest; -- parent = aa_deref_parent(ent->new); -- newest = aa_get_newest_profile(parent); -- -- /* parent replaced in this atomic set? */ -- if (newest != parent) { -- aa_get_profile(newest); -- rcu_assign_pointer(ent->new->parent, newest); -- aa_put_profile(parent); -- } -- /* aafs interface uses proxy */ -- rcu_assign_pointer(ent->new->proxy->profile, -- aa_get_profile(ent->new)); -- __list_add_profile(&newest->base.profiles, ent->new); -- aa_put_profile(newest); - } else { - struct list_head *lh; - --- -2.12.3 - diff --git a/patches.apparmor/0040-apparmor-convert-aa_change_XXX-bool-parameters-to-fl.patch b/patches.apparmor/0040-apparmor-convert-aa_change_XXX-bool-parameters-to-fl.patch deleted file mode 100644 index 25d7e26..0000000 --- a/patches.apparmor/0040-apparmor-convert-aa_change_XXX-bool-parameters-to-fl.patch +++ /dev/null @@ -1,230 +0,0 @@ -From 09b42b87f18821aabea292c8fcb71f74d878d3b6 Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Fri, 9 Jun 2017 11:36:48 -0700 -Subject: [PATCH 40/65] apparmor: convert aa_change_XXX bool parameters to - flags -Git-commit: df8073c67fd8acb7e79f203ba4c0fa456bb82762 -Patch-mainline: v4.13-rc1 -References: FATE#323500 - -Instead of passing multiple booleans consolidate on a single flags -field. - -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/domain.c | 26 +++++++++++++------------- - security/apparmor/include/domain.h | 10 +++++++--- - security/apparmor/include/procattr.h | 6 +----- - security/apparmor/lsm.c | 13 +++++-------- - security/apparmor/procattr.c | 6 +++--- - 5 files changed, 29 insertions(+), 32 deletions(-) - -diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c -index 0c02eac33a45..2ec4ae029215 100644 ---- a/security/apparmor/domain.c -+++ b/security/apparmor/domain.c -@@ -563,7 +563,7 @@ static char *new_compound_name(const char *n1, const char *n2) - * @hats: vector of hat names to try changing into (MAYBE NULL if @count == 0) - * @count: number of hat names in @hats - * @token: magic value to validate the hat change -- * @permtest: true if this is just a permission test -+ * @flags: flags affecting behavior of the change - * - * Change to the first profile specified in @hats that exists, and store - * the @hat_magic in the current task context. If the count == 0 and the -@@ -572,7 +572,7 @@ static char *new_compound_name(const char *n1, const char *n2) - * - * Returns %0 on success, error otherwise. - */ --int aa_change_hat(const char *hats[], int count, u64 token, bool permtest) -+int aa_change_hat(const char *hats[], int count, u64 token, int flags) - { - const struct cred *cred; - struct aa_task_ctx *ctx; -@@ -616,7 +616,7 @@ int aa_change_hat(const char *hats[], int count, u64 token, bool permtest) - /* released below */ - hat = aa_find_child(root, hats[i]); - if (!hat) { -- if (!COMPLAIN_MODE(root) || permtest) { -+ if (!COMPLAIN_MODE(root) || (flags & AA_CHANGE_TEST)) { - if (list_empty(&root->base.profiles)) - error = -ECHILD; - else -@@ -663,7 +663,7 @@ int aa_change_hat(const char *hats[], int count, u64 token, bool permtest) - goto audit; - } - -- if (!permtest) { -+ if (!(flags & AA_CHANGE_TEST)) { - error = aa_set_current_hat(hat, token); - if (error == -EACCES) - /* kill task in case of brute force attacks */ -@@ -684,7 +684,7 @@ int aa_change_hat(const char *hats[], int count, u64 token, bool permtest) - goto out; - - audit: -- if (!permtest) -+ if (!(flags & AA_CHANGE_TEST)) - error = aa_audit_file(profile, &perms, OP_CHANGE_HAT, - AA_MAY_CHANGEHAT, NULL, target, - GLOBAL_ROOT_UID, info, error); -@@ -703,7 +703,7 @@ int aa_change_hat(const char *hats[], int count, u64 token, bool permtest) - * aa_change_profile - perform a one-way profile transition - * @fqname: name of profile may include namespace (NOT NULL) - * @onexec: whether this transition is to take place immediately or at exec -- * @permtest: true if this is just a permission test -+ * @flags: flags affecting change behavior - * - * Change to new profile @name. Unlike with hats, there is no way - * to change back. If @name isn't specified the current profile name is -@@ -713,8 +713,7 @@ int aa_change_hat(const char *hats[], int count, u64 token, bool permtest) - * - * Returns %0 on success, error otherwise. - */ --int aa_change_profile(const char *fqname, bool onexec, -- bool permtest, bool stack) -+int aa_change_profile(const char *fqname, int flags) - { - const struct cred *cred; - struct aa_profile *profile, *target = NULL; -@@ -728,7 +727,7 @@ int aa_change_profile(const char *fqname, bool onexec, - return -EINVAL; - } - -- if (onexec) { -+ if (flags & AA_CHANGE_ONEXEC) { - request = AA_MAY_ONEXEC; - op = OP_CHANGE_ONEXEC; - } else { -@@ -755,7 +754,8 @@ int aa_change_profile(const char *fqname, bool onexec, - if (!target) { - info = "profile not found"; - error = -ENOENT; -- if (permtest || !COMPLAIN_MODE(profile)) -+ if ((flags & AA_CHANGE_TEST) || -+ !COMPLAIN_MODE(profile)) - goto audit; - /* released below */ - target = aa_new_null_profile(profile, false, fqname, -@@ -781,16 +781,16 @@ int aa_change_profile(const char *fqname, bool onexec, - goto audit; - } - -- if (permtest) -+ if (flags & AA_CHANGE_TEST) - goto audit; - -- if (onexec) -+ if (flags & AA_CHANGE_ONEXEC) - error = aa_set_current_onexec(target); - else - error = aa_replace_current_profile(target); - - audit: -- if (!permtest) -+ if (!(flags & AA_CHANGE_TEST)) - error = aa_audit_file(profile, &perms, op, request, NULL, - fqname, GLOBAL_ROOT_UID, info, error); - -diff --git a/security/apparmor/include/domain.h b/security/apparmor/include/domain.h -index 6587c4abb7e8..255aa40ec1d1 100644 ---- a/security/apparmor/include/domain.h -+++ b/security/apparmor/include/domain.h -@@ -23,12 +23,16 @@ struct aa_domain { - char **table; - }; - -+#define AA_CHANGE_NOFLAGS 0 -+#define AA_CHANGE_TEST 1 -+#define AA_CHANGE_CHILD 2 -+#define AA_CHANGE_ONEXEC 4 -+ - int apparmor_bprm_set_creds(struct linux_binprm *bprm); - int apparmor_bprm_secureexec(struct linux_binprm *bprm); - - void aa_free_domain_entries(struct aa_domain *domain); --int aa_change_hat(const char *hats[], int count, u64 token, bool permtest); --int aa_change_profile(const char *fqname, bool onexec, bool permtest, -- bool stack); -+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/procattr.h b/security/apparmor/include/procattr.h -index 6bd5f33d9533..c0055d727868 100644 ---- a/security/apparmor/include/procattr.h -+++ b/security/apparmor/include/procattr.h -@@ -15,11 +15,7 @@ - #ifndef __AA_PROCATTR_H - #define __AA_PROCATTR_H - --#define AA_DO_TEST 1 --#define AA_ONEXEC 1 -- - int aa_getprocattr(struct aa_profile *profile, char **string); --int aa_setprocattr_changehat(char *args, size_t size, int test); --int aa_setprocattr_changeprofile(char *fqname, bool onexec, int test); -+int aa_setprocattr_changehat(char *args, size_t size, int flags); - - #endif /* __AA_PROCATTR_H */ -diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c -index 49b780b4c53b..e07dd5a204d7 100644 ---- a/security/apparmor/lsm.c -+++ b/security/apparmor/lsm.c -@@ -554,22 +554,19 @@ static int apparmor_setprocattr(const char *name, void *value, - if (strcmp(name, "current") == 0) { - if (strcmp(command, "changehat") == 0) { - error = aa_setprocattr_changehat(args, arg_size, -- !AA_DO_TEST); -+ AA_CHANGE_NOFLAGS); - } else if (strcmp(command, "permhat") == 0) { - error = aa_setprocattr_changehat(args, arg_size, -- AA_DO_TEST); -+ AA_CHANGE_TEST); - } else if (strcmp(command, "changeprofile") == 0) { -- error = aa_change_profile(args, !AA_ONEXEC, -- !AA_DO_TEST, false); -+ error = aa_change_profile(args, AA_CHANGE_NOFLAGS); - } else if (strcmp(command, "permprofile") == 0) { -- error = aa_change_profile(args, !AA_ONEXEC, AA_DO_TEST, -- false); -+ error = aa_change_profile(args, AA_CHANGE_TEST); - } else - goto fail; - } else if (strcmp(name, "exec") == 0) { - if (strcmp(command, "exec") == 0) -- error = aa_change_profile(args, AA_ONEXEC, !AA_DO_TEST, -- false); -+ error = aa_change_profile(args, AA_CHANGE_ONEXEC); - else - goto fail; - } else -diff --git a/security/apparmor/procattr.c b/security/apparmor/procattr.c -index 41b7b64a906b..2f0cb424927a 100644 ---- a/security/apparmor/procattr.c -+++ b/security/apparmor/procattr.c -@@ -109,11 +109,11 @@ static char *split_token_from_name(const char *op, char *args, u64 *token) - * aa_setprocattr_chagnehat - handle procattr interface to change_hat - * @args: args received from writing to /proc//attr/current (NOT NULL) - * @size: size of the args -- * @test: true if this is a test of change_hat permissions -+ * @flags: set of flags governing behavior - * - * Returns: %0 or error code if change_hat fails - */ --int aa_setprocattr_changehat(char *args, size_t size, int test) -+int aa_setprocattr_changehat(char *args, size_t size, int flags) - { - char *hat; - u64 token; -@@ -148,5 +148,5 @@ int aa_setprocattr_changehat(char *args, size_t size, int test) - AA_DEBUG("%s: (pid %d) Magic 0x%llx count %d Hat '%s'\n", - __func__, current->pid, token, count, ""); - -- return aa_change_hat(hats, count, token, test); -+ return aa_change_hat(hats, count, token, flags); - } --- -2.12.3 - diff --git a/patches.apparmor/0041-apparmor-cleanup-rename-XXX_file_context-to-XXX_file.patch b/patches.apparmor/0041-apparmor-cleanup-rename-XXX_file_context-to-XXX_file.patch deleted file mode 100644 index 0b778bc..0000000 --- a/patches.apparmor/0041-apparmor-cleanup-rename-XXX_file_context-to-XXX_file.patch +++ /dev/null @@ -1,91 +0,0 @@ -From aa0d9460b157536a9eab29756d969afb13ba3d7e Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Fri, 9 Jun 2017 11:43:45 -0700 -Subject: [PATCH 41/65] apparmor: cleanup rename XXX_file_context() to XXX_file_ctx() -Git-commit: 2835a13bbdc09d330eafdf5e67eb407c90c01ab7 -Patch-mainline: v4.13-rc1 -References: FATE#323500 - -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/include/file.h | 17 ++++++++++++----- - security/apparmor/lsm.c | 10 ++++------ - 2 files changed, 16 insertions(+), 11 deletions(-) - -diff --git a/security/apparmor/include/file.h b/security/apparmor/include/file.h -index 365ca7ead133..19c483850770 100644 ---- a/security/apparmor/include/file.h -+++ b/security/apparmor/include/file.h -@@ -30,6 +30,8 @@ struct path; - AA_MAY_CHMOD | AA_MAY_CHOWN | AA_MAY_LOCK | \ - AA_EXEC_MMAP | AA_MAY_LINK) - -+#define file_ctx(X) ((struct aa_file_ctx *)(X)->f_security) -+ - /* struct aa_file_ctx - the AppArmor context the file was opened in - * @perms: the permission the file was opened with - * -@@ -42,21 +44,26 @@ struct aa_file_ctx { - }; - - /** -- * aa_alloc_file_context - allocate file_ctx -+ * 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_context(gfp_t gfp) -+static inline struct aa_file_ctx *aa_alloc_file_ctx(gfp_t gfp) - { -- return kzalloc(sizeof(struct aa_file_ctx), gfp); -+ struct aa_file_ctx *ctx; -+ -+ ctx = kzalloc(sizeof(struct aa_file_ctx), gfp); -+ -+ return ctx; - } - - /** -- * aa_free_file_context - free a file_ctx -+ * aa_free_file_ctx - free a file_ctx - * @ctx: file_ctx to free (MAYBE_NULL) - */ --static inline void aa_free_file_context(struct aa_file_ctx *ctx) -+static inline void aa_free_file_ctx(struct aa_file_ctx *ctx) - { - if (ctx) - kzfree(ctx); -diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c -index e07dd5a204d7..3c6fa9753675 100644 ---- a/security/apparmor/lsm.c -+++ b/security/apparmor/lsm.c -@@ -398,9 +398,9 @@ static int apparmor_file_alloc_security(struct file *file) - - /* freed by apparmor_file_free_security */ - struct aa_profile *profile = begin_current_profile_crit_section(); -- file->f_security = aa_alloc_file_context(GFP_KERNEL); -- if (!file->f_security) -- return -ENOMEM; -+ file->f_security = aa_alloc_file_ctx(GFP_KERNEL); -+ if (!file_ctx(file)) -+ error = -ENOMEM; - end_current_profile_crit_section(profile); - - return error; -@@ -408,9 +408,7 @@ static int apparmor_file_alloc_security(struct file *file) - - static void apparmor_file_free_security(struct file *file) - { -- struct aa_file_ctx *ctx = file->f_security; -- -- aa_free_file_context(ctx); -+ aa_free_file_ctx(file_ctx(file)); - } - - static int common_file_perm(const char *op, struct file *file, u32 mask) --- -2.12.3 - diff --git a/patches.apparmor/0042-apparmor-revalidate-files-during-exec.patch b/patches.apparmor/0042-apparmor-revalidate-files-during-exec.patch deleted file mode 100644 index f9dcc68..0000000 --- a/patches.apparmor/0042-apparmor-revalidate-files-during-exec.patch +++ /dev/null @@ -1,163 +0,0 @@ -From 28ab1952af9ab60e9f7ff450995d15c71c938b14 Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Fri, 9 Jun 2017 11:58:42 -0700 -Subject: [PATCH 42/65] apparmor: revalidate files during exec -Git-commit: 192ca6b55a866e838aee98d9cb6a0b5086467c03 -Patch-mainline: v4.13-rc1 -References: FATE#323500 - -Instead of running file revalidation lazily when read/write are called -copy selinux and revalidate the file table on exec. This avoids -extra mediation overhead in read/write and also prevents file handles -being passed through to a grand child unchecked. - -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/file.c | 72 +++++++++++++++++++++++++++++++++++++++ - security/apparmor/include/audit.h | 1 + - security/apparmor/include/file.h | 2 ++ - security/apparmor/lsm.c | 6 ++++ - 4 files changed, 81 insertions(+) - -diff --git a/security/apparmor/file.c b/security/apparmor/file.c -index 2e128c2aa4dc..bf508791cc1f 100644 ---- a/security/apparmor/file.c -+++ b/security/apparmor/file.c -@@ -12,8 +12,13 @@ - * License. - */ - -+#include -+#include -+#include -+ - #include "include/apparmor.h" - #include "include/audit.h" -+#include "include/context.h" - #include "include/file.h" - #include "include/match.h" - #include "include/path.h" -@@ -445,3 +450,70 @@ int aa_file_perm(const char *op, struct aa_profile *profile, struct file *file, - return aa_path_perm(op, profile, &file->f_path, PATH_DELEGATE_DELETED, - request, &cond); - } -+ -+static void revalidate_tty(struct aa_profile *profile) -+{ -+ struct tty_struct *tty; -+ int drop_tty = 0; -+ -+ tty = get_current_tty(); -+ if (!tty) -+ return; -+ -+ spin_lock(&tty->files_lock); -+ if (!list_empty(&tty->tty_files)) { -+ struct tty_file_private *file_priv; -+ struct file *file; -+ /* TODO: Revalidate access to controlling tty. */ -+ file_priv = list_first_entry(&tty->tty_files, -+ struct tty_file_private, list); -+ file = file_priv->file; -+ -+ if (aa_file_perm(OP_INHERIT, profile, file, -+ MAY_READ | MAY_WRITE)) -+ drop_tty = 1; -+ } -+ spin_unlock(&tty->files_lock); -+ tty_kref_put(tty); -+ -+ if (drop_tty) -+ no_tty(); -+} -+ -+static int match_file(const void *p, struct file *file, unsigned int fd) -+{ -+ struct aa_profile *profile = (struct aa_profile *)p; -+ -+ if (aa_file_perm(OP_INHERIT, profile, file, -+ aa_map_file_to_perms(file))) -+ return fd + 1; -+ return 0; -+} -+ -+ -+/* based on selinux's flush_unauthorized_files */ -+void aa_inherit_files(const struct cred *cred, struct files_struct *files) -+{ -+ struct aa_profile *profile = aa_get_newest_cred_profile(cred); -+ struct file *devnull = NULL; -+ unsigned int n; -+ -+ revalidate_tty(profile); -+ -+ /* Revalidate access to inherited open files. */ -+ n = iterate_fd(files, 0, match_file, profile); -+ if (!n) /* none found? */ -+ goto out; -+ -+ devnull = dentry_open(&aa_null, O_RDWR, cred); -+ if (IS_ERR(devnull)) -+ devnull = NULL; -+ /* replace all the matching ones with this */ -+ do { -+ replace_fd(n - 1, devnull, 0); -+ } while ((n = iterate_fd(files, n, match_file, profile)) != 0); -+ if (devnull) -+ fput(devnull); -+out: -+ aa_put_profile(profile); -+} -diff --git a/security/apparmor/include/audit.h b/security/apparmor/include/audit.h -index 1aeb8550fb82..d548261dd1b7 100644 ---- a/security/apparmor/include/audit.h -+++ b/security/apparmor/include/audit.h -@@ -69,6 +69,7 @@ enum audit_type { - #define OP_FLOCK "file_lock" - #define OP_FMMAP "file_mmap" - #define OP_FMPROT "file_mprotect" -+#define OP_INHERIT "file_inherit" - - #define OP_CREATE "create" - #define OP_POST_CREATE "post_create" -diff --git a/security/apparmor/include/file.h b/security/apparmor/include/file.h -index 19c483850770..df76c208473a 100644 ---- a/security/apparmor/include/file.h -+++ b/security/apparmor/include/file.h -@@ -186,6 +186,8 @@ int aa_path_link(struct aa_profile *profile, struct dentry *old_dentry, - int aa_file_perm(const char *op, struct aa_profile *profile, struct file *file, - u32 request); - -+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); -diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c -index 3c6fa9753675..7ba43c18687a 100644 ---- a/security/apparmor/lsm.c -+++ b/security/apparmor/lsm.c -@@ -417,6 +417,10 @@ static int common_file_perm(const char *op, struct file *file, u32 mask) - struct aa_profile *profile, *fprofile; - int error = 0; - -+ /* don't reaudit files closed during inheritance */ -+ if (file->f_path.dentry == aa_null.dentry) -+ return -EACCES; -+ - fprofile = aa_cred_raw_profile(file->f_cred); - AA_BUG(!fprofile); - -@@ -600,6 +604,8 @@ static void apparmor_bprm_committing_creds(struct linux_binprm *bprm) - (unconfined(new_ctx->profile))) - return; - -+ aa_inherit_files(bprm->cred, current->files); -+ - current->pdeath_signal = 0; - - /* reset soft limits and set hard limits for the new profile */ --- -2.12.3 - diff --git a/patches.apparmor/0043-apparmor-add-the-base-fns-for-domain-labels.patch b/patches.apparmor/0043-apparmor-add-the-base-fns-for-domain-labels.patch deleted file mode 100644 index 590c09d..0000000 --- a/patches.apparmor/0043-apparmor-add-the-base-fns-for-domain-labels.patch +++ /dev/null @@ -1,2597 +0,0 @@ -From 257d4352d5b1220a2a942227cd25228a7210baaa Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Fri, 9 Jun 2017 06:19:19 -0700 -Subject: [PATCH 43/65] apparmor: add the base fns() for domain labels -Patch-mainline: v4.13-rc1 -References: FATE#323500 -Git-commit: f1bd904175e8190ce14aedee37e207ab51fe3b30 - -Begin moving apparmor to using broader domain labels, that will allow -run time computation of domain type splitting via "stacking" of -profiles into a domain label vec. - -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/include/label.h | 441 ++++++++ - security/apparmor/label.c | 2120 +++++++++++++++++++++++++++++++++++++ - 2 files changed, 2561 insertions(+) - create mode 100644 security/apparmor/include/label.h - create mode 100644 security/apparmor/label.c - -diff --git a/security/apparmor/include/label.h b/security/apparmor/include/label.h -new file mode 100644 -index 000000000000..9a283b722755 ---- /dev/null -+++ b/security/apparmor/include/label.h -@@ -0,0 +1,441 @@ -+/* -+ * AppArmor security module -+ * -+ * This file contains AppArmor label definitions -+ * -+ * Copyright 2017 Canonical Ltd. -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License as -+ * published by the Free Software Foundation, version 2 of the -+ * License. -+ */ -+ -+#ifndef __AA_LABEL_H -+#define __AA_LABEL_H -+ -+#include -+#include -+#include -+#include -+ -+#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)) -+ -+void aa_labelset_destroy(struct aa_labelset *ls); -+void aa_labelset_init(struct aa_labelset *ls); -+ -+ -+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 */ -+ -+ /* 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_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_free(struct aa_label *label); -+void aa_label_kref(struct kref *kref); -+bool aa_label_init(struct aa_label *label, int size); -+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); -+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 -+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_parse(struct aa_label *base, const char *str, -+ gfp_t gfp, bool create, bool force_stack); -+ -+ -+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/label.c b/security/apparmor/label.c -new file mode 100644 -index 000000000000..e052eaba1cf6 ---- /dev/null -+++ b/security/apparmor/label.c -@@ -0,0 +1,2120 @@ -+/* -+ * AppArmor security module -+ * -+ * This file contains AppArmor label definitions -+ * -+ * Copyright 2017 Canonical Ltd. -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License as -+ * published by the Free Software Foundation, version 2 of the -+ * License. -+ */ -+ -+#include -+#include -+#include -+ -+#include "include/apparmor.h" -+#include "include/context.h" -+#include "include/label.h" -+#include "include/policy.h" -+#include "include/secid.h" -+ -+ -+/* -+ * the aa_label represents the set of profiles confining an object -+ * -+ * Labels maintain a reference count to the set of pointers they reference -+ * Labels are ref counted by -+ * tasks and object via the security field/security context off the field -+ * code - will take a ref count on a label if it needs the label -+ * beyond what is possible with an rcu_read_lock. -+ * profiles - each profile is a label -+ * secids - a pinned secid will keep a refcount of the label it is -+ * referencing -+ * objects - inode, files, sockets, ... -+ * -+ * Labels are not ref counted by the label set, so they maybe removed and -+ * freed when no longer in use. -+ * -+ */ -+ -+#define PROXY_POISON 97 -+#define LABEL_POISON 100 -+ -+static void free_proxy(struct aa_proxy *proxy) -+{ -+ if (proxy) { -+ /* p->label will not updated any more as p is dead */ -+ aa_put_label(rcu_dereference_protected(proxy->label, true)); -+ memset(proxy, 0, sizeof(*proxy)); -+ proxy->label = (struct aa_label *) PROXY_POISON; -+ kfree(proxy); -+ } -+} -+ -+void aa_proxy_kref(struct kref *kref) -+{ -+ struct aa_proxy *proxy = container_of(kref, struct aa_proxy, count); -+ -+ free_proxy(proxy); -+} -+ -+struct aa_proxy *aa_alloc_proxy(struct aa_label *label, gfp_t gfp) -+{ -+ struct aa_proxy *new; -+ -+ new = kzalloc(sizeof(struct aa_proxy), gfp); -+ if (new) { -+ kref_init(&new->count); -+ rcu_assign_pointer(new->label, aa_get_label(label)); -+ } -+ return new; -+} -+ -+/* requires profile list write lock held */ -+void __aa_proxy_redirect(struct aa_label *orig, struct aa_label *new) -+{ -+ struct aa_label *tmp; -+ -+ AA_BUG(!orig); -+ AA_BUG(!new); -+ AA_BUG(!write_is_locked(&labels_set(orig)->lock)); -+ -+ tmp = rcu_dereference_protected(orig->proxy->label, -+ &labels_ns(orig)->lock); -+ rcu_assign_pointer(orig->proxy->label, aa_get_label(new)); -+ orig->flags |= FLAG_STALE; -+ aa_put_label(tmp); -+} -+ -+static void __proxy_share(struct aa_label *old, struct aa_label *new) -+{ -+ struct aa_proxy *proxy = new->proxy; -+ -+ new->proxy = aa_get_proxy(old->proxy); -+ __aa_proxy_redirect(old, new); -+ aa_put_proxy(proxy); -+} -+ -+ -+/** -+ * ns_cmp - compare ns for label set ordering -+ * @a: ns to compare (NOT NULL) -+ * @b: ns to compare (NOT NULL) -+ * -+ * Returns: <0 if a < b -+ * ==0 if a == b -+ * >0 if a > b -+ */ -+static int ns_cmp(struct aa_ns *a, struct aa_ns *b) -+{ -+ int res; -+ -+ AA_BUG(!a); -+ AA_BUG(!b); -+ AA_BUG(!a->base.hname); -+ AA_BUG(!b->base.hname); -+ -+ if (a == b) -+ return 0; -+ -+ res = a->level - b->level; -+ if (res) -+ return res; -+ -+ return strcmp(a->base.hname, b->base.hname); -+} -+ -+/** -+ * profile_cmp - profile comparision for set ordering -+ * @a: profile to compare (NOT NULL) -+ * @b: profile to compare (NOT NULL) -+ * -+ * Returns: <0 if a < b -+ * ==0 if a == b -+ * >0 if a > b -+ */ -+static int profile_cmp(struct aa_profile *a, struct aa_profile *b) -+{ -+ int res; -+ -+ AA_BUG(!a); -+ AA_BUG(!b); -+ AA_BUG(!a->ns); -+ AA_BUG(!b->ns); -+ AA_BUG(!a->base.hname); -+ AA_BUG(!b->base.hname); -+ -+ if (a == b || a->base.hname == b->base.hname) -+ return 0; -+ res = ns_cmp(a->ns, b->ns); -+ if (res) -+ return res; -+ -+ return strcmp(a->base.hname, b->base.hname); -+} -+ -+/** -+ * vec_cmp - label comparision for set ordering -+ * @a: label to compare (NOT NULL) -+ * @vec: vector of profiles to compare (NOT NULL) -+ * @n: length of @vec -+ * -+ * Returns: <0 if a < vec -+ * ==0 if a == vec -+ * >0 if a > vec -+ */ -+static int vec_cmp(struct aa_profile **a, int an, struct aa_profile **b, int bn) -+{ -+ int i; -+ -+ AA_BUG(!a); -+ AA_BUG(!*a); -+ AA_BUG(!b); -+ AA_BUG(!*b); -+ AA_BUG(an <= 0); -+ AA_BUG(bn <= 0); -+ -+ for (i = 0; i < an && i < bn; i++) { -+ int res = profile_cmp(a[i], b[i]); -+ -+ if (res != 0) -+ return res; -+ } -+ -+ return an - bn; -+} -+ -+static bool vec_is_stale(struct aa_profile **vec, int n) -+{ -+ int i; -+ -+ AA_BUG(!vec); -+ -+ for (i = 0; i < n; i++) { -+ if (profile_is_stale(vec[i])) -+ return true; -+ } -+ -+ return false; -+} -+ -+static bool vec_unconfined(struct aa_profile **vec, int n) -+{ -+ int i; -+ -+ AA_BUG(!vec); -+ -+ for (i = 0; i < n; i++) { -+ if (!profile_unconfined(vec[i])) -+ return false; -+ } -+ -+ return true; -+} -+ -+static int sort_cmp(const void *a, const void *b) -+{ -+ return profile_cmp(*(struct aa_profile **)a, *(struct aa_profile **)b); -+} -+ -+/* -+ * assumes vec is sorted -+ * Assumes @vec has null terminator at vec[n], and will null terminate -+ * vec[n - dups] -+ */ -+static inline int unique(struct aa_profile **vec, int n) -+{ -+ int i, pos, dups = 0; -+ -+ AA_BUG(n < 1); -+ AA_BUG(!vec); -+ -+ pos = 0; -+ for (i = 1; i < n; i++) { -+ int res = profile_cmp(vec[pos], vec[i]); -+ -+ AA_BUG(res > 0, "vec not sorted"); -+ if (res == 0) { -+ /* drop duplicate */ -+ aa_put_profile(vec[i]); -+ dups++; -+ continue; -+ } -+ pos++; -+ if (dups) -+ vec[pos] = vec[i]; -+ } -+ -+ AA_BUG(dups < 0); -+ -+ return dups; -+} -+ -+/** -+ * aa_vec_unique - canonical sort and unique a list of profiles -+ * @n: number of refcounted profiles in the list (@n > 0) -+ * @vec: list of profiles to sort and merge -+ * -+ * Returns: the number of duplicates eliminated == references put -+ * -+ * If @flags & VEC_FLAG_TERMINATE @vec has null terminator at vec[n], and will -+ * null terminate vec[n - dups] -+ */ -+int aa_vec_unique(struct aa_profile **vec, int n, int flags) -+{ -+ int i, dups = 0; -+ -+ AA_BUG(n < 1); -+ AA_BUG(!vec); -+ -+ /* vecs are usually small and inorder, have a fallback for larger */ -+ if (n > 8) { -+ sort(vec, n, sizeof(struct aa_profile *), sort_cmp, NULL); -+ dups = unique(vec, n); -+ goto out; -+ } -+ -+ /* insertion sort + unique in one */ -+ for (i = 1; i < n; i++) { -+ struct aa_profile *tmp = vec[i]; -+ int pos, j; -+ -+ for (pos = i - 1 - dups; pos >= 0; pos--) { -+ int res = profile_cmp(vec[pos], tmp); -+ -+ if (res == 0) { -+ /* drop duplicate entry */ -+ aa_put_profile(tmp); -+ dups++; -+ goto continue_outer; -+ } else if (res < 0) -+ break; -+ } -+ /* pos is at entry < tmp, or index -1. Set to insert pos */ -+ pos++; -+ -+ for (j = i - dups; j > pos; j--) -+ vec[j] = vec[j - 1]; -+ vec[pos] = tmp; -+continue_outer: -+ ; -+ } -+ -+ AA_BUG(dups < 0); -+ -+out: -+ if (flags & VEC_FLAG_TERMINATE) -+ vec[n - dups] = NULL; -+ -+ return dups; -+} -+ -+ -+static void label_destroy(struct aa_label *label) -+{ -+ struct aa_label *tmp; -+ -+ AA_BUG(!label); -+ -+ if (!label_isprofile(label)) { -+ struct aa_profile *profile; -+ struct label_it i; -+ -+ aa_put_str(label->hname); -+ -+ label_for_each(i, label, profile) { -+ aa_put_profile(profile); -+ label->vec[i.i] = (struct aa_profile *) -+ (LABEL_POISON + (long) i.i); -+ } -+ } -+ -+ if (rcu_dereference_protected(label->proxy->label, true) == label) -+ rcu_assign_pointer(label->proxy->label, NULL); -+ -+ aa_free_secid(label->secid); -+ -+ tmp = rcu_dereference_protected(label->proxy->label, true); -+ if (tmp == label) -+ rcu_assign_pointer(label->proxy->label, NULL); -+ -+ aa_put_proxy(label->proxy); -+ label->proxy = (struct aa_proxy *) PROXY_POISON + 1; -+} -+ -+void aa_label_free(struct aa_label *label) -+{ -+ if (!label) -+ return; -+ -+ label_destroy(label); -+ kfree(label); -+} -+ -+static void label_free_switch(struct aa_label *label) -+{ -+ if (label->flags & FLAG_NS_COUNT) -+ aa_free_ns(labels_ns(label)); -+ else if (label_isprofile(label)) -+ aa_free_profile(labels_profile(label)); -+ else -+ aa_label_free(label); -+} -+ -+static void label_free_rcu(struct rcu_head *head) -+{ -+ struct aa_label *label = container_of(head, struct aa_label, rcu); -+ -+ if (label->flags & FLAG_IN_TREE) -+ (void) aa_label_remove(label); -+ label_free_switch(label); -+} -+ -+void aa_label_kref(struct kref *kref) -+{ -+ struct aa_label *label = container_of(kref, struct aa_label, count); -+ struct aa_ns *ns = labels_ns(label); -+ -+ if (!ns) { -+ /* never live, no rcu callback needed, just using the fn */ -+ label_free_switch(label); -+ return; -+ } -+ /* TODO: update labels_profile macro so it works here */ -+ AA_BUG(label_isprofile(label) && -+ on_list_rcu(&label->vec[0]->base.profiles)); -+ AA_BUG(label_isprofile(label) && -+ on_list_rcu(&label->vec[0]->base.list)); -+ -+ /* TODO: if compound label and not stale add to reclaim cache */ -+ call_rcu(&label->rcu, label_free_rcu); -+} -+ -+static void label_free_or_put_new(struct aa_label *label, struct aa_label *new) -+{ -+ if (label != new) -+ /* need to free directly to break circular ref with proxy */ -+ aa_label_free(new); -+ else -+ aa_put_label(new); -+} -+ -+bool aa_label_init(struct aa_label *label, int size) -+{ -+ AA_BUG(!label); -+ AA_BUG(size < 1); -+ -+ label->secid = aa_alloc_secid(); -+ if (label->secid == AA_SECID_INVALID) -+ return false; -+ -+ label->size = size; /* doesn't include null */ -+ label->vec[size] = NULL; /* null terminate */ -+ kref_init(&label->count); -+ RB_CLEAR_NODE(&label->node); -+ -+ return true; -+} -+ -+/** -+ * aa_label_alloc - allocate a label with a profile vector of @size length -+ * @size: size of profile vector in the label -+ * @proxy: proxy to use OR null if to allocate a new one -+ * @gfp: memory allocation type -+ * -+ * Returns: new label -+ * else NULL if failed -+ */ -+struct aa_label *aa_label_alloc(int size, struct aa_proxy *proxy, gfp_t gfp) -+{ -+ struct aa_label *new; -+ -+ AA_BUG(size < 1); -+ -+ /* + 1 for null terminator entry on vec */ -+ new = kzalloc(sizeof(*new) + sizeof(struct aa_profile *) * (size + 1), -+ gfp); -+ AA_DEBUG("%s (%p)\n", __func__, new); -+ if (!new) -+ goto fail; -+ -+ if (!aa_label_init(new, size)) -+ goto fail; -+ -+ if (!proxy) { -+ proxy = aa_alloc_proxy(new, gfp); -+ if (!proxy) -+ goto fail; -+ } else -+ aa_get_proxy(proxy); -+ /* just set new's proxy, don't redirect proxy here if it was passed in*/ -+ new->proxy = proxy; -+ -+ return new; -+ -+fail: -+ kfree(new); -+ -+ return NULL; -+} -+ -+ -+/** -+ * label_cmp - label comparision for set ordering -+ * @a: label to compare (NOT NULL) -+ * @b: label to compare (NOT NULL) -+ * -+ * Returns: <0 if a < b -+ * ==0 if a == b -+ * >0 if a > b -+ */ -+static int label_cmp(struct aa_label *a, struct aa_label *b) -+{ -+ AA_BUG(!b); -+ -+ if (a == b) -+ return 0; -+ -+ return vec_cmp(a->vec, a->size, b->vec, b->size); -+} -+ -+/* helper fn for label_for_each_confined */ -+int aa_label_next_confined(struct aa_label *label, int i) -+{ -+ AA_BUG(!label); -+ AA_BUG(i < 0); -+ -+ for (; i < label->size; i++) { -+ if (!profile_unconfined(label->vec[i])) -+ return i; -+ } -+ -+ return i; -+} -+ -+/** -+ * aa_label_next_not_in_set - return the next profile of @sub not in @set -+ * @I: label iterator -+ * @set: label to test against -+ * @sub: label to if is subset of @set -+ * -+ * Returns: profile in @sub that is not in @set, with iterator set pos after -+ * else NULL if @sub is a subset of @set -+ */ -+struct aa_profile *__aa_label_next_not_in_set(struct label_it *I, -+ struct aa_label *set, -+ struct aa_label *sub) -+{ -+ AA_BUG(!set); -+ AA_BUG(!I); -+ AA_BUG(I->i < 0); -+ AA_BUG(I->i > set->size); -+ AA_BUG(!sub); -+ AA_BUG(I->j < 0); -+ AA_BUG(I->j > sub->size); -+ -+ while (I->j < sub->size && I->i < set->size) { -+ int res = profile_cmp(sub->vec[I->j], set->vec[I->i]); -+ -+ if (res == 0) { -+ (I->j)++; -+ (I->i)++; -+ } else if (res > 0) -+ (I->i)++; -+ else -+ return sub->vec[(I->j)++]; -+ } -+ -+ if (I->j < sub->size) -+ return sub->vec[(I->j)++]; -+ -+ return NULL; -+} -+ -+/** -+ * aa_label_is_subset - test if @sub is a subset of @set -+ * @set: label to test against -+ * @sub: label to test if is subset of @set -+ * -+ * Returns: true if @sub is subset of @set -+ * else false -+ */ -+bool aa_label_is_subset(struct aa_label *set, struct aa_label *sub) -+{ -+ struct label_it i = { }; -+ -+ AA_BUG(!set); -+ AA_BUG(!sub); -+ -+ if (sub == set) -+ return true; -+ -+ return __aa_label_next_not_in_set(&i, set, sub) == NULL; -+} -+ -+ -+ -+/** -+ * __label_remove - remove @label from the label set -+ * @l: label to remove -+ * @new: label to redirect to -+ * -+ * Requires: labels_set(@label)->lock write_lock -+ * Returns: true if the label was in the tree and removed -+ */ -+static bool __label_remove(struct aa_label *label, struct aa_label *new) -+{ -+ struct aa_labelset *ls = labels_set(label); -+ -+ AA_BUG(!ls); -+ AA_BUG(!label); -+ AA_BUG(!write_is_locked(&ls->lock)); -+ -+ if (new) -+ __aa_proxy_redirect(label, new); -+ -+ if (!label_is_stale(label)) -+ __label_make_stale(label); -+ -+ if (label->flags & FLAG_IN_TREE) { -+ rb_erase(&label->node, &ls->root); -+ label->flags &= ~FLAG_IN_TREE; -+ return true; -+ } -+ -+ return false; -+} -+ -+/** -+ * __label_replace - replace @old with @new in label set -+ * @old: label to remove from label set -+ * @new: label to replace @old with -+ * -+ * Requires: labels_set(@old)->lock write_lock -+ * valid ref count be held on @new -+ * Returns: true if @old was in set and replaced by @new -+ * -+ * Note: current implementation requires label set be order in such a way -+ * that @new directly replaces @old position in the set (ie. -+ * using pointer comparison of the label address would not work) -+ */ -+static bool __label_replace(struct aa_label *old, struct aa_label *new) -+{ -+ struct aa_labelset *ls = labels_set(old); -+ -+ AA_BUG(!ls); -+ AA_BUG(!old); -+ AA_BUG(!new); -+ AA_BUG(!write_is_locked(&ls->lock)); -+ AA_BUG(new->flags & FLAG_IN_TREE); -+ -+ if (!label_is_stale(old)) -+ __label_make_stale(old); -+ -+ if (old->flags & FLAG_IN_TREE) { -+ rb_replace_node(&old->node, &new->node, &ls->root); -+ old->flags &= ~FLAG_IN_TREE; -+ new->flags |= FLAG_IN_TREE; -+ return true; -+ } -+ -+ return false; -+} -+ -+/** -+ * __label_insert - attempt to insert @l into a label set -+ * @ls: set of labels to insert @l into (NOT NULL) -+ * @label: new label to insert (NOT NULL) -+ * @replace: whether insertion should replace existing entry that is not stale -+ * -+ * Requires: @ls->lock -+ * caller to hold a valid ref on l -+ * if @replace is true l has a preallocated proxy associated -+ * Returns: @l if successful in inserting @l - with additional refcount -+ * else ref counted equivalent label that is already in the set, -+ * the else condition only happens if @replace is false -+ */ -+static struct aa_label *__label_insert(struct aa_labelset *ls, -+ struct aa_label *label, bool replace) -+{ -+ struct rb_node **new, *parent = NULL; -+ -+ AA_BUG(!ls); -+ AA_BUG(!label); -+ AA_BUG(labels_set(label) != ls); -+ AA_BUG(!write_is_locked(&ls->lock)); -+ AA_BUG(label->flags & FLAG_IN_TREE); -+ -+ /* Figure out where to put new node */ -+ new = &ls->root.rb_node; -+ while (*new) { -+ struct aa_label *this = rb_entry(*new, struct aa_label, node); -+ int result = label_cmp(label, this); -+ -+ parent = *new; -+ if (result == 0) { -+ /* !__aa_get_label means queued for destruction, -+ * so replace in place, however the label has -+ * died before the replacement so do not share -+ * the proxy -+ */ -+ if (!replace && !label_is_stale(this)) { -+ if (__aa_get_label(this)) -+ return this; -+ } else -+ __proxy_share(this, label); -+ AA_BUG(!__label_replace(this, label)); -+ return aa_get_label(label); -+ } else if (result < 0) -+ new = &((*new)->rb_left); -+ else /* (result > 0) */ -+ new = &((*new)->rb_right); -+ } -+ -+ /* Add new node and rebalance tree. */ -+ rb_link_node(&label->node, parent, new); -+ rb_insert_color(&label->node, &ls->root); -+ label->flags |= FLAG_IN_TREE; -+ -+ return aa_get_label(label); -+} -+ -+/** -+ * __vec_find - find label that matches @vec in label set -+ * @vec: vec of profiles to find matching label for (NOT NULL) -+ * @n: length of @vec -+ * -+ * Requires: @vec_labelset(vec) lock held -+ * caller to hold a valid ref on l -+ * -+ * Returns: ref counted @label if matching label is in tree -+ * ref counted label that is equiv to @l in tree -+ * else NULL if @vec equiv is not in tree -+ */ -+static struct aa_label *__vec_find(struct aa_profile **vec, int n) -+{ -+ struct rb_node *node; -+ -+ AA_BUG(!vec); -+ AA_BUG(!*vec); -+ AA_BUG(n <= 0); -+ -+ node = vec_labelset(vec, n)->root.rb_node; -+ while (node) { -+ struct aa_label *this = rb_entry(node, struct aa_label, node); -+ int result = vec_cmp(this->vec, this->size, vec, n); -+ -+ if (result > 0) -+ node = node->rb_left; -+ else if (result < 0) -+ node = node->rb_right; -+ else -+ return __aa_get_label(this); -+ } -+ -+ return NULL; -+} -+ -+/** -+ * __label_find - find label @label in label set -+ * @label: label to find (NOT NULL) -+ * -+ * Requires: labels_set(@label)->lock held -+ * caller to hold a valid ref on l -+ * -+ * Returns: ref counted @label if @label is in tree OR -+ * ref counted label that is equiv to @label in tree -+ * else NULL if @label or equiv is not in tree -+ */ -+static struct aa_label *__label_find(struct aa_label *label) -+{ -+ AA_BUG(!label); -+ -+ return __vec_find(label->vec, label->size); -+} -+ -+ -+/** -+ * aa_label_remove - remove a label from the labelset -+ * @label: label to remove -+ * -+ * Returns: true if @label was removed from the tree -+ * else @label was not in tree so it could not be removed -+ */ -+bool aa_label_remove(struct aa_label *label) -+{ -+ struct aa_labelset *ls = labels_set(label); -+ unsigned long flags; -+ bool res; -+ -+ AA_BUG(!ls); -+ -+ write_lock_irqsave(&ls->lock, flags); -+ res = __label_remove(label, ns_unconfined(labels_ns(label))); -+ write_unlock_irqrestore(&ls->lock, flags); -+ -+ return res; -+} -+ -+/** -+ * aa_label_replace - replace a label @old with a new version @new -+ * @old: label to replace -+ * @new: label replacing @old -+ * -+ * Returns: true if @old was in tree and replaced -+ * else @old was not in tree, and @new was not inserted -+ */ -+bool aa_label_replace(struct aa_label *old, struct aa_label *new) -+{ -+ unsigned long flags; -+ bool res; -+ -+ if (name_is_shared(old, new) && labels_ns(old) == labels_ns(new)) { -+ write_lock_irqsave(&labels_set(old)->lock, flags); -+ if (old->proxy != new->proxy) -+ __proxy_share(old, new); -+ else -+ __aa_proxy_redirect(old, new); -+ res = __label_replace(old, new); -+ write_unlock_irqrestore(&labels_set(old)->lock, flags); -+ } else { -+ struct aa_label *l; -+ struct aa_labelset *ls = labels_set(old); -+ -+ write_lock_irqsave(&ls->lock, flags); -+ res = __label_remove(old, new); -+ if (labels_ns(old) != labels_ns(new)) { -+ write_unlock_irqrestore(&ls->lock, flags); -+ ls = labels_set(new); -+ write_lock_irqsave(&ls->lock, flags); -+ } -+ l = __label_insert(ls, new, true); -+ res = (l == new); -+ write_unlock_irqrestore(&ls->lock, flags); -+ aa_put_label(l); -+ } -+ -+ return res; -+} -+ -+/** -+ * vec_find - find label @l in label set -+ * @vec: array of profiles to find equiv label for (NOT NULL) -+ * @n: length of @vec -+ * -+ * Returns: refcounted label if @vec equiv is in tree -+ * else NULL if @vec equiv is not in tree -+ */ -+static struct aa_label *vec_find(struct aa_profile **vec, int n) -+{ -+ struct aa_labelset *ls; -+ struct aa_label *label; -+ unsigned long flags; -+ -+ AA_BUG(!vec); -+ AA_BUG(!*vec); -+ AA_BUG(n <= 0); -+ -+ ls = vec_labelset(vec, n); -+ read_lock_irqsave(&ls->lock, flags); -+ label = __vec_find(vec, n); -+ read_unlock_irqrestore(&ls->lock, flags); -+ -+ return label; -+} -+ -+/* requires sort and merge done first */ -+static struct aa_label *vec_create_and_insert_label(struct aa_profile **vec, -+ int len, gfp_t gfp) -+{ -+ struct aa_label *label = NULL; -+ struct aa_labelset *ls; -+ unsigned long flags; -+ struct aa_label *new; -+ int i; -+ -+ AA_BUG(!vec); -+ -+ if (len == 1) -+ return aa_get_label(&vec[0]->label); -+ -+ ls = labels_set(&vec[len - 1]->label); -+ -+ /* TODO: enable when read side is lockless -+ * check if label exists before taking locks -+ */ -+ new = aa_label_alloc(len, NULL, gfp); -+ if (!new) -+ return NULL; -+ -+ for (i = 0; i < len; i++) -+ new->vec[i] = aa_get_profile(vec[i]); -+ -+ write_lock_irqsave(&ls->lock, flags); -+ label = __label_insert(ls, new, false); -+ write_unlock_irqrestore(&ls->lock, flags); -+ label_free_or_put_new(label, new); -+ -+ return label; -+} -+ -+struct aa_label *aa_vec_find_or_create_label(struct aa_profile **vec, int len, -+ gfp_t gfp) -+{ -+ struct aa_label *label = vec_find(vec, len); -+ -+ if (label) -+ return label; -+ -+ return vec_create_and_insert_label(vec, len, gfp); -+} -+ -+/** -+ * aa_label_find - find label @label in label set -+ * @label: label to find (NOT NULL) -+ * -+ * Requires: caller to hold a valid ref on l -+ * -+ * Returns: refcounted @label if @label is in tree -+ * refcounted label that is equiv to @label in tree -+ * else NULL if @label or equiv is not in tree -+ */ -+struct aa_label *aa_label_find(struct aa_label *label) -+{ -+ AA_BUG(!label); -+ -+ return vec_find(label->vec, label->size); -+} -+ -+ -+/** -+ * aa_label_insert - insert label @label into @ls or return existing label -+ * @ls - labelset to insert @label into -+ * @label - label to insert -+ * -+ * Requires: caller to hold a valid ref on @label -+ * -+ * Returns: ref counted @label if successful in inserting @label -+ * else ref counted equivalent label that is already in the set -+ */ -+struct aa_label *aa_label_insert(struct aa_labelset *ls, struct aa_label *label) -+{ -+ struct aa_label *l; -+ unsigned long flags; -+ -+ AA_BUG(!ls); -+ AA_BUG(!label); -+ -+ /* check if label exists before taking lock */ -+ if (!label_is_stale(label)) { -+ read_lock_irqsave(&ls->lock, flags); -+ l = __label_find(label); -+ read_unlock_irqrestore(&ls->lock, flags); -+ if (l) -+ return l; -+ } -+ -+ write_lock_irqsave(&ls->lock, flags); -+ l = __label_insert(ls, label, false); -+ write_unlock_irqrestore(&ls->lock, flags); -+ -+ return l; -+} -+ -+ -+/** -+ * aa_label_next_in_merge - find the next profile when merging @a and @b -+ * @I: label iterator -+ * @a: label to merge -+ * @b: label to merge -+ * -+ * Returns: next profile -+ * else null if no more profiles -+ */ -+struct aa_profile *aa_label_next_in_merge(struct label_it *I, -+ struct aa_label *a, -+ struct aa_label *b) -+{ -+ AA_BUG(!a); -+ AA_BUG(!b); -+ AA_BUG(!I); -+ AA_BUG(I->i < 0); -+ AA_BUG(I->i > a->size); -+ AA_BUG(I->j < 0); -+ AA_BUG(I->j > b->size); -+ -+ if (I->i < a->size) { -+ if (I->j < b->size) { -+ int res = profile_cmp(a->vec[I->i], b->vec[I->j]); -+ -+ if (res > 0) -+ return b->vec[(I->j)++]; -+ if (res == 0) -+ (I->j)++; -+ } -+ -+ return a->vec[(I->i)++]; -+ } -+ -+ if (I->j < b->size) -+ return b->vec[(I->j)++]; -+ -+ return NULL; -+} -+ -+/** -+ * label_merge_cmp - cmp of @a merging with @b against @z for set ordering -+ * @a: label to merge then compare (NOT NULL) -+ * @b: label to merge then compare (NOT NULL) -+ * @z: label to compare merge against (NOT NULL) -+ * -+ * Assumes: using the most recent versions of @a, @b, and @z -+ * -+ * Returns: <0 if a < b -+ * ==0 if a == b -+ * >0 if a > b -+ */ -+static int label_merge_cmp(struct aa_label *a, struct aa_label *b, -+ struct aa_label *z) -+{ -+ struct aa_profile *p = NULL; -+ struct label_it i = { }; -+ int k; -+ -+ AA_BUG(!a); -+ AA_BUG(!b); -+ AA_BUG(!z); -+ -+ for (k = 0; -+ k < z->size && (p = aa_label_next_in_merge(&i, a, b)); -+ k++) { -+ int res = profile_cmp(p, z->vec[k]); -+ -+ if (res != 0) -+ return res; -+ } -+ -+ if (p) -+ return 1; -+ else if (k < z->size) -+ return -1; -+ return 0; -+} -+ -+/** -+ * label_merge_insert - create a new label by merging @a and @b -+ * @new: preallocated label to merge into (NOT NULL) -+ * @a: label to merge with @b (NOT NULL) -+ * @b: label to merge with @a (NOT NULL) -+ * -+ * Requires: preallocated proxy -+ * -+ * Returns: ref counted label either @new if merge is unique -+ * @a if @b is a subset of @a -+ * @b if @a is a subset of @b -+ * -+ * NOTE: will not use @new if the merge results in @new == @a or @b -+ * -+ * Must be used within labelset write lock to avoid racing with -+ * setting labels stale. -+ */ -+static struct aa_label *label_merge_insert(struct aa_label *new, -+ struct aa_label *a, -+ struct aa_label *b) -+{ -+ struct aa_label *label; -+ struct aa_labelset *ls; -+ struct aa_profile *next; -+ struct label_it i; -+ unsigned long flags; -+ int k = 0, invcount = 0; -+ bool stale = false; -+ -+ AA_BUG(!a); -+ AA_BUG(a->size < 0); -+ AA_BUG(!b); -+ AA_BUG(b->size < 0); -+ AA_BUG(!new); -+ AA_BUG(new->size < a->size + b->size); -+ -+ label_for_each_in_merge(i, a, b, next) { -+ AA_BUG(!next); -+ if (profile_is_stale(next)) { -+ new->vec[k] = aa_get_newest_profile(next); -+ AA_BUG(!new->vec[k]->label.proxy); -+ AA_BUG(!new->vec[k]->label.proxy->label); -+ if (next->label.proxy != new->vec[k]->label.proxy) -+ invcount++; -+ k++; -+ stale = true; -+ } else -+ new->vec[k++] = aa_get_profile(next); -+ } -+ /* set to actual size which is <= allocated len */ -+ new->size = k; -+ new->vec[k] = NULL; -+ -+ if (invcount) { -+ new->size -= aa_vec_unique(&new->vec[0], new->size, -+ VEC_FLAG_TERMINATE); -+ /* TODO: deal with reference labels */ -+ if (new->size == 1) { -+ label = aa_get_label(&new->vec[0]->label); -+ return label; -+ } -+ } else if (!stale) { -+ /* -+ * merge could be same as a || b, note: it is not possible -+ * for new->size == a->size == b->size unless a == b -+ */ -+ if (k == a->size) -+ return aa_get_label(a); -+ else if (k == b->size) -+ return aa_get_label(b); -+ } -+ if (vec_unconfined(new->vec, new->size)) -+ new->flags |= FLAG_UNCONFINED; -+ ls = labels_set(new); -+ write_lock_irqsave(&ls->lock, flags); -+ label = __label_insert(labels_set(new), new, false); -+ write_unlock_irqrestore(&ls->lock, flags); -+ -+ return label; -+} -+ -+/** -+ * labelset_of_merge - find which labelset a merged label should be inserted -+ * @a: label to merge and insert -+ * @b: label to merge and insert -+ * -+ * Returns: labelset that the merged label should be inserted into -+ */ -+static struct aa_labelset *labelset_of_merge(struct aa_label *a, -+ struct aa_label *b) -+{ -+ struct aa_ns *nsa = labels_ns(a); -+ struct aa_ns *nsb = labels_ns(b); -+ -+ if (ns_cmp(nsa, nsb) <= 0) -+ return &nsa->labels; -+ return &nsb->labels; -+} -+ -+/** -+ * __label_find_merge - find label that is equiv to merge of @a and @b -+ * @ls: set of labels to search (NOT NULL) -+ * @a: label to merge with @b (NOT NULL) -+ * @b: label to merge with @a (NOT NULL) -+ * -+ * Requires: ls->lock read_lock held -+ * -+ * Returns: ref counted label that is equiv to merge of @a and @b -+ * else NULL if merge of @a and @b is not in set -+ */ -+static struct aa_label *__label_find_merge(struct aa_labelset *ls, -+ struct aa_label *a, -+ struct aa_label *b) -+{ -+ struct rb_node *node; -+ -+ AA_BUG(!ls); -+ AA_BUG(!a); -+ AA_BUG(!b); -+ -+ if (a == b) -+ return __label_find(a); -+ -+ node = ls->root.rb_node; -+ while (node) { -+ struct aa_label *this = container_of(node, struct aa_label, -+ node); -+ int result = label_merge_cmp(a, b, this); -+ -+ if (result < 0) -+ node = node->rb_left; -+ else if (result > 0) -+ node = node->rb_right; -+ else -+ return __aa_get_label(this); -+ } -+ -+ return NULL; -+} -+ -+ -+/** -+ * aa_label_find_merge - find label that is equiv to merge of @a and @b -+ * @a: label to merge with @b (NOT NULL) -+ * @b: label to merge with @a (NOT NULL) -+ * -+ * Requires: labels be fully constructed with a valid ns -+ * -+ * Returns: ref counted label that is equiv to merge of @a and @b -+ * else NULL if merge of @a and @b is not in set -+ */ -+struct aa_label *aa_label_find_merge(struct aa_label *a, struct aa_label *b) -+{ -+ struct aa_labelset *ls; -+ struct aa_label *label, *ar = NULL, *br = NULL; -+ unsigned long flags; -+ -+ AA_BUG(!a); -+ AA_BUG(!b); -+ -+ if (label_is_stale(a)) -+ a = ar = aa_get_newest_label(a); -+ if (label_is_stale(b)) -+ b = br = aa_get_newest_label(b); -+ ls = labelset_of_merge(a, b); -+ read_lock_irqsave(&ls->lock, flags); -+ label = __label_find_merge(ls, a, b); -+ read_unlock_irqrestore(&ls->lock, flags); -+ aa_put_label(ar); -+ aa_put_label(br); -+ -+ return label; -+} -+ -+/** -+ * aa_label_merge - attempt to insert new merged label of @a and @b -+ * @ls: set of labels to insert label into (NOT NULL) -+ * @a: label to merge with @b (NOT NULL) -+ * @b: label to merge with @a (NOT NULL) -+ * @gfp: memory allocation type -+ * -+ * Requires: caller to hold valid refs on @a and @b -+ * labels be fully constructed with a valid ns -+ * -+ * Returns: ref counted new label if successful in inserting merge of a & b -+ * else ref counted equivalent label that is already in the set. -+ * else NULL if could not create label (-ENOMEM) -+ */ -+struct aa_label *aa_label_merge(struct aa_label *a, struct aa_label *b, -+ gfp_t gfp) -+{ -+ struct aa_label *label = NULL; -+ -+ AA_BUG(!a); -+ AA_BUG(!b); -+ -+ if (a == b) -+ return aa_get_newest_label(a); -+ -+ /* TODO: enable when read side is lockless -+ * check if label exists before taking locks -+ if (!label_is_stale(a) && !label_is_stale(b)) -+ label = aa_label_find_merge(a, b); -+ */ -+ -+ if (!label) { -+ struct aa_label *new; -+ -+ a = aa_get_newest_label(a); -+ b = aa_get_newest_label(b); -+ -+ /* could use label_merge_len(a, b), but requires double -+ * comparison for small savings -+ */ -+ new = aa_label_alloc(a->size + b->size, NULL, gfp); -+ if (!new) -+ goto out; -+ -+ label = label_merge_insert(new, a, b); -+ label_free_or_put_new(label, new); -+out: -+ aa_put_label(a); -+ aa_put_label(b); -+ } -+ -+ return label; -+} -+ -+static inline bool label_is_visible(struct aa_profile *profile, -+ struct aa_label *label) -+{ -+ return aa_ns_visible(profile->ns, labels_ns(label), true); -+} -+ -+/* match a profile and its associated ns component if needed -+ * Assumes visibility test has already been done. -+ * If a subns profile is not to be matched should be prescreened with -+ * visibility test. -+ */ -+static inline unsigned int match_component(struct aa_profile *profile, -+ struct aa_profile *tp, -+ unsigned int state) -+{ -+ const char *ns_name; -+ -+ if (profile->ns == tp->ns) -+ return aa_dfa_match(profile->policy.dfa, state, tp->base.hname); -+ -+ /* try matching with namespace name and then profile */ -+ ns_name = aa_ns_name(profile->ns, tp->ns, true); -+ state = aa_dfa_match_len(profile->policy.dfa, state, ":", 1); -+ state = aa_dfa_match(profile->policy.dfa, state, ns_name); -+ state = aa_dfa_match_len(profile->policy.dfa, state, ":", 1); -+ return aa_dfa_match(profile->policy.dfa, state, tp->base.hname); -+} -+ -+/** -+ * label_compound_match - find perms for full compound label -+ * @profile: profile to find perms for -+ * @label: label to check access permissions for -+ * @start: state to start match in -+ * @subns: whether to do permission checks on components in a subns -+ * @request: permissions to request -+ * @perms: perms struct to set -+ * -+ * Returns: 0 on success else ERROR -+ * -+ * For the label A//&B//&C this does the perm match for A//&B//&C -+ * @perms should be preinitialized with allperms OR a previous permission -+ * check to be stacked. -+ */ -+static int label_compound_match(struct aa_profile *profile, -+ struct aa_label *label, -+ unsigned int state, bool subns, u32 request, -+ struct aa_perms *perms) -+{ -+ struct aa_profile *tp; -+ struct label_it i; -+ -+ /* find first subcomponent that is visible */ -+ label_for_each(i, label, tp) { -+ if (!aa_ns_visible(profile->ns, tp->ns, subns)) -+ continue; -+ state = match_component(profile, tp, state); -+ if (!state) -+ goto fail; -+ goto next; -+ } -+ -+ /* no component visible */ -+ *perms = allperms; -+ return 0; -+ -+next: -+ label_for_each_cont(i, label, tp) { -+ if (!aa_ns_visible(profile->ns, tp->ns, subns)) -+ continue; -+ state = aa_dfa_match(profile->policy.dfa, state, "//&"); -+ state = match_component(profile, tp, state); -+ if (!state) -+ goto fail; -+ } -+ aa_compute_perms(profile->policy.dfa, state, perms); -+ aa_apply_modes_to_perms(profile, perms); -+ if ((perms->allow & request) != request) -+ return -EACCES; -+ -+ return 0; -+ -+fail: -+ *perms = nullperms; -+ return state; -+} -+ -+/** -+ * label_components_match - find perms for all subcomponents of a label -+ * @profile: profile to find perms for -+ * @label: label to check access permissions for -+ * @start: state to start match in -+ * @subns: whether to do permission checks on components in a subns -+ * @request: permissions to request -+ * @perms: an initialized perms struct to add accumulation to -+ * -+ * Returns: 0 on success else ERROR -+ * -+ * For the label A//&B//&C this does the perm match for each of A and B and C -+ * @perms should be preinitialized with allperms OR a previous permission -+ * check to be stacked. -+ */ -+static int label_components_match(struct aa_profile *profile, -+ struct aa_label *label, unsigned int start, -+ bool subns, u32 request, -+ struct aa_perms *perms) -+{ -+ struct aa_profile *tp; -+ struct label_it i; -+ struct aa_perms tmp; -+ unsigned int state = 0; -+ -+ /* find first subcomponent to test */ -+ label_for_each(i, label, tp) { -+ if (!aa_ns_visible(profile->ns, tp->ns, subns)) -+ continue; -+ state = match_component(profile, tp, start); -+ if (!state) -+ goto fail; -+ goto next; -+ } -+ -+ /* no subcomponents visible - no change in perms */ -+ return 0; -+ -+next: -+ aa_compute_perms(profile->policy.dfa, state, &tmp); -+ aa_apply_modes_to_perms(profile, &tmp); -+ aa_perms_accum(perms, &tmp); -+ label_for_each_cont(i, label, tp) { -+ if (!aa_ns_visible(profile->ns, tp->ns, subns)) -+ continue; -+ state = match_component(profile, tp, start); -+ if (!state) -+ goto fail; -+ aa_compute_perms(profile->policy.dfa, state, &tmp); -+ aa_apply_modes_to_perms(profile, &tmp); -+ aa_perms_accum(perms, &tmp); -+ } -+ -+ if ((perms->allow & request) != request) -+ return -EACCES; -+ -+ return 0; -+ -+fail: -+ *perms = nullperms; -+ return -EACCES; -+} -+ -+/** -+ * aa_label_match - do a multi-component label match -+ * @profile: profile to match against (NOT NULL) -+ * @label: label to match (NOT NULL) -+ * @state: state to start in -+ * @subns: whether to match subns components -+ * @request: permission request -+ * @perms: Returns computed perms (NOT NULL) -+ * -+ * Returns: the state the match finished in, may be the none matching state -+ */ -+int aa_label_match(struct aa_profile *profile, struct aa_label *label, -+ unsigned int state, bool subns, u32 request, -+ struct aa_perms *perms) -+{ -+ int error = label_compound_match(profile, label, state, subns, request, -+ perms); -+ if (!error) -+ return error; -+ -+ *perms = allperms; -+ return label_components_match(profile, label, state, subns, request, -+ perms); -+} -+ -+ -+/** -+ * aa_update_label_name - update a label to have a stored name -+ * @ns: ns being viewed from (NOT NULL) -+ * @label: label to update (NOT NULL) -+ * @gfp: type of memory allocation -+ * -+ * Requires: labels_set(label) not locked in caller -+ * -+ * note: only updates the label name if it does not have a name already -+ * and if it is in the labelset -+ */ -+bool aa_update_label_name(struct aa_ns *ns, struct aa_label *label, gfp_t gfp) -+{ -+ struct aa_labelset *ls; -+ unsigned long flags; -+ char __counted *name; -+ bool res = false; -+ -+ AA_BUG(!ns); -+ AA_BUG(!label); -+ -+ if (label->hname || labels_ns(label) != ns) -+ return res; -+ -+ if (aa_label_acntsxprint(&name, ns, label, FLAGS_NONE, gfp) == -1) -+ return res; -+ -+ ls = labels_set(label); -+ write_lock_irqsave(&ls->lock, flags); -+ if (!label->hname && label->flags & FLAG_IN_TREE) { -+ label->hname = name; -+ res = true; -+ } else -+ aa_put_str(name); -+ write_unlock_irqrestore(&ls->lock, flags); -+ -+ return res; -+} -+ -+/* -+ * cached label name is present and visible -+ * @label->hname only exists if label is namespace hierachical -+ */ -+static inline bool use_label_hname(struct aa_ns *ns, struct aa_label *label) -+{ -+ if (label->hname && labels_ns(label) == ns) -+ return true; -+ -+ return false; -+} -+ -+/* helper macro for snprint routines */ -+#define update_for_len(total, len, size, str) \ -+do { \ -+ AA_BUG(len < 0); \ -+ total += len; \ -+ len = min(len, size); \ -+ size -= len; \ -+ str += len; \ -+} while (0) -+ -+/** -+ * aa_profile_snxprint - print a profile name to a buffer -+ * @str: buffer to write to. (MAY BE NULL if @size == 0) -+ * @size: size of buffer -+ * @view: namespace profile is being viewed from -+ * @profile: profile to view (NOT NULL) -+ * @flags: whether to include the mode string -+ * @prev_ns: last ns printed when used in compound print -+ * -+ * Returns: size of name written or would be written if larger than -+ * available buffer -+ * -+ * Note: will not print anything if the profile is not visible -+ */ -+static int aa_profile_snxprint(char *str, size_t size, struct aa_ns *view, -+ struct aa_profile *profile, int flags, -+ struct aa_ns **prev_ns) -+{ -+ const char *ns_name = NULL; -+ -+ AA_BUG(!str && size != 0); -+ AA_BUG(!profile); -+ -+ if (!view) -+ view = profiles_ns(profile); -+ -+ if (view != profile->ns && -+ (!prev_ns || (prev_ns && *prev_ns != profile->ns))) { -+ if (prev_ns) -+ *prev_ns = profile->ns; -+ ns_name = aa_ns_name(view, profile->ns, -+ flags & FLAG_VIEW_SUBNS); -+ if (ns_name == aa_hidden_ns_name) { -+ if (flags & FLAG_HIDDEN_UNCONFINED) -+ return snprintf(str, size, "%s", "unconfined"); -+ return snprintf(str, size, "%s", ns_name); -+ } -+ } -+ -+ if ((flags & FLAG_SHOW_MODE) && profile != profile->ns->unconfined) { -+ const char *modestr = aa_profile_mode_names[profile->mode]; -+ -+ if (ns_name) -+ return snprintf(str, size, ":%s:%s (%s)", ns_name, -+ profile->base.hname, modestr); -+ return snprintf(str, size, "%s (%s)", profile->base.hname, -+ modestr); -+ } -+ -+ if (ns_name) -+ return snprintf(str, size, ":%s:%s", ns_name, -+ profile->base.hname); -+ return snprintf(str, size, "%s", profile->base.hname); -+} -+ -+static const char *label_modename(struct aa_ns *ns, struct aa_label *label, -+ int flags) -+{ -+ struct aa_profile *profile; -+ struct label_it i; -+ int mode = -1, count = 0; -+ -+ label_for_each(i, label, profile) { -+ if (aa_ns_visible(ns, profile->ns, flags & FLAG_VIEW_SUBNS)) { -+ if (profile->mode == APPARMOR_UNCONFINED) -+ /* special case unconfined so stacks with -+ * unconfined don't report as mixed. ie. -+ * profile_foo//&:ns1:unconfined (mixed) -+ */ -+ continue; -+ count++; -+ if (mode == -1) -+ mode = profile->mode; -+ else if (mode != profile->mode) -+ return "mixed"; -+ } -+ } -+ -+ if (count == 0) -+ return "-"; -+ if (mode == -1) -+ /* everything was unconfined */ -+ mode = APPARMOR_UNCONFINED; -+ -+ return aa_profile_mode_names[mode]; -+} -+ -+/* if any visible label is not unconfined the display_mode returns true */ -+static inline bool display_mode(struct aa_ns *ns, struct aa_label *label, -+ int flags) -+{ -+ if ((flags & FLAG_SHOW_MODE)) { -+ struct aa_profile *profile; -+ struct label_it i; -+ -+ label_for_each(i, label, profile) { -+ if (aa_ns_visible(ns, profile->ns, -+ flags & FLAG_VIEW_SUBNS) && -+ profile != profile->ns->unconfined) -+ return true; -+ } -+ /* only ns->unconfined in set of profiles in ns */ -+ return false; -+ } -+ -+ return false; -+} -+ -+/** -+ * aa_label_snxprint - print a label name to a string buffer -+ * @str: buffer to write to. (MAY BE NULL if @size == 0) -+ * @size: size of buffer -+ * @ns: namespace profile is being viewed from -+ * @label: label to view (NOT NULL) -+ * @flags: whether to include the mode string -+ * -+ * Returns: size of name written or would be written if larger than -+ * available buffer -+ * -+ * Note: labels do not have to be strictly hierarchical to the ns as -+ * objects may be shared across different namespaces and thus -+ * pickup labeling from each ns. If a particular part of the -+ * label is not visible it will just be excluded. And if none -+ * of the label is visible "---" will be used. -+ */ -+int aa_label_snxprint(char *str, size_t size, struct aa_ns *ns, -+ struct aa_label *label, int flags) -+{ -+ struct aa_profile *profile; -+ struct aa_ns *prev_ns = NULL; -+ struct label_it i; -+ int count = 0, total = 0; -+ size_t len; -+ -+ AA_BUG(!str && size != 0); -+ AA_BUG(!label); -+ -+ if (!ns) -+ ns = labels_ns(label); -+ -+ label_for_each(i, label, profile) { -+ if (aa_ns_visible(ns, profile->ns, flags & FLAG_VIEW_SUBNS)) { -+ if (count > 0) { -+ len = snprintf(str, size, "//&"); -+ update_for_len(total, len, size, str); -+ } -+ len = aa_profile_snxprint(str, size, ns, profile, -+ flags & FLAG_VIEW_SUBNS, -+ &prev_ns); -+ update_for_len(total, len, size, str); -+ count++; -+ } -+ } -+ -+ if (count == 0) { -+ if (flags & FLAG_HIDDEN_UNCONFINED) -+ return snprintf(str, size, "%s", "unconfined"); -+ return snprintf(str, size, "%s", aa_hidden_ns_name); -+ } -+ -+ /* count == 1 && ... is for backwards compat where the mode -+ * is not displayed for 'unconfined' in the current ns -+ */ -+ if (display_mode(ns, label, flags)) { -+ len = snprintf(str, size, " (%s)", -+ label_modename(ns, label, flags)); -+ update_for_len(total, len, size, str); -+ } -+ -+ return total; -+} -+#undef update_for_len -+ -+/** -+ * aa_label_asxprint - allocate a string buffer and print label into it -+ * @strp: Returns - the allocated buffer with the label name. (NOT NULL) -+ * @ns: namespace profile is being viewed from -+ * @label: label to view (NOT NULL) -+ * @flags: flags controlling what label info is printed -+ * @gfp: kernel memory allocation type -+ * -+ * Returns: size of name written or would be written if larger than -+ * available buffer -+ */ -+int aa_label_asxprint(char **strp, struct aa_ns *ns, struct aa_label *label, -+ int flags, gfp_t gfp) -+{ -+ int size; -+ -+ AA_BUG(!strp); -+ AA_BUG(!label); -+ -+ size = aa_label_snxprint(NULL, 0, ns, label, flags); -+ if (size < 0) -+ return size; -+ -+ *strp = kmalloc(size + 1, gfp); -+ if (!*strp) -+ return -ENOMEM; -+ return aa_label_snxprint(*strp, size + 1, ns, label, flags); -+} -+ -+/** -+ * aa_label_acntsxprint - allocate a __counted string buffer and print label -+ * @strp: buffer to write to. (MAY BE NULL if @size == 0) -+ * @ns: namespace profile is being viewed from -+ * @label: label to view (NOT NULL) -+ * @flags: flags controlling what label info is printed -+ * @gfp: kernel memory allocation type -+ * -+ * Returns: size of name written or would be written if larger than -+ * available buffer -+ */ -+int aa_label_acntsxprint(char __counted **strp, struct aa_ns *ns, -+ struct aa_label *label, int flags, gfp_t gfp) -+{ -+ int size; -+ -+ AA_BUG(!strp); -+ AA_BUG(!label); -+ -+ size = aa_label_snxprint(NULL, 0, ns, label, flags); -+ if (size < 0) -+ return size; -+ -+ *strp = aa_str_alloc(size + 1, gfp); -+ if (!*strp) -+ return -ENOMEM; -+ return aa_label_snxprint(*strp, size + 1, ns, label, flags); -+} -+ -+ -+void aa_label_xaudit(struct audit_buffer *ab, struct aa_ns *ns, -+ struct aa_label *label, int flags, gfp_t gfp) -+{ -+ const char *str; -+ char *name = NULL; -+ int len; -+ -+ AA_BUG(!ab); -+ AA_BUG(!label); -+ -+ if (!ns) -+ ns = labels_ns(label); -+ -+ if (!use_label_hname(ns, label) || display_mode(ns, label, flags)) { -+ len = aa_label_asxprint(&name, ns, label, flags, gfp); -+ if (len == -1) { -+ AA_DEBUG("label print error"); -+ return; -+ } -+ str = name; -+ } else { -+ str = (char *) label->hname; -+ len = strlen(str); -+ } -+ if (audit_string_contains_control(str, len)) -+ audit_log_n_hex(ab, str, len); -+ else -+ audit_log_n_string(ab, str, len); -+ -+ kfree(name); -+} -+ -+void aa_label_seq_xprint(struct seq_file *f, struct aa_ns *ns, -+ struct aa_label *label, int flags, gfp_t gfp) -+{ -+ AA_BUG(!f); -+ AA_BUG(!label); -+ -+ if (!ns) -+ ns = labels_ns(label); -+ -+ if (!use_label_hname(ns, label)) { -+ char *str; -+ int len; -+ -+ len = aa_label_asxprint(&str, ns, label, flags, gfp); -+ if (len == -1) { -+ AA_DEBUG("label print error"); -+ return; -+ } -+ seq_printf(f, "%s", str); -+ kfree(str); -+ } else if (display_mode(ns, label, flags)) -+ seq_printf(f, "%s (%s)", label->hname, -+ label_modename(ns, label, flags)); -+ else -+ seq_printf(f, "%s", label->hname); -+} -+ -+void aa_label_xprintk(struct aa_ns *ns, struct aa_label *label, int flags, -+ gfp_t gfp) -+{ -+ AA_BUG(!label); -+ -+ if (!ns) -+ ns = labels_ns(label); -+ -+ if (!use_label_hname(ns, label)) { -+ char *str; -+ int len; -+ -+ len = aa_label_asxprint(&str, ns, label, flags, gfp); -+ if (len == -1) { -+ AA_DEBUG("label print error"); -+ return; -+ } -+ pr_info("%s", str); -+ kfree(str); -+ } else if (display_mode(ns, label, flags)) -+ pr_info("%s (%s)", label->hname, -+ label_modename(ns, label, flags)); -+ else -+ pr_info("%s", label->hname); -+} -+ -+void aa_label_audit(struct audit_buffer *ab, struct aa_label *label, gfp_t gfp) -+{ -+ struct aa_ns *ns = aa_get_current_ns(); -+ -+ aa_label_xaudit(ab, ns, label, FLAG_VIEW_SUBNS, gfp); -+ aa_put_ns(ns); -+} -+ -+void aa_label_seq_print(struct seq_file *f, struct aa_label *label, gfp_t gfp) -+{ -+ struct aa_ns *ns = aa_get_current_ns(); -+ -+ aa_label_seq_xprint(f, ns, label, FLAG_VIEW_SUBNS, gfp); -+ aa_put_ns(ns); -+} -+ -+void aa_label_printk(struct aa_label *label, gfp_t gfp) -+{ -+ struct aa_ns *ns = aa_get_current_ns(); -+ -+ aa_label_xprintk(ns, label, FLAG_VIEW_SUBNS, gfp); -+ aa_put_ns(ns); -+} -+ -+static int label_count_str_entries(const char *str) -+{ -+ const char *split; -+ int count = 1; -+ -+ AA_BUG(!str); -+ -+ for (split = strstr(str, "//&"); split; split = strstr(str, "//&")) { -+ count++; -+ str = split + 3; -+ } -+ -+ return count; -+} -+ -+/* -+ * ensure stacks with components like -+ * :ns:A//&B -+ * have :ns: applied to both 'A' and 'B' by making the lookup relative -+ * to the base if the lookup specifies an ns, else making the stacked lookup -+ * relative to the last embedded ns in the string. -+ */ -+static struct aa_profile *fqlookupn_profile(struct aa_label *base, -+ struct aa_label *currentbase, -+ const char *str, size_t n) -+{ -+ const char *first = skipn_spaces(str, n); -+ -+ if (first && *first == ':') -+ return aa_fqlookupn_profile(base, str, n); -+ -+ return aa_fqlookupn_profile(currentbase, str, n); -+} -+ -+/** -+ * aa_label_parse - parse, validate and convert a text string to a label -+ * @base: base label to use for lookups (NOT NULL) -+ * @str: null terminated text string (NOT NULL) -+ * @gfp: allocation type -+ * @create: true if should create compound labels if they don't exist -+ * @force_stack: true if should stack even if no leading & -+ * -+ * Returns: the matching refcounted label if present -+ * else ERRPTR -+ */ -+struct aa_label *aa_label_parse(struct aa_label *base, const char *str, -+ gfp_t gfp, bool create, bool force_stack) -+{ -+ DEFINE_VEC(profile, vec); -+ struct aa_label *label, *currbase = base; -+ int i, len, stack = 0, error; -+ char *split; -+ -+ AA_BUG(!base); -+ AA_BUG(!str); -+ -+ str = skip_spaces(str); -+ len = label_count_str_entries(str); -+ if (*str == '&' || force_stack) { -+ /* stack on top of base */ -+ stack = base->size; -+ len += stack; -+ if (*str == '&') -+ str++; -+ } -+ error = vec_setup(profile, vec, len, gfp); -+ if (error) -+ return ERR_PTR(error); -+ -+ for (i = 0; i < stack; i++) -+ vec[i] = aa_get_profile(base->vec[i]); -+ -+ for (split = strstr(str, "//&"), i = stack; split && i < len; i++) { -+ vec[i] = fqlookupn_profile(base, currbase, str, split - str); -+ if (!vec[i]) -+ goto fail; -+ /* -+ * if component specified a new ns it becomes the new base -+ * so that subsequent lookups are relative to it -+ */ -+ if (vec[i]->ns != labels_ns(currbase)) -+ currbase = &vec[i]->label; -+ str = split + 3; -+ split = strstr(str, "//&"); -+ } -+ /* last element doesn't have a split */ -+ if (i < len) { -+ vec[i] = fqlookupn_profile(base, currbase, str, strlen(str)); -+ if (!vec[i]) -+ goto fail; -+ } -+ if (len == 1) -+ /* no need to free vec as len < LOCAL_VEC_ENTRIES */ -+ return &vec[0]->label; -+ -+ len -= aa_vec_unique(vec, len, VEC_FLAG_TERMINATE); -+ /* TODO: deal with reference labels */ -+ if (len == 1) { -+ label = aa_get_label(&vec[0]->label); -+ goto out; -+ } -+ -+ if (create) -+ label = aa_vec_find_or_create_label(vec, len, gfp); -+ else -+ label = vec_find(vec, len); -+ if (!label) -+ goto fail; -+ -+out: -+ /* use adjusted len from after vec_unique, not original */ -+ vec_cleanup(profile, vec, len); -+ return label; -+ -+fail: -+ label = ERR_PTR(-ENOENT); -+ goto out; -+} -+ -+ -+/** -+ * aa_labelset_destroy - remove all labels from the label set -+ * @ls: label set to cleanup (NOT NULL) -+ * -+ * Labels that are removed from the set may still exist beyond the set -+ * being destroyed depending on their reference counting -+ */ -+void aa_labelset_destroy(struct aa_labelset *ls) -+{ -+ struct rb_node *node; -+ unsigned long flags; -+ -+ AA_BUG(!ls); -+ -+ write_lock_irqsave(&ls->lock, flags); -+ for (node = rb_first(&ls->root); node; node = rb_first(&ls->root)) { -+ struct aa_label *this = rb_entry(node, struct aa_label, node); -+ -+ if (labels_ns(this) != root_ns) -+ __label_remove(this, -+ ns_unconfined(labels_ns(this)->parent)); -+ else -+ __label_remove(this, NULL); -+ } -+ write_unlock_irqrestore(&ls->lock, flags); -+} -+ -+/* -+ * @ls: labelset to init (NOT NULL) -+ */ -+void aa_labelset_init(struct aa_labelset *ls) -+{ -+ AA_BUG(!ls); -+ -+ rwlock_init(&ls->lock); -+ ls->root = RB_ROOT; -+} -+ -+static struct aa_label *labelset_next_stale(struct aa_labelset *ls) -+{ -+ struct aa_label *label; -+ struct rb_node *node; -+ unsigned long flags; -+ -+ AA_BUG(!ls); -+ -+ read_lock_irqsave(&ls->lock, flags); -+ -+ __labelset_for_each(ls, node) { -+ label = rb_entry(node, struct aa_label, node); -+ if ((label_is_stale(label) || -+ vec_is_stale(label->vec, label->size)) && -+ __aa_get_label(label)) -+ goto out; -+ -+ } -+ label = NULL; -+ -+out: -+ read_unlock_irqrestore(&ls->lock, flags); -+ -+ return label; -+} -+ -+/** -+ * __label_update - insert updated version of @label into labelset -+ * @label - the label to update/repace -+ * -+ * Returns: new label that is up to date -+ * else NULL on failure -+ * -+ * Requires: @ns lock be held -+ * -+ * Note: worst case is the stale @label does not get updated and has -+ * to be updated at a later time. -+ */ -+static struct aa_label *__label_update(struct aa_label *label) -+{ -+ struct aa_label *new, *tmp; -+ struct aa_labelset *ls; -+ unsigned long flags; -+ int i, invcount = 0; -+ -+ AA_BUG(!label); -+ AA_BUG(!mutex_is_locked(&labels_ns(label)->lock)); -+ -+ new = aa_label_alloc(label->size, label->proxy, GFP_KERNEL); -+ if (!new) -+ return NULL; -+ -+ /* -+ * while holding the ns_lock will stop profile replacement, removal, -+ * and label updates, label merging and removal can be occurring -+ */ -+ ls = labels_set(label); -+ write_lock_irqsave(&ls->lock, flags); -+ for (i = 0; i < label->size; i++) { -+ AA_BUG(!label->vec[i]); -+ new->vec[i] = aa_get_newest_profile(label->vec[i]); -+ AA_BUG(!new->vec[i]); -+ AA_BUG(!new->vec[i]->label.proxy); -+ AA_BUG(!new->vec[i]->label.proxy->label); -+ if (new->vec[i]->label.proxy != label->vec[i]->label.proxy) -+ invcount++; -+ } -+ -+ /* updated stale label by being removed/renamed from labelset */ -+ if (invcount) { -+ new->size -= aa_vec_unique(&new->vec[0], new->size, -+ VEC_FLAG_TERMINATE); -+ /* TODO: deal with reference labels */ -+ if (new->size == 1) { -+ tmp = aa_get_label(&new->vec[0]->label); -+ AA_BUG(tmp == label); -+ goto remove; -+ } -+ if (labels_set(label) != labels_set(new)) { -+ write_unlock_irqrestore(&ls->lock, flags); -+ tmp = aa_label_insert(labels_set(new), new); -+ write_lock_irqsave(&ls->lock, flags); -+ goto remove; -+ } -+ } else -+ AA_BUG(labels_ns(label) != labels_ns(new)); -+ -+ tmp = __label_insert(labels_set(label), new, true); -+remove: -+ /* ensure label is removed, and redirected correctly */ -+ __label_remove(label, tmp); -+ write_unlock_irqrestore(&ls->lock, flags); -+ label_free_or_put_new(tmp, new); -+ -+ return tmp; -+} -+ -+/** -+ * __labelset_update - update labels in @ns -+ * @ns: namespace to update labels in (NOT NULL) -+ * -+ * Requires: @ns lock be held -+ * -+ * Walk the labelset ensuring that all labels are up to date and valid -+ * Any label that has a stale component is marked stale and replaced and -+ * by an updated version. -+ * -+ * If failures happen due to memory pressures then stale labels will -+ * be left in place until the next pass. -+ */ -+static void __labelset_update(struct aa_ns *ns) -+{ -+ struct aa_label *label; -+ -+ AA_BUG(!ns); -+ AA_BUG(!mutex_is_locked(&ns->lock)); -+ -+ do { -+ label = labelset_next_stale(&ns->labels); -+ if (label) { -+ struct aa_label *l = __label_update(label); -+ -+ aa_put_label(l); -+ aa_put_label(label); -+ } -+ } while (label); -+} -+ -+/** -+ * __aa_labelset_udate_subtree - update all labels with a stale component -+ * @ns: ns to start update at (NOT NULL) -+ * -+ * Requires: @ns lock be held -+ * -+ * Invalidates labels based on @p in @ns and any children namespaces. -+ */ -+void __aa_labelset_update_subtree(struct aa_ns *ns) -+{ -+ struct aa_ns *child; -+ -+ AA_BUG(!ns); -+ AA_BUG(!mutex_is_locked(&ns->lock)); -+ -+ __labelset_update(ns); -+ -+ list_for_each_entry(child, &ns->sub_ns, base.list) { -+ mutex_lock(&child->lock); -+ __aa_labelset_update_subtree(child); -+ mutex_unlock(&child->lock); -+ } -+} --- -2.12.3 - diff --git a/patches.apparmor/0044-apparmor-switch-from-profiles-to-using-labels-on-con.patch b/patches.apparmor/0044-apparmor-switch-from-profiles-to-using-labels-on-con.patch deleted file mode 100644 index 0bc217d..0000000 --- a/patches.apparmor/0044-apparmor-switch-from-profiles-to-using-labels-on-con.patch +++ /dev/null @@ -1,2908 +0,0 @@ -From b8091427b679f9536316bca6a61ba747226b7ada Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Fri, 9 Jun 2017 08:14:28 -0700 -Subject: [PATCH 44/65] apparmor: switch from profiles to using labels on - contexts -Git-commit: 637f688dc3dc304a89f441d76f49a0e35bc49c08 -Patch-mainline: v4.13-rc1 -References: FATE#323500 - -Begin the actual switch to using domain labels by storing them on -the context and converting the label to a singular profile where -possible. - -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/Makefile | 2 +- - security/apparmor/apparmorfs.c | 128 +++++++++++---------- - security/apparmor/audit.c | 27 +++-- - security/apparmor/context.c | 87 +++++++------- - security/apparmor/domain.c | 77 +++++++------ - security/apparmor/file.c | 18 +-- - security/apparmor/include/apparmor.h | 5 +- - security/apparmor/include/audit.h | 9 +- - security/apparmor/include/context.h | 158 +++++++++++++------------- - security/apparmor/include/perms.h | 12 +- - security/apparmor/include/policy.h | 110 ++++++------------ - security/apparmor/include/policy_ns.h | 4 + - security/apparmor/ipc.c | 29 +++-- - security/apparmor/lib.c | 163 ++++++++++++++++++++++++++ - security/apparmor/lsm.c | 134 ++++++++++++---------- - security/apparmor/policy.c | 208 +++++++++++++++------------------- - security/apparmor/policy_ns.c | 20 +++- - security/apparmor/policy_unpack.c | 12 +- - security/apparmor/procattr.c | 4 +- - security/apparmor/resource.c | 8 +- - 20 files changed, 686 insertions(+), 529 deletions(-) - -diff --git a/security/apparmor/Makefile b/security/apparmor/Makefile -index b3e7c04b7e7b..a16b195274de 100644 ---- a/security/apparmor/Makefile -+++ b/security/apparmor/Makefile -@@ -4,7 +4,7 @@ obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o - - apparmor-y := apparmorfs.o audit.o capability.o context.o ipc.o lib.o match.o \ - path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \ -- resource.o secid.o file.o policy_ns.o -+ resource.o secid.o file.o policy_ns.o label.o - apparmor-$(CONFIG_SECURITY_APPARMOR_HASH) += crypto.o - - clean-files := capability_names.h rlim_names.h -diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c -index e2919a0766b0..976af6da45c3 100644 ---- a/security/apparmor/apparmorfs.c -+++ b/security/apparmor/apparmorfs.c -@@ -405,26 +405,26 @@ static struct aa_loaddata *aa_simple_write_to_buffer(const char __user *userbuf, - static ssize_t policy_update(u32 mask, const char __user *buf, size_t size, - loff_t *pos, struct aa_ns *ns) - { -- ssize_t error; - struct aa_loaddata *data; -- struct aa_profile *profile; -+ struct aa_label *label; -+ ssize_t error; - -- profile = begin_current_profile_crit_section(); -+ label = begin_current_label_crit_section(); - - /* high level check about policy management - fine grained in - * below after unpack - */ -- error = aa_may_manage_policy(profile, ns, mask); -+ error = aa_may_manage_policy(label, ns, mask); - if (error) - return error; - - data = aa_simple_write_to_buffer(buf, size, size, pos); - error = PTR_ERR(data); - if (!IS_ERR(data)) { -- error = aa_replace_profiles(ns, profile, mask, data); -+ error = aa_replace_profiles(ns, label, mask, data); - aa_put_loaddata(data); - } -- end_current_profile_crit_section(profile); -+ end_current_label_crit_section(label); - - return error; - } -@@ -468,15 +468,15 @@ static ssize_t profile_remove(struct file *f, const char __user *buf, - size_t size, loff_t *pos) - { - struct aa_loaddata *data; -- struct aa_profile *profile; -+ struct aa_label *label; - ssize_t error; - struct aa_ns *ns = aa_get_ns(f->f_inode->i_private); - -- profile = begin_current_profile_crit_section(); -+ label = begin_current_label_crit_section(); - /* high level check about policy management - fine grained in - * below after unpack - */ -- error = aa_may_manage_policy(profile, ns, AA_MAY_REMOVE_POLICY); -+ error = aa_may_manage_policy(label, ns, AA_MAY_REMOVE_POLICY); - if (error) - goto out; - -@@ -489,11 +489,11 @@ static ssize_t profile_remove(struct file *f, const char __user *buf, - error = PTR_ERR(data); - if (!IS_ERR(data)) { - data->data[size] = 0; -- error = aa_remove_profiles(ns, profile, data->data, size); -+ error = aa_remove_profiles(ns, label, data->data, size); - aa_put_loaddata(data); - } - out: -- end_current_profile_crit_section(profile); -+ end_current_label_crit_section(label); - aa_put_ns(ns); - return error; - } -@@ -605,7 +605,7 @@ static void profile_query_cb(struct aa_profile *profile, struct aa_perms *perms, - struct aa_dfa *dfa; - unsigned int state = 0; - -- if (unconfined(profile)) -+ if (profile_unconfined(profile)) - return; - if (profile->file.dfa && *match_str == AA_CLASS_FILE) { - dfa = profile->file.dfa; -@@ -655,7 +655,7 @@ static ssize_t query_data(char *buf, size_t buf_len, - { - char *out; - const char *key; -- struct aa_profile *profile, *curr; -+ struct aa_label *label, *curr; - struct aa_data *data; - u32 bytes, blocks; - __le32 outle32; -@@ -672,11 +672,11 @@ static ssize_t query_data(char *buf, size_t buf_len, - if (buf_len < sizeof(bytes) + sizeof(blocks)) - return -EINVAL; /* not enough space */ - -- curr = begin_current_profile_crit_section(); -- profile = aa_fqlookupn_profile(curr, query, strnlen(query, query_len)); -- end_current_profile_crit_section(curr); -- if (!profile) -- return -ENOENT; -+ curr = begin_current_label_crit_section(); -+ label = aa_label_parse(curr, query, GFP_KERNEL, false, false); -+ end_current_label_crit_section(curr); -+ if (IS_ERR(label)) -+ return PTR_ERR(label); - - /* We are going to leave space for two numbers. The first is the total - * number of bytes we are writing after the first number. This is so -@@ -690,13 +690,16 @@ static ssize_t query_data(char *buf, size_t buf_len, - out = buf + sizeof(bytes) + sizeof(blocks); - - blocks = 0; -- if (profile->data) { -- data = rhashtable_lookup_fast(profile->data, &key, -- profile->data->p); -+ if (labels_profile(label)->data) { -+ data = rhashtable_lookup_fast(labels_profile(label)->data, &key, -+ labels_profile(label)->data->p); - - if (data) { -- if (out + sizeof(outle32) + data->size > buf + buf_len) -+ if (out + sizeof(outle32) + data->size > -+ buf + buf_len) { -+ aa_put_label(label); - return -EINVAL; /* not enough space */ -+ } - outle32 = __cpu_to_le32(data->size); - memcpy(out, &outle32, sizeof(outle32)); - out += sizeof(outle32); -@@ -705,7 +708,7 @@ static ssize_t query_data(char *buf, size_t buf_len, - blocks++; - } - } -- aa_put_profile(profile); -+ aa_put_label(label); - - outle32 = __cpu_to_le32(out - buf - sizeof(bytes)); - memcpy(buf, &outle32, sizeof(outle32)); -@@ -738,7 +741,7 @@ static ssize_t query_data(char *buf, size_t buf_len, - static ssize_t query_label(char *buf, size_t buf_len, - char *query, size_t query_len, bool view_only) - { -- struct aa_profile *profile, *curr; -+ struct aa_label *label, *curr; - char *label_name, *match_str; - size_t label_name_len, match_len; - struct aa_perms perms; -@@ -760,14 +763,14 @@ static ssize_t query_label(char *buf, size_t buf_len, - match_str = label_name + label_name_len + 1; - match_len = query_len - label_name_len - 1; - -- curr = begin_current_profile_crit_section(); -- profile = aa_fqlookupn_profile(curr, label_name, label_name_len); -- end_current_profile_crit_section(curr); -- if (!profile) -- return -ENOENT; -+ curr = begin_current_label_crit_section(); -+ label = aa_label_parse(curr, label_name, GFP_KERNEL, false, false); -+ end_current_label_crit_section(curr); -+ if (IS_ERR(label)) -+ return PTR_ERR(label); - - perms = allperms; -- profile_query_cb(profile, &perms, match_str, match_len); -+ profile_query_cb(labels_profile(label), &perms, match_str, match_len); - - return scnprintf(buf, buf_len, - "allow 0x%08x\ndeny 0x%08x\naudit 0x%08x\nquiet 0x%08x\n", -@@ -1026,9 +1029,10 @@ static int seq_profile_release(struct inode *inode, struct file *file) - static int seq_profile_name_show(struct seq_file *seq, void *v) - { - struct aa_proxy *proxy = seq->private; -- struct aa_profile *profile = aa_get_profile_rcu(&proxy->profile); -+ struct aa_label *label = aa_get_label_rcu(&proxy->label); -+ struct aa_profile *profile = labels_profile(label); - seq_printf(seq, "%s\n", profile->base.name); -- aa_put_profile(profile); -+ aa_put_label(label); - - return 0; - } -@@ -1036,9 +1040,10 @@ static int seq_profile_name_show(struct seq_file *seq, void *v) - static int seq_profile_mode_show(struct seq_file *seq, void *v) - { - struct aa_proxy *proxy = seq->private; -- struct aa_profile *profile = aa_get_profile_rcu(&proxy->profile); -+ struct aa_label *label = aa_get_label_rcu(&proxy->label); -+ struct aa_profile *profile = labels_profile(label); - seq_printf(seq, "%s\n", aa_profile_mode_names[profile->mode]); -- aa_put_profile(profile); -+ aa_put_label(label); - - return 0; - } -@@ -1046,14 +1051,15 @@ static int seq_profile_mode_show(struct seq_file *seq, void *v) - static int seq_profile_attach_show(struct seq_file *seq, void *v) - { - struct aa_proxy *proxy = seq->private; -- struct aa_profile *profile = aa_get_profile_rcu(&proxy->profile); -+ struct aa_label *label = aa_get_label_rcu(&proxy->label); -+ struct aa_profile *profile = labels_profile(label); - if (profile->attach) - seq_printf(seq, "%s\n", profile->attach); - else if (profile->xmatch) - seq_puts(seq, "\n"); - else - seq_printf(seq, "%s\n", profile->base.name); -- aa_put_profile(profile); -+ aa_put_label(label); - - return 0; - } -@@ -1061,7 +1067,8 @@ static int seq_profile_attach_show(struct seq_file *seq, void *v) - static int seq_profile_hash_show(struct seq_file *seq, void *v) - { - struct aa_proxy *proxy = seq->private; -- struct aa_profile *profile = aa_get_profile_rcu(&proxy->profile); -+ struct aa_label *label = aa_get_label_rcu(&proxy->label); -+ struct aa_profile *profile = labels_profile(label); - unsigned int i, size = aa_hash_size(); - - if (profile->hash) { -@@ -1069,7 +1076,7 @@ static int seq_profile_hash_show(struct seq_file *seq, void *v) - seq_printf(seq, "%.2x", profile->hash[i]); - seq_putc(seq, '\n'); - } -- aa_put_profile(profile); -+ aa_put_label(label); - - return 0; - } -@@ -1101,22 +1108,22 @@ static const struct file_operations seq_ns_ ##NAME ##_fops = { \ - - static int seq_ns_level_show(struct seq_file *seq, void *v) - { -- struct aa_profile *profile; -+ struct aa_label *label; - -- profile = begin_current_profile_crit_section(); -- seq_printf(seq, "%d\n", profile->ns->level); -- end_current_profile_crit_section(profile); -+ label = begin_current_label_crit_section(); -+ seq_printf(seq, "%d\n", labels_ns(label)->level); -+ end_current_label_crit_section(label); - - return 0; - } - - static int seq_ns_name_show(struct seq_file *seq, void *v) - { -- struct aa_profile *profile; -+ struct aa_label *label = begin_current_label_crit_section(); - -- profile = begin_current_profile_crit_section(); -- seq_printf(seq, "%s\n", aa_ns_name(profile->ns, profile->ns, true)); -- end_current_profile_crit_section(profile); -+ seq_printf(seq, "%s\n", aa_ns_name(labels_ns(label), -+ labels_ns(label), true)); -+ end_current_label_crit_section(label); - - return 0; - } -@@ -1380,7 +1387,7 @@ static struct dentry *create_profile_file(struct dentry *dir, const char *name, - struct aa_profile *profile, - const struct file_operations *fops) - { -- struct aa_proxy *proxy = aa_get_proxy(profile->proxy); -+ struct aa_proxy *proxy = aa_get_proxy(profile->label.proxy); - struct dentry *dent; - - dent = aafs_create_file(name, S_IFREG | 0444, dir, proxy, fops); -@@ -1541,9 +1548,12 @@ static int ns_mkdir_op(struct inode *dir, struct dentry *dentry, umode_t mode) - { - struct aa_ns *ns, *parent; - /* TODO: improve permission check */ -- struct aa_profile *profile = begin_current_profile_crit_section(); -- int error = aa_may_manage_policy(profile, NULL, AA_MAY_LOAD_POLICY); -- end_current_profile_crit_section(profile); -+ struct aa_label *label; -+ int error; -+ -+ label = begin_current_label_crit_section(); -+ error = aa_may_manage_policy(label, NULL, AA_MAY_LOAD_POLICY); -+ end_current_label_crit_section(label); - if (error) - return error; - -@@ -1587,13 +1597,16 @@ static int ns_rmdir_op(struct inode *dir, struct dentry *dentry) - { - struct aa_ns *ns, *parent; - /* TODO: improve permission check */ -- struct aa_profile *profile = begin_current_profile_crit_section(); -- int error = aa_may_manage_policy(profile, NULL, AA_MAY_LOAD_POLICY); -- end_current_profile_crit_section(profile); -+ struct aa_label *label; -+ int error; -+ -+ label = begin_current_label_crit_section(); -+ error = aa_may_manage_policy(label, NULL, AA_MAY_LOAD_POLICY); -+ end_current_label_crit_section(label); - if (error) - return error; - -- parent = aa_get_ns(dir->i_private); -+ parent = aa_get_ns(dir->i_private); - /* rmdir calls the generic securityfs functions to remove files - * from the apparmor dir. It is up to the apparmor ns locking - * to avoid races. -@@ -1999,10 +2012,9 @@ static int seq_show_profile(struct seq_file *f, void *p) - struct aa_profile *profile = (struct aa_profile *)p; - struct aa_ns *root = f->private; - -- if (profile->ns != root) -- seq_printf(f, ":%s://", aa_ns_name(root, profile->ns, true)); -- seq_printf(f, "%s (%s)\n", profile->base.hname, -- aa_profile_mode_names[profile->mode]); -+ aa_label_seq_xprint(f, root, &profile->label, -+ FLAG_SHOW_MODE | FLAG_VIEW_SUBNS, GFP_KERNEL); -+ seq_putc(f, '\n'); - - return 0; - } -diff --git a/security/apparmor/audit.c b/security/apparmor/audit.c -index 87f40fa8c431..8f9ecac7f8de 100644 ---- a/security/apparmor/audit.c -+++ b/security/apparmor/audit.c -@@ -77,14 +77,24 @@ static void audit_pre(struct audit_buffer *ab, void *ca) - audit_log_format(ab, " error=%d", aad(sa)->error); - } - -- if (aad(sa)->profile) { -- struct aa_profile *profile = aad(sa)->profile; -- if (profile->ns != root_ns) { -- audit_log_format(ab, " namespace="); -- audit_log_untrustedstring(ab, profile->ns->base.hname); -+ if (aad(sa)->label) { -+ struct aa_label *label = aad(sa)->label; -+ -+ if (label_isprofile(label)) { -+ struct aa_profile *profile = labels_profile(label); -+ -+ if (profile->ns != root_ns) { -+ audit_log_format(ab, " namespace="); -+ audit_log_untrustedstring(ab, -+ profile->ns->base.hname); -+ } -+ audit_log_format(ab, " profile="); -+ audit_log_untrustedstring(ab, profile->base.hname); -+ } else { -+ audit_log_format(ab, " label="); -+ aa_label_xaudit(ab, root_ns, label, FLAG_VIEW_SUBNS, -+ GFP_ATOMIC); - } -- audit_log_format(ab, " profile="); -- audit_log_untrustedstring(ab, profile->base.hname); - } - - if (aad(sa)->name) { -@@ -139,8 +149,7 @@ int aa_audit(int type, struct aa_profile *profile, struct common_audit_data *sa, - if (KILL_MODE(profile) && type == AUDIT_APPARMOR_DENIED) - type = AUDIT_APPARMOR_KILL; - -- if (!unconfined(profile)) -- aad(sa)->profile = profile; -+ aad(sa)->label = &profile->label; - - aa_audit_msg(type, sa, cb); - -diff --git a/security/apparmor/context.c b/security/apparmor/context.c -index 410b9f7f68a1..c95f1ac6190b 100644 ---- a/security/apparmor/context.c -+++ b/security/apparmor/context.c -@@ -14,9 +14,9 @@ - * - * - * AppArmor sets confinement on every task, via the the aa_task_ctx and -- * the aa_task_ctx.profile, both of which are required and are not allowed -+ * the aa_task_ctx.label, both of which are required and are not allowed - * to be NULL. The aa_task_ctx is not reference counted and is unique -- * to each cred (which is reference count). The profile pointed to by -+ * to each cred (which is reference count). The label pointed to by - * the task_ctx is reference counted. - * - * TODO -@@ -47,9 +47,9 @@ struct aa_task_ctx *aa_alloc_task_context(gfp_t flags) - void aa_free_task_context(struct aa_task_ctx *ctx) - { - if (ctx) { -- aa_put_profile(ctx->profile); -- aa_put_profile(ctx->previous); -- aa_put_profile(ctx->onexec); -+ aa_put_label(ctx->label); -+ aa_put_label(ctx->previous); -+ aa_put_label(ctx->onexec); - - kzfree(ctx); - } -@@ -63,41 +63,41 @@ void aa_free_task_context(struct aa_task_ctx *ctx) - void aa_dup_task_context(struct aa_task_ctx *new, const struct aa_task_ctx *old) - { - *new = *old; -- aa_get_profile(new->profile); -- aa_get_profile(new->previous); -- aa_get_profile(new->onexec); -+ aa_get_label(new->label); -+ aa_get_label(new->previous); -+ aa_get_label(new->onexec); - } - - /** -- * aa_get_task_profile - Get another task's profile -+ * aa_get_task_label - Get another task's label - * @task: task to query (NOT NULL) - * -- * Returns: counted reference to @task's profile -+ * Returns: counted reference to @task's label - */ --struct aa_profile *aa_get_task_profile(struct task_struct *task) -+struct aa_label *aa_get_task_label(struct task_struct *task) - { -- struct aa_profile *p; -+ struct aa_label *p; - - rcu_read_lock(); -- p = aa_get_newest_profile(__aa_task_raw_profile(task)); -+ p = aa_get_newest_label(__aa_task_raw_label(task)); - rcu_read_unlock(); - - return p; - } - - /** -- * aa_replace_current_profile - replace the current tasks profiles -- * @profile: new profile (NOT NULL) -+ * aa_replace_current_label - replace the current tasks label -+ * @label: new label (NOT NULL) - * - * Returns: 0 or error on failure - */ --int aa_replace_current_profile(struct aa_profile *profile) -+int aa_replace_current_label(struct aa_label *label) - { - struct aa_task_ctx *ctx = current_ctx(); - struct cred *new; -- AA_BUG(!profile); -+ AA_BUG(!label); - -- if (ctx->profile == profile) -+ if (ctx->label == label) - return 0; - - if (current_cred() != current_real_cred()) -@@ -108,8 +108,8 @@ int aa_replace_current_profile(struct aa_profile *profile) - return -ENOMEM; - - ctx = cred_ctx(new); -- if (unconfined(profile) || (ctx->profile->ns != profile->ns)) -- /* if switching to unconfined or a different profile namespace -+ if (unconfined(label) || (labels_ns(ctx->label) != labels_ns(label))) -+ /* if switching to unconfined or a different label namespace - * clear out context state - */ - aa_clear_task_ctx_trans(ctx); -@@ -120,9 +120,9 @@ int aa_replace_current_profile(struct aa_profile *profile) - * keeping @profile valid, so make sure to get its reference before - * dropping the reference on ctx->profile - */ -- aa_get_profile(profile); -- aa_put_profile(ctx->profile); -- ctx->profile = profile; -+ aa_get_label(label); -+ aa_put_label(ctx->label); -+ ctx->label = label; - - commit_creds(new); - return 0; -@@ -130,11 +130,11 @@ int aa_replace_current_profile(struct aa_profile *profile) - - /** - * aa_set_current_onexec - set the tasks change_profile to happen onexec -- * @profile: system profile to set at exec (MAYBE NULL to clear value) -- * -+ * @label: system label to set at exec (MAYBE NULL to clear value) -+ * @stack: whether stacking should be done - * Returns: 0 or error on failure - */ --int aa_set_current_onexec(struct aa_profile *profile) -+int aa_set_current_onexec(struct aa_label *label, bool stack) - { - struct aa_task_ctx *ctx; - struct cred *new = prepare_creds(); -@@ -142,9 +142,10 @@ int aa_set_current_onexec(struct aa_profile *profile) - return -ENOMEM; - - ctx = cred_ctx(new); -- aa_get_profile(profile); -- aa_put_profile(ctx->onexec); -- ctx->onexec = profile; -+ aa_get_label(label); -+ aa_clear_task_ctx_trans(ctx); -+ ctx->onexec = label; -+ ctx->token = stack; - - commit_creds(new); - return 0; -@@ -152,7 +153,7 @@ int aa_set_current_onexec(struct aa_profile *profile) - - /** - * aa_set_current_hat - set the current tasks hat -- * @profile: profile to set as the current hat (NOT NULL) -+ * @label: label to set as the current hat (NOT NULL) - * @token: token value that must be specified to change from the hat - * - * Do switch of tasks hat. If the task is currently in a hat -@@ -160,29 +161,29 @@ int aa_set_current_onexec(struct aa_profile *profile) - * - * Returns: 0 or error on failure - */ --int aa_set_current_hat(struct aa_profile *profile, u64 token) -+int aa_set_current_hat(struct aa_label *label, u64 token) - { - struct aa_task_ctx *ctx; - struct cred *new = prepare_creds(); - if (!new) - return -ENOMEM; -- AA_BUG(!profile); -+ AA_BUG(!label); - - ctx = cred_ctx(new); - if (!ctx->previous) { - /* transfer refcount */ -- ctx->previous = ctx->profile; -+ ctx->previous = ctx->label; - ctx->token = token; - } else if (ctx->token == token) { -- aa_put_profile(ctx->profile); -+ aa_put_label(ctx->label); - } else { - /* previous_profile && ctx->token != token */ - abort_creds(new); - return -EACCES; - } -- ctx->profile = aa_get_newest_profile(profile); -+ ctx->label = aa_get_newest_label(label); - /* clear exec on switching context */ -- aa_put_profile(ctx->onexec); -+ aa_put_label(ctx->onexec); - ctx->onexec = NULL; - - commit_creds(new); -@@ -190,15 +191,15 @@ int aa_set_current_hat(struct aa_profile *profile, u64 token) - } - - /** -- * aa_restore_previous_profile - exit from hat context restoring the profile -+ * aa_restore_previous_label - exit from hat context restoring previous label - * @token: the token that must be matched to exit hat context - * -- * Attempt to return out of a hat to the previous profile. The token -+ * Attempt to return out of a hat to the previous label. The token - * must match the stored token value. - * - * Returns: 0 or error of failure - */ --int aa_restore_previous_profile(u64 token) -+int aa_restore_previous_label(u64 token) - { - struct aa_task_ctx *ctx; - struct cred *new = prepare_creds(); -@@ -210,15 +211,15 @@ int aa_restore_previous_profile(u64 token) - abort_creds(new); - return -EACCES; - } -- /* ignore restores when there is no saved profile */ -+ /* ignore restores when there is no saved label */ - if (!ctx->previous) { - abort_creds(new); - return 0; - } - -- aa_put_profile(ctx->profile); -- ctx->profile = aa_get_newest_profile(ctx->previous); -- AA_BUG(!ctx->profile); -+ aa_put_label(ctx->label); -+ ctx->label = aa_get_newest_label(ctx->previous); -+ AA_BUG(!ctx->label); - /* clear exec && prev information when restoring to previous context */ - aa_clear_task_ctx_trans(ctx); - -diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c -index 2ec4ae029215..8d6797c849fe 100644 ---- a/security/apparmor/domain.c -+++ b/security/apparmor/domain.c -@@ -61,24 +61,25 @@ void aa_free_domain_entries(struct aa_domain *domain) - static int may_change_ptraced_domain(struct aa_profile *to_profile) - { - struct task_struct *tracer; -- struct aa_profile *tracerp = NULL; -+ struct aa_label *tracerl = NULL; - int error = 0; - - rcu_read_lock(); - tracer = ptrace_parent(current); - if (tracer) - /* released below */ -- tracerp = aa_get_task_profile(tracer); -+ tracerl = aa_get_task_label(tracer); - - /* not ptraced */ -- if (!tracer || unconfined(tracerp)) -+ if (!tracer || unconfined(tracerl)) - goto out; - -- error = aa_may_ptrace(tracerp, to_profile, PTRACE_MODE_ATTACH); -+ error = aa_may_ptrace(labels_profile(tracerl), to_profile, -+ PTRACE_MODE_ATTACH); - - out: - rcu_read_unlock(); -- aa_put_profile(tracerp); -+ aa_put_label(tracerl); - - return error; - } -@@ -102,7 +103,7 @@ static struct aa_perms change_profile_perms(struct aa_profile *profile, - struct path_cond cond = { }; - unsigned int state; - -- if (unconfined(profile)) { -+ if (profile_unconfined(profile)) { - perms.allow = AA_MAY_CHANGE_PROFILE | AA_MAY_ONEXEC; - perms.audit = perms.quiet = perms.kill = 0; - return perms; -@@ -144,7 +145,7 @@ static struct aa_profile *__attach_match(const char *name, - struct aa_profile *profile, *candidate = NULL; - - list_for_each_entry_rcu(profile, head, base.list) { -- if (profile->flags & PFLAG_NULL) -+ if (profile->label.flags & FLAG_NULL) - continue; - if (profile->xmatch && profile->xmatch_len > len) { - unsigned int state = aa_dfa_match(profile->xmatch, -@@ -338,6 +339,7 @@ static struct aa_profile *x_to_profile(struct aa_profile *profile, - int apparmor_bprm_set_creds(struct linux_binprm *bprm) - { - struct aa_task_ctx *ctx; -+ struct aa_label *label; - struct aa_profile *profile, *new_profile = NULL; - struct aa_ns *ns; - char *buffer = NULL; -@@ -356,7 +358,8 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm) - ctx = cred_ctx(bprm->cred); - AA_BUG(!ctx); - -- profile = aa_get_newest_profile(ctx->profile); -+ label = aa_get_newest_label(ctx->label); -+ profile = labels_profile(label); - - /* buffer freed below, name is pointer into buffer */ - get_buffers(buffer); -@@ -370,8 +373,8 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm) - error = aa_path_name(&bprm->file->f_path, profile->path_flags, buffer, - &name, &info, profile->disconnected); - if (error) { -- if (unconfined(profile) || -- (profile->flags & PFLAG_IX_ON_NAME_ERROR)) -+ if (profile_unconfined(profile) || -+ (profile->label.flags & FLAG_IX_ON_NAME_ERROR)) - error = 0; - name = bprm->filename; - goto audit; -@@ -380,11 +383,11 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm) - /* Test for onexec first as onexec directives override other - * x transitions. - */ -- if (unconfined(profile)) { -+ if (profile_unconfined(profile)) { - /* unconfined task */ - if (ctx->onexec) - /* change_profile on exec already been granted */ -- new_profile = aa_get_profile(ctx->onexec); -+ new_profile = labels_profile(aa_get_label(ctx->onexec)); - else - new_profile = find_attach(ns, &ns->base.profiles, name); - if (!new_profile) -@@ -402,7 +405,7 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm) - if (ctx->onexec) { - struct aa_perms cp; - info = "change_profile onexec"; -- new_profile = aa_get_newest_profile(ctx->onexec); -+ new_profile = labels_profile(aa_get_newest_label(ctx->onexec)); - if (!(perms.allow & AA_MAY_ONEXEC)) - goto audit; - -@@ -411,9 +414,9 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm) - * exec\0change_profile - */ - state = aa_dfa_null_transition(profile->file.dfa, state); -- cp = change_profile_perms(profile, ctx->onexec->ns, -- ctx->onexec->base.name, -- AA_MAY_ONEXEC, state); -+ cp = change_profile_perms(profile, labels_ns(ctx->onexec), -+ labels_profile(ctx->onexec)->base.name, -+ AA_MAY_ONEXEC, state); - - if (!(cp.allow & AA_MAY_ONEXEC)) - goto audit; -@@ -501,9 +504,9 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm) - bprm->per_clear |= PER_CLEAR_ON_SETID; - - x_clear: -- aa_put_profile(ctx->profile); -+ aa_put_label(ctx->label); - /* transfer new profile reference will be released when ctx is freed */ -- ctx->profile = new_profile; -+ ctx->label = &new_profile->label; - new_profile = NULL; - - /* clear out all temporary/transitional state from the context */ -@@ -516,7 +519,7 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm) - - cleanup: - aa_put_profile(new_profile); -- aa_put_profile(profile); -+ aa_put_label(label); - put_buffers(buffer); - - return error; -@@ -576,7 +579,8 @@ int aa_change_hat(const char *hats[], int count, u64 token, int flags) - { - const struct cred *cred; - struct aa_task_ctx *ctx; -- struct aa_profile *profile, *previous_profile, *hat = NULL; -+ struct aa_label *label, *previous_label; -+ struct aa_profile *profile, *hat = NULL; - char *name = NULL; - int i; - struct aa_perms perms = {}; -@@ -594,10 +598,11 @@ int aa_change_hat(const char *hats[], int count, u64 token, int flags) - /* released below */ - cred = get_current_cred(); - ctx = cred_ctx(cred); -- profile = aa_get_newest_cred_profile(cred); -- previous_profile = aa_get_newest_profile(ctx->previous); -+ label = aa_get_newest_cred_label(cred); -+ previous_label = aa_get_newest_label(ctx->previous); -+ profile = labels_profile(label); - -- if (unconfined(profile)) { -+ if (unconfined(label)) { - info = "unconfined"; - error = -EPERM; - goto audit; -@@ -664,7 +669,7 @@ int aa_change_hat(const char *hats[], int count, u64 token, int flags) - } - - if (!(flags & AA_CHANGE_TEST)) { -- error = aa_set_current_hat(hat, token); -+ error = aa_set_current_hat(&hat->label, token); - if (error == -EACCES) - /* kill task in case of brute force attacks */ - perms.kill = AA_MAY_CHANGEHAT; -@@ -672,12 +677,12 @@ int aa_change_hat(const char *hats[], int count, u64 token, int flags) - /* reset error for learning of new hats */ - error = -ENOENT; - } -- } else if (previous_profile) { -+ } else if (previous_label) { - /* Return to saved profile. Kill task if restore fails - * to avoid brute force attacks - */ -- target = previous_profile->base.hname; -- error = aa_restore_previous_profile(token); -+ target = previous_label->hname; -+ error = aa_restore_previous_label(token); - perms.kill = AA_MAY_CHANGEHAT; - } else - /* ignore restores when there is no saved profile */ -@@ -692,8 +697,8 @@ int aa_change_hat(const char *hats[], int count, u64 token, int flags) - out: - aa_put_profile(hat); - kfree(name); -- aa_put_profile(profile); -- aa_put_profile(previous_profile); -+ aa_put_label(label); -+ aa_put_label(previous_label); - put_cred(cred); - - return error; -@@ -716,6 +721,7 @@ int aa_change_hat(const char *hats[], int count, u64 token, int flags) - int aa_change_profile(const char *fqname, int flags) - { - const struct cred *cred; -+ struct aa_label *label; - struct aa_profile *profile, *target = NULL; - struct aa_perms perms = {}; - const char *info = NULL, *op; -@@ -736,7 +742,8 @@ int aa_change_profile(const char *fqname, int flags) - } - - cred = get_current_cred(); -- profile = aa_get_newest_cred_profile(cred); -+ label = aa_get_newest_cred_label(cred); -+ profile = labels_profile(label); - - /* - * Fail explicitly requested domain transitions if no_new_privs -@@ -745,12 +752,12 @@ int aa_change_profile(const char *fqname, int flags) - * no_new_privs is set because this aways results in a reduction - * of permissions. - */ -- if (task_no_new_privs(current) && !unconfined(profile)) { -+ if (task_no_new_privs(current) && !profile_unconfined(profile)) { - put_cred(cred); - return -EPERM; - } - -- target = aa_fqlookupn_profile(profile, fqname, strlen(fqname)); -+ target = aa_fqlookupn_profile(label, fqname, strlen(fqname)); - if (!target) { - info = "profile not found"; - error = -ENOENT; -@@ -785,9 +792,9 @@ int aa_change_profile(const char *fqname, int flags) - goto audit; - - if (flags & AA_CHANGE_ONEXEC) -- error = aa_set_current_onexec(target); -+ error = aa_set_current_onexec(&target->label, 0); - else -- error = aa_replace_current_profile(target); -+ error = aa_replace_current_label(&target->label); - - audit: - if (!(flags & AA_CHANGE_TEST)) -@@ -795,7 +802,7 @@ int aa_change_profile(const char *fqname, int flags) - fqname, GLOBAL_ROOT_UID, info, error); - - aa_put_profile(target); -- aa_put_profile(profile); -+ aa_put_label(label); - put_cred(cred); - - return error; -diff --git a/security/apparmor/file.c b/security/apparmor/file.c -index bf508791cc1f..5289c8db832b 100644 ---- a/security/apparmor/file.c -+++ b/security/apparmor/file.c -@@ -451,7 +451,7 @@ int aa_file_perm(const char *op, struct aa_profile *profile, struct file *file, - request, &cond); - } - --static void revalidate_tty(struct aa_profile *profile) -+static void revalidate_tty(struct aa_label *label) - { - struct tty_struct *tty; - int drop_tty = 0; -@@ -469,7 +469,7 @@ static void revalidate_tty(struct aa_profile *profile) - struct tty_file_private, list); - file = file_priv->file; - -- if (aa_file_perm(OP_INHERIT, profile, file, -+ if (aa_file_perm(OP_INHERIT, labels_profile(label), file, - MAY_READ | MAY_WRITE)) - drop_tty = 1; - } -@@ -482,9 +482,9 @@ static void revalidate_tty(struct aa_profile *profile) - - static int match_file(const void *p, struct file *file, unsigned int fd) - { -- struct aa_profile *profile = (struct aa_profile *)p; -+ struct aa_label *label = (struct aa_label *)p; - -- if (aa_file_perm(OP_INHERIT, profile, file, -+ if (aa_file_perm(OP_INHERIT, labels_profile(label), file, - aa_map_file_to_perms(file))) - return fd + 1; - return 0; -@@ -494,14 +494,14 @@ static int match_file(const void *p, struct file *file, unsigned int fd) - /* based on selinux's flush_unauthorized_files */ - void aa_inherit_files(const struct cred *cred, struct files_struct *files) - { -- struct aa_profile *profile = aa_get_newest_cred_profile(cred); -+ struct aa_label *label = aa_get_newest_cred_label(cred); - struct file *devnull = NULL; - unsigned int n; - -- revalidate_tty(profile); -+ revalidate_tty(label); - - /* Revalidate access to inherited open files. */ -- n = iterate_fd(files, 0, match_file, profile); -+ n = iterate_fd(files, 0, match_file, label); - if (!n) /* none found? */ - goto out; - -@@ -511,9 +511,9 @@ void aa_inherit_files(const struct cred *cred, struct files_struct *files) - /* replace all the matching ones with this */ - do { - replace_fd(n - 1, devnull, 0); -- } while ((n = iterate_fd(files, n, match_file, profile)) != 0); -+ } while ((n = iterate_fd(files, n, match_file, label)) != 0); - if (devnull) - fput(devnull); - out: -- aa_put_profile(profile); -+ aa_put_label(label); - } -diff --git a/security/apparmor/include/apparmor.h b/security/apparmor/include/apparmor.h -index 1750cc0721c1..c4a900488e76 100644 ---- a/security/apparmor/include/apparmor.h -+++ b/security/apparmor/include/apparmor.h -@@ -4,7 +4,7 @@ - * This file contains AppArmor basic global - * - * Copyright (C) 1998-2008 Novell/SUSE -- * Copyright 2009-2010 Canonical Ltd. -+ * Copyright 2009-2017 Canonical Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as -@@ -27,8 +27,9 @@ - #define AA_CLASS_NET 4 - #define AA_CLASS_RLIMITS 5 - #define AA_CLASS_DOMAIN 6 -+#define AA_CLASS_LABEL 16 - --#define AA_CLASS_LAST AA_CLASS_DOMAIN -+#define AA_CLASS_LAST AA_CLASS_LABEL - - /* Control parameters settable through module/boot flags */ - extern enum audit_mode aa_g_audit; -diff --git a/security/apparmor/include/audit.h b/security/apparmor/include/audit.h -index d548261dd1b7..20fa6c77db05 100644 ---- a/security/apparmor/include/audit.h -+++ b/security/apparmor/include/audit.h -@@ -22,8 +22,7 @@ - #include - - #include "file.h" -- --struct aa_profile; -+#include "label.h" - - extern const char *const audit_mode_names[]; - #define AUDIT_MAX_INDEX 5 -@@ -103,9 +102,9 @@ enum audit_type { - - struct apparmor_audit_data { - int error; -- const char *op; - int type; -- void *profile; -+ const char *op; -+ struct aa_label *label; - const char *name; - const char *info; - u32 request; -@@ -113,7 +112,7 @@ struct apparmor_audit_data { - union { - /* these entries require a custom callback fn */ - struct { -- struct aa_profile *peer; -+ struct aa_label *peer; - struct { - const char *target; - kuid_t ouid; -diff --git a/security/apparmor/include/context.h b/security/apparmor/include/context.h -index 7665fae7131f..6ae07e9aaa17 100644 ---- a/security/apparmor/include/context.h -+++ b/security/apparmor/include/context.h -@@ -19,7 +19,7 @@ - #include - #include - --#include "policy.h" -+#include "label.h" - #include "policy_ns.h" - - #define cred_ctx(X) ((X)->security) -@@ -27,20 +27,20 @@ - - /** - * struct aa_task_ctx - primary label for confined tasks -- * @profile: the current profile (NOT NULL) -- * @exec: profile to transition to on next exec (MAYBE NULL) -- * @previous: profile the task may return to (MAYBE NULL) -- * @token: magic value the task must know for returning to @previous_profile -+ * @label: the current label (NOT NULL) -+ * @exec: label to transition to on next exec (MAYBE NULL) -+ * @previous: label the task may return to (MAYBE NULL) -+ * @token: magic value the task must know for returning to @previous - * -- * Contains the task's current profile (which could change due to -+ * Contains the task's current label (which could change due to - * change_hat). Plus the hat_magic needed during change_hat. - * - * TODO: make so a task can be confined by a stack of contexts - */ - struct aa_task_ctx { -- struct aa_profile *profile; -- struct aa_profile *onexec; -- struct aa_profile *previous; -+ struct aa_label *label; -+ struct aa_label *onexec; -+ struct aa_label *previous; - u64 token; - }; - -@@ -48,52 +48,51 @@ struct aa_task_ctx *aa_alloc_task_context(gfp_t flags); - void aa_free_task_context(struct aa_task_ctx *ctx); - void aa_dup_task_context(struct aa_task_ctx *new, - const struct aa_task_ctx *old); --int aa_replace_current_profile(struct aa_profile *profile); --int aa_set_current_onexec(struct aa_profile *profile); --int aa_set_current_hat(struct aa_profile *profile, u64 token); --int aa_restore_previous_profile(u64 cookie); --struct aa_profile *aa_get_task_profile(struct task_struct *task); -+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_cred_raw_profile - obtain cred's profiles -- * @cred: cred to obtain profiles from (NOT NULL) -+ * aa_cred_raw_label - obtain cred's label -+ * @cred: cred to obtain label from (NOT NULL) - * -- * Returns: confining profile -+ * Returns: confining label - * - * does NOT increment reference count - */ --static inline struct aa_profile *aa_cred_raw_profile(const struct cred *cred) -+static inline struct aa_label *aa_cred_raw_label(const struct cred *cred) - { - struct aa_task_ctx *ctx = cred_ctx(cred); - -- AA_BUG(!ctx || !ctx->profile); -- return ctx->profile; -+ AA_BUG(!ctx || !ctx->label); -+ return ctx->label; - } - - /** -- * aa_get_newest_cred_profile - obtain the newest profile on a cred -- * @cred: cred to obtain profile from (NOT NULL) -+ * 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 profile -+ * Returns: newest version of confining label - */ --static inline --struct aa_profile *aa_get_newest_cred_profile(const struct cred *cred) -+static inline struct aa_label *aa_get_newest_cred_label(const struct cred *cred) - { -- return aa_get_newest_profile(aa_cred_raw_profile(cred)); -+ return aa_get_newest_label(aa_cred_raw_label(cred)); - } - - /** -- * __aa_task_raw_profile - retrieve another task's profile -+ * __aa_task_raw_label - retrieve another task's label - * @task: task to query (NOT NULL) - * -- * Returns: @task's profile without incrementing its ref count -+ * 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_profile *__aa_task_raw_profile(struct task_struct *task) -+static inline struct aa_label *__aa_task_raw_label(struct task_struct *task) - { -- return aa_cred_raw_profile(__task_cred(task)); -+ return aa_cred_raw_label(__task_cred(task)); - } - - /** -@@ -104,113 +103,112 @@ static inline struct aa_profile *__aa_task_raw_profile(struct task_struct *task) - */ - static inline bool __aa_task_is_confined(struct task_struct *task) - { -- return !unconfined(__aa_task_raw_profile(task)); -+ return !unconfined(__aa_task_raw_label(task)); - } - - /** -- * aa_current_raw_profile - find the current tasks confining profile -+ * aa_current_raw_label - find the current tasks confining label - * -- * Returns: up to date confining profile or the ns unconfined profile (NOT NULL) -+ * 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 profile so it is safe to call when inside of locks. -+ * of the label so it is safe to call when inside of locks. - */ --static inline struct aa_profile *aa_current_raw_profile(void) -+static inline struct aa_label *aa_current_raw_label(void) - { -- return aa_cred_raw_profile(current_cred()); -+ return aa_cred_raw_label(current_cred()); - } - - /** -- * aa_get_current_profile - get the newest version of the current tasks profile -+ * aa_get_current_label - get the newest version of the current tasks label - * -- * Returns: newest version of confining profile (NOT NULL) -+ * 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_profile() -+ * The returned reference must be put with aa_put_label() - */ --static inline struct aa_profile *aa_get_current_profile(void) -+static inline struct aa_label *aa_get_current_label(void) - { -- struct aa_profile *p = aa_current_raw_profile(); -+ struct aa_label *l = aa_current_raw_label(); - -- if (profile_is_stale(p)) -- return aa_get_newest_profile(p); -- return aa_get_profile(p); -+ if (label_is_stale(l)) -+ return aa_get_newest_label(l); -+ return aa_get_label(l); - } - --#define __end_current_profile_crit_section(X) \ -- end_current_profile_crit_section(X) -+#define __end_current_label_crit_section(X) end_current_label_crit_section(X) - - /** -- * end_profile_crit_section - put a reference found with begin_current_profile.. -- * @profile: profile reference to put -+ * 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_profile_crit_section and never used in situations where the -+ * begin_current_label_crit_section and never used in situations where the - * task cred may be updated - */ --static inline void end_current_profile_crit_section(struct aa_profile *profile) -+static inline void end_current_label_crit_section(struct aa_label *label) - { -- if (profile != aa_current_raw_profile()) -- aa_put_profile(profile); -+ if (label != aa_current_raw_label()) -+ aa_put_label(label); - } - - /** -- * __begin_current_profile_crit_section - current's confining profile -+ * __begin_current_label_crit_section - current's confining label - * -- * Returns: up to date confining profile or the ns unconfined profile (NOT NULL) -+ * 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_profile_crit_section() -+ * 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_profile_crit_section() .. -- * __end_current_profile_crit_section() -+ * critical section between __begin_current_label_crit_section() .. -+ * __end_current_label_crit_section() - */ --static inline struct aa_profile *__begin_current_profile_crit_section(void) -+static inline struct aa_label *__begin_current_label_crit_section(void) - { -- struct aa_profile *profile = aa_current_raw_profile(); -+ struct aa_label *label = aa_current_raw_label(); - -- if (profile_is_stale(profile)) -- profile = aa_get_newest_profile(profile); -+ if (label_is_stale(label)) -+ label = aa_get_newest_label(label); - -- return profile; -+ return label; - } - - /** -- * begin_current_profile_crit_section - current's profile and update if needed -+ * begin_current_label_crit_section - current's confining label and update it - * -- * Returns: up to date confining profile or the ns unconfined profile (NOT NULL) -+ * 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_profile_crit_section() -+ * 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_profile_crit_section() .. -- * end_current_profile_crit_section() -+ * critical section between begin_current_label_crit_section() .. -+ * end_current_label_crit_section() - */ --static inline struct aa_profile *begin_current_profile_crit_section(void) -+static inline struct aa_label *begin_current_label_crit_section(void) - { -- struct aa_profile *profile = aa_current_raw_profile(); -+ struct aa_label *label = aa_current_raw_label(); - -- if (profile_is_stale(profile)) { -- profile = aa_get_newest_profile(profile); -- if (aa_replace_current_profile(profile) == 0) -+ 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_profile(profile); -+ aa_put_label(label); - } - -- return profile; -+ return label; - } - - static inline struct aa_ns *aa_get_current_ns(void) - { -- struct aa_profile *profile; -+ struct aa_label *label; - struct aa_ns *ns; - -- profile = __begin_current_profile_crit_section(); -- ns = aa_get_ns(profile->ns); -- __end_current_profile_crit_section(profile); -+ label = __begin_current_label_crit_section(); -+ ns = aa_get_ns(labels_ns(label)); -+ __end_current_label_crit_section(label); - - return ns; - } -@@ -221,8 +219,8 @@ static inline struct aa_ns *aa_get_current_ns(void) - */ - static inline void aa_clear_task_ctx_trans(struct aa_task_ctx *ctx) - { -- aa_put_profile(ctx->previous); -- aa_put_profile(ctx->onexec); -+ aa_put_label(ctx->previous); -+ aa_put_label(ctx->onexec); - ctx->previous = NULL; - ctx->onexec = NULL; - ctx->token = 0; -diff --git a/security/apparmor/include/perms.h b/security/apparmor/include/perms.h -index 82946fb81f91..0c5c2b00be02 100644 ---- a/security/apparmor/include/perms.h -+++ b/security/apparmor/include/perms.h -@@ -15,6 +15,7 @@ - #define __AA_PERM_H - - #include -+#include "label.h" - - #define AA_MAY_EXEC MAY_EXEC - #define AA_MAY_WRITE MAY_WRITE -@@ -101,5 +102,14 @@ 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 -index d93f475bfd8b..17fe41a9cac3 100644 ---- a/security/apparmor/include/policy.h -+++ b/security/apparmor/include/policy.h -@@ -29,6 +29,7 @@ - #include "domain.h" - #include "file.h" - #include "lib.h" -+#include "label.h" - #include "perms.h" - #include "resource.h" - -@@ -48,9 +49,9 @@ extern const char *const aa_profile_mode_names[]; - - #define KILL_MODE(_profile) PROFILE_MODE((_profile), APPARMOR_KILL) - --#define PROFILE_IS_HAT(_profile) ((_profile)->flags & PFLAG_HAT) -+#define PROFILE_IS_HAT(_profile) ((_profile)->label.flags & FLAG_HAT) - --#define profile_is_stale(_profile) ((_profile)->flags & PFLAG_STALE) -+#define profile_is_stale(_profile) (label_is_stale(&(_profile)->label)) - - #define on_list_rcu(X) (!list_empty(X) && (X)->prev != LIST_POISON2) - -@@ -67,22 +68,6 @@ enum profile_mode { - APPARMOR_UNCONFINED, /* profile set to unconfined */ - }; - --enum profile_flags { -- PFLAG_HAT = 1, /* profile is a hat */ -- PFLAG_NULL = 4, /* profile is null learning profile */ -- PFLAG_IX_ON_NAME_ERROR = 8, /* fallback to ix on name lookup fail */ -- PFLAG_IMMUTABLE = 0x10, /* don't allow changes/replacement */ -- PFLAG_USER_DEFINED = 0x20, /* user based profile - lower privs */ -- PFLAG_NO_LIST_REF = 0x40, /* list doesn't keep profile ref */ -- PFLAG_OLD_NULL_TRANS = 0x100, /* use // as the null transition */ -- PFLAG_STALE = 0x200, /* profile replaced/removed */ -- PFLAG_NS_COUNT = 0x400, /* carries NS ref count */ -- -- /* These flags must correspond with PATH_flags */ -- PFLAG_MEDIATE_DELETED = 0x10000, /* mediate instead delegate deleted */ --}; -- --struct aa_profile; - - /* struct aa_policydb - match engine for a policy - * dfa: dfa pattern match -@@ -95,11 +80,6 @@ struct aa_policydb { - - }; - --struct aa_proxy { -- struct kref count; -- struct aa_profile __rcu *profile; --}; -- - /* struct aa_data - generic data structure - * key: name for retrieving this data - * size: size of data in bytes -@@ -116,18 +96,15 @@ struct aa_data { - - /* struct aa_profile - basic confinement data - * @base - base components of the profile (name, refcount, lists, lock ...) -- * @count: reference count of the obj -- * @rcu: rcu head used when removing from @list -+ * @label - label this profile is an extension of - * @parent: parent of profile - * @ns: namespace the profile is in -- * @proxy: is set to the profile that replaced this profile - * @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 -- * @flags: flags controlling profile behavior - * @path_flags: flags controlling path generation behavior - * @disconnected: what to prepend if attach_disconnected is specified - * @size: the memory consumed by this profiles rules -@@ -145,8 +122,6 @@ struct aa_data { - * used to determine profile attachment against unconfined tasks. All other - * attachments are determined by profile X transition rules. - * -- * The @proxy struct is write protected by the profile lock. -- * - * Profiles have a hierarchy where hats and children profiles keep - * a reference to their parent. - * -@@ -156,12 +131,9 @@ struct aa_data { - */ - struct aa_profile { - struct aa_policy base; -- struct kref count; -- struct rcu_head rcu; - struct aa_profile __rcu *parent; - - struct aa_ns *ns; -- struct aa_proxy *proxy; - const char *rename; - - const char *attach; -@@ -169,7 +141,6 @@ struct aa_profile { - int xmatch_len; - enum audit_mode audit; - long mode; -- long flags; - u32 path_flags; - const char *disconnected; - int size; -@@ -184,6 +155,7 @@ struct aa_profile { - char *dirname; - struct dentry *dents[AAFS_PROF_SIZEOF]; - struct rhashtable *data; -+ struct aa_label label; - }; - - extern enum profile_mode aa_g_profile_mode; -@@ -192,13 +164,15 @@ extern enum profile_mode aa_g_profile_mode; - #define AA_MAY_REPLACE_POLICY AA_MAY_WRITE - #define AA_MAY_REMOVE_POLICY AA_MAY_DELETE - --void __aa_update_proxy(struct aa_profile *orig, struct aa_profile *new); -+#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, gfp_t gfp); -+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); -@@ -207,20 +181,33 @@ 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_profile *base, -+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_profile *profile, -+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_profile *profile, -- char *name, size_t size); -+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 unconfined(X) ((X)->mode == APPARMOR_UNCONFINED) -+#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)); -+} - - #define PROFILE_MEDIATES(P, T) ((P)->policy.start[(T)]) - /* safe version of POLICY_MEDIATES for full range input */ -@@ -243,7 +230,7 @@ static inline unsigned int PROFILE_MEDIATES_SAFE(struct aa_profile *profile, - static inline struct aa_profile *aa_get_profile(struct aa_profile *p) - { - if (p) -- kref_get(&(p->count)); -+ kref_get(&(p->label.count)); - - return p; - } -@@ -257,7 +244,7 @@ static inline struct aa_profile *aa_get_profile(struct aa_profile *p) - */ - static inline struct aa_profile *aa_get_profile_not0(struct aa_profile *p) - { -- if (p && kref_get_unless_zero(&p->count)) -+ if (p && kref_get_unless_zero(&p->label.count)) - return p; - - return NULL; -@@ -277,53 +264,20 @@ static inline struct aa_profile *aa_get_profile_rcu(struct aa_profile __rcu **p) - rcu_read_lock(); - do { - c = rcu_dereference(*p); -- } while (c && !kref_get_unless_zero(&c->count)); -+ } while (c && !kref_get_unless_zero(&c->label.count)); - rcu_read_unlock(); - - return c; - } - - /** -- * aa_get_newest_profile - find the newest version of @profile -- * @profile: the profile to check for newer versions of -- * -- * Returns: refcounted newest version of @profile taking into account -- * replacement, renames and removals -- * return @profile. -- */ --static inline struct aa_profile *aa_get_newest_profile(struct aa_profile *p) --{ -- if (!p) -- return NULL; -- -- if (profile_is_stale(p)) -- return aa_get_profile_rcu(&p->proxy->profile); -- -- return aa_get_profile(p); --} -- --/** - * 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->count, aa_free_profile_kref); --} -- --static inline struct aa_proxy *aa_get_proxy(struct aa_proxy *p) --{ -- if (p) -- kref_get(&(p->count)); -- -- return p; --} -- --static inline void aa_put_proxy(struct aa_proxy *p) --{ -- if (p) -- kref_put(&p->count, aa_free_proxy_kref); -+ kref_put(&p->label.count, aa_label_kref); - } - - static inline int AUDIT_MODE(struct aa_profile *profile) -@@ -336,7 +290,7 @@ static inline int AUDIT_MODE(struct aa_profile *profile) - - bool policy_view_capable(struct aa_ns *ns); - bool policy_admin_capable(struct aa_ns *ns); --int aa_may_manage_policy(struct aa_profile *profile, struct aa_ns *ns, -+int aa_may_manage_policy(struct aa_label *label, struct aa_ns *ns, - u32 mask); - - #endif /* __AA_POLICY_H */ -diff --git a/security/apparmor/include/policy_ns.h b/security/apparmor/include/policy_ns.h -index 2f7e480a34e0..9605f18624e2 100644 ---- a/security/apparmor/include/policy_ns.h -+++ b/security/apparmor/include/policy_ns.h -@@ -19,6 +19,7 @@ - - #include "apparmor.h" - #include "apparmorfs.h" -+#include "label.h" - #include "policy.h" - - -@@ -71,6 +72,7 @@ struct aa_ns { - long revision; - wait_queue_head_t wait; - -+ struct aa_labelset labels; - struct list_head rawdata_list; - - struct dentry *dents[AAFS_NS_SIZEOF]; -@@ -80,6 +82,8 @@ 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); -diff --git a/security/apparmor/ipc.c b/security/apparmor/ipc.c -index edac790923c3..fa68cd42bd15 100644 ---- a/security/apparmor/ipc.c -+++ b/security/apparmor/ipc.c -@@ -22,11 +22,12 @@ - #include "include/ipc.h" - - /* call back to audit ptrace fields */ --static void audit_cb(struct audit_buffer *ab, void *va) -+static void audit_ptrace_cb(struct audit_buffer *ab, void *va) - { - struct common_audit_data *sa = va; - audit_log_format(ab, " peer="); -- audit_log_untrustedstring(ab, aad(sa)->peer->base.hname); -+ aa_label_xaudit(ab, labels_ns(aad(sa)->label), aad(sa)->peer, -+ FLAGS_NONE, GFP_ATOMIC); - } - - /** -@@ -42,10 +43,10 @@ static int aa_audit_ptrace(struct aa_profile *profile, - { - DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, OP_PTRACE); - -- aad(&sa)->peer = target; -+ aad(&sa)->peer = &target->label; - aad(&sa)->error = error; - -- return aa_audit(AUDIT_APPARMOR_AUTO, profile, &sa, audit_cb); -+ return aa_audit(AUDIT_APPARMOR_AUTO, profile, &sa, audit_ptrace_cb); - } - - /** -@@ -64,7 +65,7 @@ int aa_may_ptrace(struct aa_profile *tracer, struct aa_profile *tracee, - * Test mode for PTRACE_MODE_READ || PTRACE_MODE_ATTACH - */ - -- if (unconfined(tracer) || tracer == tracee) -+ if (profile_unconfined(tracer) || tracer == tracee) - return 0; - /* log this capability request */ - return aa_capable(tracer, CAP_SYS_PTRACE, 1); -@@ -90,18 +91,22 @@ int aa_ptrace(struct task_struct *tracer, struct task_struct *tracee, - * - tracer profile has CAP_SYS_PTRACE - */ - -- struct aa_profile *tracer_p = aa_get_task_profile(tracer); -+ struct aa_label *tracer_l = aa_get_task_label(tracer); - int error = 0; - -- if (!unconfined(tracer_p)) { -- struct aa_profile *tracee_p = aa_get_task_profile(tracee); -+ if (!unconfined(tracer_l)) { -+ struct aa_label *tracee_l = aa_get_task_label(tracee); - -- error = aa_may_ptrace(tracer_p, tracee_p, mode); -- error = aa_audit_ptrace(tracer_p, tracee_p, error); -+ error = aa_may_ptrace(labels_profile(tracer_l), -+ labels_profile(tracee_l), -+ mode); -+ error = aa_audit_ptrace(labels_profile(tracer_l), -+ labels_profile(tracee_l), -+ error); - -- aa_put_profile(tracee_p); -+ aa_put_label(tracee_l); - } -- aa_put_profile(tracer_p); -+ aa_put_label(tracer_l); - - return error; - } -diff --git a/security/apparmor/lib.c b/security/apparmor/lib.c -index 0ceecdbb4658..08ca26bcca77 100644 ---- a/security/apparmor/lib.c -+++ b/security/apparmor/lib.c -@@ -247,6 +247,32 @@ void aa_audit_perm_mask(struct audit_buffer *ab, u32 mask, const char *chrs, - } - - /** -+ * aa_audit_perms_cb - generic callback fn for auditing perms -+ * @ab: audit buffer (NOT NULL) -+ * @va: audit struct to audit values of (NOT NULL) -+ */ -+static void aa_audit_perms_cb(struct audit_buffer *ab, void *va) -+{ -+ struct common_audit_data *sa = va; -+ -+ if (aad(sa)->request) { -+ audit_log_format(ab, " requested_mask="); -+ aa_audit_perm_mask(ab, aad(sa)->request, aa_file_perm_chrs, -+ PERMS_CHRS_MASK, aa_file_perm_names, -+ PERMS_NAMES_MASK); -+ } -+ if (aad(sa)->denied) { -+ audit_log_format(ab, "denied_mask="); -+ aa_audit_perm_mask(ab, aad(sa)->denied, aa_file_perm_chrs, -+ PERMS_CHRS_MASK, aa_file_perm_names, -+ PERMS_NAMES_MASK); -+ } -+ audit_log_format(ab, " peer="); -+ aa_label_xaudit(ab, labels_ns(aad(sa)->label), aad(sa)->peer, -+ FLAGS_NONE, GFP_ATOMIC); -+} -+ -+/** - * aa_apply_modes_to_perms - apply namespace and profile flags to perms - * @profile: that perms where computed from - * @perms: perms to apply mode modifiers to -@@ -310,6 +336,143 @@ void aa_compute_perms(struct aa_dfa *dfa, unsigned int state, - } - - /** -+ * aa_perms_accum_raw - accumulate perms with out masking off overlapping perms -+ * @accum - perms struct to accumulate into -+ * @addend - perms struct to add to @accum -+ */ -+void aa_perms_accum_raw(struct aa_perms *accum, struct aa_perms *addend) -+{ -+ accum->deny |= addend->deny; -+ accum->allow &= addend->allow & ~addend->deny; -+ accum->audit |= addend->audit & addend->allow; -+ accum->quiet &= addend->quiet & ~addend->allow; -+ accum->kill |= addend->kill & ~addend->allow; -+ accum->stop |= addend->stop & ~addend->allow; -+ accum->complain |= addend->complain & ~addend->allow & ~addend->deny; -+ accum->cond |= addend->cond & ~addend->allow & ~addend->deny; -+ accum->hide &= addend->hide & ~addend->allow; -+ accum->prompt |= addend->prompt & ~addend->allow & ~addend->deny; -+} -+ -+/** -+ * aa_perms_accum - accumulate perms, masking off overlapping perms -+ * @accum - perms struct to accumulate into -+ * @addend - perms struct to add to @accum -+ */ -+void aa_perms_accum(struct aa_perms *accum, struct aa_perms *addend) -+{ -+ accum->deny |= addend->deny; -+ accum->allow &= addend->allow & ~accum->deny; -+ accum->audit |= addend->audit & accum->allow; -+ accum->quiet &= addend->quiet & ~accum->allow; -+ accum->kill |= addend->kill & ~accum->allow; -+ accum->stop |= addend->stop & ~accum->allow; -+ accum->complain |= addend->complain & ~accum->allow & ~accum->deny; -+ accum->cond |= addend->cond & ~accum->allow & ~accum->deny; -+ accum->hide &= addend->hide & ~accum->allow; -+ accum->prompt |= addend->prompt & ~accum->allow & ~accum->deny; -+} -+ -+void aa_profile_match_label(struct aa_profile *profile, struct aa_label *label, -+ int type, u32 request, struct aa_perms *perms) -+{ -+ /* TODO: doesn't yet handle extended types */ -+ unsigned int state; -+ -+ state = aa_dfa_next(profile->policy.dfa, -+ profile->policy.start[AA_CLASS_LABEL], -+ type); -+ aa_label_match(profile, label, state, false, request, perms); -+} -+ -+ -+/* currently unused */ -+int aa_profile_label_perm(struct aa_profile *profile, struct aa_profile *target, -+ u32 request, int type, u32 *deny, -+ struct common_audit_data *sa) -+{ -+ struct aa_perms perms; -+ -+ aad(sa)->label = &profile->label; -+ aad(sa)->peer = &target->label; -+ aad(sa)->request = request; -+ -+ aa_profile_match_label(profile, &target->label, type, request, &perms); -+ aa_apply_modes_to_perms(profile, &perms); -+ *deny |= request & perms.deny; -+ return aa_check_perms(profile, &perms, request, sa, aa_audit_perms_cb); -+} -+ -+/** -+ * aa_check_perms - do audit mode selection based on perms set -+ * @profile: profile being checked -+ * @perms: perms computed for the request -+ * @request: requested perms -+ * @deny: Returns: explicit deny set -+ * @sa: initialized audit structure (MAY BE NULL if not auditing) -+ * @cb: callback fn for tpye specific fields (MAY BE NULL) -+ * -+ * Returns: 0 if permission else error code -+ * -+ * Note: profile audit modes need to be set before calling by setting the -+ * perm masks appropriately. -+ * -+ * If not auditing then complain mode is not enabled and the -+ * error code will indicate whether there was an explicit deny -+ * with a positive value. -+ */ -+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 *)) -+{ -+ int type, error; -+ bool stop = false; -+ u32 denied = request & (~perms->allow | perms->deny); -+ -+ if (likely(!denied)) { -+ /* mask off perms that are not being force audited */ -+ request &= perms->audit; -+ if (!request || !sa) -+ return 0; -+ -+ type = AUDIT_APPARMOR_AUDIT; -+ error = 0; -+ } else { -+ error = -EACCES; -+ -+ if (denied & perms->kill) -+ type = AUDIT_APPARMOR_KILL; -+ else if (denied == (denied & perms->complain)) -+ type = AUDIT_APPARMOR_ALLOWED; -+ else -+ type = AUDIT_APPARMOR_DENIED; -+ -+ if (denied & perms->stop) -+ stop = true; -+ if (denied == (denied & perms->hide)) -+ error = -ENOENT; -+ -+ denied &= ~perms->quiet; -+ if (!sa || !denied) -+ return error; -+ } -+ -+ if (sa) { -+ aad(sa)->label = &profile->label; -+ aad(sa)->request = request; -+ aad(sa)->denied = denied; -+ aad(sa)->error = error; -+ aa_audit_msg(type, sa, cb); -+ } -+ -+ if (type == AUDIT_APPARMOR_ALLOWED) -+ error = 0; -+ -+ return error; -+} -+ -+ -+/** - * aa_policy_init - initialize a policy structure - * @policy: policy to initialize (NOT NULL) - * @prefix: prefix name if any is required. (MAYBE NULL) -diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c -index 7ba43c18687a..3ba08530c92e 100644 ---- a/security/apparmor/lsm.c -+++ b/security/apparmor/lsm.c -@@ -34,6 +34,7 @@ - #include "include/file.h" - #include "include/ipc.h" - #include "include/path.h" -+#include "include/label.h" - #include "include/policy.h" - #include "include/policy_ns.h" - #include "include/procattr.h" -@@ -49,7 +50,7 @@ DEFINE_PER_CPU(struct aa_buffers, aa_buffers); - */ - - /* -- * free the associated aa_task_ctx and put its profiles -+ * free the associated aa_task_ctx and put its labels - */ - static void apparmor_cred_free(struct cred *cred) - { -@@ -115,23 +116,24 @@ static int apparmor_ptrace_traceme(struct task_struct *parent) - static int apparmor_capget(struct task_struct *target, kernel_cap_t *effective, - kernel_cap_t *inheritable, kernel_cap_t *permitted) - { -+ struct aa_label *label; - struct aa_profile *profile; - const struct cred *cred; - - rcu_read_lock(); - cred = __task_cred(target); -- profile = aa_get_newest_cred_profile(cred); -- -+ label = aa_get_newest_cred_label(cred); -+ profile = labels_profile(label); - /* - * cap_capget is stacked ahead of this and will - * initialize effective and permitted. - */ -- if (!unconfined(profile) && !COMPLAIN_MODE(profile)) { -+ if (!profile_unconfined(profile) && !COMPLAIN_MODE(profile)) { - *effective = cap_intersect(*effective, profile->caps.allow); - *permitted = cap_intersect(*permitted, profile->caps.allow); - } - rcu_read_unlock(); -- aa_put_profile(profile); -+ aa_put_label(label); - - return 0; - } -@@ -139,13 +141,13 @@ static int apparmor_capget(struct task_struct *target, kernel_cap_t *effective, - static int apparmor_capable(const struct cred *cred, struct user_namespace *ns, - int cap, int audit) - { -- struct aa_profile *profile; -+ struct aa_label *label; - int error = 0; - -- profile = aa_get_newest_cred_profile(cred); -- if (!unconfined(profile)) -- error = aa_capable(profile, cap, audit); -- aa_put_profile(profile); -+ label = aa_get_newest_cred_label(cred); -+ if (!unconfined(label)) -+ error = aa_capable(labels_profile(label), cap, audit); -+ aa_put_label(label); - - return error; - } -@@ -162,13 +164,14 @@ static int apparmor_capable(const struct cred *cred, struct user_namespace *ns, - static int common_perm(const char *op, const struct path *path, u32 mask, - struct path_cond *cond) - { -- struct aa_profile *profile; -+ struct aa_label *label; - int error = 0; - -- profile = __begin_current_profile_crit_section(); -- if (!unconfined(profile)) -- error = aa_path_perm(op, profile, path, 0, mask, cond); -- __end_current_profile_crit_section(profile); -+ label = __begin_current_label_crit_section(); -+ if (!unconfined(label)) -+ error = aa_path_perm(op, labels_profile(label), path, 0, mask, -+ cond); -+ __end_current_label_crit_section(label); - - return error; - } -@@ -295,16 +298,17 @@ static int apparmor_path_symlink(const struct path *dir, struct dentry *dentry, - static int apparmor_path_link(struct dentry *old_dentry, const struct path *new_dir, - struct dentry *new_dentry) - { -- struct aa_profile *profile; -+ struct aa_label *label; - int error = 0; - - if (!path_mediated_fs(old_dentry)) - return 0; - -- profile = begin_current_profile_crit_section(); -- if (!unconfined(profile)) -- error = aa_path_link(profile, old_dentry, new_dir, new_dentry); -- end_current_profile_crit_section(profile); -+ label = begin_current_label_crit_section(); -+ if (!unconfined(label)) -+ error = aa_path_link(labels_profile(label), old_dentry, new_dir, -+ new_dentry); -+ end_current_label_crit_section(label); - - return error; - } -@@ -312,14 +316,14 @@ static int apparmor_path_link(struct dentry *old_dentry, const struct path *new_ - static int apparmor_path_rename(const struct path *old_dir, struct dentry *old_dentry, - const struct path *new_dir, struct dentry *new_dentry) - { -- struct aa_profile *profile; -+ struct aa_label *label; - int error = 0; - - if (!path_mediated_fs(old_dentry)) - return 0; - -- profile = begin_current_profile_crit_section(); -- if (!unconfined(profile)) { -+ label = begin_current_label_crit_section(); -+ if (!unconfined(label)) { - struct path old_path = { .mnt = old_dir->mnt, - .dentry = old_dentry }; - struct path new_path = { .mnt = new_dir->mnt, -@@ -328,17 +332,20 @@ static int apparmor_path_rename(const struct path *old_dir, struct dentry *old_d - d_backing_inode(old_dentry)->i_mode - }; - -- error = aa_path_perm(OP_RENAME_SRC, profile, &old_path, 0, -+ error = aa_path_perm(OP_RENAME_SRC, labels_profile(label), -+ &old_path, 0, - MAY_READ | AA_MAY_GETATTR | MAY_WRITE | - AA_MAY_SETATTR | AA_MAY_DELETE, - &cond); - if (!error) -- error = aa_path_perm(OP_RENAME_DEST, profile, &new_path, -+ error = aa_path_perm(OP_RENAME_DEST, -+ labels_profile(label), -+ &new_path, - 0, MAY_WRITE | AA_MAY_SETATTR | - AA_MAY_CREATE, &cond); - - } -- end_current_profile_crit_section(profile); -+ end_current_label_crit_section(label); - - return error; - } -@@ -360,8 +367,8 @@ static int apparmor_inode_getattr(const struct path *path) - - static int apparmor_file_open(struct file *file, const struct cred *cred) - { -- struct aa_file_ctx *fctx = file->f_security; -- struct aa_profile *profile; -+ struct aa_file_ctx *fctx = file_ctx(file); -+ struct aa_label *label; - int error = 0; - - if (!path_mediated_fs(file->f_path.dentry)) -@@ -377,17 +384,18 @@ static int apparmor_file_open(struct file *file, const struct cred *cred) - return 0; - } - -- profile = aa_get_newest_cred_profile(cred); -- if (!unconfined(profile)) { -+ label = aa_get_newest_cred_label(cred); -+ if (!unconfined(label)) { - struct inode *inode = file_inode(file); - struct path_cond cond = { inode->i_uid, inode->i_mode }; - -- error = aa_path_perm(OP_OPEN, profile, &file->f_path, 0, -+ error = aa_path_perm(OP_OPEN, labels_profile(label), -+ &file->f_path, 0, - aa_map_file_to_perms(file), &cond); - /* todo cache full allowed permissions set and state */ - fctx->allow = aa_map_file_to_perms(file); - } -- aa_put_profile(profile); -+ aa_put_label(label); - - return error; - } -@@ -397,11 +405,11 @@ static int apparmor_file_alloc_security(struct file *file) - int error = 0; - - /* freed by apparmor_file_free_security */ -- struct aa_profile *profile = begin_current_profile_crit_section(); -+ struct aa_label *label = begin_current_label_crit_section(); - file->f_security = aa_alloc_file_ctx(GFP_KERNEL); - if (!file_ctx(file)) - error = -ENOMEM; -- end_current_profile_crit_section(profile); -+ end_current_label_crit_section(label); - - return error; - } -@@ -414,21 +422,21 @@ static void apparmor_file_free_security(struct file *file) - static int common_file_perm(const char *op, struct file *file, u32 mask) - { - struct aa_file_ctx *fctx = file->f_security; -- struct aa_profile *profile, *fprofile; -+ struct aa_label *label, *flabel; - int error = 0; - - /* don't reaudit files closed during inheritance */ - if (file->f_path.dentry == aa_null.dentry) - return -EACCES; - -- fprofile = aa_cred_raw_profile(file->f_cred); -- AA_BUG(!fprofile); -+ flabel = aa_cred_raw_label(file->f_cred); -+ AA_BUG(!flabel); - - if (!file->f_path.mnt || - !path_mediated_fs(file->f_path.dentry)) - return 0; - -- profile = __begin_current_profile_crit_section(); -+ label = __begin_current_label_crit_section(); - - /* revalidate access, if task is unconfined, or the cached cred - * doesn't match or if the request is for more permissions than -@@ -437,10 +445,10 @@ static int common_file_perm(const char *op, struct file *file, u32 mask) - * Note: the test for !unconfined(fprofile) is to handle file - * delegation from unconfined tasks - */ -- if (!unconfined(profile) && !unconfined(fprofile) && -- ((fprofile != profile) || (mask & ~fctx->allow))) -- error = aa_file_perm(op, profile, file, mask); -- __end_current_profile_crit_section(profile); -+ if (!unconfined(label) && !unconfined(flabel) && -+ ((flabel != label) || (mask & ~fctx->allow))) -+ error = aa_file_perm(op, labels_profile(label), file, mask); -+ __end_current_label_crit_section(label); - - return error; - } -@@ -465,7 +473,7 @@ static int common_mmap(const char *op, struct file *file, unsigned long prot, - { - int mask = 0; - -- if (!file || !file->f_security) -+ if (!file || !file_ctx(file)) - return 0; - - if (prot & PROT_READ) -@@ -502,21 +510,21 @@ static int apparmor_getprocattr(struct task_struct *task, char *name, - /* released below */ - const struct cred *cred = get_task_cred(task); - struct aa_task_ctx *ctx = cred_ctx(cred); -- struct aa_profile *profile = NULL; -+ struct aa_label *label = NULL; - - if (strcmp(name, "current") == 0) -- profile = aa_get_newest_profile(ctx->profile); -+ label = aa_get_newest_label(ctx->label); - else if (strcmp(name, "prev") == 0 && ctx->previous) -- profile = aa_get_newest_profile(ctx->previous); -+ label = aa_get_newest_label(ctx->previous); - else if (strcmp(name, "exec") == 0 && ctx->onexec) -- profile = aa_get_newest_profile(ctx->onexec); -+ label = aa_get_newest_label(ctx->onexec); - else - error = -EINVAL; - -- if (profile) -- error = aa_getprocattr(profile, value); -+ if (label) -+ error = aa_getprocattr(labels_profile(label), value); - -- aa_put_profile(profile); -+ aa_put_label(label); - put_cred(cred); - - return error; -@@ -582,11 +590,11 @@ static int apparmor_setprocattr(const char *name, void *value, - return error; - - fail: -- aad(&sa)->profile = begin_current_profile_crit_section(); -+ aad(&sa)->label = begin_current_label_crit_section(); - aad(&sa)->info = name; - aad(&sa)->error = error = -EINVAL; - aa_audit_msg(AUDIT_APPARMOR_DENIED, &sa, NULL); -- end_current_profile_crit_section(aad(&sa)->profile); -+ end_current_label_crit_section(aad(&sa)->label); - goto out; - } - -@@ -596,20 +604,21 @@ static int apparmor_setprocattr(const char *name, void *value, - */ - static void apparmor_bprm_committing_creds(struct linux_binprm *bprm) - { -- struct aa_profile *profile = aa_current_raw_profile(); -+ struct aa_label *label = aa_current_raw_label(); - struct aa_task_ctx *new_ctx = cred_ctx(bprm->cred); - - /* bail out if unconfined or not changing profile */ -- if ((new_ctx->profile == profile) || -- (unconfined(new_ctx->profile))) -+ if ((new_ctx->label->proxy == label->proxy) || -+ (unconfined(new_ctx->label))) - return; - - aa_inherit_files(bprm->cred, current->files); - - current->pdeath_signal = 0; - -- /* reset soft limits and set hard limits for the new profile */ -- __aa_transition_rlimits(profile, new_ctx->profile); -+ /* reset soft limits and set hard limits for the new label */ -+ __aa_transition_rlimits(labels_profile(label), -+ labels_profile(new_ctx->label)); - } - - /** -@@ -625,12 +634,13 @@ static void apparmor_bprm_committed_creds(struct linux_binprm *bprm) - static int apparmor_task_setrlimit(struct task_struct *task, - unsigned int resource, struct rlimit *new_rlim) - { -- struct aa_profile *profile = __begin_current_profile_crit_section(); -+ struct aa_label *label = __begin_current_label_crit_section(); - int error = 0; - -- if (!unconfined(profile)) -- error = aa_task_setrlimit(profile, task, resource, new_rlim); -- __end_current_profile_crit_section(profile); -+ if (!unconfined(label)) -+ error = aa_task_setrlimit(labels_profile(label), task, -+ resource, new_rlim); -+ __end_current_label_crit_section(label); - - return error; - } -@@ -924,7 +934,7 @@ static int __init set_init_ctx(void) - if (!ctx) - return -ENOMEM; - -- ctx->profile = aa_get_profile(root_ns->unconfined); -+ ctx->label = aa_get_label(ns_unconfined(root_ns)); - cred_ctx(cred) = ctx; - - return 0; -diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c -index 605cb5949c60..244ea4a4a8f0 100644 ---- a/security/apparmor/policy.c -+++ b/security/apparmor/policy.c -@@ -101,20 +101,9 @@ const char *const aa_profile_mode_names[] = { - "unconfined", - }; - --/* requires profile list write lock held */ --void __aa_update_proxy(struct aa_profile *orig, struct aa_profile *new) --{ -- struct aa_profile *tmp; -- -- tmp = rcu_dereference_protected(orig->proxy->profile, -- mutex_is_locked(&orig->ns->lock)); -- rcu_assign_pointer(orig->proxy->profile, aa_get_profile(new)); -- orig->flags |= PFLAG_STALE; -- aa_put_profile(tmp); --} - - /** -- * __list_add_profile - add a profile to a list -+ * __add_profile - add a profiles to list and label tree - * @list: list to add it to (NOT NULL) - * @profile: the profile to add (NOT NULL) - * -@@ -122,12 +111,21 @@ void __aa_update_proxy(struct aa_profile *orig, struct aa_profile *new) - * - * Requires: namespace lock be held, or list not be shared - */ --static void __list_add_profile(struct list_head *list, -- struct aa_profile *profile) -+static void __add_profile(struct list_head *list, struct aa_profile *profile) - { -+ struct aa_label *l; -+ -+ AA_BUG(!list); -+ AA_BUG(!profile); -+ AA_BUG(!profile->ns); -+ AA_BUG(!mutex_is_locked(&profile->ns->lock)); -+ - list_add_rcu(&profile->base.list, list); - /* get list reference */ - aa_get_profile(profile); -+ l = aa_label_insert(&profile->ns->labels, &profile->label); -+ AA_BUG(l != &profile->label); -+ aa_put_label(l); - } - - /** -@@ -144,6 +142,10 @@ static void __list_add_profile(struct list_head *list, - */ - static void __list_remove_profile(struct aa_profile *profile) - { -+ AA_BUG(!profile); -+ AA_BUG(!profile->ns); -+ AA_BUG(!mutex_is_locked(&profile->ns->lock)); -+ - list_del_rcu(&profile->base.list); - aa_put_profile(profile); - } -@@ -156,10 +158,14 @@ static void __list_remove_profile(struct aa_profile *profile) - */ - static void __remove_profile(struct aa_profile *profile) - { -+ AA_BUG(!profile); -+ AA_BUG(!profile->ns); -+ AA_BUG(!mutex_is_locked(&profile->ns->lock)); -+ - /* release any children lists first */ - __aa_profile_list_release(&profile->base.profiles); - /* released by free_profile */ -- __aa_update_proxy(profile, profile->ns->unconfined); -+ aa_label_remove(&profile->label); - __aafs_profile_rmdir(profile); - __list_remove_profile(profile); - } -@@ -177,24 +183,6 @@ void __aa_profile_list_release(struct list_head *head) - __remove_profile(profile); - } - -- --static void free_proxy(struct aa_proxy *p) --{ -- if (p) { -- /* r->profile will not be updated any more as r is dead */ -- aa_put_profile(rcu_dereference_protected(p->profile, true)); -- kzfree(p); -- } --} -- -- --void aa_free_proxy_kref(struct kref *kref) --{ -- struct aa_proxy *p = container_of(kref, struct aa_proxy, count); -- -- free_proxy(p); --} -- - /** - * aa_free_data - free a data blob - * @ptr: data to free -@@ -242,7 +230,6 @@ void aa_free_profile(struct aa_profile *profile) - kzfree(profile->dirname); - aa_put_dfa(profile->xmatch); - aa_put_dfa(profile->policy.dfa); -- aa_put_proxy(profile->proxy); - - if (profile->data) { - rht = profile->data; -@@ -253,30 +240,8 @@ void aa_free_profile(struct aa_profile *profile) - - kzfree(profile->hash); - aa_put_loaddata(profile->rawdata); -- kzfree(profile); --} - --/** -- * aa_free_profile_rcu - free aa_profile by rcu (called by aa_free_profile_kref) -- * @head: rcu_head callback for freeing of a profile (NOT NULL) -- */ --static void aa_free_profile_rcu(struct rcu_head *head) --{ -- struct aa_profile *p = container_of(head, struct aa_profile, rcu); -- if (p->flags & PFLAG_NS_COUNT) -- aa_free_ns(p->ns); -- else -- aa_free_profile(p); --} -- --/** -- * aa_free_profile_kref - free aa_profile by kref (called by aa_put_profile) -- * @kr: kref callback for freeing of a profile (NOT NULL) -- */ --void aa_free_profile_kref(struct kref *kref) --{ -- struct aa_profile *p = container_of(kref, struct aa_profile, count); -- call_rcu(&p->rcu, aa_free_profile_rcu); -+ kzfree(profile); - } - - /** -@@ -286,30 +251,40 @@ void aa_free_profile_kref(struct kref *kref) - * - * Returns: refcount profile or NULL on failure - */ --struct aa_profile *aa_alloc_profile(const char *hname, gfp_t gfp) -+struct aa_profile *aa_alloc_profile(const char *hname, struct aa_proxy *proxy, -+ gfp_t gfp) - { - struct aa_profile *profile; - - /* freed by free_profile - usually through aa_put_profile */ -- profile = kzalloc(sizeof(*profile), gfp); -+ profile = kzalloc(sizeof(*profile) + sizeof(struct aa_profile *) * 2, -+ gfp); - if (!profile) - return NULL; - -- profile->proxy = kzalloc(sizeof(struct aa_proxy), gfp); -- if (!profile->proxy) -- goto fail; -- kref_init(&profile->proxy->count); -- - if (!aa_policy_init(&profile->base, NULL, hname, gfp)) - goto fail; -- kref_init(&profile->count); -+ if (!aa_label_init(&profile->label, 1)) -+ goto fail; -+ -+ /* update being set needed by fs interface */ -+ if (!proxy) { -+ proxy = aa_alloc_proxy(&profile->label, gfp); -+ if (!proxy) -+ goto fail; -+ } else -+ aa_get_proxy(proxy); -+ profile->label.proxy = proxy; -+ -+ profile->label.hname = profile->base.hname; -+ profile->label.flags |= FLAG_PROFILE; -+ profile->label.vec[0] = profile; - - /* refcount released by caller */ - return profile; - - fail: -- kzfree(profile->proxy); -- kzfree(profile); -+ aa_free_profile(profile); - - return NULL; - } -@@ -362,14 +337,14 @@ struct aa_profile *aa_new_null_profile(struct aa_profile *parent, bool hat, - if (profile) - goto out; - -- profile = aa_alloc_profile(name, gfp); -+ profile = aa_alloc_profile(name, NULL, gfp); - if (!profile) - goto fail; - - profile->mode = APPARMOR_COMPLAIN; -- profile->flags |= PFLAG_NULL; -+ profile->label.flags |= FLAG_NULL; - if (hat) -- profile->flags |= PFLAG_HAT; -+ profile->label.flags |= FLAG_HAT; - profile->path_flags = parent->path_flags; - - /* released on free_profile */ -@@ -379,7 +354,7 @@ struct aa_profile *aa_new_null_profile(struct aa_profile *parent, bool hat, - profile->policy.dfa = aa_get_dfa(nulldfa); - - mutex_lock(&profile->ns->lock); -- __list_add_profile(&parent->base.profiles, profile); -+ __add_profile(&parent->base.profiles, profile); - mutex_unlock(&profile->ns->lock); - - /* refcount released by caller */ -@@ -389,7 +364,6 @@ struct aa_profile *aa_new_null_profile(struct aa_profile *parent, bool hat, - return profile; - - fail: -- kfree(name); - aa_free_profile(profile); - return NULL; - } -@@ -556,7 +530,7 @@ struct aa_profile *aa_lookup_profile(struct aa_ns *ns, const char *hname) - return aa_lookupn_profile(ns, hname, strlen(hname)); - } - --struct aa_profile *aa_fqlookupn_profile(struct aa_profile *base, -+struct aa_profile *aa_fqlookupn_profile(struct aa_label *base, - const char *fqname, size_t n) - { - struct aa_profile *profile; -@@ -566,11 +540,11 @@ struct aa_profile *aa_fqlookupn_profile(struct aa_profile *base, - - name = aa_splitn_fqname(fqname, n, &ns_name, &ns_len); - if (ns_name) { -- ns = aa_lookupn_ns(base->ns, ns_name, ns_len); -+ ns = aa_lookupn_ns(labels_ns(base), ns_name, ns_len); - if (!ns) - return NULL; - } else -- ns = aa_get_ns(base->ns); -+ ns = aa_get_ns(labels_ns(base)); - - if (name) - profile = aa_lookupn_profile(ns, name, n - (name - fqname)); -@@ -596,7 +570,7 @@ static int replacement_allowed(struct aa_profile *profile, int noreplace, - const char **info) - { - if (profile) { -- if (profile->flags & PFLAG_IMMUTABLE) { -+ if (profile->label.flags & FLAG_IMMUTIBLE) { - *info = "cannot replace immutible profile"; - return -EPERM; - } else if (noreplace) { -@@ -619,29 +593,31 @@ static void audit_cb(struct audit_buffer *ab, void *va) - } - - /** -- * aa_audit_policy - Do auditing of policy changes -- * @profile: profile to check if it can manage policy -+ * audit_policy - Do auditing of policy changes -+ * @label: label to check if it can manage policy - * @op: policy operation being performed -- * @gfp: memory allocation flags -- * @nsname: name of the ns being manipulated (MAY BE NULL) -+ * @ns_name: name of namespace being manipulated - * @name: name of profile being manipulated (NOT NULL) - * @info: any extra information to be audited (MAYBE NULL) - * @error: error code - * - * Returns: the error to be returned after audit is done - */ --static int audit_policy(struct aa_profile *profile, const char *op, -- const char *nsname, const char *name, -+static int audit_policy(struct aa_label *label, const char *op, -+ const char *ns_name, const char *name, - const char *info, int error) - { - DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, op); - -- aad(&sa)->iface.ns = nsname; -+ aad(&sa)->iface.ns = ns_name; - aad(&sa)->name = name; - aad(&sa)->info = info; - aad(&sa)->error = error; -+ aad(&sa)->label = label; - -- return aa_audit(AUDIT_APPARMOR_STATUS, profile, &sa, audit_cb); -+ aa_audit_msg(AUDIT_APPARMOR_STATUS, &sa, audit_cb); -+ -+ return error; - } - - /** -@@ -685,12 +661,12 @@ bool policy_admin_capable(struct aa_ns *ns) - - /** - * aa_may_manage_policy - can the current task manage policy -- * @profile: profile to check if it can manage policy -+ * @label: label to check if it can manage policy - * @op: the policy manipulation operation being done - * - * Returns: 0 if the task is allowed to manipulate policy else error - */ --int aa_may_manage_policy(struct aa_profile *profile, struct aa_ns *ns, u32 mask) -+int aa_may_manage_policy(struct aa_label *label, struct aa_ns *ns, u32 mask) - { - const char *op; - -@@ -703,11 +679,11 @@ int aa_may_manage_policy(struct aa_profile *profile, struct aa_ns *ns, u32 mask) - - /* check if loading policy is locked out */ - if (aa_g_lock_policy) -- return audit_policy(profile, op, NULL, NULL, "policy_locked", -+ return audit_policy(label, op, NULL, NULL, "policy_locked", - -EACCES); - - if (!policy_admin_capable(ns)) -- return audit_policy(profile, op, NULL, NULL, "not policy admin", -+ return audit_policy(label, op, NULL, NULL, "not policy admin", - -EACCES); - - /* TODO: add fine grained mediation of policy loads */ -@@ -750,8 +726,7 @@ static struct aa_profile *__list_lookup_parent(struct list_head *lh, - * - * Requires: namespace list lock be held, or list not be shared - */ --static void __replace_profile(struct aa_profile *old, struct aa_profile *new, -- bool share_proxy) -+static void __replace_profile(struct aa_profile *old, struct aa_profile *new) - { - struct aa_profile *child, *tmp; - -@@ -766,7 +741,7 @@ static void __replace_profile(struct aa_profile *old, struct aa_profile *new, - p = __find_child(&new->base.profiles, child->base.name); - if (p) { - /* @p replaces @child */ -- __replace_profile(child, p, share_proxy); -+ __replace_profile(child, p); - continue; - } - -@@ -784,14 +759,8 @@ static void __replace_profile(struct aa_profile *old, struct aa_profile *new, - struct aa_profile *parent = aa_deref_parent(old); - rcu_assign_pointer(new->parent, aa_get_profile(parent)); - } -- __aa_update_proxy(old, new); -- if (share_proxy) { -- aa_put_proxy(new->proxy); -- new->proxy = aa_get_proxy(old->proxy); -- } else if (!rcu_access_pointer(new->proxy->profile)) -- /* aafs interface uses proxy */ -- rcu_assign_pointer(new->proxy->profile, -- aa_get_profile(new)); -+ aa_label_replace(&old->label, &new->label); -+ /* migrate dents must come after label replacement b/c update */ - __aafs_profile_migrate_dents(old, new); - - if (list_empty(&new->base.list)) { -@@ -835,6 +804,7 @@ static void share_name(struct aa_profile *old, struct aa_profile *new) - aa_get_str(old->base.hname); - new->base.hname = old->base.hname; - new->base.name = old->base.name; -+ new->label.hname = old->label.hname; - } - - /* Update to newest version of parent after previous replacements -@@ -871,7 +841,7 @@ static struct aa_profile *update_to_newest_parent(struct aa_profile *new) - * - * Returns: size of data consumed else error code on failure. - */ --ssize_t aa_replace_profiles(struct aa_ns *policy_ns, struct aa_profile *profile, -+ssize_t aa_replace_profiles(struct aa_ns *policy_ns, struct aa_label *label, - u32 mask, struct aa_loaddata *udata) - { - const char *ns_name, *info = NULL; -@@ -914,7 +884,7 @@ ssize_t aa_replace_profiles(struct aa_ns *policy_ns, struct aa_profile *profile, - count++; - } - if (ns_name) { -- ns = aa_prepare_ns(policy_ns ? policy_ns : profile->ns, -+ ns = aa_prepare_ns(policy_ns ? policy_ns : labels_ns(label), - ns_name); - if (IS_ERR(ns)) { - op = OP_PROF_LOAD; -@@ -925,7 +895,7 @@ ssize_t aa_replace_profiles(struct aa_ns *policy_ns, struct aa_profile *profile, - goto fail; - } - } else -- ns = aa_get_ns(policy_ns ? policy_ns : profile->ns); -+ ns = aa_get_ns(policy_ns ? policy_ns : labels_ns(label)); - - mutex_lock(&ns->lock); - /* check for duplicate rawdata blobs: space and file dedup */ -@@ -955,8 +925,8 @@ ssize_t aa_replace_profiles(struct aa_ns *policy_ns, struct aa_profile *profile, - - if (ent->new->rename) { - error = __lookup_replace(ns, ent->new->rename, -- !(mask & AA_MAY_REPLACE_POLICY), -- &ent->rename, &info); -+ !(mask & AA_MAY_REPLACE_POLICY), -+ &ent->rename, &info); - if (error) - goto fail_lock; - } -@@ -1021,7 +991,7 @@ ssize_t aa_replace_profiles(struct aa_ns *policy_ns, struct aa_profile *profile, - - if (ent->old && ent->old->rawdata == ent->new->rawdata) { - /* dedup actual profile replacement */ -- audit_policy(profile, op, ns_name, ent->new->base.hname, -+ audit_policy(label, op, ns_name, ent->new->base.hname, - "same as current profile, skipping", - error); - goto skip; -@@ -1031,12 +1001,12 @@ ssize_t aa_replace_profiles(struct aa_ns *policy_ns, struct aa_profile *profile, - * TODO: finer dedup based on profile range in data. Load set - * can differ but profile may remain unchanged - */ -- audit_policy(profile, op, NULL, ent->new->base.hname, -- NULL, error); -+ audit_policy(label, op, ns_name, ent->new->base.hname, NULL, -+ error); - - if (ent->old) { - share_name(ent->old, ent->new); -- __replace_profile(ent->old, ent->new, 1); -+ __replace_profile(ent->old, ent->new); - } else { - struct list_head *lh; - -@@ -1047,11 +1017,12 @@ ssize_t aa_replace_profiles(struct aa_ns *policy_ns, struct aa_profile *profile, - lh = &parent->base.profiles; - } else - lh = &ns->base.profiles; -- __list_add_profile(lh, ent->new); -+ __add_profile(lh, ent->new); - } - skip: - aa_load_ent_free(ent); - } -+ __aa_labelset_update_subtree(ns); - mutex_unlock(&ns->lock); - - out: -@@ -1068,8 +1039,8 @@ ssize_t aa_replace_profiles(struct aa_ns *policy_ns, struct aa_profile *profile, - /* audit cause of failure */ - op = (ent && !ent->old) ? OP_PROF_LOAD : OP_PROF_REPL; - fail: -- audit_policy(profile, op, ns_name, ent ? ent->new->base.hname : NULL, -- info, error); -+ audit_policy(label, op, ns_name, ent ? ent->new->base.hname : NULL, -+ info, error); - /* audit status that rest of profiles in the atomic set failed too */ - info = "valid profile in failed atomic policy load"; - list_for_each_entry(tmp, &lh, list) { -@@ -1079,8 +1050,8 @@ ssize_t aa_replace_profiles(struct aa_ns *policy_ns, struct aa_profile *profile, - continue; - } - op = (!tmp->old) ? OP_PROF_LOAD : OP_PROF_REPL; -- audit_policy(profile, op, ns_name, -- tmp->new->base.hname, info, error); -+ audit_policy(label, op, ns_name, tmp->new->base.hname, info, -+ error); - } - list_for_each_entry_safe(ent, tmp, &lh, list) { - list_del_init(&ent->list); -@@ -1093,7 +1064,7 @@ ssize_t aa_replace_profiles(struct aa_ns *policy_ns, struct aa_profile *profile, - /** - * aa_remove_profiles - remove profile(s) from the system - * @policy_ns: namespace the remove is being done from -- * @subj: profile attempting to remove policy -+ * @subj: label attempting to remove policy - * @fqname: name of the profile or namespace to remove (NOT NULL) - * @size: size of the name - * -@@ -1104,7 +1075,7 @@ ssize_t aa_replace_profiles(struct aa_ns *policy_ns, struct aa_profile *profile, - * - * Returns: size of data consume else error code if fails - */ --ssize_t aa_remove_profiles(struct aa_ns *policy_ns, struct aa_profile *subj, -+ssize_t aa_remove_profiles(struct aa_ns *policy_ns, struct aa_label *subj, - char *fqname, size_t size) - { - struct aa_ns *ns = NULL; -@@ -1124,8 +1095,8 @@ ssize_t aa_remove_profiles(struct aa_ns *policy_ns, struct aa_profile *subj, - - name = aa_splitn_fqname(fqname, size, &ns_name, &ns_len); - /* released below */ -- ns = aa_lookupn_ns(policy_ns ? policy_ns : subj->ns, ns_name, -- ns_len); -+ ns = aa_lookupn_ns(policy_ns ? policy_ns : labels_ns(subj), -+ ns_name, ns_len); - if (!ns) { - info = "namespace does not exist"; - error = -ENOENT; -@@ -1133,7 +1104,7 @@ ssize_t aa_remove_profiles(struct aa_ns *policy_ns, struct aa_profile *subj, - } - } else - /* released below */ -- ns = aa_get_ns(policy_ns ? policy_ns : subj->ns); -+ ns = aa_get_ns(policy_ns ? policy_ns : labels_ns(subj)); - - if (!name) { - /* remove namespace - can only happen if fqname[0] == ':' */ -@@ -1152,6 +1123,7 @@ ssize_t aa_remove_profiles(struct aa_ns *policy_ns, struct aa_profile *subj, - } - name = profile->base.hname; - __remove_profile(profile); -+ __aa_labelset_update_subtree(ns); - __aa_bump_ns_revision(ns); - mutex_unlock(&ns->lock); - } -diff --git a/security/apparmor/policy_ns.c b/security/apparmor/policy_ns.c -index c05316809a5e..351d3bab3a3d 100644 ---- a/security/apparmor/policy_ns.c -+++ b/security/apparmor/policy_ns.c -@@ -23,6 +23,7 @@ - #include "include/apparmor.h" - #include "include/context.h" - #include "include/policy_ns.h" -+#include "include/label.h" - #include "include/policy.h" - - /* root profile namespace */ -@@ -104,12 +105,12 @@ static struct aa_ns *alloc_ns(const char *prefix, const char *name) - init_waitqueue_head(&ns->wait); - - /* released by aa_free_ns() */ -- ns->unconfined = aa_alloc_profile("unconfined", GFP_KERNEL); -+ ns->unconfined = aa_alloc_profile("unconfined", NULL, GFP_KERNEL); - if (!ns->unconfined) - goto fail_unconfined; - -- ns->unconfined->flags = PFLAG_IX_ON_NAME_ERROR | -- PFLAG_IMMUTABLE | PFLAG_NS_COUNT; -+ ns->unconfined->label.flags |= FLAG_IX_ON_NAME_ERROR | -+ FLAG_IMMUTIBLE | FLAG_NS_COUNT | FLAG_UNCONFINED; - ns->unconfined->mode = APPARMOR_UNCONFINED; - - /* ns and ns->unconfined share ns->unconfined refcount */ -@@ -117,6 +118,8 @@ static struct aa_ns *alloc_ns(const char *prefix, const char *name) - - atomic_set(&ns->uniq_null, 0); - -+ aa_labelset_init(&ns->labels); -+ - return ns; - - fail_unconfined: -@@ -139,6 +142,7 @@ void aa_free_ns(struct aa_ns *ns) - return; - - aa_policy_destroy(&ns->base); -+ aa_labelset_destroy(&ns->labels); - aa_put_ns(ns->parent); - - ns->unconfined->ns = NULL; -@@ -337,8 +341,14 @@ static void destroy_ns(struct aa_ns *ns) - /* release all sub namespaces */ - __ns_list_release(&ns->sub_ns); - -- if (ns->parent) -- __aa_update_proxy(ns->unconfined, ns->parent->unconfined); -+ if (ns->parent) { -+ unsigned long flags; -+ -+ write_lock_irqsave(&ns->labels.lock, flags); -+ __aa_proxy_redirect(ns_unconfined(ns), -+ ns_unconfined(ns->parent)); -+ write_unlock_irqrestore(&ns->labels.lock, flags); -+ } - __aafs_ns_rmdir(ns); - mutex_unlock(&ns->lock); - } -diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c -index 1db4746270ab..c010f8b56e1f 100644 ---- a/security/apparmor/policy_unpack.c -+++ b/security/apparmor/policy_unpack.c -@@ -26,6 +26,7 @@ - #include "include/context.h" - #include "include/crypto.h" - #include "include/match.h" -+#include "include/path.h" - #include "include/policy.h" - #include "include/policy_unpack.h" - -@@ -107,7 +108,7 @@ static int audit_iface(struct aa_profile *new, const char *ns_name, - const char *name, const char *info, struct aa_ext *e, - int error) - { -- struct aa_profile *profile = aa_current_raw_profile(); -+ struct aa_profile *profile = labels_profile(aa_current_raw_label()); - DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, NULL); - if (e) - aad(&sa)->iface.pos = e->pos - e->start; -@@ -602,7 +603,7 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name) - name = tmpname; - } - -- profile = aa_alloc_profile(name, GFP_KERNEL); -+ profile = aa_alloc_profile(name, NULL, GFP_KERNEL); - if (!profile) - return ERR_PTR(-ENOMEM); - -@@ -635,7 +636,7 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name) - if (!unpack_u32(e, &tmp, NULL)) - goto fail; - if (tmp & PACKED_FLAG_HAT) -- profile->flags |= PFLAG_HAT; -+ profile->label.flags |= FLAG_HAT; - if (!unpack_u32(e, &tmp, NULL)) - goto fail; - if (tmp == PACKED_MODE_COMPLAIN || (e->version & FORCE_COMPLAIN_FLAG)) -@@ -654,10 +655,11 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name) - - /* path_flags is optional */ - if (unpack_u32(e, &profile->path_flags, "path_flags")) -- profile->path_flags |= profile->flags & PFLAG_MEDIATE_DELETED; -+ profile->path_flags |= profile->label.flags & -+ PATH_MEDIATE_DELETED; - else - /* set a default value if path_flags field is not present */ -- profile->path_flags = PFLAG_MEDIATE_DELETED; -+ profile->path_flags = PATH_MEDIATE_DELETED; - - if (!unpack_u32(e, &(profile->caps.allow.cap[0]), NULL)) - goto fail; -diff --git a/security/apparmor/procattr.c b/security/apparmor/procattr.c -index 2f0cb424927a..dce970d1f46b 100644 ---- a/security/apparmor/procattr.c -+++ b/security/apparmor/procattr.c -@@ -55,7 +55,7 @@ int aa_getprocattr(struct aa_profile *profile, char **string) - ns_len += 4; - - /* unconfined profiles don't have a mode string appended */ -- if (!unconfined(profile)) -+ if (!profile_unconfined(profile)) - mode_len = strlen(mode_str) + 3; /* + 3 for _() */ - - name_len = strlen(profile->base.hname); -@@ -69,7 +69,7 @@ int aa_getprocattr(struct aa_profile *profile, char **string) - sprintf(s, ":%s://", ns_name); - s += ns_len; - } -- if (unconfined(profile)) -+ if (profile_unconfined(profile)) - /* mode string not being appended */ - sprintf(s, "%s\n", profile->base.hname); - else -diff --git a/security/apparmor/resource.c b/security/apparmor/resource.c -index b26f1dac5106..ab8e104c1970 100644 ---- a/security/apparmor/resource.c -+++ b/security/apparmor/resource.c -@@ -86,11 +86,11 @@ int aa_map_resource(int resource) - int aa_task_setrlimit(struct aa_profile *profile, struct task_struct *task, - unsigned int resource, struct rlimit *new_rlim) - { -- struct aa_profile *task_profile; -+ struct aa_label *task_label; - int error = 0; - - rcu_read_lock(); -- task_profile = aa_get_newest_cred_profile((__task_cred(task))); -+ task_label = aa_get_newest_cred_label((__task_cred(task))); - rcu_read_unlock(); - - /* TODO: extend resource control to handle other (non current) -@@ -99,13 +99,13 @@ int aa_task_setrlimit(struct aa_profile *profile, struct task_struct *task, - * the same profile or that the task setting the resource of another - * task has CAP_SYS_RESOURCE. - */ -- if ((profile != task_profile && -+ if ((profile != labels_profile(task_label) && - aa_capable(profile, CAP_SYS_RESOURCE, 1)) || - (profile->rlimits.mask & (1 << resource) && - new_rlim->rlim_max > profile->rlimits.limits[resource].rlim_max)) - error = -EACCES; - -- aa_put_profile(task_profile); -+ aa_put_label(task_label); - - return audit_resource(profile, resource, new_rlim->rlim_max, error); - } --- -2.12.3 - diff --git a/patches.apparmor/0045-apparmor-switch-getprocattr-to-using-label_print-fns.patch b/patches.apparmor/0045-apparmor-switch-getprocattr-to-using-label_print-fns.patch deleted file mode 100644 index 47b764d..0000000 --- a/patches.apparmor/0045-apparmor-switch-getprocattr-to-using-label_print-fns.patch +++ /dev/null @@ -1,126 +0,0 @@ -From d9ae8bd017650ae43ef2c633694a36b8ea8186a7 Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Fri, 9 Jun 2017 12:47:17 -0700 -Subject: [PATCH 45/65] apparmor: switch getprocattr to using label_print fns( -Git-commit: 76a1d263aba3c97db7a2ba673059e0f17d983efb -Patch-mainline: v4.13-rc1 -References: FATE#323500 - -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/include/procattr.h | 2 +- - security/apparmor/lsm.c | 2 +- - security/apparmor/procattr.c | 60 +++++++++++++++--------------------- - 3 files changed, 27 insertions(+), 37 deletions(-) - -diff --git a/security/apparmor/include/procattr.h b/security/apparmor/include/procattr.h -index c0055d727868..c8fd99c9357d 100644 ---- a/security/apparmor/include/procattr.h -+++ b/security/apparmor/include/procattr.h -@@ -15,7 +15,7 @@ - #ifndef __AA_PROCATTR_H - #define __AA_PROCATTR_H - --int aa_getprocattr(struct aa_profile *profile, char **string); -+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/lsm.c b/security/apparmor/lsm.c -index 3ba08530c92e..f7f82ce00d73 100644 ---- a/security/apparmor/lsm.c -+++ b/security/apparmor/lsm.c -@@ -522,7 +522,7 @@ static int apparmor_getprocattr(struct task_struct *task, char *name, - error = -EINVAL; - - if (label) -- error = aa_getprocattr(labels_profile(label), value); -+ error = aa_getprocattr(label, value); - - aa_put_label(label); - put_cred(cred); -diff --git a/security/apparmor/procattr.c b/security/apparmor/procattr.c -index dce970d1f46b..d81617379d63 100644 ---- a/security/apparmor/procattr.c -+++ b/security/apparmor/procattr.c -@@ -34,51 +34,41 @@ - * - * Returns: size of string placed in @string else error code on failure - */ --int aa_getprocattr(struct aa_profile *profile, char **string) -+int aa_getprocattr(struct aa_label *label, char **string) - { -- char *str; -- int len = 0, mode_len = 0, ns_len = 0, name_len; -- const char *mode_str = aa_profile_mode_names[profile->mode]; -- const char *ns_name = NULL; -- struct aa_ns *ns = profile->ns; -+ struct aa_ns *ns = labels_ns(label); - struct aa_ns *current_ns = aa_get_current_ns(); -- char *s; -+ int len; - -- if (!aa_ns_visible(current_ns, ns, true)) -+ if (!aa_ns_visible(current_ns, ns, true)) { -+ aa_put_ns(current_ns); - return -EACCES; -+ } - -- ns_name = aa_ns_name(current_ns, ns, true); -- ns_len = strlen(ns_name); -- -- /* if the visible ns_name is > 0 increase size for : :// seperator */ -- if (ns_len) -- ns_len += 4; -- -- /* unconfined profiles don't have a mode string appended */ -- if (!profile_unconfined(profile)) -- mode_len = strlen(mode_str) + 3; /* + 3 for _() */ -+ len = aa_label_snxprint(NULL, 0, current_ns, label, -+ FLAG_SHOW_MODE | FLAG_VIEW_SUBNS | -+ FLAG_HIDDEN_UNCONFINED); -+ AA_BUG(len < 0); - -- name_len = strlen(profile->base.hname); -- len = mode_len + ns_len + name_len + 1; /* + 1 for \n */ -- s = str = kmalloc(len + 1, GFP_KERNEL); /* + 1 \0 */ -- if (!str) -+ *string = kmalloc(len + 2, GFP_KERNEL); -+ if (!*string) { -+ aa_put_ns(current_ns); - return -ENOMEM; -+ } - -- if (ns_len) { -- /* skip over prefix current_ns->base.hname and separating // */ -- sprintf(s, ":%s://", ns_name); -- s += ns_len; -+ len = aa_label_snxprint(*string, len + 2, current_ns, label, -+ FLAG_SHOW_MODE | FLAG_VIEW_SUBNS | -+ FLAG_HIDDEN_UNCONFINED); -+ if (len < 0) { -+ aa_put_ns(current_ns); -+ return len; - } -- if (profile_unconfined(profile)) -- /* mode string not being appended */ -- sprintf(s, "%s\n", profile->base.hname); -- else -- sprintf(s, "%s (%s)\n", profile->base.hname, mode_str); -- *string = str; -- aa_put_ns(current_ns); - -- /* NOTE: len does not include \0 of string, not saved as part of file */ -- return len; -+ (*string)[len] = '\n'; -+ (*string)[len + 1] = 0; -+ -+ aa_put_ns(current_ns); -+ return len + 1; - } - - /** --- -2.12.3 - diff --git a/patches.apparmor/0046-apparmor-update-query-interface-to-support-label-que.patch b/patches.apparmor/0046-apparmor-update-query-interface-to-support-label-que.patch deleted file mode 100644 index f4961a1..0000000 --- a/patches.apparmor/0046-apparmor-update-query-interface-to-support-label-que.patch +++ /dev/null @@ -1,133 +0,0 @@ -From 6feb97ea1cabb9d24fc2ff57be1c5e3901b54d0f Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Fri, 9 Jun 2017 13:55:38 -0700 -Subject: [PATCH 46/65] apparmor: update query interface to support label - queries -Git-commit: 317d9a054e1c6d5f18b02b99ce09911942f8e603 -Patch-mainline: v4.13-rc1 -References: FATE#323500 - -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/apparmorfs.c | 46 +++++++++++++++++++++++++++++++++++------- - 1 file changed, 39 insertions(+), 7 deletions(-) - -diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c -index 976af6da45c3..d24100f8fd98 100644 ---- a/security/apparmor/apparmorfs.c -+++ b/security/apparmor/apparmorfs.c -@@ -33,6 +33,7 @@ - #include "include/context.h" - #include "include/crypto.h" - #include "include/policy_ns.h" -+#include "include/label.h" - #include "include/policy.h" - #include "include/policy_ns.h" - #include "include/resource.h" -@@ -629,6 +630,7 @@ static void profile_query_cb(struct aa_profile *profile, struct aa_perms *perms, - tmp = nullperms; - } - aa_apply_modes_to_perms(profile, &tmp); -+ aa_perms_accum_raw(perms, &tmp); - } - - -@@ -655,7 +657,9 @@ static ssize_t query_data(char *buf, size_t buf_len, - { - char *out; - const char *key; -+ struct label_it i; - struct aa_label *label, *curr; -+ struct aa_profile *profile; - struct aa_data *data; - u32 bytes, blocks; - __le32 outle32; -@@ -690,13 +694,16 @@ static ssize_t query_data(char *buf, size_t buf_len, - out = buf + sizeof(bytes) + sizeof(blocks); - - blocks = 0; -- if (labels_profile(label)->data) { -- data = rhashtable_lookup_fast(labels_profile(label)->data, &key, -- labels_profile(label)->data->p); -+ label_for_each_confined(i, label, profile) { -+ if (!profile->data) -+ continue; -+ -+ data = rhashtable_lookup_fast(profile->data, &key, -+ profile->data->p); - - if (data) { -- if (out + sizeof(outle32) + data->size > -- buf + buf_len) { -+ if (out + sizeof(outle32) + data->size > buf + -+ buf_len) { - aa_put_label(label); - return -EINVAL; /* not enough space */ - } -@@ -741,10 +748,12 @@ static ssize_t query_data(char *buf, size_t buf_len, - static ssize_t query_label(char *buf, size_t buf_len, - char *query, size_t query_len, bool view_only) - { -+ struct aa_profile *profile; - struct aa_label *label, *curr; - char *label_name, *match_str; - size_t label_name_len, match_len; - struct aa_perms perms; -+ struct label_it i; - - if (!query_len) - return -EINVAL; -@@ -770,7 +779,16 @@ static ssize_t query_label(char *buf, size_t buf_len, - return PTR_ERR(label); - - perms = allperms; -- profile_query_cb(labels_profile(label), &perms, match_str, match_len); -+ if (view_only) { -+ label_for_each_in_ns(i, labels_ns(label), label, profile) { -+ profile_query_cb(profile, &perms, match_str, match_len); -+ } -+ } else { -+ label_for_each(i, label, profile) { -+ profile_query_cb(profile, &perms, match_str, match_len); -+ } -+ } -+ aa_put_label(label); - - return scnprintf(buf, buf_len, - "allow 0x%08x\ndeny 0x%08x\naudit 0x%08x\nquiet 0x%08x\n", -@@ -877,9 +895,12 @@ static int multi_transaction_release(struct inode *inode, struct file *file) - return 0; - } - -+#define QUERY_CMD_LABEL "label\0" -+#define QUERY_CMD_LABEL_LEN 6 - #define QUERY_CMD_PROFILE "profile\0" - #define QUERY_CMD_PROFILE_LEN 8 -- -+#define QUERY_CMD_LABELALL "labelall\0" -+#define QUERY_CMD_LABELALL_LEN 9 - #define QUERY_CMD_DATA "data\0" - #define QUERY_CMD_DATA_LEN 5 - -@@ -922,6 +943,17 @@ static ssize_t aa_write_access(struct file *file, const char __user *ubuf, - len = query_label(t->data, MULTI_TRANSACTION_LIMIT, - t->data + QUERY_CMD_PROFILE_LEN, - count - QUERY_CMD_PROFILE_LEN, true); -+ } else if (count > QUERY_CMD_LABEL_LEN && -+ !memcmp(t->data, QUERY_CMD_LABEL, QUERY_CMD_LABEL_LEN)) { -+ len = query_label(t->data, MULTI_TRANSACTION_LIMIT, -+ t->data + QUERY_CMD_LABEL_LEN, -+ count - QUERY_CMD_LABEL_LEN, true); -+ } else if (count > QUERY_CMD_LABELALL_LEN && -+ !memcmp(t->data, QUERY_CMD_LABELALL, -+ QUERY_CMD_LABELALL_LEN)) { -+ len = query_label(t->data, MULTI_TRANSACTION_LIMIT, -+ t->data + QUERY_CMD_LABELALL_LEN, -+ count - QUERY_CMD_LABELALL_LEN, false); - } else if (count > QUERY_CMD_DATA_LEN && - !memcmp(t->data, QUERY_CMD_DATA, QUERY_CMD_DATA_LEN)) { - len = query_data(t->data, MULTI_TRANSACTION_LIMIT, --- -2.12.3 - diff --git a/patches.apparmor/0047-apparmor-move-capability-checks-to-using-labels.patch b/patches.apparmor/0047-apparmor-move-capability-checks-to-using-labels.patch deleted file mode 100644 index c5ae5be..0000000 --- a/patches.apparmor/0047-apparmor-move-capability-checks-to-using-labels.patch +++ /dev/null @@ -1,244 +0,0 @@ -From a5ebc252a7894a6f0fabd7f3a96422a2ef6d0f72 Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Fri, 9 Jun 2017 14:07:02 -0700 -Subject: [PATCH 47/65] apparmor: move capability checks to using labels -Git-commit: c70c86c421427fd8487867de66c4104b15abd772 -Patch-mainline: v4.13-rc1 -References: FATE#323500 - -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/capability.c | 57 ++++++++++++++++++++++------------ - security/apparmor/include/capability.h | 6 ++-- - security/apparmor/ipc.c | 2 +- - security/apparmor/lsm.c | 20 ++++++++---- - security/apparmor/resource.c | 2 +- - 5 files changed, 58 insertions(+), 29 deletions(-) - -diff --git a/security/apparmor/capability.c b/security/apparmor/capability.c -index 3bc19843d8df..67e347192a55 100644 ---- a/security/apparmor/capability.c -+++ b/security/apparmor/capability.c -@@ -48,15 +48,16 @@ static DEFINE_PER_CPU(struct audit_cache, audit_cache); - static void audit_cb(struct audit_buffer *ab, void *va) - { - struct common_audit_data *sa = va; -+ - audit_log_format(ab, " capname="); - audit_log_untrustedstring(ab, capability_names[sa->u.cap]); - } - - /** - * audit_caps - audit a capability -+ * @sa: audit data - * @profile: profile being tested for confinement (NOT NULL) - * @cap: capability tested -- @audit: whether an audit record should be generated - * @error: error code returned by test - * - * Do auditing of capability and handle, audit/complain/kill modes switching -@@ -64,16 +65,13 @@ static void audit_cb(struct audit_buffer *ab, void *va) - * - * Returns: 0 or sa->error on success, error code on failure - */ --static int audit_caps(struct aa_profile *profile, int cap, int audit, -- int error) -+static int audit_caps(struct common_audit_data *sa, struct aa_profile *profile, -+ int cap, int error) - { - struct audit_cache *ent; - int type = AUDIT_APPARMOR_AUTO; -- DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_CAP, OP_CAPABLE); -- sa.u.cap = cap; -- aad(&sa)->error = error; -- if (audit == SECURITY_CAP_NOAUDIT) -- aad(&sa)->info = "optional: no audit"; -+ -+ aad(sa)->error = error; - - if (likely(!error)) { - /* test if auditing is being forced */ -@@ -105,24 +103,44 @@ static int audit_caps(struct aa_profile *profile, int cap, int audit, - } - put_cpu_var(audit_cache); - -- return aa_audit(type, profile, &sa, audit_cb); -+ return aa_audit(type, profile, sa, audit_cb); - } - - /** - * profile_capable - test if profile allows use of capability @cap - * @profile: profile being enforced (NOT NULL, NOT unconfined) - * @cap: capability to test if allowed -+ * @audit: whether an audit record should be generated -+ * @sa: audit data (MAY BE NULL indicating no auditing) - * - * Returns: 0 if allowed else -EPERM - */ --static int profile_capable(struct aa_profile *profile, int cap) -+static int profile_capable(struct aa_profile *profile, int cap, int audit, -+ struct common_audit_data *sa) - { -- return cap_raised(profile->caps.allow, cap) ? 0 : -EPERM; -+ int error; -+ -+ if (cap_raised(profile->caps.allow, cap) && -+ !cap_raised(profile->caps.denied, cap)) -+ error = 0; -+ else -+ error = -EPERM; -+ -+ if (audit == SECURITY_CAP_NOAUDIT) { -+ if (!COMPLAIN_MODE(profile)) -+ return error; -+ /* audit the cap request in complain mode but note that it -+ * should be optional. -+ */ -+ aad(sa)->info = "optional: no audit"; -+ } -+ -+ return audit_caps(sa, profile, cap, error); - } - - /** - * aa_capable - test permission to use capability -- * @profile: profile being tested against (NOT NULL) -+ * @label: label being tested for capability (NOT NULL) - * @cap: capability to be tested - * @audit: whether an audit record should be generated - * -@@ -130,14 +148,15 @@ static int profile_capable(struct aa_profile *profile, int cap) - * - * Returns: 0 on success, or else an error code. - */ --int aa_capable(struct aa_profile *profile, int cap, int audit) -+int aa_capable(struct aa_label *label, int cap, int audit) - { -- int error = profile_capable(profile, cap); -+ struct aa_profile *profile; -+ int error = 0; -+ DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_CAP, OP_CAPABLE); - -- if (audit == SECURITY_CAP_NOAUDIT) { -- if (!COMPLAIN_MODE(profile)) -- return error; -- } -+ sa.u.cap = cap; -+ error = fn_for_each_confined(label, profile, -+ profile_capable(profile, cap, audit, &sa)); - -- return audit_caps(profile, cap, audit, error); -+ return error; - } -diff --git a/security/apparmor/include/capability.h b/security/apparmor/include/capability.h -index 1218e95ebe49..e0304e2aeb7f 100644 ---- a/security/apparmor/include/capability.h -+++ b/security/apparmor/include/capability.h -@@ -19,11 +19,12 @@ - - #include "apparmorfs.h" - --struct aa_profile; -+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 -@@ -31,6 +32,7 @@ struct aa_profile; - 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; -@@ -38,7 +40,7 @@ struct aa_caps { - - extern struct aa_sfs_entry aa_sfs_entry_caps[]; - --int aa_capable(struct aa_profile *profile, int cap, int audit); -+int aa_capable(struct aa_label *label, int cap, int audit); - - static inline void aa_free_cap_rules(struct aa_caps *caps) - { -diff --git a/security/apparmor/ipc.c b/security/apparmor/ipc.c -index fa68cd42bd15..7678d94c4002 100644 ---- a/security/apparmor/ipc.c -+++ b/security/apparmor/ipc.c -@@ -68,7 +68,7 @@ int aa_may_ptrace(struct aa_profile *tracer, struct aa_profile *tracee, - if (profile_unconfined(tracer) || tracer == tracee) - return 0; - /* log this capability request */ -- return aa_capable(tracer, CAP_SYS_PTRACE, 1); -+ return aa_capable(&tracer->label, CAP_SYS_PTRACE, 1); - } - - /** -diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c -index f7f82ce00d73..bcfdcdb3eae2 100644 ---- a/security/apparmor/lsm.c -+++ b/security/apparmor/lsm.c -@@ -117,20 +117,28 @@ static int apparmor_capget(struct task_struct *target, kernel_cap_t *effective, - kernel_cap_t *inheritable, kernel_cap_t *permitted) - { - struct aa_label *label; -- struct aa_profile *profile; - const struct cred *cred; - - rcu_read_lock(); - cred = __task_cred(target); - label = aa_get_newest_cred_label(cred); -- profile = labels_profile(label); -+ - /* - * cap_capget is stacked ahead of this and will - * initialize effective and permitted. - */ -- if (!profile_unconfined(profile) && !COMPLAIN_MODE(profile)) { -- *effective = cap_intersect(*effective, profile->caps.allow); -- *permitted = cap_intersect(*permitted, profile->caps.allow); -+ if (!unconfined(label)) { -+ struct aa_profile *profile; -+ struct label_it i; -+ -+ label_for_each_confined(i, label, profile) { -+ if (COMPLAIN_MODE(profile)) -+ continue; -+ *effective = cap_intersect(*effective, -+ profile->caps.allow); -+ *permitted = cap_intersect(*permitted, -+ profile->caps.allow); -+ } - } - rcu_read_unlock(); - aa_put_label(label); -@@ -146,7 +154,7 @@ static int apparmor_capable(const struct cred *cred, struct user_namespace *ns, - - label = aa_get_newest_cred_label(cred); - if (!unconfined(label)) -- error = aa_capable(labels_profile(label), cap, audit); -+ error = aa_capable(label, cap, audit); - aa_put_label(label); - - return error; -diff --git a/security/apparmor/resource.c b/security/apparmor/resource.c -index ab8e104c1970..2474ee0b3467 100644 ---- a/security/apparmor/resource.c -+++ b/security/apparmor/resource.c -@@ -100,7 +100,7 @@ int aa_task_setrlimit(struct aa_profile *profile, struct task_struct *task, - * task has CAP_SYS_RESOURCE. - */ - if ((profile != labels_profile(task_label) && -- aa_capable(profile, CAP_SYS_RESOURCE, 1)) || -+ aa_capable(&profile->label, CAP_SYS_RESOURCE, 1)) || - (profile->rlimits.mask & (1 << resource) && - new_rlim->rlim_max > profile->rlimits.limits[resource].rlim_max)) - error = -EACCES; --- -2.12.3 - diff --git a/patches.apparmor/0048-apparmor-move-resource-checks-to-using-labels.patch b/patches.apparmor/0048-apparmor-move-resource-checks-to-using-labels.patch deleted file mode 100644 index 5fe9690..0000000 --- a/patches.apparmor/0048-apparmor-move-resource-checks-to-using-labels.patch +++ /dev/null @@ -1,247 +0,0 @@ -From b8f8ac1fb23f86967c3f7ffcb3569b6b449006ee Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Fri, 9 Jun 2017 14:15:20 -0700 -Subject: [PATCH 48/65] apparmor: move resource checks to using labels -Git-commit: 86b92cb782b38d71ee344af20fcbe5106dd19dbe -Patch-mainline: v4.13-rc1 -References: FATE#323500 - -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/include/resource.h | 4 +- - security/apparmor/lsm.c | 6 +- - security/apparmor/resource.c | 112 ++++++++++++++++++++++++----------- - 3 files changed, 80 insertions(+), 42 deletions(-) - -diff --git a/security/apparmor/include/resource.h b/security/apparmor/include/resource.h -index f6289f335c4d..76f1586c9adb 100644 ---- a/security/apparmor/include/resource.h -+++ b/security/apparmor/include/resource.h -@@ -37,10 +37,10 @@ struct aa_rlimit { - extern struct aa_sfs_entry aa_sfs_entry_rlimit[]; - - int aa_map_resource(int resource); --int aa_task_setrlimit(struct aa_profile *profile, struct task_struct *, -+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_profile *old, struct aa_profile *new); -+void __aa_transition_rlimits(struct aa_label *old, struct aa_label *new); - - static inline void aa_free_rlimit_rules(struct aa_rlimit *rlims) - { -diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c -index bcfdcdb3eae2..c3e98f74268f 100644 ---- a/security/apparmor/lsm.c -+++ b/security/apparmor/lsm.c -@@ -625,8 +625,7 @@ static void apparmor_bprm_committing_creds(struct linux_binprm *bprm) - current->pdeath_signal = 0; - - /* reset soft limits and set hard limits for the new label */ -- __aa_transition_rlimits(labels_profile(label), -- labels_profile(new_ctx->label)); -+ __aa_transition_rlimits(label, new_ctx->label); - } - - /** -@@ -646,8 +645,7 @@ static int apparmor_task_setrlimit(struct task_struct *task, - int error = 0; - - if (!unconfined(label)) -- error = aa_task_setrlimit(labels_profile(label), task, -- resource, new_rlim); -+ error = aa_task_setrlimit(label, task, resource, new_rlim); - __end_current_label_crit_section(label); - - return error; -diff --git a/security/apparmor/resource.c b/security/apparmor/resource.c -index 2474ee0b3467..d8bc842594ed 100644 ---- a/security/apparmor/resource.c -+++ b/security/apparmor/resource.c -@@ -13,6 +13,7 @@ - */ - - #include -+#include - - #include "include/audit.h" - #include "include/context.h" -@@ -36,6 +37,11 @@ static void audit_cb(struct audit_buffer *ab, void *va) - - audit_log_format(ab, " rlimit=%s value=%lu", - rlim_names[aad(sa)->rlim.rlim], aad(sa)->rlim.max); -+ if (aad(sa)->peer) { -+ audit_log_format(ab, " peer="); -+ aa_label_xaudit(ab, labels_ns(aad(sa)->label), aad(sa)->peer, -+ FLAGS_NONE, GFP_ATOMIC); -+ } - } - - /** -@@ -48,13 +54,17 @@ static void audit_cb(struct audit_buffer *ab, void *va) - * Returns: 0 or sa->error else other error code on failure - */ - static int audit_resource(struct aa_profile *profile, unsigned int resource, -- unsigned long value, int error) -+ unsigned long value, struct aa_label *peer, -+ const char *info, int error) - { - DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, OP_SETRLIMIT); - - aad(&sa)->rlim.rlim = resource; - aad(&sa)->rlim.max = value; -+ aad(&sa)->peer = peer; -+ aad(&sa)->info = info; - aad(&sa)->error = error; -+ - return aa_audit(AUDIT_APPARMOR_AUTO, profile, &sa, audit_cb); - } - -@@ -72,9 +82,21 @@ int aa_map_resource(int resource) - return rlim_map[resource]; - } - -+static int profile_setrlimit(struct aa_profile *profile, unsigned int resource, -+ struct rlimit *new_rlim) -+{ -+ int e = 0; -+ -+ if (profile->rlimits.mask & (1 << resource) && new_rlim->rlim_max > -+ profile->rlimits.limits[resource].rlim_max) -+ e = -EACCES; -+ return audit_resource(profile, resource, new_rlim->rlim_max, NULL, NULL, -+ e); -+} -+ - /** - * aa_task_setrlimit - test permission to set an rlimit -- * @profile - profile confining the task (NOT NULL) -+ * @label - label confining the task (NOT NULL) - * @task - task the resource is being set on - * @resource - the resource being set - * @new_rlim - the new resource limit (NOT NULL) -@@ -83,14 +105,15 @@ int aa_map_resource(int resource) - * - * Returns: 0 or error code if setting resource failed - */ --int aa_task_setrlimit(struct aa_profile *profile, struct task_struct *task, -+int aa_task_setrlimit(struct aa_label *label, struct task_struct *task, - unsigned int resource, struct rlimit *new_rlim) - { -- struct aa_label *task_label; -+ struct aa_profile *profile; -+ struct aa_label *peer; - int error = 0; - - rcu_read_lock(); -- task_label = aa_get_newest_cred_label((__task_cred(task))); -+ peer = aa_get_newest_cred_label(__task_cred(task)); - rcu_read_unlock(); - - /* TODO: extend resource control to handle other (non current) -@@ -99,53 +122,70 @@ int aa_task_setrlimit(struct aa_profile *profile, struct task_struct *task, - * the same profile or that the task setting the resource of another - * task has CAP_SYS_RESOURCE. - */ -- if ((profile != labels_profile(task_label) && -- aa_capable(&profile->label, CAP_SYS_RESOURCE, 1)) || -- (profile->rlimits.mask & (1 << resource) && -- new_rlim->rlim_max > profile->rlimits.limits[resource].rlim_max)) -- error = -EACCES; - -- aa_put_label(task_label); -- -- return audit_resource(profile, resource, new_rlim->rlim_max, error); -+ if (label != peer && -+ !aa_capable(label, CAP_SYS_RESOURCE, SECURITY_CAP_NOAUDIT)) -+ error = fn_for_each(label, profile, -+ audit_resource(profile, resource, -+ new_rlim->rlim_max, peer, -+ "cap_sys_resoure", -EACCES)); -+ else -+ error = fn_for_each_confined(label, profile, -+ profile_setrlimit(profile, resource, new_rlim)); -+ aa_put_label(peer); -+ -+ return error; - } - - /** - * __aa_transition_rlimits - apply new profile rlimits -- * @old: old profile on task (NOT NULL) -- * @new: new profile with rlimits to apply (NOT NULL) -+ * @old_l: old label on task (NOT NULL) -+ * @new_l: new label with rlimits to apply (NOT NULL) - */ --void __aa_transition_rlimits(struct aa_profile *old, struct aa_profile *new) -+void __aa_transition_rlimits(struct aa_label *old_l, struct aa_label *new_l) - { - unsigned int mask = 0; - struct rlimit *rlim, *initrlim; -- int i; -+ struct aa_profile *old, *new; -+ struct label_it i; -+ -+ old = labels_profile(old_l); -+ new = labels_profile(new_l); - -- /* for any rlimits the profile controlled reset the soft limit -- * to the less of the tasks hard limit and the init tasks soft limit -+ /* for any rlimits the profile controlled, reset the soft limit -+ * to the lesser of the tasks hard limit and the init tasks soft limit - */ -- if (old->rlimits.mask) { -- for (i = 0, mask = 1; i < RLIM_NLIMITS; i++, mask <<= 1) { -- if (old->rlimits.mask & mask) { -- rlim = current->signal->rlim + i; -- initrlim = init_task.signal->rlim + i; -- rlim->rlim_cur = min(rlim->rlim_max, -- initrlim->rlim_cur); -+ label_for_each_confined(i, old_l, old) { -+ if (old->rlimits.mask) { -+ int j; -+ -+ for (j = 0, mask = 1; j < RLIM_NLIMITS; j++, -+ mask <<= 1) { -+ if (old->rlimits.mask & mask) { -+ rlim = current->signal->rlim + j; -+ initrlim = init_task.signal->rlim + j; -+ rlim->rlim_cur = min(rlim->rlim_max, -+ initrlim->rlim_cur); -+ } - } - } - } - - /* set any new hard limits as dictated by the new profile */ -- if (!new->rlimits.mask) -- return; -- for (i = 0, mask = 1; i < RLIM_NLIMITS; i++, mask <<= 1) { -- if (!(new->rlimits.mask & mask)) -- continue; -+ label_for_each_confined(i, new_l, new) { -+ int j; - -- rlim = current->signal->rlim + i; -- rlim->rlim_max = min(rlim->rlim_max, -- new->rlimits.limits[i].rlim_max); -- /* soft limit should not exceed hard limit */ -- rlim->rlim_cur = min(rlim->rlim_cur, rlim->rlim_max); -+ if (!new->rlimits.mask) -+ continue; -+ for (j = 0, mask = 1; j < RLIM_NLIMITS; j++, mask <<= 1) { -+ if (!(new->rlimits.mask & mask)) -+ continue; -+ -+ rlim = current->signal->rlim + j; -+ rlim->rlim_max = min(rlim->rlim_max, -+ new->rlimits.limits[j].rlim_max); -+ /* soft limit should not exceed hard limit */ -+ rlim->rlim_cur = min(rlim->rlim_cur, rlim->rlim_max); -+ } - } - } --- -2.12.3 - diff --git a/patches.apparmor/0049-apparmor-add-cross-check-permission-helper-macros.patch b/patches.apparmor/0049-apparmor-add-cross-check-permission-helper-macros.patch deleted file mode 100644 index 7e0d15f..0000000 --- a/patches.apparmor/0049-apparmor-add-cross-check-permission-helper-macros.patch +++ /dev/null @@ -1,73 +0,0 @@ -From 85bf84d2d3551b4493f22c89cb5b6899a0a6fe16 Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Fri, 9 Jun 2017 14:23:09 -0700 -Subject: [PATCH 49/65] apparmor: add cross check permission helper macros -Git-commit: ca916e8e2d88e97134a313eb3100ce9c3d8fd3f2 -Patch-mainline: v4.13-rc1 -References: FATE#323500 - -The cross check permission helper macros will help simplify code -that does cross task permission checks like ptrace. - -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/include/perms.h | 42 ++++++++++++++++++++++++++++++++++++++- - 1 file changed, 41 insertions(+), 1 deletion(-) - -diff --git a/security/apparmor/include/perms.h b/security/apparmor/include/perms.h -index 0c5c2b00be02..2b27bb79aec4 100644 ---- a/security/apparmor/include/perms.h -+++ b/security/apparmor/include/perms.h -@@ -92,7 +92,47 @@ struct aa_perms { - extern struct aa_perms nullperms; - extern struct aa_perms allperms; - --struct aa_profile; -+ -+#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) -+ - - void aa_perm_mask_to_str(char *str, const char *chrs, u32 mask); - void aa_audit_perm_names(struct audit_buffer *ab, const char **names, u32 mask); --- -2.12.3 - diff --git a/patches.apparmor/0050-apparmor-move-ptrace-checks-to-using-labels.patch b/patches.apparmor/0050-apparmor-move-ptrace-checks-to-using-labels.patch deleted file mode 100644 index 3317def..0000000 --- a/patches.apparmor/0050-apparmor-move-ptrace-checks-to-using-labels.patch +++ /dev/null @@ -1,288 +0,0 @@ -From 218d19e4b976907ea7f1855fdcbf83a38b758225 Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Fri, 9 Jun 2017 14:22:14 -0700 -Subject: [PATCH 50/65] apparmor: move ptrace checks to using labels -Git-commit: b2d09ae449cedc6f276ac485c013d22a97d36992 -Patch-mainline: v4.13-rc1 -References: FATE#323500 - -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/domain.c | 17 ++++--- - security/apparmor/include/apparmor.h | 1 + - security/apparmor/include/ipc.h | 10 ++--- - security/apparmor/ipc.c | 87 +++++++++--------------------------- - security/apparmor/lsm.c | 23 +++++++++- - 5 files changed, 58 insertions(+), 80 deletions(-) - -diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c -index 8d6797c849fe..fab8923ae38e 100644 ---- a/security/apparmor/domain.c -+++ b/security/apparmor/domain.c -@@ -51,14 +51,16 @@ void aa_free_domain_entries(struct aa_domain *domain) - - /** - * may_change_ptraced_domain - check if can change profile on ptraced task -- * @to_profile: profile to change to (NOT NULL) -+ * @to_label: profile to change to (NOT NULL) -+ * @info: message if there is an error - * - * Check if current is ptraced and if so if the tracing task is allowed - * to trace the new domain - * - * Returns: %0 or error if change not allowed - */ --static int may_change_ptraced_domain(struct aa_profile *to_profile) -+static int may_change_ptraced_domain(struct aa_label *to_label, -+ const char **info) - { - struct task_struct *tracer; - struct aa_label *tracerl = NULL; -@@ -74,13 +76,14 @@ static int may_change_ptraced_domain(struct aa_profile *to_profile) - if (!tracer || unconfined(tracerl)) - goto out; - -- error = aa_may_ptrace(labels_profile(tracerl), to_profile, -- PTRACE_MODE_ATTACH); -+ error = aa_may_ptrace(tracerl, to_label, PTRACE_MODE_ATTACH); - - out: - rcu_read_unlock(); - aa_put_label(tracerl); - -+ if (error) -+ *info = "ptrace prevents transition"; - return error; - } - -@@ -477,7 +480,7 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm) - } - - if (bprm->unsafe & LSM_UNSAFE_PTRACE) { -- error = may_change_ptraced_domain(new_profile); -+ error = may_change_ptraced_domain(&new_profile->label, &info); - if (error) - goto audit; - } -@@ -661,7 +664,7 @@ int aa_change_hat(const char *hats[], int count, u64 token, int flags) - } - } - -- error = may_change_ptraced_domain(hat); -+ error = may_change_ptraced_domain(&hat->label, &info); - if (error) { - info = "ptraced"; - error = -EPERM; -@@ -782,7 +785,7 @@ int aa_change_profile(const char *fqname, int flags) - } - - /* check if tracing task is allowed to trace target domain */ -- error = may_change_ptraced_domain(target); -+ error = may_change_ptraced_domain(&target->label, &info); - if (error) { - info = "ptrace prevents transition"; - goto audit; -diff --git a/security/apparmor/include/apparmor.h b/security/apparmor/include/apparmor.h -index c4a900488e76..aaf893f4e4f5 100644 ---- a/security/apparmor/include/apparmor.h -+++ b/security/apparmor/include/apparmor.h -@@ -27,6 +27,7 @@ - #define AA_CLASS_NET 4 - #define AA_CLASS_RLIMITS 5 - #define AA_CLASS_DOMAIN 6 -+#define AA_CLASS_PTRACE 9 - #define AA_CLASS_LABEL 16 - - #define AA_CLASS_LAST AA_CLASS_LABEL -diff --git a/security/apparmor/include/ipc.h b/security/apparmor/include/ipc.h -index 288ca76e2fb1..fb3e751e6eed 100644 ---- a/security/apparmor/include/ipc.h -+++ b/security/apparmor/include/ipc.h -@@ -4,7 +4,7 @@ - * This file contains AppArmor ipc mediation function definitions. - * - * Copyright (C) 1998-2008 Novell/SUSE -- * Copyright 2009-2010 Canonical Ltd. -+ * Copyright 2009-2017 Canonical Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as -@@ -19,10 +19,10 @@ - - struct aa_profile; - --int aa_may_ptrace(struct aa_profile *tracer, struct aa_profile *tracee, -- unsigned int mode); -+#define AA_PTRACE_TRACE MAY_WRITE -+#define AA_PTRACE_READ MAY_READ - --int aa_ptrace(struct task_struct *tracer, struct task_struct *tracee, -- unsigned int mode); -+int aa_may_ptrace(struct aa_label *tracer, struct aa_label *tracee, -+ u32 request); - - #endif /* __AA_IPC_H */ -diff --git a/security/apparmor/ipc.c b/security/apparmor/ipc.c -index 7678d94c4002..f81649369f05 100644 ---- a/security/apparmor/ipc.c -+++ b/security/apparmor/ipc.c -@@ -4,7 +4,7 @@ - * This file contains AppArmor ipc mediation - * - * Copyright (C) 1998-2008 Novell/SUSE -- * Copyright 2009-2010 Canonical Ltd. -+ * Copyright 2009-2017 Canonical Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as -@@ -25,88 +25,43 @@ - static void audit_ptrace_cb(struct audit_buffer *ab, void *va) - { - struct common_audit_data *sa = va; -+ - audit_log_format(ab, " peer="); - aa_label_xaudit(ab, labels_ns(aad(sa)->label), aad(sa)->peer, - FLAGS_NONE, GFP_ATOMIC); - } - --/** -- * aa_audit_ptrace - do auditing for ptrace -- * @profile: profile being enforced (NOT NULL) -- * @target: profile being traced (NOT NULL) -- * @error: error condition -- * -- * Returns: %0 or error code -- */ --static int aa_audit_ptrace(struct aa_profile *profile, -- struct aa_profile *target, int error) -+static int cross_ptrace_perm(struct aa_profile *tracer, -+ struct aa_profile *tracee, u32 request, -+ struct common_audit_data *sa) - { -- DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, OP_PTRACE); -+ /* policy uses the old style capability check for ptrace */ -+ if (profile_unconfined(tracer) || tracer == tracee) -+ return 0; - -- aad(&sa)->peer = &target->label; -- aad(&sa)->error = error; -+ aad(sa)->label = &tracer->label; -+ aad(sa)->peer = &tracee->label; -+ aad(sa)->request = 0; -+ aad(sa)->error = aa_capable(&tracer->label, CAP_SYS_PTRACE, 1); - -- return aa_audit(AUDIT_APPARMOR_AUTO, profile, &sa, audit_ptrace_cb); -+ return aa_audit(AUDIT_APPARMOR_AUTO, tracer, sa, audit_ptrace_cb); - } - - /** - * aa_may_ptrace - test if tracer task can trace the tracee -- * @tracer: profile of the task doing the tracing (NOT NULL) -- * @tracee: task to be traced -- * @mode: whether PTRACE_MODE_READ || PTRACE_MODE_ATTACH -+ * @tracer: label of the task doing the tracing (NOT NULL) -+ * @tracee: task label to be traced -+ * @request: permission request - * - * Returns: %0 else error code if permission denied or error - */ --int aa_may_ptrace(struct aa_profile *tracer, struct aa_profile *tracee, -- unsigned int mode) -+int aa_may_ptrace(struct aa_label *tracer, struct aa_label *tracee, -+ u32 request) - { -- /* TODO: currently only based on capability, not extended ptrace -- * rules, -- * Test mode for PTRACE_MODE_READ || PTRACE_MODE_ATTACH -- */ -+ DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, OP_PTRACE); - -- if (profile_unconfined(tracer) || tracer == tracee) -- return 0; -- /* log this capability request */ -- return aa_capable(&tracer->label, CAP_SYS_PTRACE, 1); -+ return xcheck_labels_profiles(tracer, tracee, cross_ptrace_perm, -+ request, &sa); - } - --/** -- * aa_ptrace - do ptrace permission check and auditing -- * @tracer: task doing the tracing (NOT NULL) -- * @tracee: task being traced (NOT NULL) -- * @mode: ptrace mode either PTRACE_MODE_READ || PTRACE_MODE_ATTACH -- * -- * Returns: %0 else error code if permission denied or error -- */ --int aa_ptrace(struct task_struct *tracer, struct task_struct *tracee, -- unsigned int mode) --{ -- /* -- * tracer can ptrace tracee when -- * - tracer is unconfined || -- * - tracer is in complain mode -- * - tracer has rules allowing it to trace tracee currently this is: -- * - confined by the same profile || -- * - tracer profile has CAP_SYS_PTRACE -- */ - -- struct aa_label *tracer_l = aa_get_task_label(tracer); -- int error = 0; -- -- if (!unconfined(tracer_l)) { -- struct aa_label *tracee_l = aa_get_task_label(tracee); -- -- error = aa_may_ptrace(labels_profile(tracer_l), -- labels_profile(tracee_l), -- mode); -- error = aa_audit_ptrace(labels_profile(tracer_l), -- labels_profile(tracee_l), -- error); -- -- aa_put_label(tracee_l); -- } -- aa_put_label(tracer_l); -- -- return error; --} -diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c -index c3e98f74268f..bf28b48bf6dd 100644 ---- a/security/apparmor/lsm.c -+++ b/security/apparmor/lsm.c -@@ -104,12 +104,31 @@ static void apparmor_cred_transfer(struct cred *new, const struct cred *old) - static int apparmor_ptrace_access_check(struct task_struct *child, - unsigned int mode) - { -- return aa_ptrace(current, child, mode); -+ struct aa_label *tracer, *tracee; -+ int error; -+ -+ tracer = begin_current_label_crit_section(); -+ tracee = aa_get_task_label(child); -+ error = aa_may_ptrace(tracer, tracee, -+ mode == PTRACE_MODE_READ ? AA_PTRACE_READ : AA_PTRACE_TRACE); -+ aa_put_label(tracee); -+ end_current_label_crit_section(tracer); -+ -+ return error; - } - - static int apparmor_ptrace_traceme(struct task_struct *parent) - { -- return aa_ptrace(parent, current, PTRACE_MODE_ATTACH); -+ struct aa_label *tracer, *tracee; -+ int error; -+ -+ tracee = begin_current_label_crit_section(); -+ tracer = aa_get_task_label(parent); -+ error = aa_may_ptrace(tracer, tracee, AA_PTRACE_TRACE); -+ aa_put_label(tracer); -+ end_current_label_crit_section(tracee); -+ -+ return error; - } - - /* Derived from security/commoncap.c:cap_capget */ --- -2.12.3 - diff --git a/patches.apparmor/0051-apparmor-allow-ptrace-checks-to-be-finer-grained-tha.patch b/patches.apparmor/0051-apparmor-allow-ptrace-checks-to-be-finer-grained-tha.patch deleted file mode 100644 index 589b4ab..0000000 --- a/patches.apparmor/0051-apparmor-allow-ptrace-checks-to-be-finer-grained-tha.patch +++ /dev/null @@ -1,142 +0,0 @@ -From 16bbb5ecd60f4ddc377ae12dbfa1be428ad93d03 Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Fri, 9 Jun 2017 14:38:35 -0700 -Subject: [PATCH 51/65] apparmor: allow ptrace checks to be finer grained than - just capability -Git-commit: 290f458a4f16f9cf6cb6562b249e69fe1c3c3a07 -Patch-mainline: v4.13-rc1 -References: FATE#323500 - -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/apparmorfs.c | 6 +++++ - security/apparmor/include/ipc.h | 6 +++++ - security/apparmor/ipc.c | 56 +++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 68 insertions(+) - -diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c -index d24100f8fd98..d1a6ce499776 100644 ---- a/security/apparmor/apparmorfs.c -+++ b/security/apparmor/apparmorfs.c -@@ -2086,6 +2086,11 @@ static struct aa_sfs_entry aa_sfs_entry_file[] = { - { } - }; - -+static struct aa_sfs_entry aa_sfs_entry_ptrace[] = { -+ AA_SFS_FILE_STRING("mask", "read trace"), -+ { } -+}; -+ - static struct aa_sfs_entry aa_sfs_entry_domain[] = { - AA_SFS_FILE_BOOLEAN("change_hat", 1), - AA_SFS_FILE_BOOLEAN("change_hatv", 1), -@@ -2125,6 +2130,7 @@ static struct aa_sfs_entry aa_sfs_entry_features[] = { - AA_SFS_FILE_U64("capability", VFS_CAP_FLAGS_MASK), - AA_SFS_DIR("rlimit", aa_sfs_entry_rlimit), - AA_SFS_DIR("caps", aa_sfs_entry_caps), -+ AA_SFS_DIR("ptrace", aa_sfs_entry_ptrace), - AA_SFS_DIR("query", aa_sfs_entry_query), - { } - }; -diff --git a/security/apparmor/include/ipc.h b/security/apparmor/include/ipc.h -index fb3e751e6eed..656fdb81c8a0 100644 ---- a/security/apparmor/include/ipc.h -+++ b/security/apparmor/include/ipc.h -@@ -21,6 +21,12 @@ struct aa_profile; - - #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) - - int aa_may_ptrace(struct aa_label *tracer, struct aa_label *tracee, - u32 request); -diff --git a/security/apparmor/ipc.c b/security/apparmor/ipc.c -index f81649369f05..11e66b5bbc42 100644 ---- a/security/apparmor/ipc.c -+++ b/security/apparmor/ipc.c -@@ -21,20 +21,76 @@ - #include "include/policy.h" - #include "include/ipc.h" - -+/** -+ * audit_ptrace_mask - convert mask to permission string -+ * @buffer: buffer to write string to (NOT NULL) -+ * @mask: permission mask to convert -+ */ -+static void audit_ptrace_mask(struct audit_buffer *ab, u32 mask) -+{ -+ switch (mask) { -+ case MAY_READ: -+ audit_log_string(ab, "read"); -+ break; -+ case MAY_WRITE: -+ audit_log_string(ab, "trace"); -+ break; -+ case AA_MAY_BE_READ: -+ audit_log_string(ab, "readby"); -+ break; -+ case AA_MAY_BE_TRACED: -+ audit_log_string(ab, "tracedby"); -+ break; -+ } -+} -+ - /* call back to audit ptrace fields */ - static void audit_ptrace_cb(struct audit_buffer *ab, void *va) - { - struct common_audit_data *sa = va; - -+ if (aad(sa)->request & AA_PTRACE_PERM_MASK) { -+ audit_log_format(ab, " requested_mask="); -+ audit_ptrace_mask(ab, aad(sa)->request); -+ -+ if (aad(sa)->denied & AA_PTRACE_PERM_MASK) { -+ audit_log_format(ab, " denied_mask="); -+ audit_ptrace_mask(ab, aad(sa)->denied); -+ } -+ } - audit_log_format(ab, " peer="); - aa_label_xaudit(ab, labels_ns(aad(sa)->label), aad(sa)->peer, - FLAGS_NONE, GFP_ATOMIC); - } - -+/* TODO: conditionals */ -+static int profile_ptrace_perm(struct aa_profile *profile, -+ struct aa_profile *peer, u32 request, -+ struct common_audit_data *sa) -+{ -+ struct aa_perms perms = { }; -+ -+ /* need because of peer in cross check */ -+ if (profile_unconfined(profile) || -+ !PROFILE_MEDIATES(profile, AA_CLASS_PTRACE)) -+ return 0; -+ -+ aad(sa)->peer = &peer->label; -+ aa_profile_match_label(profile, &peer->label, AA_CLASS_PTRACE, request, -+ &perms); -+ aa_apply_modes_to_perms(profile, &perms); -+ return aa_check_perms(profile, &perms, request, sa, audit_ptrace_cb); -+} -+ - static int cross_ptrace_perm(struct aa_profile *tracer, - struct aa_profile *tracee, u32 request, - struct common_audit_data *sa) - { -+ if (PROFILE_MEDIATES(tracer, AA_CLASS_PTRACE)) -+ return xcheck(profile_ptrace_perm(tracer, tracee, request, sa), -+ profile_ptrace_perm(tracee, tracer, -+ request << PTRACE_PERM_SHIFT, -+ sa)); - /* policy uses the old style capability check for ptrace */ - if (profile_unconfined(tracer) || tracer == tracee) - return 0; --- -2.12.3 - diff --git a/patches.apparmor/0052-apparmor-move-aa_file_perm-to-use-labels.patch b/patches.apparmor/0052-apparmor-move-aa_file_perm-to-use-labels.patch deleted file mode 100644 index 160f79d..0000000 --- a/patches.apparmor/0052-apparmor-move-aa_file_perm-to-use-labels.patch +++ /dev/null @@ -1,236 +0,0 @@ -From e5e8d36904b2193543063d2991bfd1dcef8cfe38 Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Fri, 9 Jun 2017 14:59:51 -0700 -Subject: [PATCH 52/65] apparmor: move aa_file_perm() to use labels -Patch-mainline: v4.13-rc1 -References: FATE#323500 -Git-commit: 190a95189eb9e2233ed71a85cd6dd0c8efc9d392 - -Acked-by: Goldwyn Rodrigues -Signed-off-by: John Johansen ---- - security/apparmor/file.c | 48 +++++++++++++++++++++++++++++++++------- - security/apparmor/include/file.h | 29 +++++++++++++++++------- - security/apparmor/lsm.c | 24 +++----------------- - 3 files changed, 64 insertions(+), 37 deletions(-) - -diff --git a/security/apparmor/file.c b/security/apparmor/file.c -index 5289c8db832b..c13e967137a8 100644 ---- a/security/apparmor/file.c -+++ b/security/apparmor/file.c -@@ -23,6 +23,7 @@ - #include "include/match.h" - #include "include/path.h" - #include "include/policy.h" -+#include "include/label.h" - - static u32 map_mask_to_chr_mask(u32 mask) - { -@@ -433,22 +434,55 @@ int aa_path_link(struct aa_profile *profile, struct dentry *old_dentry, - /** - * aa_file_perm - do permission revalidation check & audit for @file - * @op: operation being checked -- * @profile: profile being enforced (NOT NULL) -+ * @label: label being enforced (NOT NULL) - * @file: file to revalidate access permissions on (NOT NULL) - * @request: requested permissions - * - * Returns: %0 if access allowed else error - */ --int aa_file_perm(const char *op, struct aa_profile *profile, struct file *file, -+int aa_file_perm(const char *op, struct aa_label *label, struct file *file, - u32 request) - { - struct path_cond cond = { - .uid = file_inode(file)->i_uid, - .mode = file_inode(file)->i_mode - }; -+ struct aa_file_ctx *fctx; -+ struct aa_label *flabel; -+ u32 denied; -+ int error = 0; -+ -+ AA_BUG(!label); -+ AA_BUG(!file); -+ -+ fctx = file_ctx(file); -+ -+ rcu_read_lock(); -+ flabel = rcu_dereference(fctx->label); -+ AA_BUG(!flabel); -+ -+ /* revalidate access, if task is unconfined, or the cached cred -+ * doesn't match or if the request is for more permissions than -+ * was granted. -+ * -+ * Note: the test for !unconfined(flabel) is to handle file -+ * delegation from unconfined tasks -+ */ -+ denied = request & ~fctx->allow; -+ if (unconfined(label) || unconfined(flabel) || -+ (!denied && aa_label_is_subset(flabel, label))) -+ goto done; -+ -+ /* TODO: label cross check */ -+ -+ if (file->f_path.mnt && path_mediated_fs(file->f_path.dentry)) -+ error = aa_path_perm(op, labels_profile(label), &file->f_path, -+ PATH_DELEGATE_DELETED, request, &cond); - -- return aa_path_perm(op, profile, &file->f_path, PATH_DELEGATE_DELETED, -- request, &cond); -+done: -+ rcu_read_unlock(); -+ -+ return error; - } - - static void revalidate_tty(struct aa_label *label) -@@ -469,8 +503,7 @@ static void revalidate_tty(struct aa_label *label) - struct tty_file_private, list); - file = file_priv->file; - -- if (aa_file_perm(OP_INHERIT, labels_profile(label), file, -- MAY_READ | MAY_WRITE)) -+ if (aa_file_perm(OP_INHERIT, label, file, MAY_READ | MAY_WRITE)) - drop_tty = 1; - } - spin_unlock(&tty->files_lock); -@@ -484,8 +517,7 @@ static int match_file(const void *p, struct file *file, unsigned int fd) - { - struct aa_label *label = (struct aa_label *)p; - -- if (aa_file_perm(OP_INHERIT, labels_profile(label), file, -- aa_map_file_to_perms(file))) -+ if (aa_file_perm(OP_INHERIT, label, file, aa_map_file_to_perms(file))) - return fd + 1; - return 0; - } -diff --git a/security/apparmor/include/file.h b/security/apparmor/include/file.h -index df76c208473a..415512771bff 100644 ---- a/security/apparmor/include/file.h -+++ b/security/apparmor/include/file.h -@@ -15,6 +15,8 @@ - #ifndef __AA_FILE_H - #define __AA_FILE_H - -+#include -+ - #include "domain.h" - #include "match.h" - #include "perms.h" -@@ -33,13 +35,13 @@ struct path; - #define file_ctx(X) ((struct aa_file_ctx *)(X)->f_security) - - /* 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 -- * -- * The file_ctx could currently be directly stored in file->f_security -- * as the profile reference is now stored in the f_cred. However the -- * ctx struct will expand in the future so we keep the struct. - */ - struct aa_file_ctx { -+ spinlock_t lock; -+ struct aa_label __rcu *label; - u32 allow; - }; - -@@ -50,12 +52,16 @@ struct aa_file_ctx { - * - * Returns: file_ctx or NULL on failure - */ --static inline struct aa_file_ctx *aa_alloc_file_ctx(gfp_t gfp) -+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; - } - -@@ -65,8 +71,15 @@ static inline struct aa_file_ctx *aa_alloc_file_ctx(gfp_t gfp) - */ - static inline void aa_free_file_ctx(struct aa_file_ctx *ctx) - { -- if (ctx) -+ if (ctx) { -+ aa_put_label(rcu_access_pointer(ctx->label)); - kzfree(ctx); -+ } -+} -+ -+static inline struct aa_label *aa_get_file_label(struct aa_file_ctx *ctx) -+{ -+ return aa_get_label_rcu(&ctx->label); - } - - /* -@@ -183,7 +196,7 @@ int aa_path_perm(const char *op, struct aa_profile *profile, - int aa_path_link(struct aa_profile *profile, struct dentry *old_dentry, - const struct path *new_dir, struct dentry *new_dentry); - --int aa_file_perm(const char *op, struct aa_profile *profile, struct file *file, -+int aa_file_perm(const char *op, struct aa_label *label, struct file *file, - u32 request); - - void aa_inherit_files(const struct cred *cred, struct files_struct *files); -diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c -index bf28b48bf6dd..011fbb009663 100644 ---- a/security/apparmor/lsm.c -+++ b/security/apparmor/lsm.c -@@ -433,7 +433,7 @@ static int apparmor_file_alloc_security(struct file *file) - - /* freed by apparmor_file_free_security */ - struct aa_label *label = begin_current_label_crit_section(); -- file->f_security = aa_alloc_file_ctx(GFP_KERNEL); -+ file->f_security = aa_alloc_file_ctx(label, GFP_KERNEL); - if (!file_ctx(file)) - error = -ENOMEM; - end_current_label_crit_section(label); -@@ -448,33 +448,15 @@ static void apparmor_file_free_security(struct file *file) - - static int common_file_perm(const char *op, struct file *file, u32 mask) - { -- struct aa_file_ctx *fctx = file->f_security; -- struct aa_label *label, *flabel; -+ struct aa_label *label; - int error = 0; - - /* don't reaudit files closed during inheritance */ - if (file->f_path.dentry == aa_null.dentry) - return -EACCES; - -- flabel = aa_cred_raw_label(file->f_cred); -- AA_BUG(!flabel); -- -- if (!file->f_path.mnt || -- !path_mediated_fs(file->f_path.dentry)) -- return 0; -- - label = __begin_current_label_crit_section(); -- -- /* revalidate access, if task is unconfined, or the cached cred -- * doesn't match or if the request is for more permissions than -- * was granted. -- * -- * Note: the test for !unconfined(fprofile) is to handle file -- * delegation from unconfined tasks -- */ -- if (!unconfined(label) && !unconfined(flabel) && -- ((flabel != label) || (mask & ~fctx->allow))) -- error = aa_file_perm(op, labels_profile(label), file, mask); -+ error = aa_file_perm(op, label, file, mask); - __end_current_label_crit_section(label); - - return error; --- -2.12.3 - diff --git a/patches.apparmor/0053-apparmor-update-aa_audit_file-to-use-labels.patch b/patches.apparmor/0053-apparmor-update-aa_audit_file-to-use-labels.patch deleted file mode 100644 index 74eb88d..0000000 --- a/patches.apparmor/0053-apparmor-update-aa_audit_file-to-use-labels.patch +++ /dev/null @@ -1,139 +0,0 @@ -From 9f953bce43a028fa2b60531081f881a1c67197c6 Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Fri, 9 Jun 2017 15:48:20 -0700 -Subject: [PATCH 53/65] apparmor: update aa_audit_file() to use labels -Git-commit: 98c3d182321d489d8bfaa596127020ec3027edb2 -Patch-mainline: v4.13-rc1 -References: FATE#323500 - -Acked-by: Goldwyn Rodrigues -Signed-off-by: John Johansen ---- - security/apparmor/domain.c | 6 ++++-- - security/apparmor/file.c | 18 ++++++++++++------ - security/apparmor/include/file.h | 3 ++- - 3 files changed, 18 insertions(+), 9 deletions(-) - -diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c -index fab8923ae38e..896bca01828e 100644 ---- a/security/apparmor/domain.c -+++ b/security/apparmor/domain.c -@@ -518,6 +518,7 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm) - audit: - error = aa_audit_file(profile, &perms, OP_EXEC, MAY_EXEC, name, - new_profile ? new_profile->base.hname : NULL, -+ new_profile ? &new_profile->label : NULL, - cond.uid, info, error); - - cleanup: -@@ -694,7 +695,7 @@ int aa_change_hat(const char *hats[], int count, u64 token, int flags) - audit: - if (!(flags & AA_CHANGE_TEST)) - error = aa_audit_file(profile, &perms, OP_CHANGE_HAT, -- AA_MAY_CHANGEHAT, NULL, target, -+ AA_MAY_CHANGEHAT, NULL, target, NULL, - GLOBAL_ROOT_UID, info, error); - - out: -@@ -802,7 +803,8 @@ int aa_change_profile(const char *fqname, int flags) - audit: - if (!(flags & AA_CHANGE_TEST)) - error = aa_audit_file(profile, &perms, op, request, NULL, -- fqname, GLOBAL_ROOT_UID, info, error); -+ fqname, NULL, GLOBAL_ROOT_UID, info, -+ error); - - aa_put_profile(target); - aa_put_label(label); -diff --git a/security/apparmor/file.c b/security/apparmor/file.c -index c13e967137a8..a40bc1e276dc 100644 ---- a/security/apparmor/file.c -+++ b/security/apparmor/file.c -@@ -75,7 +75,11 @@ static void file_audit_cb(struct audit_buffer *ab, void *va) - from_kuid(&init_user_ns, aad(sa)->fs.ouid)); - } - -- if (aad(sa)->fs.target) { -+ if (aad(sa)->peer) { -+ audit_log_format(ab, " target="); -+ aa_label_xaudit(ab, labels_ns(aad(sa)->label), aad(sa)->peer, -+ FLAG_VIEW_SUBNS, GFP_ATOMIC); -+ } else if (aad(sa)->fs.target) { - audit_log_format(ab, " target="); - audit_log_untrustedstring(ab, aad(sa)->fs.target); - } -@@ -85,11 +89,11 @@ static void file_audit_cb(struct audit_buffer *ab, void *va) - * aa_audit_file - handle the auditing of file operations - * @profile: the profile being enforced (NOT NULL) - * @perms: the permissions computed for the request (NOT NULL) -- * @gfp: allocation flags - * @op: operation being mediated - * @request: permissions requested - * @name: name of object being mediated (MAYBE NULL) - * @target: name of target (MAYBE NULL) -+ * @tlabel: target label (MAY BE NULL) - * @ouid: object uid - * @info: extra information message (MAYBE NULL) - * @error: 0 if operation allowed else failure error code -@@ -98,7 +102,8 @@ static void file_audit_cb(struct audit_buffer *ab, void *va) - */ - int aa_audit_file(struct aa_profile *profile, struct aa_perms *perms, - const char *op, u32 request, const char *name, -- const char *target, kuid_t ouid, const char *info, int error) -+ const char *target, struct aa_label *tlabel, -+ kuid_t ouid, const char *info, int error) - { - int type = AUDIT_APPARMOR_AUTO; - DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_TASK, op); -@@ -107,6 +112,7 @@ int aa_audit_file(struct aa_profile *profile, struct aa_perms *perms, - aad(&sa)->request = request; - aad(&sa)->name = name; - aad(&sa)->fs.target = target; -+ aad(&sa)->peer = tlabel; - aad(&sa)->fs.ouid = ouid; - aad(&sa)->info = info; - aad(&sa)->error = error; -@@ -139,7 +145,7 @@ int aa_audit_file(struct aa_profile *profile, struct aa_perms *perms, - aad(&sa)->request &= ~perms->quiet; - - if (!aad(&sa)->request) -- return COMPLAIN_MODE(profile) ? 0 : aad(&sa)->error; -+ return aad(&sa)->error; - } - - aad(&sa)->denied = aad(&sa)->request & ~perms->allow; -@@ -295,7 +301,7 @@ int aa_path_perm(const char *op, struct aa_profile *profile, - if (request & ~perms.allow) - error = -EACCES; - } -- error = aa_audit_file(profile, &perms, op, request, name, NULL, -+ error = aa_audit_file(profile, &perms, op, request, name, NULL, NULL, - cond->uid, info, error); - put_buffers(buffer); - -@@ -425,7 +431,7 @@ int aa_path_link(struct aa_profile *profile, struct dentry *old_dentry, - - audit: - error = aa_audit_file(profile, &lperms, OP_LINK, request, -- lname, tname, cond.uid, info, error); -+ lname, tname, NULL, cond.uid, info, error); - put_buffers(buffer, buffer2); - - return error; -diff --git a/security/apparmor/include/file.h b/security/apparmor/include/file.h -index 415512771bff..7c6026460272 100644 ---- a/security/apparmor/include/file.h -+++ b/security/apparmor/include/file.h -@@ -162,7 +162,8 @@ static inline u16 dfa_map_xindex(u16 mask) - - int aa_audit_file(struct aa_profile *profile, struct aa_perms *perms, - const char *op, u32 request, const char *name, -- const char *target, kuid_t ouid, const char *info, int error); -+ 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 --- -2.12.3 - diff --git a/patches.apparmor/0054-apparmor-refactor-path-name-lookup-and-permission-ch.patch b/patches.apparmor/0054-apparmor-refactor-path-name-lookup-and-permission-ch.patch deleted file mode 100644 index a85a03c..0000000 --- a/patches.apparmor/0054-apparmor-refactor-path-name-lookup-and-permission-ch.patch +++ /dev/null @@ -1,235 +0,0 @@ -From 746e2b0396d3856ad7ef746ae9a4108e00c77b0e Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Fri, 9 Jun 2017 16:02:25 -0700 -Subject: [PATCH 54/65] apparmor: refactor path name lookup and permission - checks around labels -Git-commit: aebd873e8d3e34757c9295eef074d1be229f5893 -Patch-mainline: v4.13-rc1 -References: FATE#323500 - -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/file.c | 112 +++++++++++++++++++++++++++------------ - security/apparmor/include/file.h | 5 +- - security/apparmor/lsm.c | 13 ++--- - 3 files changed, 85 insertions(+), 45 deletions(-) - -diff --git a/security/apparmor/file.c b/security/apparmor/file.c -index a40bc1e276dc..1b216f889131 100644 ---- a/security/apparmor/file.c -+++ b/security/apparmor/file.c -@@ -153,6 +153,39 @@ int aa_audit_file(struct aa_profile *profile, struct aa_perms *perms, - } - - /** -+ * is_deleted - test if a file has been completely unlinked -+ * @dentry: dentry of file to test for deletion (NOT NULL) -+ * -+ * Returns: %1 if deleted else %0 -+ */ -+static inline bool is_deleted(struct dentry *dentry) -+{ -+ if (d_unlinked(dentry) && d_backing_inode(dentry)->i_nlink == 0) -+ return 1; -+ return 0; -+} -+ -+static int path_name(const char *op, struct aa_label *label, -+ const struct path *path, int flags, char *buffer, -+ const char **name, struct path_cond *cond, u32 request) -+{ -+ struct aa_profile *profile; -+ const char *info = NULL; -+ int error; -+ -+ error = aa_path_name(path, flags, buffer, name, &info, -+ labels_profile(label)->disconnected); -+ if (error) { -+ fn_for_each_confined(label, profile, -+ aa_audit_file(profile, &nullperms, op, request, *name, -+ NULL, NULL, cond->uid, info, error)); -+ return error; -+ } -+ -+ return 0; -+} -+ -+/** - * map_old_perms - map old file perms layout to the new layout - * @old: permission set in old mapping - * -@@ -249,23 +282,46 @@ unsigned int aa_str_perms(struct aa_dfa *dfa, unsigned int start, - return state; - } - --/** -- * is_deleted - test if a file has been completely unlinked -- * @dentry: dentry of file to test for deletion (NOT NULL) -- * -- * Returns: %1 if deleted else %0 -- */ --static inline bool is_deleted(struct dentry *dentry) -+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) - { -- if (d_unlinked(dentry) && d_backing_inode(dentry)->i_nlink == 0) -- return 1; -- return 0; -+ int e = 0; -+ -+ if (profile_unconfined(profile)) -+ return 0; -+ aa_str_perms(profile->file.dfa, profile->file.start, name, cond, perms); -+ if (request & ~perms->allow) -+ e = -EACCES; -+ return aa_audit_file(profile, perms, op, request, name, NULL, NULL, -+ cond->uid, NULL, e); -+} -+ -+ -+static int profile_path_perm(const char *op, struct aa_profile *profile, -+ const struct path *path, char *buffer, u32 request, -+ struct path_cond *cond, int flags, -+ struct aa_perms *perms) -+{ -+ const char *name; -+ int error; -+ -+ if (profile_unconfined(profile)) -+ return 0; -+ -+ error = path_name(op, &profile->label, path, -+ flags | profile->path_flags, buffer, &name, cond, -+ request); -+ if (error) -+ return error; -+ return __aa_path_perm(op, profile, name, request, cond, flags, -+ perms); - } - - /** - * aa_path_perm - do permissions check & audit for @path - * @op: operation being checked -- * @profile: profile being enforced (NOT NULL) -+ * @label: profile being enforced (NOT NULL) - * @path: path to check permissions of (NOT NULL) - * @flags: any additional path flags beyond what the profile specifies - * @request: requested permissions -@@ -273,36 +329,22 @@ static inline bool is_deleted(struct dentry *dentry) - * - * Returns: %0 else error if access denied or other error - */ --int aa_path_perm(const char *op, struct aa_profile *profile, -+int aa_path_perm(const char *op, struct aa_label *label, - const struct path *path, int flags, u32 request, - struct path_cond *cond) - { -- char *buffer = NULL; - struct aa_perms perms = {}; -- const char *name, *info = NULL; -+ struct aa_profile *profile; -+ char *buffer = NULL; - int error; - -- flags |= profile->path_flags | (S_ISDIR(cond->mode) ? PATH_IS_DIR : 0); -+ flags |= PATH_DELEGATE_DELETED | (S_ISDIR(cond->mode) ? PATH_IS_DIR : -+ 0); - get_buffers(buffer); -- error = aa_path_name(path, flags, buffer, &name, &info, -- profile->disconnected); -- if (error) { -- if (error == -ENOENT && is_deleted(path->dentry)) { -- /* Access to open files that are deleted are -- * give a pass (implicit delegation) -- */ -- error = 0; -- info = NULL; -- perms.allow = request; -- } -- } else { -- aa_str_perms(profile->file.dfa, profile->file.start, name, cond, -- &perms); -- if (request & ~perms.allow) -- error = -EACCES; -- } -- error = aa_audit_file(profile, &perms, op, request, name, NULL, NULL, -- cond->uid, info, error); -+ error = fn_for_each_confined(label, profile, -+ profile_path_perm(op, profile, path, buffer, request, -+ cond, flags, &perms)); -+ - put_buffers(buffer); - - return error; -@@ -482,7 +524,7 @@ int aa_file_perm(const char *op, struct aa_label *label, struct file *file, - /* TODO: label cross check */ - - if (file->f_path.mnt && path_mediated_fs(file->f_path.dentry)) -- error = aa_path_perm(op, labels_profile(label), &file->f_path, -+ error = aa_path_perm(op, label, &file->f_path, - PATH_DELEGATE_DELETED, request, &cond); - - done: -diff --git a/security/apparmor/include/file.h b/security/apparmor/include/file.h -index 7c6026460272..8daad14c47fd 100644 ---- a/security/apparmor/include/file.h -+++ b/security/apparmor/include/file.h -@@ -190,7 +190,10 @@ 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, -+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); - -diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c -index 011fbb009663..d0c5721aa8b3 100644 ---- a/security/apparmor/lsm.c -+++ b/security/apparmor/lsm.c -@@ -196,8 +196,7 @@ static int common_perm(const char *op, const struct path *path, u32 mask, - - label = __begin_current_label_crit_section(); - if (!unconfined(label)) -- error = aa_path_perm(op, labels_profile(label), path, 0, mask, -- cond); -+ error = aa_path_perm(op, label, path, 0, mask, cond); - __end_current_label_crit_section(label); - - return error; -@@ -359,15 +358,12 @@ static int apparmor_path_rename(const struct path *old_dir, struct dentry *old_d - d_backing_inode(old_dentry)->i_mode - }; - -- error = aa_path_perm(OP_RENAME_SRC, labels_profile(label), -- &old_path, 0, -+ error = aa_path_perm(OP_RENAME_SRC, label, &old_path, 0, - MAY_READ | AA_MAY_GETATTR | MAY_WRITE | - AA_MAY_SETATTR | AA_MAY_DELETE, - &cond); - if (!error) -- error = aa_path_perm(OP_RENAME_DEST, -- labels_profile(label), -- &new_path, -+ error = aa_path_perm(OP_RENAME_DEST, label, &new_path, - 0, MAY_WRITE | AA_MAY_SETATTR | - AA_MAY_CREATE, &cond); - -@@ -416,8 +412,7 @@ static int apparmor_file_open(struct file *file, const struct cred *cred) - struct inode *inode = file_inode(file); - struct path_cond cond = { inode->i_uid, inode->i_mode }; - -- error = aa_path_perm(OP_OPEN, labels_profile(label), -- &file->f_path, 0, -+ error = aa_path_perm(OP_OPEN, label, &file->f_path, 0, - aa_map_file_to_perms(file), &cond); - /* todo cache full allowed permissions set and state */ - fctx->allow = aa_map_file_to_perms(file); --- -2.12.3 - diff --git a/patches.apparmor/0055-apparmor-move-path_link-mediation-to-using-labels.patch b/patches.apparmor/0055-apparmor-move-path_link-mediation-to-using-labels.patch deleted file mode 100644 index 1381e0d..0000000 --- a/patches.apparmor/0055-apparmor-move-path_link-mediation-to-using-labels.patch +++ /dev/null @@ -1,201 +0,0 @@ -From 4349ae2aac8cb88ec0ab8219303d5ed071180ed9 Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Fri, 9 Jun 2017 16:06:21 -0700 -Subject: [PATCH 55/65] apparmor: move path_link mediation to using labels -Git-commit: 8014370f1257619226b79cb6de8e28563fbbc070 -Patch-mainline: v4.13-rc1 -References: FATE#323500 - -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/file.c | 101 ++++++++++++++++++++++----------------- - security/apparmor/include/file.h | 2 +- - security/apparmor/lsm.c | 3 +- - 3 files changed, 59 insertions(+), 47 deletions(-) - -diff --git a/security/apparmor/file.c b/security/apparmor/file.c -index 1b216f889131..eb4c3006af67 100644 ---- a/security/apparmor/file.c -+++ b/security/apparmor/file.c -@@ -370,66 +370,40 @@ static inline bool xindex_is_subset(u32 link, u32 target) - return 1; - } - --/** -- * aa_path_link - Handle hard link permission check -- * @profile: the profile being enforced (NOT NULL) -- * @old_dentry: the target dentry (NOT NULL) -- * @new_dir: directory the new link will be created in (NOT NULL) -- * @new_dentry: the link being created (NOT NULL) -- * -- * Handle the permission test for a link & target pair. Permission -- * is encoded as a pair where the link permission is determined -- * first, and if allowed, the target is tested. The target test -- * is done from the point of the link match (not start of DFA) -- * making the target permission dependent on the link permission match. -- * -- * The subset test if required forces that permissions granted -- * on link are a subset of the permission granted to target. -- * -- * Returns: %0 if allowed else error -- */ --int aa_path_link(struct aa_profile *profile, struct dentry *old_dentry, -- const struct path *new_dir, struct dentry *new_dentry) -+static int profile_path_link(struct aa_profile *profile, -+ const struct path *link, char *buffer, -+ const struct path *target, char *buffer2, -+ struct path_cond *cond) - { -- struct path link = { .mnt = new_dir->mnt, .dentry = new_dentry }; -- struct path target = { .mnt = new_dir->mnt, .dentry = old_dentry }; -- struct path_cond cond = { -- d_backing_inode(old_dentry)->i_uid, -- d_backing_inode(old_dentry)->i_mode -- }; -- char *buffer = NULL, *buffer2 = NULL; -- const char *lname, *tname = NULL, *info = NULL; -- struct aa_perms lperms, perms; -+ const char *lname, *tname = NULL; -+ struct aa_perms lperms = {}, perms; -+ const char *info = NULL; - u32 request = AA_MAY_LINK; - unsigned int state; - int error; - -- get_buffers(buffer, buffer2); -- lperms = nullperms; -- -- /* buffer freed below, lname is pointer in buffer */ -- error = aa_path_name(&link, profile->path_flags, buffer, &lname, -- &info, profile->disconnected); -+ error = path_name(OP_LINK, &profile->label, link, profile->path_flags, -+ buffer, &lname, cond, AA_MAY_LINK); - if (error) - goto audit; - - /* buffer2 freed below, tname is pointer in buffer2 */ -- error = aa_path_name(&target, profile->path_flags, buffer2, &tname, -- &info, profile->disconnected); -+ error = path_name(OP_LINK, &profile->label, target, profile->path_flags, -+ buffer2, &tname, cond, AA_MAY_LINK); - if (error) - goto audit; - - error = -EACCES; - /* aa_str_perms - handles the case of the dfa being NULL */ - state = aa_str_perms(profile->file.dfa, profile->file.start, lname, -- &cond, &lperms); -+ cond, &lperms); - - if (!(lperms.allow & AA_MAY_LINK)) - goto audit; - - /* test to see if target can be paired with link */ - state = aa_dfa_null_transition(profile->file.dfa, state); -- aa_str_perms(profile->file.dfa, state, tname, &cond, &perms); -+ aa_str_perms(profile->file.dfa, state, tname, cond, &perms); - - /* force audit/quiet masks for link are stored in the second entry - * in the link pair. -@@ -440,6 +414,7 @@ int aa_path_link(struct aa_profile *profile, struct dentry *old_dentry, - - if (!(perms.allow & AA_MAY_LINK)) { - info = "target restricted"; -+ lperms = perms; - goto audit; - } - -@@ -447,10 +422,10 @@ int aa_path_link(struct aa_profile *profile, struct dentry *old_dentry, - if (!(perms.allow & AA_LINK_SUBSET)) - goto done_tests; - -- /* Do link perm subset test requiring allowed permission on link are a -- * subset of the allowed permissions on target. -+ /* Do link perm subset test requiring allowed permission on link are -+ * a subset of the allowed permissions on target. - */ -- aa_str_perms(profile->file.dfa, profile->file.start, tname, &cond, -+ aa_str_perms(profile->file.dfa, profile->file.start, tname, cond, - &perms); - - /* AA_MAY_LINK is not considered in the subset test */ -@@ -472,8 +447,46 @@ int aa_path_link(struct aa_profile *profile, struct dentry *old_dentry, - error = 0; - - audit: -- error = aa_audit_file(profile, &lperms, OP_LINK, request, -- lname, tname, NULL, cond.uid, info, error); -+ return aa_audit_file(profile, &lperms, OP_LINK, request, lname, tname, -+ NULL, cond->uid, info, error); -+} -+ -+/** -+ * aa_path_link - Handle hard link permission check -+ * @label: the label being enforced (NOT NULL) -+ * @old_dentry: the target dentry (NOT NULL) -+ * @new_dir: directory the new link will be created in (NOT NULL) -+ * @new_dentry: the link being created (NOT NULL) -+ * -+ * Handle the permission test for a link & target pair. Permission -+ * is encoded as a pair where the link permission is determined -+ * first, and if allowed, the target is tested. The target test -+ * is done from the point of the link match (not start of DFA) -+ * making the target permission dependent on the link permission match. -+ * -+ * The subset test if required forces that permissions granted -+ * on link are a subset of the permission granted to target. -+ * -+ * Returns: %0 if allowed else error -+ */ -+int aa_path_link(struct aa_label *label, struct dentry *old_dentry, -+ const struct path *new_dir, struct dentry *new_dentry) -+{ -+ struct path link = { new_dir->mnt, new_dentry }; -+ struct path target = { new_dir->mnt, old_dentry }; -+ struct path_cond cond = { -+ d_backing_inode(old_dentry)->i_uid, -+ d_backing_inode(old_dentry)->i_mode -+ }; -+ char *buffer = NULL, *buffer2 = NULL; -+ struct aa_profile *profile; -+ int error; -+ -+ /* buffer freed below, lname is pointer in buffer */ -+ get_buffers(buffer, buffer2); -+ error = fn_for_each_confined(label, profile, -+ profile_path_link(profile, &link, buffer, &target, -+ buffer2, &cond)); - put_buffers(buffer, buffer2); - - return error; -diff --git a/security/apparmor/include/file.h b/security/apparmor/include/file.h -index 8daad14c47fd..001e40073ff9 100644 ---- a/security/apparmor/include/file.h -+++ b/security/apparmor/include/file.h -@@ -197,7 +197,7 @@ 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_profile *profile, struct dentry *old_dentry, -+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, -diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c -index d0c5721aa8b3..7a986763b2b7 100644 ---- a/security/apparmor/lsm.c -+++ b/security/apparmor/lsm.c -@@ -332,8 +332,7 @@ static int apparmor_path_link(struct dentry *old_dentry, const struct path *new_ - - label = begin_current_label_crit_section(); - if (!unconfined(label)) -- error = aa_path_link(labels_profile(label), old_dentry, new_dir, -- new_dentry); -+ error = aa_path_link(label, old_dentry, new_dir, new_dentry); - end_current_label_crit_section(label); - - return error; --- -2.12.3 - diff --git a/patches.apparmor/0056-apparmor-rework-file-permission-to-cache-file-access.patch b/patches.apparmor/0056-apparmor-rework-file-permission-to-cache-file-access.patch deleted file mode 100644 index aa11e63..0000000 --- a/patches.apparmor/0056-apparmor-rework-file-permission-to-cache-file-access.patch +++ /dev/null @@ -1,129 +0,0 @@ -From 76c7d634246759381c5d558769bbc02cedc35f7f Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Fri, 9 Jun 2017 16:19:02 -0700 -Subject: [PATCH 56/65] apparmor: rework file permission to cache file access - in file->ctx -Git-commit: 496c93196654d3e604013d750b7047886af14506 -Patch-mainline: v4.13-rc1 -References: FATE#323500 - -This is a temporary step, towards using the file->ctx for delegation, -and also helps speed up file queries, until the permission lookup -cache is introduced. - -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/file.c | 82 ++++++++++++++++++++++++++++++++++++++++++++---- - 1 file changed, 76 insertions(+), 6 deletions(-) - -diff --git a/security/apparmor/file.c b/security/apparmor/file.c -index eb4c3006af67..b6e8e5b11e05 100644 ---- a/security/apparmor/file.c -+++ b/security/apparmor/file.c -@@ -492,6 +492,80 @@ int aa_path_link(struct aa_label *label, struct dentry *old_dentry, - return error; - } - -+static void update_file_ctx(struct aa_file_ctx *fctx, struct aa_label *label, -+ u32 request) -+{ -+ struct aa_label *l, *old; -+ -+ /* update caching of label on file_ctx */ -+ spin_lock(&fctx->lock); -+ old = rcu_dereference_protected(fctx->label, -+ spin_is_locked(&fctx->lock)); -+ l = aa_label_merge(old, label, GFP_ATOMIC); -+ if (l) { -+ if (l != old) { -+ rcu_assign_pointer(fctx->label, l); -+ aa_put_label(old); -+ } else -+ aa_put_label(l); -+ fctx->allow |= request; -+ } -+ spin_unlock(&fctx->lock); -+} -+ -+static int __file_path_perm(const char *op, struct aa_label *label, -+ struct aa_label *flabel, struct file *file, -+ u32 request, u32 denied) -+{ -+ struct aa_profile *profile; -+ struct aa_perms perms = {}; -+ struct path_cond cond = { -+ .uid = file_inode(file)->i_uid, -+ .mode = file_inode(file)->i_mode -+ }; -+ char *buffer; -+ int flags, error; -+ -+ /* revalidation due to label out of date. No revocation at this time */ -+ if (!denied && aa_label_is_subset(flabel, label)) -+ /* TODO: check for revocation on stale profiles */ -+ return 0; -+ -+ flags = PATH_DELEGATE_DELETED | (S_ISDIR(cond.mode) ? PATH_IS_DIR : 0); -+ get_buffers(buffer); -+ -+ /* check every profile in task label not in current cache */ -+ error = fn_for_each_not_in_set(flabel, label, profile, -+ profile_path_perm(op, profile, &file->f_path, buffer, -+ request, &cond, flags, &perms)); -+ if (denied && !error) { -+ /* -+ * check every profile in file label that was not tested -+ * in the initial check above. -+ * -+ * TODO: cache full perms so this only happens because of -+ * conditionals -+ * TODO: don't audit here -+ */ -+ if (label == flabel) -+ error = fn_for_each(label, profile, -+ profile_path_perm(op, profile, &file->f_path, -+ buffer, request, &cond, flags, -+ &perms)); -+ else -+ error = fn_for_each_not_in_set(label, flabel, profile, -+ profile_path_perm(op, profile, &file->f_path, -+ buffer, request, &cond, flags, -+ &perms)); -+ } -+ if (!error) -+ update_file_ctx(file_ctx(file), label, request); -+ -+ put_buffers(buffer); -+ -+ return error; -+} -+ - /** - * aa_file_perm - do permission revalidation check & audit for @file - * @op: operation being checked -@@ -504,10 +578,6 @@ int aa_path_link(struct aa_label *label, struct dentry *old_dentry, - int aa_file_perm(const char *op, struct aa_label *label, struct file *file, - u32 request) - { -- struct path_cond cond = { -- .uid = file_inode(file)->i_uid, -- .mode = file_inode(file)->i_mode -- }; - struct aa_file_ctx *fctx; - struct aa_label *flabel; - u32 denied; -@@ -537,8 +607,8 @@ int aa_file_perm(const char *op, struct aa_label *label, struct file *file, - /* TODO: label cross check */ - - if (file->f_path.mnt && path_mediated_fs(file->f_path.dentry)) -- error = aa_path_perm(op, label, &file->f_path, -- PATH_DELEGATE_DELETED, request, &cond); -+ error = __file_path_perm(op, label, flabel, file, request, -+ denied); - - done: - rcu_read_unlock(); --- -2.12.3 - diff --git a/patches.apparmor/0057-apparmor-mediate-files-when-they-are-received.patch b/patches.apparmor/0057-apparmor-mediate-files-when-they-are-received.patch deleted file mode 100644 index 1aec5ee..0000000 --- a/patches.apparmor/0057-apparmor-mediate-files-when-they-are-received.patch +++ /dev/null @@ -1,54 +0,0 @@ -From fc1655b35668bd61223020beddf1713c3fa4bdbb Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Fri, 9 Jun 2017 17:15:56 -0700 -Subject: [PATCH 57/65] apparmor: mediate files when they are received -Git-commit: 064dc9472fa2bc31a7b178882bd7eff782c3d239 -Patch-mainline: v4.13-rc1 -References: FATE#323500 - -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/include/audit.h | 1 + - security/apparmor/lsm.c | 6 ++++++ - 2 files changed, 7 insertions(+) - -diff --git a/security/apparmor/include/audit.h b/security/apparmor/include/audit.h -index 20fa6c77db05..99ed83cf6941 100644 ---- a/security/apparmor/include/audit.h -+++ b/security/apparmor/include/audit.h -@@ -64,6 +64,7 @@ enum audit_type { - #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" -diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c -index 7a986763b2b7..0f7c5c2be732 100644 ---- a/security/apparmor/lsm.c -+++ b/security/apparmor/lsm.c -@@ -456,6 +456,11 @@ static int common_file_perm(const char *op, struct file *file, u32 mask) - return error; - } - -+static int apparmor_file_receive(struct file *file) -+{ -+ return common_file_perm(OP_FRECEIVE, file, aa_map_file_to_perms(file)); -+} -+ - static int apparmor_file_permission(struct file *file, int mask) - { - return common_file_perm(OP_FPERM, file, mask); -@@ -665,6 +670,7 @@ static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = { - LSM_HOOK_INIT(inode_getattr, apparmor_inode_getattr), - - LSM_HOOK_INIT(file_open, apparmor_file_open), -+ LSM_HOOK_INIT(file_receive, apparmor_file_receive), - LSM_HOOK_INIT(file_permission, apparmor_file_permission), - LSM_HOOK_INIT(file_alloc_security, apparmor_file_alloc_security), - LSM_HOOK_INIT(file_free_security, apparmor_file_free_security), --- -2.12.3 - diff --git a/patches.apparmor/0058-apparmor-support-v7-transition-format-compatible-wit.patch b/patches.apparmor/0058-apparmor-support-v7-transition-format-compatible-wit.patch deleted file mode 100644 index 0a8b642..0000000 --- a/patches.apparmor/0058-apparmor-support-v7-transition-format-compatible-wit.patch +++ /dev/null @@ -1,77 +0,0 @@ -From 1b90c295d8cdcc73da028b88a328b1a1fc572389 Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Fri, 9 Jun 2017 17:29:12 -0700 -Subject: [PATCH 58/65] apparmor: support v7 transition format compatible with - label_parse -Git-commit: 5379a3312024a8befe7728238fc50ed05d2938ac -Patch-mainline: v4.13-rc1 -References: FATE#323500 - -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/apparmorfs.c | 2 ++ - security/apparmor/policy_unpack.c | 20 +++++++++++++------- - 2 files changed, 15 insertions(+), 7 deletions(-) - -diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c -index d1a6ce499776..e460f2d8337d 100644 ---- a/security/apparmor/apparmorfs.c -+++ b/security/apparmor/apparmorfs.c -@@ -2103,6 +2103,8 @@ static struct aa_sfs_entry aa_sfs_entry_domain[] = { - - static struct aa_sfs_entry aa_sfs_entry_versions[] = { - AA_SFS_FILE_BOOLEAN("v5", 1), -+ AA_SFS_FILE_BOOLEAN("v6", 1), -+ AA_SFS_FILE_BOOLEAN("v7", 1), - { } - }; - -diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c -index c010f8b56e1f..c600f4dd1783 100644 ---- a/security/apparmor/policy_unpack.c -+++ b/security/apparmor/policy_unpack.c -@@ -466,7 +466,7 @@ static bool unpack_trans_table(struct aa_ext *e, struct aa_profile *profile) - profile->file.trans.size = size; - for (i = 0; i < size; i++) { - char *str; -- int c, j, size2 = unpack_strdup(e, &str, NULL); -+ int c, j, pos, size2 = unpack_strdup(e, &str, NULL); - /* unpack_strdup verifies that the last character is - * null termination byte. - */ -@@ -478,19 +478,25 @@ static bool unpack_trans_table(struct aa_ext *e, struct aa_profile *profile) - goto fail; - - /* count internal # of internal \0 */ -- for (c = j = 0; j < size2 - 2; j++) { -- if (!str[j]) -+ for (c = j = 0; j < size2 - 1; j++) { -+ if (!str[j]) { -+ pos = j; - c++; -+ } - } - if (*str == ':') { -+ /* first character after : must be valid */ -+ if (!str[1]) -+ goto fail; - /* beginning with : requires an embedded \0, - * verify that exactly 1 internal \0 exists - * trailing \0 already verified by unpack_strdup -+ * -+ * convert \0 back to : for label_parse - */ -- if (c != 1) -- goto fail; -- /* first character after : must be valid */ -- if (!str[1]) -+ if (c == 1) -+ str[pos] = ':'; -+ else if (c > 1) - goto fail; - } else if (c) - /* fail - all other cases with embedded \0 */ --- -2.12.3 - diff --git a/patches.apparmor/0059-apparmor-move-exec-domain-mediation-to-using-labels.patch b/patches.apparmor/0059-apparmor-move-exec-domain-mediation-to-using-labels.patch deleted file mode 100644 index aea1013..0000000 --- a/patches.apparmor/0059-apparmor-move-exec-domain-mediation-to-using-labels.patch +++ /dev/null @@ -1,1118 +0,0 @@ -From 62e644c79d558d9f93bbc64b172145aff38ce8e0 Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Fri, 9 Jun 2017 16:55:04 -0700 -Subject: [PATCH 59/65] apparmor: move exec domain mediation to using labels -Git-commit: 93c98a484c4900f0d2c65c16466d45f90ea5b175 -Patch-mainline: v4.13-rc1 -References: FATE#323500 - -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/domain.c | 850 ++++++++++++++++++++++++++++------------ - security/apparmor/include/lib.h | 87 +++- - 2 files changed, 678 insertions(+), 259 deletions(-) - -diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c -index 896bca01828e..cb8509373ea3 100644 ---- a/security/apparmor/domain.c -+++ b/security/apparmor/domain.c -@@ -87,42 +87,236 @@ static int may_change_ptraced_domain(struct aa_label *to_label, - return error; - } - -+/**** TODO: dedup to aa_label_match - needs perm and dfa, merging -+ * specifically this is an exact copy of aa_label_match except -+ * aa_compute_perms is replaced with aa_compute_fperms -+ * and policy.dfa with file.dfa -+ ****/ -+/* match a profile and its associated ns component if needed -+ * Assumes visibility test has already been done. -+ * If a subns profile is not to be matched should be prescreened with -+ * visibility test. -+ */ -+static inline unsigned int match_component(struct aa_profile *profile, -+ struct aa_profile *tp, -+ bool stack, unsigned int state) -+{ -+ const char *ns_name; -+ -+ if (stack) -+ state = aa_dfa_match(profile->file.dfa, state, "&"); -+ if (profile->ns == tp->ns) -+ return aa_dfa_match(profile->file.dfa, state, tp->base.hname); -+ -+ /* try matching with namespace name and then profile */ -+ ns_name = aa_ns_name(profile->ns, tp->ns, true); -+ state = aa_dfa_match_len(profile->file.dfa, state, ":", 1); -+ state = aa_dfa_match(profile->file.dfa, state, ns_name); -+ state = aa_dfa_match_len(profile->file.dfa, state, ":", 1); -+ return aa_dfa_match(profile->file.dfa, state, tp->base.hname); -+} -+ -+/** -+ * label_compound_match - find perms for full compound label -+ * @profile: profile to find perms for -+ * @label: label to check access permissions for -+ * @stack: whether this is a stacking request -+ * @start: state to start match in -+ * @subns: whether to do permission checks on components in a subns -+ * @request: permissions to request -+ * @perms: perms struct to set -+ * -+ * Returns: 0 on success else ERROR -+ * -+ * For the label A//&B//&C this does the perm match for A//&B//&C -+ * @perms should be preinitialized with allperms OR a previous permission -+ * check to be stacked. -+ */ -+static int label_compound_match(struct aa_profile *profile, -+ struct aa_label *label, bool stack, -+ unsigned int state, bool subns, u32 request, -+ struct aa_perms *perms) -+{ -+ struct aa_profile *tp; -+ struct label_it i; -+ struct path_cond cond = { }; -+ -+ /* find first subcomponent that is visible */ -+ label_for_each(i, label, tp) { -+ if (!aa_ns_visible(profile->ns, tp->ns, subns)) -+ continue; -+ state = match_component(profile, tp, stack, state); -+ if (!state) -+ goto fail; -+ goto next; -+ } -+ -+ /* no component visible */ -+ *perms = allperms; -+ return 0; -+ -+next: -+ label_for_each_cont(i, label, tp) { -+ if (!aa_ns_visible(profile->ns, tp->ns, subns)) -+ continue; -+ state = aa_dfa_match(profile->file.dfa, state, "//&"); -+ state = match_component(profile, tp, false, state); -+ if (!state) -+ goto fail; -+ } -+ *perms = aa_compute_fperms(profile->file.dfa, state, &cond); -+ aa_apply_modes_to_perms(profile, perms); -+ if ((perms->allow & request) != request) -+ return -EACCES; -+ -+ return 0; -+ -+fail: -+ *perms = nullperms; -+ return -EACCES; -+} -+ -+/** -+ * label_components_match - find perms for all subcomponents of a label -+ * @profile: profile to find perms for -+ * @label: label to check access permissions for -+ * @stack: whether this is a stacking request -+ * @start: state to start match in -+ * @subns: whether to do permission checks on components in a subns -+ * @request: permissions to request -+ * @perms: an initialized perms struct to add accumulation to -+ * -+ * Returns: 0 on success else ERROR -+ * -+ * For the label A//&B//&C this does the perm match for each of A and B and C -+ * @perms should be preinitialized with allperms OR a previous permission -+ * check to be stacked. -+ */ -+static int label_components_match(struct aa_profile *profile, -+ struct aa_label *label, bool stack, -+ unsigned int start, bool subns, u32 request, -+ struct aa_perms *perms) -+{ -+ struct aa_profile *tp; -+ struct label_it i; -+ struct aa_perms tmp; -+ struct path_cond cond = { }; -+ unsigned int state = 0; -+ -+ /* find first subcomponent to test */ -+ label_for_each(i, label, tp) { -+ if (!aa_ns_visible(profile->ns, tp->ns, subns)) -+ continue; -+ state = match_component(profile, tp, stack, start); -+ if (!state) -+ goto fail; -+ goto next; -+ } -+ -+ /* no subcomponents visible - no change in perms */ -+ return 0; -+ -+next: -+ tmp = aa_compute_fperms(profile->file.dfa, state, &cond); -+ aa_apply_modes_to_perms(profile, &tmp); -+ aa_perms_accum(perms, &tmp); -+ label_for_each_cont(i, label, tp) { -+ if (!aa_ns_visible(profile->ns, tp->ns, subns)) -+ continue; -+ state = match_component(profile, tp, stack, start); -+ if (!state) -+ goto fail; -+ tmp = aa_compute_fperms(profile->file.dfa, state, &cond); -+ aa_apply_modes_to_perms(profile, &tmp); -+ aa_perms_accum(perms, &tmp); -+ } -+ -+ if ((perms->allow & request) != request) -+ return -EACCES; -+ -+ return 0; -+ -+fail: -+ *perms = nullperms; -+ return -EACCES; -+} -+ -+/** -+ * label_match - do a multi-component label match -+ * @profile: profile to match against (NOT NULL) -+ * @label: label to match (NOT NULL) -+ * @stack: whether this is a stacking request -+ * @state: state to start in -+ * @subns: whether to match subns components -+ * @request: permission request -+ * @perms: Returns computed perms (NOT NULL) -+ * -+ * Returns: the state the match finished in, may be the none matching state -+ */ -+static int label_match(struct aa_profile *profile, struct aa_label *label, -+ bool stack, unsigned int state, bool subns, u32 request, -+ struct aa_perms *perms) -+{ -+ int error; -+ -+ *perms = nullperms; -+ error = label_compound_match(profile, label, stack, state, subns, -+ request, perms); -+ if (!error) -+ return error; -+ -+ *perms = allperms; -+ return label_components_match(profile, label, stack, state, subns, -+ request, perms); -+} -+ -+/******* end TODO: dedup *****/ -+ - /** - * change_profile_perms - find permissions for change_profile - * @profile: the current profile (NOT NULL) -- * @ns: the namespace being switched to (NOT NULL) -- * @name: the name of the profile to change to (NOT NULL) -+ * @target: label to transition to (NOT NULL) -+ * @stack: whether this is a stacking request - * @request: requested perms - * @start: state to start matching in - * -+ * - * Returns: permission set -+ * -+ * currently only matches full label A//&B//&C or individual components A, B, C -+ * not arbitrary combinations. Eg. A//&B, C - */ --static struct aa_perms change_profile_perms(struct aa_profile *profile, -- struct aa_ns *ns, -- const char *name, u32 request, -- unsigned int start) -+static int change_profile_perms(struct aa_profile *profile, -+ struct aa_label *target, bool stack, -+ u32 request, unsigned int start, -+ struct aa_perms *perms) -+{ -+ if (profile_unconfined(profile)) { -+ perms->allow = AA_MAY_CHANGE_PROFILE | AA_MAY_ONEXEC; -+ perms->audit = perms->quiet = perms->kill = 0; -+ return 0; -+ } -+ -+ /* TODO: add profile in ns screening */ -+ return label_match(profile, target, stack, start, true, request, perms); -+} -+ -+static struct aa_perms change_profile_perms_wrapper(struct aa_profile *profile, -+ struct aa_profile *target, -+ u32 request, -+ unsigned int start) - { - struct aa_perms perms; -- struct path_cond cond = { }; -- unsigned int state; - - if (profile_unconfined(profile)) { - perms.allow = AA_MAY_CHANGE_PROFILE | AA_MAY_ONEXEC; - perms.audit = perms.quiet = perms.kill = 0; - return perms; -- } else if (!profile->file.dfa) { -- return nullperms; -- } else if ((ns == profile->ns)) { -- /* try matching against rules with out namespace prepended */ -- aa_str_perms(profile->file.dfa, start, name, &cond, &perms); -- if (COMBINED_PERM_MASK(perms) & request) -- return perms; - } - -- /* try matching with namespace name and then profile */ -- state = aa_dfa_match(profile->file.dfa, start, ns->base.name); -- state = aa_dfa_match_len(profile->file.dfa, state, ":", 1); -- aa_str_perms(profile->file.dfa, state, name, &cond, &perms); -+ if (change_profile_perms(profile, &target->label, false, request, -+ start, &perms)) -+ return nullperms; - - return perms; - } -@@ -173,10 +367,10 @@ static struct aa_profile *__attach_match(const char *name, - * @list: list to search (NOT NULL) - * @name: the executable name to match against (NOT NULL) - * -- * Returns: profile or NULL if no match found -+ * Returns: label or NULL if no match found - */ --static struct aa_profile *find_attach(struct aa_ns *ns, -- struct list_head *list, const char *name) -+static struct aa_label *find_attach(struct aa_ns *ns, struct list_head *list, -+ const char *name) - { - struct aa_profile *profile; - -@@ -184,49 +378,7 @@ static struct aa_profile *find_attach(struct aa_ns *ns, - profile = aa_get_profile(__attach_match(name, list)); - rcu_read_unlock(); - -- return profile; --} -- --/** -- * separate_fqname - separate the namespace and profile names -- * @fqname: the fqname name to split (NOT NULL) -- * @ns_name: the namespace name if it exists (NOT NULL) -- * -- * This is the xtable equivalent routine of aa_split_fqname. It finds the -- * split in an xtable fqname which contains an embedded \0 instead of a : -- * if a namespace is specified. This is done so the xtable is constant and -- * isn't re-split on every lookup. -- * -- * Either the profile or namespace name may be optional but if the namespace -- * is specified the profile name termination must be present. This results -- * in the following possible encodings: -- * profile_name\0 -- * :ns_name\0profile_name\0 -- * :ns_name\0\0 -- * -- * NOTE: the xtable fqname is pre-validated at load time in unpack_trans_table -- * -- * Returns: profile name if it is specified else NULL -- */ --static const char *separate_fqname(const char *fqname, const char **ns_name) --{ -- const char *name; -- -- if (fqname[0] == ':') { -- /* In this case there is guaranteed to be two \0 terminators -- * in the string. They are verified at load time by -- * by unpack_trans_table -- */ -- *ns_name = fqname + 1; /* skip : */ -- name = *ns_name + strlen(*ns_name) + 1; -- if (!*name) -- name = NULL; -- } else { -- *ns_name = NULL; -- name = fqname; -- } -- -- return name; -+ return profile ? &profile->label : NULL; - } - - static const char *next_name(int xtype, const char *name) -@@ -238,295 +390,477 @@ static const char *next_name(int xtype, const char *name) - * x_table_lookup - lookup an x transition name via transition table - * @profile: current profile (NOT NULL) - * @xindex: index into x transition table -+ * @name: returns: name tested to find label (NOT NULL) - * -- * Returns: refcounted profile, or NULL on failure (MAYBE NULL) -+ * Returns: refcounted label, or NULL on failure (MAYBE NULL) - */ --static struct aa_profile *x_table_lookup(struct aa_profile *profile, u32 xindex) -+static struct aa_label *x_table_lookup(struct aa_profile *profile, u32 xindex, -+ const char **name) - { -- struct aa_profile *new_profile = NULL; -- struct aa_ns *ns = profile->ns; -+ struct aa_label *label = NULL; - u32 xtype = xindex & AA_X_TYPE_MASK; - int index = xindex & AA_X_INDEX_MASK; -- const char *name; - -- /* index is guaranteed to be in range, validated at load time */ -- for (name = profile->file.trans.table[index]; !new_profile && name; -- name = next_name(xtype, name)) { -- struct aa_ns *new_ns; -- const char *xname = NULL; -+ AA_BUG(!name); - -- new_ns = NULL; -+ /* index is guaranteed to be in range, validated at load time */ -+ /* TODO: move lookup parsing to unpack time so this is a straight -+ * index into the resultant label -+ */ -+ for (*name = profile->file.trans.table[index]; !label && *name; -+ *name = next_name(xtype, *name)) { - if (xindex & AA_X_CHILD) { -+ struct aa_profile *new_profile; - /* release by caller */ -- new_profile = aa_find_child(profile, name); -+ new_profile = aa_find_child(profile, *name); -+ if (new_profile) -+ label = &new_profile->label; - continue; -- } else if (*name == ':') { -- /* switching namespace */ -- const char *ns_name; -- xname = name = separate_fqname(name, &ns_name); -- if (!xname) -- /* no name so use profile name */ -- xname = profile->base.hname; -- if (*ns_name == '@') { -- /* TODO: variable support */ -- ; -- } -- /* released below */ -- new_ns = aa_find_ns(ns, ns_name); -- if (!new_ns) -- continue; -- } else if (*name == '@') { -- /* TODO: variable support */ -- continue; -- } else { -- /* basic namespace lookup */ -- xname = name; - } -- -- /* released by caller */ -- new_profile = aa_lookup_profile(new_ns ? new_ns : ns, xname); -- aa_put_ns(new_ns); -+ label = aa_label_parse(&profile->label, *name, GFP_ATOMIC, -+ true, false); -+ if (IS_ERR(label)) -+ label = NULL; - } - - /* released by caller */ -- return new_profile; -+ -+ return label; - } - - /** -- * x_to_profile - get target profile for a given xindex -+ * x_to_label - get target label for a given xindex - * @profile: current profile (NOT NULL) - * @name: name to lookup (NOT NULL) - * @xindex: index into x transition table -+ * @lookupname: returns: name used in lookup if one was specified (NOT NULL) - * -- * find profile for a transition index -+ * find label for a transition index - * -- * Returns: refcounted profile or NULL if not found available -+ * Returns: refcounted label or NULL if not found available - */ --static struct aa_profile *x_to_profile(struct aa_profile *profile, -- const char *name, u32 xindex) -+static struct aa_label *x_to_label(struct aa_profile *profile, -+ const char *name, u32 xindex, -+ const char **lookupname, -+ const char **info) - { -- struct aa_profile *new_profile = NULL; -+ struct aa_label *new = NULL; - struct aa_ns *ns = profile->ns; - u32 xtype = xindex & AA_X_TYPE_MASK; -+ const char *stack = NULL; - - switch (xtype) { - case AA_X_NONE: - /* fail exec unless ix || ux fallback - handled by caller */ -- return NULL; -+ *lookupname = NULL; -+ break; -+ case AA_X_TABLE: -+ /* TODO: fix when perm mapping done at unload */ -+ stack = profile->file.trans.table[xindex & AA_X_INDEX_MASK]; -+ if (*stack != '&') { -+ /* released by caller */ -+ new = x_table_lookup(profile, xindex, lookupname); -+ stack = NULL; -+ break; -+ } -+ /* fall through to X_NAME */ - case AA_X_NAME: - if (xindex & AA_X_CHILD) - /* released by caller */ -- new_profile = find_attach(ns, &profile->base.profiles, -- name); -+ new = find_attach(ns, &profile->base.profiles, -+ name); - else - /* released by caller */ -- new_profile = find_attach(ns, &ns->base.profiles, -- name); -- break; -- case AA_X_TABLE: -- /* released by caller */ -- new_profile = x_table_lookup(profile, xindex); -+ new = find_attach(ns, &ns->base.profiles, -+ name); -+ *lookupname = name; - break; - } - -+ if (!new) { -+ if (xindex & AA_X_INHERIT) { -+ /* (p|c|n)ix - don't change profile but do -+ * use the newest version -+ */ -+ *info = "ix fallback"; -+ /* no profile && no error */ -+ new = aa_get_newest_label(&profile->label); -+ } else if (xindex & AA_X_UNCONFINED) { -+ new = aa_get_newest_label(ns_unconfined(profile->ns)); -+ *info = "ux fallback"; -+ } -+ } -+ -+ if (new && stack) { -+ /* base the stack on post domain transition */ -+ struct aa_label *base = new; -+ -+ new = aa_label_parse(base, stack, GFP_ATOMIC, true, false); -+ if (IS_ERR(new)) -+ new = NULL; -+ aa_put_label(base); -+ } -+ - /* released by caller */ -- return new_profile; -+ return new; - } - --/** -- * apparmor_bprm_set_creds - set the new creds on the bprm struct -- * @bprm: binprm for the exec (NOT NULL) -- * -- * Returns: %0 or error on failure -- */ --int apparmor_bprm_set_creds(struct linux_binprm *bprm) -+static struct aa_label *profile_transition(struct aa_profile *profile, -+ const struct linux_binprm *bprm, -+ char *buffer, struct path_cond *cond, -+ bool *secure_exec) - { -- struct aa_task_ctx *ctx; -- struct aa_label *label; -- struct aa_profile *profile, *new_profile = NULL; -- struct aa_ns *ns; -- char *buffer = NULL; -- unsigned int state; -+ struct aa_label *new = NULL; -+ const char *info = NULL, *name = NULL, *target = NULL; -+ unsigned int state = profile->file.start; - struct aa_perms perms = {}; -- struct path_cond cond = { -- file_inode(bprm->file)->i_uid, -- file_inode(bprm->file)->i_mode -- }; -- const char *name = NULL, *info = NULL; -+ bool nonewprivs = false; - int error = 0; - -- if (bprm->cred_prepared) -- return 0; -- -- ctx = cred_ctx(bprm->cred); -- AA_BUG(!ctx); -- -- label = aa_get_newest_label(ctx->label); -- profile = labels_profile(label); -- -- /* buffer freed below, name is pointer into buffer */ -- get_buffers(buffer); -- /* -- * get the namespace from the replacement profile as replacement -- * can change the namespace -- */ -- ns = profile->ns; -- state = profile->file.start; -+ AA_BUG(!profile); -+ AA_BUG(!bprm); -+ AA_BUG(!buffer); - - error = aa_path_name(&bprm->file->f_path, profile->path_flags, buffer, - &name, &info, profile->disconnected); - if (error) { - if (profile_unconfined(profile) || -- (profile->label.flags & FLAG_IX_ON_NAME_ERROR)) -+ (profile->label.flags & FLAG_IX_ON_NAME_ERROR)) { -+ AA_DEBUG("name lookup ix on error"); - error = 0; -+ new = aa_get_newest_label(&profile->label); -+ } - name = bprm->filename; - goto audit; - } - -- /* Test for onexec first as onexec directives override other -- * x transitions. -- */ - if (profile_unconfined(profile)) { -- /* unconfined task */ -- if (ctx->onexec) -- /* change_profile on exec already been granted */ -- new_profile = labels_profile(aa_get_label(ctx->onexec)); -- else -- new_profile = find_attach(ns, &ns->base.profiles, name); -- if (!new_profile) -- goto cleanup; -- /* -- * NOTE: Domain transitions from unconfined are allowed -- * even when no_new_privs is set because this aways results -- * in a further reduction of permissions. -- */ -- goto apply; -+ new = find_attach(profile->ns, &profile->ns->base.profiles, -+ name); -+ if (new) { -+ AA_DEBUG("unconfined attached to new label"); -+ return new; -+ } -+ AA_DEBUG("unconfined exec no attachment"); -+ return aa_get_newest_label(&profile->label); - } - - /* find exec permissions for name */ -- state = aa_str_perms(profile->file.dfa, state, name, &cond, &perms); -- if (ctx->onexec) { -- struct aa_perms cp; -- info = "change_profile onexec"; -- new_profile = labels_profile(aa_get_newest_label(ctx->onexec)); -- if (!(perms.allow & AA_MAY_ONEXEC)) -- goto audit; -- -- /* test if this exec can be paired with change_profile onexec. -- * onexec permission is linked to exec with a standard pairing -- * exec\0change_profile -- */ -- state = aa_dfa_null_transition(profile->file.dfa, state); -- cp = change_profile_perms(profile, labels_ns(ctx->onexec), -- labels_profile(ctx->onexec)->base.name, -- AA_MAY_ONEXEC, state); -- -- if (!(cp.allow & AA_MAY_ONEXEC)) -- goto audit; -- goto apply; -- } -- -+ state = aa_str_perms(profile->file.dfa, state, name, cond, &perms); - if (perms.allow & MAY_EXEC) { - /* exec permission determine how to transition */ -- new_profile = x_to_profile(profile, name, perms.xindex); -- if (!new_profile) { -- if (perms.xindex & AA_X_INHERIT) { -- /* (p|c|n)ix - don't change profile but do -- * use the newest version, which was picked -- * up above when getting profile -- */ -- info = "ix fallback"; -- new_profile = aa_get_profile(profile); -- goto x_clear; -- } else if (perms.xindex & AA_X_UNCONFINED) { -- new_profile = aa_get_newest_profile(ns->unconfined); -- info = "ux fallback"; -- } else { -- error = -EACCES; -- info = "profile not found"; -- /* remove MAY_EXEC to audit as failure */ -- perms.allow &= ~MAY_EXEC; -- } -+ new = x_to_label(profile, name, perms.xindex, &target, &info); -+ if (new && new->proxy == profile->label.proxy && info) { -+ /* hack ix fallback - improve how this is detected */ -+ goto audit; -+ } else if (!new) { -+ error = -EACCES; -+ info = "profile transition not found"; -+ /* remove MAY_EXEC to audit as failure */ -+ perms.allow &= ~MAY_EXEC; - } - } else if (COMPLAIN_MODE(profile)) { -- /* no exec permission - are we in learning mode */ -- new_profile = aa_new_null_profile(profile, false, name, -- GFP_ATOMIC); -+ /* no exec permission - learning mode */ -+ struct aa_profile *new_profile = aa_new_null_profile(profile, -+ false, name, -+ GFP_ATOMIC); - if (!new_profile) { - error = -ENOMEM; - info = "could not create null profile"; -- } else -+ } else { - error = -EACCES; -+ new = &new_profile->label; -+ } - perms.xindex |= AA_X_UNSAFE; - } else - /* fail exec */ - error = -EACCES; - -- /* -- * Policy has specified a domain transition, if no_new_privs then -- * fail the exec. -+ if (!new) -+ goto audit; -+ -+ /* Policy has specified a domain transitions. if no_new_privs and -+ * confined and not transitioning to the current domain fail. -+ * -+ * NOTE: Domain transitions from unconfined and to stritly stacked -+ * subsets are allowed even when no_new_privs is set because this -+ * aways results in a further reduction of permissions. - */ -- if (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS) { -+ if ((bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS) && -+ !profile_unconfined(profile) && -+ !aa_label_is_subset(new, &profile->label)) { - error = -EPERM; -- goto cleanup; -+ info = "no new privs"; -+ nonewprivs = true; -+ perms.allow &= ~MAY_EXEC; -+ goto audit; -+ } -+ -+ if (!(perms.xindex & AA_X_UNSAFE)) { -+ if (DEBUG_ON) { -+ dbg_printk("apparmor: scrubbing environment variables" -+ " for %s profile=", name); -+ aa_label_printk(new, GFP_ATOMIC); -+ dbg_printk("\n"); -+ } -+ *secure_exec = true; - } - -- if (!new_profile) -+audit: -+ aa_audit_file(profile, &perms, OP_EXEC, MAY_EXEC, name, target, new, -+ cond->uid, info, error); -+ if (!new || nonewprivs) { -+ aa_put_label(new); -+ return ERR_PTR(error); -+ } -+ -+ return new; -+} -+ -+static int profile_onexec(struct aa_profile *profile, struct aa_label *onexec, -+ bool stack, const struct linux_binprm *bprm, -+ char *buffer, struct path_cond *cond, -+ bool *secure_exec) -+{ -+ unsigned int state = profile->file.start; -+ struct aa_perms perms = {}; -+ const char *xname = NULL, *info = "change_profile onexec"; -+ int error = -EACCES; -+ -+ AA_BUG(!profile); -+ AA_BUG(!onexec); -+ AA_BUG(!bprm); -+ AA_BUG(!buffer); -+ -+ if (profile_unconfined(profile)) { -+ /* change_profile on exec already granted */ -+ /* -+ * NOTE: Domain transitions from unconfined are allowed -+ * even when no_new_privs is set because this aways results -+ * in a further reduction of permissions. -+ */ -+ return 0; -+ } -+ -+ error = aa_path_name(&bprm->file->f_path, profile->path_flags, buffer, -+ &xname, &info, profile->disconnected); -+ if (error) { -+ if (profile_unconfined(profile) || -+ (profile->label.flags & FLAG_IX_ON_NAME_ERROR)) { -+ AA_DEBUG("name lookup ix on error"); -+ error = 0; -+ } -+ xname = bprm->filename; - goto audit; -+ } -+ -+ /* find exec permissions for name */ -+ state = aa_str_perms(profile->file.dfa, state, xname, cond, &perms); -+ if (!(perms.allow & AA_MAY_ONEXEC)) { -+ info = "no change_onexec valid for executable"; -+ goto audit; -+ } -+ /* test if this exec can be paired with change_profile onexec. -+ * onexec permission is linked to exec with a standard pairing -+ * exec\0change_profile -+ */ -+ state = aa_dfa_null_transition(profile->file.dfa, state); -+ error = change_profile_perms(profile, onexec, stack, AA_MAY_ONEXEC, -+ state, &perms); -+ if (error) { -+ perms.allow &= ~AA_MAY_ONEXEC; -+ goto audit; -+ } -+ /* Policy has specified a domain transitions. if no_new_privs and -+ * confined and not transitioning to the current domain fail. -+ * -+ * NOTE: Domain transitions from unconfined and to stritly stacked -+ * subsets are allowed even when no_new_privs is set because this -+ * aways results in a further reduction of permissions. -+ */ -+ if ((bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS) && -+ !profile_unconfined(profile) && -+ !aa_label_is_subset(onexec, &profile->label)) { -+ error = -EPERM; -+ info = "no new privs"; -+ perms.allow &= ~AA_MAY_ONEXEC; -+ goto audit; -+ } -+ -+ if (!(perms.xindex & AA_X_UNSAFE)) { -+ if (DEBUG_ON) { -+ dbg_printk("apparmor: scrubbing environment " -+ "variables for %s label=", xname); -+ aa_label_printk(onexec, GFP_ATOMIC); -+ dbg_printk("\n"); -+ } -+ *secure_exec = true; -+ } -+ -+audit: -+ return aa_audit_file(profile, &perms, OP_EXEC, AA_MAY_ONEXEC, xname, -+ NULL, onexec, cond->uid, info, error); -+} -+ -+/* ensure none ns domain transitions are correctly applied with onexec */ -+ -+static struct aa_label *handle_onexec(struct aa_label *label, -+ struct aa_label *onexec, bool stack, -+ const struct linux_binprm *bprm, -+ char *buffer, struct path_cond *cond, -+ bool *unsafe) -+{ -+ struct aa_profile *profile; -+ struct aa_label *new; -+ int error; -+ -+ AA_BUG(!label); -+ AA_BUG(!onexec); -+ AA_BUG(!bprm); -+ AA_BUG(!buffer); -+ -+ if (!stack) { -+ error = fn_for_each_in_ns(label, profile, -+ profile_onexec(profile, onexec, stack, -+ bprm, buffer, cond, unsafe)); -+ if (error) -+ return ERR_PTR(error); -+ new = fn_label_build_in_ns(label, profile, GFP_ATOMIC, -+ aa_get_newest_label(onexec), -+ profile_transition(profile, bprm, buffer, -+ cond, unsafe)); -+ -+ } else { -+ /* TODO: determine how much we want to losen this */ -+ error = fn_for_each_in_ns(label, profile, -+ profile_onexec(profile, onexec, stack, bprm, -+ buffer, cond, unsafe)); -+ if (error) -+ return ERR_PTR(error); -+ new = fn_label_build_in_ns(label, profile, GFP_ATOMIC, -+ aa_label_merge(&profile->label, onexec, -+ GFP_ATOMIC), -+ profile_transition(profile, bprm, buffer, -+ cond, unsafe)); -+ } -+ -+ if (new) -+ return new; -+ -+ /* TODO: get rid of GLOBAL_ROOT_UID */ -+ error = fn_for_each_in_ns(label, profile, -+ aa_audit_file(profile, &nullperms, OP_CHANGE_ONEXEC, -+ AA_MAY_ONEXEC, bprm->filename, NULL, -+ onexec, GLOBAL_ROOT_UID, -+ "failed to build target label", -ENOMEM)); -+ return ERR_PTR(error); -+} -+ -+/** -+ * apparmor_bprm_set_creds - set the new creds on the bprm struct -+ * @bprm: binprm for the exec (NOT NULL) -+ * -+ * Returns: %0 or error on failure -+ * -+ * TODO: once the other paths are done see if we can't refactor into a fn -+ */ -+int apparmor_bprm_set_creds(struct linux_binprm *bprm) -+{ -+ struct aa_task_ctx *ctx; -+ struct aa_label *label, *new = NULL; -+ struct aa_profile *profile; -+ char *buffer = NULL; -+ const char *info = NULL; -+ int error = 0; -+ bool unsafe = false; -+ struct path_cond cond = { -+ file_inode(bprm->file)->i_uid, -+ file_inode(bprm->file)->i_mode -+ }; -+ -+ if (bprm->cred_prepared) -+ return 0; -+ -+ ctx = cred_ctx(bprm->cred); -+ AA_BUG(!ctx); -+ -+ label = aa_get_newest_label(ctx->label); -+ -+ /* buffer freed below, name is pointer into buffer */ -+ get_buffers(buffer); -+ /* Test for onexec first as onexec override other x transitions. */ -+ if (ctx->onexec) -+ new = handle_onexec(label, ctx->onexec, ctx->token, -+ bprm, buffer, &cond, &unsafe); -+ else -+ new = fn_label_build(label, profile, GFP_ATOMIC, -+ profile_transition(profile, bprm, buffer, -+ &cond, &unsafe)); -+ -+ AA_BUG(!new); -+ if (IS_ERR(new)) { -+ error = PTR_ERR(new); -+ goto done; -+ } else if (!new) { -+ error = -ENOMEM; -+ goto done; -+ } -+ -+ /* TODO: Add ns level no_new_privs subset test */ - - if (bprm->unsafe & LSM_UNSAFE_SHARE) { - /* FIXME: currently don't mediate shared state */ - ; - } - -- if (bprm->unsafe & LSM_UNSAFE_PTRACE) { -- error = may_change_ptraced_domain(&new_profile->label, &info); -+ if (bprm->unsafe & (LSM_UNSAFE_PTRACE)) { -+ /* TODO: test needs to be profile of label to new */ -+ error = may_change_ptraced_domain(new, &info); - if (error) - goto audit; - } - -- /* Determine if secure exec is needed. -- * Can be at this point for the following reasons: -- * 1. unconfined switching to confined -- * 2. confined switching to different confinement -- * 3. confined switching to unconfined -- * -- * Cases 2 and 3 are marked as requiring secure exec -- * (unless policy specified "unsafe exec") -- * -- * bprm->unsafe is used to cache the AA_X_UNSAFE permission -- * to avoid having to recompute in secureexec -- */ -- if (!(perms.xindex & AA_X_UNSAFE)) { -- AA_DEBUG("scrubbing environment variables for %s profile=%s\n", -- name, new_profile->base.hname); -+ if (unsafe) { -+ if (DEBUG_ON) { -+ dbg_printk("scrubbing environment variables for %s " -+ "label=", bprm->filename); -+ aa_label_printk(new, GFP_ATOMIC); -+ dbg_printk("\n"); -+ } - bprm->unsafe |= AA_SECURE_X_NEEDED; - } --apply: -- /* when transitioning profiles clear unsafe personality bits */ -- bprm->per_clear |= PER_CLEAR_ON_SETID; - --x_clear: -+ if (label->proxy != new->proxy) { -+ /* when transitioning clear unsafe personality bits */ -+ if (DEBUG_ON) { -+ dbg_printk("apparmor: clearing unsafe personality " -+ "bits. %s label=", bprm->filename); -+ aa_label_printk(new, GFP_ATOMIC); -+ dbg_printk("\n"); -+ } -+ bprm->per_clear |= PER_CLEAR_ON_SETID; -+ } - aa_put_label(ctx->label); -- /* transfer new profile reference will be released when ctx is freed */ -- ctx->label = &new_profile->label; -- new_profile = NULL; -+ /* transfer reference, released when ctx is freed */ -+ ctx->label = new; - -- /* clear out all temporary/transitional state from the context */ -+done: -+ /* clear out temporary/transitional state from the context */ - aa_clear_task_ctx_trans(ctx); - --audit: -- error = aa_audit_file(profile, &perms, OP_EXEC, MAY_EXEC, name, -- new_profile ? new_profile->base.hname : NULL, -- new_profile ? &new_profile->label : NULL, -- cond.uid, info, error); -- --cleanup: -- aa_put_profile(new_profile); - aa_put_label(label); - put_buffers(buffer); - - return error; -+ -+audit: -+ error = fn_for_each(label, profile, -+ aa_audit_file(profile, &nullperms, OP_EXEC, MAY_EXEC, -+ bprm->filename, NULL, new, -+ file_inode(bprm->file)->i_uid, info, -+ error)); -+ aa_put_label(new); -+ goto done; - } - - /** -@@ -778,8 +1112,8 @@ int aa_change_profile(const char *fqname, int flags) - } - } - -- perms = change_profile_perms(profile, target->ns, target->base.hname, -- request, profile->file.start); -+ perms = change_profile_perms_wrapper(profile, target, request, -+ profile->file.start); - if (!(perms.allow & request)) { - error = -EACCES; - goto audit; -diff --git a/security/apparmor/include/lib.h b/security/apparmor/include/lib.h -index 593877d38088..436b3a722357 100644 ---- a/security/apparmor/include/lib.h -+++ b/security/apparmor/include/lib.h -@@ -211,4 +211,89 @@ 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); - --#endif /* AA_LIB_H */ -+ -+/* -+ * 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 */ --- -2.12.3 - diff --git a/patches.apparmor/0060-apparmor-move-change_hat-mediation-to-using-labels.patch b/patches.apparmor/0060-apparmor-move-change_hat-mediation-to-using-labels.patch deleted file mode 100644 index 6496f20..0000000 --- a/patches.apparmor/0060-apparmor-move-change_hat-mediation-to-using-labels.patch +++ /dev/null @@ -1,385 +0,0 @@ -From c1156392ac099bdf755a9b680034240af6ee70ea Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Fri, 9 Jun 2017 17:01:43 -0700 -Subject: [PATCH 60/65] apparmor: move change_hat mediation to using labels -Git-commit: 89dbf1962aa636341658c26034c0e113cc9d1776 -Patch-mainline: v4.13-rc1 -References: FATE#323500 - -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/domain.c | 303 ++++++++++++++++++++++++++++++--------------- - 1 file changed, 201 insertions(+), 102 deletions(-) - -diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c -index cb8509373ea3..a1d73033b42e 100644 ---- a/security/apparmor/domain.c -+++ b/security/apparmor/domain.c -@@ -884,19 +884,153 @@ int apparmor_bprm_secureexec(struct linux_binprm *bprm) - * Functions for self directed profile change - */ - --/** -- * new_compound_name - create an hname with @n2 appended to @n1 -- * @n1: base of hname (NOT NULL) -- * @n2: name to append (NOT NULL) -+ -+/* helper fn for change_hat - * -- * Returns: new name or NULL on error -+ * Returns: label for hat transition OR ERR_PTR. Does NOT return NULL - */ --static char *new_compound_name(const char *n1, const char *n2) -+static struct aa_label *build_change_hat(struct aa_profile *profile, -+ const char *name, bool sibling) - { -- char *name = kmalloc(strlen(n1) + strlen(n2) + 3, GFP_KERNEL); -- if (name) -- sprintf(name, "%s//%s", n1, n2); -- return name; -+ struct aa_profile *root, *hat = NULL; -+ const char *info = NULL; -+ int error = 0; -+ -+ if (sibling && PROFILE_IS_HAT(profile)) { -+ root = aa_get_profile_rcu(&profile->parent); -+ } else if (!sibling && !PROFILE_IS_HAT(profile)) { -+ root = aa_get_profile(profile); -+ } else { -+ info = "conflicting target types"; -+ error = -EPERM; -+ goto audit; -+ } -+ -+ hat = aa_find_child(root, name); -+ if (!hat) { -+ error = -ENOENT; -+ if (COMPLAIN_MODE(profile)) { -+ hat = aa_new_null_profile(profile, true, name, -+ GFP_KERNEL); -+ if (!hat) { -+ info = "failed null profile create"; -+ error = -ENOMEM; -+ } -+ } -+ } -+ aa_put_profile(root); -+ -+audit: -+ aa_audit_file(profile, &nullperms, OP_CHANGE_HAT, AA_MAY_CHANGEHAT, -+ name, hat ? hat->base.hname : NULL, -+ hat ? &hat->label : NULL, GLOBAL_ROOT_UID, NULL, -+ error); -+ if (!hat || (error && error != -ENOENT)) -+ return ERR_PTR(error); -+ /* if hat && error - complain mode, already audited and we adjust for -+ * complain mode allow by returning hat->label -+ */ -+ return &hat->label; -+} -+ -+/* helper fn for changing into a hat -+ * -+ * Returns: label for hat transition or ERR_PTR. Does not return NULL -+ */ -+static struct aa_label *change_hat(struct aa_label *label, const char *hats[], -+ int count, int flags) -+{ -+ struct aa_profile *profile, *root, *hat = NULL; -+ struct aa_label *new; -+ struct label_it it; -+ bool sibling = false; -+ const char *name, *info = NULL; -+ int i, error; -+ -+ AA_BUG(!label); -+ AA_BUG(!hats); -+ AA_BUG(count < 1); -+ -+ if (PROFILE_IS_HAT(labels_profile(label))) -+ sibling = true; -+ -+ /*find first matching hat */ -+ for (i = 0; i < count && !hat; i++) { -+ name = hats[i]; -+ label_for_each_in_ns(it, labels_ns(label), label, profile) { -+ if (sibling && PROFILE_IS_HAT(profile)) { -+ root = aa_get_profile_rcu(&profile->parent); -+ } else if (!sibling && !PROFILE_IS_HAT(profile)) { -+ root = aa_get_profile(profile); -+ } else { /* conflicting change type */ -+ info = "conflicting targets types"; -+ error = -EPERM; -+ goto fail; -+ } -+ hat = aa_find_child(root, name); -+ aa_put_profile(root); -+ if (!hat) { -+ if (!COMPLAIN_MODE(profile)) -+ goto outer_continue; -+ /* complain mode succeed as if hat */ -+ } else if (!PROFILE_IS_HAT(hat)) { -+ info = "target not hat"; -+ error = -EPERM; -+ aa_put_profile(hat); -+ goto fail; -+ } -+ aa_put_profile(hat); -+ } -+ /* found a hat for all profiles in ns */ -+ goto build; -+outer_continue: -+ ; -+ } -+ /* no hats that match, find appropriate error -+ * -+ * In complain mode audit of the failure is based off of the first -+ * hat supplied. This is done due how userspace interacts with -+ * change_hat. -+ */ -+ name = NULL; -+ label_for_each_in_ns(it, labels_ns(label), label, profile) { -+ if (!list_empty(&profile->base.profiles)) { -+ info = "hat not found"; -+ error = -ENOENT; -+ goto fail; -+ } -+ } -+ info = "no hats defined"; -+ error = -ECHILD; -+ -+fail: -+ label_for_each_in_ns(it, labels_ns(label), label, profile) { -+ /* -+ * no target as it has failed to be found or built -+ * -+ * change_hat uses probing and should not log failures -+ * related to missing hats -+ */ -+ /* TODO: get rid of GLOBAL_ROOT_UID */ -+ if (count > 1 || COMPLAIN_MODE(profile)) { -+ aa_audit_file(profile, &nullperms, OP_CHANGE_HAT, -+ AA_MAY_CHANGEHAT, name, NULL, NULL, -+ GLOBAL_ROOT_UID, info, error); -+ } -+ } -+ return ERR_PTR(error); -+ -+build: -+ new = fn_label_build_in_ns(label, profile, GFP_KERNEL, -+ build_change_hat(profile, name, sibling), -+ aa_get_label(&profile->label)); -+ if (!new) { -+ info = "label build failed"; -+ error = -ENOMEM; -+ goto fail; -+ } /* else if (IS_ERR) build_change_hat has logged error so return new */ -+ -+ return new; - } - - /** -@@ -906,23 +1040,24 @@ static char *new_compound_name(const char *n1, const char *n2) - * @token: magic value to validate the hat change - * @flags: flags affecting behavior of the change - * -+ * Returns %0 on success, error otherwise. -+ * - * Change to the first profile specified in @hats that exists, and store - * the @hat_magic in the current task context. If the count == 0 and the - * @token matches that stored in the current task context, return to the - * top level profile. - * -- * Returns %0 on success, error otherwise. -+ * change_hat only applies to profiles in the current ns, and each profile -+ * in the ns must make the same transition otherwise change_hat will fail. - */ - int aa_change_hat(const char *hats[], int count, u64 token, int flags) - { - const struct cred *cred; - struct aa_task_ctx *ctx; -- struct aa_label *label, *previous_label; -- struct aa_profile *profile, *hat = NULL; -- char *name = NULL; -- int i; -+ struct aa_label *label, *previous, *new = NULL, *target = NULL; -+ struct aa_profile *profile; - struct aa_perms perms = {}; -- const char *target = NULL, *info = NULL; -+ const char *info = NULL; - int error = 0; - - /* -@@ -930,118 +1065,82 @@ int aa_change_hat(const char *hats[], int count, u64 token, int flags) - * There is no exception for unconfined as change_hat is not - * available. - */ -- if (task_no_new_privs(current)) -+ if (task_no_new_privs(current)) { -+ /* not an apparmor denial per se, so don't log it */ -+ AA_DEBUG("no_new_privs - change_hat denied"); - return -EPERM; -+ } - - /* released below */ - cred = get_current_cred(); - ctx = cred_ctx(cred); - label = aa_get_newest_cred_label(cred); -- previous_label = aa_get_newest_label(ctx->previous); -- profile = labels_profile(label); -+ previous = aa_get_newest_label(ctx->previous); - - if (unconfined(label)) { -- info = "unconfined"; -+ info = "unconfined can not change_hat"; - error = -EPERM; -- goto audit; -+ goto fail; - } - - if (count) { -- /* attempting to change into a new hat or switch to a sibling */ -- struct aa_profile *root; -- if (PROFILE_IS_HAT(profile)) -- root = aa_get_profile_rcu(&profile->parent); -- else -- root = aa_get_profile(profile); -- -- /* find first matching hat */ -- for (i = 0; i < count && !hat; i++) -- /* released below */ -- hat = aa_find_child(root, hats[i]); -- if (!hat) { -- if (!COMPLAIN_MODE(root) || (flags & AA_CHANGE_TEST)) { -- if (list_empty(&root->base.profiles)) -- error = -ECHILD; -- else -- error = -ENOENT; -- aa_put_profile(root); -- goto out; -- } -- -- /* -- * In complain mode and failed to match any hats. -- * Audit the failure is based off of the first hat -- * supplied. This is done due how userspace -- * interacts with change_hat. -- * -- * TODO: Add logging of all failed hats -- */ -- -- /* freed below */ -- name = new_compound_name(root->base.hname, hats[0]); -- aa_put_profile(root); -- target = name; -- /* released below */ -- hat = aa_new_null_profile(profile, true, hats[0], -- GFP_KERNEL); -- if (!hat) { -- info = "failed null profile create"; -- error = -ENOMEM; -- goto audit; -- } -- } else { -- aa_put_profile(root); -- target = hat->base.hname; -- if (!PROFILE_IS_HAT(hat)) { -- info = "target not hat"; -- error = -EPERM; -- goto audit; -- } -+ new = change_hat(label, hats, count, flags); -+ AA_BUG(!new); -+ if (IS_ERR(new)) { -+ error = PTR_ERR(new); -+ new = NULL; -+ /* already audited */ -+ goto out; - } - -- error = may_change_ptraced_domain(&hat->label, &info); -- if (error) { -- info = "ptraced"; -- error = -EPERM; -- goto audit; -- } -+ error = may_change_ptraced_domain(new, &info); -+ if (error) -+ goto fail; - -- if (!(flags & AA_CHANGE_TEST)) { -- error = aa_set_current_hat(&hat->label, token); -- if (error == -EACCES) -- /* kill task in case of brute force attacks */ -- perms.kill = AA_MAY_CHANGEHAT; -- else if (name && !error) -- /* reset error for learning of new hats */ -- error = -ENOENT; -- } -- } else if (previous_label) { -- /* Return to saved profile. Kill task if restore fails -+ if (flags & AA_CHANGE_TEST) -+ goto out; -+ -+ target = new; -+ error = aa_set_current_hat(new, token); -+ if (error == -EACCES) -+ /* kill task in case of brute force attacks */ -+ goto kill; -+ } else if (previous && !(flags & AA_CHANGE_TEST)) { -+ /* Return to saved label. Kill task if restore fails - * to avoid brute force attacks - */ -- target = previous_label->hname; -+ target = previous; - error = aa_restore_previous_label(token); -- perms.kill = AA_MAY_CHANGEHAT; -- } else -- /* ignore restores when there is no saved profile */ -- goto out; -- --audit: -- if (!(flags & AA_CHANGE_TEST)) -- error = aa_audit_file(profile, &perms, OP_CHANGE_HAT, -- AA_MAY_CHANGEHAT, NULL, target, NULL, -- GLOBAL_ROOT_UID, info, error); -+ if (error) { -+ if (error == -EACCES) -+ goto kill; -+ goto fail; -+ } -+ } /* else ignore @flags && restores when there is no saved profile */ - - out: -- aa_put_profile(hat); -- kfree(name); -+ aa_put_label(new); -+ aa_put_label(previous); - aa_put_label(label); -- aa_put_label(previous_label); - put_cred(cred); - - return error; -+ -+kill: -+ info = "failed token match"; -+ perms.kill = AA_MAY_CHANGEHAT; -+ -+fail: -+ fn_for_each_in_ns(label, profile, -+ aa_audit_file(profile, &perms, OP_CHANGE_HAT, -+ AA_MAY_CHANGEHAT, NULL, NULL, target, -+ GLOBAL_ROOT_UID, info, error)); -+ -+ goto out; - } - -+ -+ - /** - * aa_change_profile - perform a one-way profile transition - * @fqname: name of profile may include namespace (NOT NULL) --- -2.12.3 - diff --git a/patches.apparmor/0061-apparmor-move-change_profile-mediation-to-using-labe.patch b/patches.apparmor/0061-apparmor-move-change_profile-mediation-to-using-labe.patch deleted file mode 100644 index 6fdcbd4..0000000 --- a/patches.apparmor/0061-apparmor-move-change_profile-mediation-to-using-labe.patch +++ /dev/null @@ -1,268 +0,0 @@ -From 74f96ddbc58f30ac52a3b5de2dc18aba10e3bb35 Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Fri, 9 Jun 2017 17:07:58 -0700 -Subject: [PATCH 61/65] apparmor: move change_profile mediation to using labels -Git-commit: e00b02bb6ac2a1893227ce8014b649028d6425d2 -Patch-mainline: v4.13-rc1 -References: FATE#323500 - -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/domain.c | 191 +++++++++++++++++++++++++++++---------------- - 1 file changed, 123 insertions(+), 68 deletions(-) - -diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c -index a1d73033b42e..d0594446ae3f 100644 ---- a/security/apparmor/domain.c -+++ b/security/apparmor/domain.c -@@ -301,26 +301,6 @@ static int change_profile_perms(struct aa_profile *profile, - return label_match(profile, target, stack, start, true, request, perms); - } - --static struct aa_perms change_profile_perms_wrapper(struct aa_profile *profile, -- struct aa_profile *target, -- u32 request, -- unsigned int start) --{ -- struct aa_perms perms; -- -- if (profile_unconfined(profile)) { -- perms.allow = AA_MAY_CHANGE_PROFILE | AA_MAY_ONEXEC; -- perms.audit = perms.quiet = perms.kill = 0; -- return perms; -- } -- -- if (change_profile_perms(profile, &target->label, false, request, -- start, &perms)) -- return nullperms; -- -- return perms; --} -- - /** - * __attach_match_ - find an attachment match - * @name - to match against (NOT NULL) -@@ -1140,6 +1120,39 @@ int aa_change_hat(const char *hats[], int count, u64 token, int flags) - } - - -+static int change_profile_perms_wrapper(const char *op, const char *name, -+ struct aa_profile *profile, -+ struct aa_label *target, bool stack, -+ u32 request, struct aa_perms *perms) -+{ -+ const char *info = NULL; -+ int error = 0; -+ -+ /* -+ * Fail explicitly requested domain transitions when no_new_privs -+ * and not unconfined OR the transition results in a stack on -+ * the current label. -+ * Stacking domain transitions and transitions from unconfined are -+ * allowed even when no_new_privs is set because this aways results -+ * in a reduction of permissions. -+ */ -+ if (task_no_new_privs(current) && !stack && -+ !profile_unconfined(profile) && -+ !aa_label_is_subset(target, &profile->label)) { -+ info = "no new privs"; -+ error = -EPERM; -+ } -+ -+ if (!error) -+ error = change_profile_perms(profile, target, stack, request, -+ profile->file.start, perms); -+ if (error) -+ error = aa_audit_file(profile, perms, op, request, name, -+ NULL, target, GLOBAL_ROOT_UID, info, -+ error); -+ -+ return error; -+} - - /** - * aa_change_profile - perform a one-way profile transition -@@ -1157,12 +1170,14 @@ int aa_change_hat(const char *hats[], int count, u64 token, int flags) - */ - int aa_change_profile(const char *fqname, int flags) - { -- const struct cred *cred; -- struct aa_label *label; -- struct aa_profile *profile, *target = NULL; -+ struct aa_label *label, *new = NULL, *target = NULL; -+ struct aa_profile *profile; - struct aa_perms perms = {}; -- const char *info = NULL, *op; -+ const char *info = NULL; -+ const char *auditname = fqname; /* retain leading & if stack */ -+ bool stack = flags & AA_CHANGE_STACK; - int error = 0; -+ char *op; - u32 request; - - if (!fqname || !*fqname) { -@@ -1172,76 +1187,116 @@ int aa_change_profile(const char *fqname, int flags) - - if (flags & AA_CHANGE_ONEXEC) { - request = AA_MAY_ONEXEC; -- op = OP_CHANGE_ONEXEC; -+ if (stack) -+ op = OP_STACK_ONEXEC; -+ else -+ op = OP_CHANGE_ONEXEC; - } else { - request = AA_MAY_CHANGE_PROFILE; -- op = OP_CHANGE_PROFILE; -+ if (stack) -+ op = OP_STACK; -+ else -+ op = OP_CHANGE_PROFILE; - } - -- cred = get_current_cred(); -- label = aa_get_newest_cred_label(cred); -- profile = labels_profile(label); -+ label = aa_get_current_label(); - -- /* -- * Fail explicitly requested domain transitions if no_new_privs -- * and not unconfined. -- * Domain transitions from unconfined are allowed even when -- * no_new_privs is set because this aways results in a reduction -- * of permissions. -- */ -- if (task_no_new_privs(current) && !profile_unconfined(profile)) { -- put_cred(cred); -- return -EPERM; -+ if (*fqname == '&') { -+ stack = true; -+ /* don't have label_parse() do stacking */ -+ fqname++; - } -+ target = aa_label_parse(label, fqname, GFP_KERNEL, true, false); -+ if (IS_ERR(target)) { -+ struct aa_profile *tprofile; - -- target = aa_fqlookupn_profile(label, fqname, strlen(fqname)); -- if (!target) { -- info = "profile not found"; -- error = -ENOENT; -+ info = "label not found"; -+ error = PTR_ERR(target); -+ target = NULL; -+ /* -+ * TODO: fixme using labels_profile is not right - do profile -+ * per complain profile -+ */ - if ((flags & AA_CHANGE_TEST) || -- !COMPLAIN_MODE(profile)) -+ !COMPLAIN_MODE(labels_profile(label))) - goto audit; - /* released below */ -- target = aa_new_null_profile(profile, false, fqname, -- GFP_KERNEL); -- if (!target) { -+ tprofile = aa_new_null_profile(labels_profile(label), false, -+ fqname, GFP_KERNEL); -+ if (!tprofile) { - info = "failed null profile create"; - error = -ENOMEM; - goto audit; - } -+ target = &tprofile->label; -+ goto check; - } - -- perms = change_profile_perms_wrapper(profile, target, request, -- profile->file.start); -- if (!(perms.allow & request)) { -- error = -EACCES; -- goto audit; -- } -+ /* -+ * self directed transitions only apply to current policy ns -+ * TODO: currently requiring perms for stacking and straight change -+ * stacking doesn't strictly need this. Determine how much -+ * we want to loosen this restriction for stacking -+ * -+ * if (!stack) { -+ */ -+ error = fn_for_each_in_ns(label, profile, -+ change_profile_perms_wrapper(op, auditname, -+ profile, target, stack, -+ request, &perms)); -+ if (error) -+ /* auditing done in change_profile_perms_wrapper */ -+ goto out; - -+ /* } */ -+ -+check: - /* check if tracing task is allowed to trace target domain */ -- error = may_change_ptraced_domain(&target->label, &info); -- if (error) { -- info = "ptrace prevents transition"; -+ error = may_change_ptraced_domain(target, &info); -+ if (error && !fn_for_each_in_ns(label, profile, -+ COMPLAIN_MODE(profile))) - goto audit; -- } - -+ /* TODO: add permission check to allow this -+ * if ((flags & AA_CHANGE_ONEXEC) && !current_is_single_threaded()) { -+ * info = "not a single threaded task"; -+ * error = -EACCES; -+ * goto audit; -+ * } -+ */ - if (flags & AA_CHANGE_TEST) -- goto audit; -+ goto out; - -- if (flags & AA_CHANGE_ONEXEC) -- error = aa_set_current_onexec(&target->label, 0); -- else -- error = aa_replace_current_label(&target->label); -+ if (!(flags & AA_CHANGE_ONEXEC)) { -+ /* only transition profiles in the current ns */ -+ if (stack) -+ new = aa_label_merge(label, target, GFP_KERNEL); -+ else -+ new = fn_label_build_in_ns(label, profile, GFP_KERNEL, -+ aa_get_label(target), -+ aa_get_label(&profile->label)); -+ if (IS_ERR_OR_NULL(new)) { -+ info = "failed to build target label"; -+ error = PTR_ERR(new); -+ new = NULL; -+ perms.allow = 0; -+ goto audit; -+ } -+ error = aa_replace_current_label(new); -+ } else -+ /* full transition will be built in exec path */ -+ error = aa_set_current_onexec(target, stack); - - audit: -- if (!(flags & AA_CHANGE_TEST)) -- error = aa_audit_file(profile, &perms, op, request, NULL, -- fqname, NULL, GLOBAL_ROOT_UID, info, -- error); -+ error = fn_for_each_in_ns(label, profile, -+ aa_audit_file(profile, &perms, op, request, auditname, -+ NULL, new ? new : target, -+ GLOBAL_ROOT_UID, info, error)); - -- aa_put_profile(target); -+out: -+ aa_put_label(new); -+ aa_put_label(target); - aa_put_label(label); -- put_cred(cred); - - return error; - } --- -2.12.3 - diff --git a/patches.apparmor/0062-apparmor-add-domain-label-stacking-info-to-apparmorf.patch b/patches.apparmor/0062-apparmor-add-domain-label-stacking-info-to-apparmorf.patch deleted file mode 100644 index cd6e289..0000000 --- a/patches.apparmor/0062-apparmor-add-domain-label-stacking-info-to-apparmorf.patch +++ /dev/null @@ -1,101 +0,0 @@ -From f4e764a0e945d7945dee901c6322f2f6e3315325 Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Fri, 9 Jun 2017 17:11:17 -0700 -Subject: [PATCH 62/65] apparmor: add domain label stacking info to apparmorfs -Git-commit: 40cde7fcc344bc77c1ec9d291dcc35ab12f078aa -Patch-mainline: v4.13-rc1 -References: FATE#323500 - -Now that the domain label transition is complete advertise it to -userspace. - -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/apparmorfs.c | 36 ++++++++++++++++++++++++++++++++++++ - security/apparmor/include/audit.h | 2 ++ - security/apparmor/include/domain.h | 1 + - 3 files changed, 39 insertions(+) - -diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c -index e460f2d8337d..6310bf1485b6 100644 ---- a/security/apparmor/apparmorfs.c -+++ b/security/apparmor/apparmorfs.c -@@ -1138,6 +1138,40 @@ static const struct file_operations seq_ns_ ##NAME ##_fops = { \ - .release = single_release, \ - } \ - -+static int seq_ns_stacked_show(struct seq_file *seq, void *v) -+{ -+ struct aa_label *label; -+ -+ label = begin_current_label_crit_section(); -+ seq_printf(seq, "%s\n", label->size > 1 ? "yes" : "no"); -+ end_current_label_crit_section(label); -+ -+ return 0; -+} -+ -+static int seq_ns_nsstacked_show(struct seq_file *seq, void *v) -+{ -+ struct aa_label *label; -+ struct aa_profile *profile; -+ struct label_it it; -+ int count = 1; -+ -+ label = begin_current_label_crit_section(); -+ -+ if (label->size > 1) { -+ label_for_each(it, label, profile) -+ if (profile->ns != labels_ns(label)) { -+ count++; -+ break; -+ } -+ } -+ -+ seq_printf(seq, "%s\n", count > 1 ? "yes" : "no"); -+ end_current_label_crit_section(label); -+ -+ return 0; -+} -+ - static int seq_ns_level_show(struct seq_file *seq, void *v) - { - struct aa_label *label; -@@ -1160,6 +1194,8 @@ static int seq_ns_name_show(struct seq_file *seq, void *v) - return 0; - } - -+SEQ_NS_FOPS(stacked); -+SEQ_NS_FOPS(nsstacked); - SEQ_NS_FOPS(level); - SEQ_NS_FOPS(name); - -diff --git a/security/apparmor/include/audit.h b/security/apparmor/include/audit.h -index 99ed83cf6941..c68839a44351 100644 ---- a/security/apparmor/include/audit.h -+++ b/security/apparmor/include/audit.h -@@ -92,6 +92,8 @@ enum audit_type { - #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" -diff --git a/security/apparmor/include/domain.h b/security/apparmor/include/domain.h -index 255aa40ec1d1..bab5810b6e9a 100644 ---- a/security/apparmor/include/domain.h -+++ b/security/apparmor/include/domain.h -@@ -27,6 +27,7 @@ struct aa_domain { - #define AA_CHANGE_TEST 1 - #define AA_CHANGE_CHILD 2 - #define AA_CHANGE_ONEXEC 4 -+#define AA_CHANGE_STACK 8 - - int apparmor_bprm_set_creds(struct linux_binprm *bprm); - int apparmor_bprm_secureexec(struct linux_binprm *bprm); --- -2.12.3 - diff --git a/patches.apparmor/0063-apparmor-add-stacked-domain-labels-interface.patch b/patches.apparmor/0063-apparmor-add-stacked-domain-labels-interface.patch deleted file mode 100644 index d919bfa..0000000 --- a/patches.apparmor/0063-apparmor-add-stacked-domain-labels-interface.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 8f8f414e28dc4d92ed8b98f18f32e2c58f37f726 Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Fri, 9 Jun 2017 17:22:50 -0700 -Subject: [PATCH 63/65] apparmor: add stacked domain labels interface -Git-commit: 6c5fc8f17a2528052bace1d91a3bef003bd1331d -Patch-mainline: v4.13-rc1 -References: FATE#323500 - -Update the user interface to support the stacked change_profile transition. - -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/apparmorfs.c | 3 +++ - security/apparmor/lsm.c | 5 +++++ - 2 files changed, 8 insertions(+) - -diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c -index 6310bf1485b6..229845009a95 100644 ---- a/security/apparmor/apparmorfs.c -+++ b/security/apparmor/apparmorfs.c -@@ -2132,6 +2132,7 @@ static struct aa_sfs_entry aa_sfs_entry_domain[] = { - AA_SFS_FILE_BOOLEAN("change_hatv", 1), - AA_SFS_FILE_BOOLEAN("change_onexec", 1), - AA_SFS_FILE_BOOLEAN("change_profile", 1), -+ AA_SFS_FILE_BOOLEAN("stack", 1), - AA_SFS_FILE_BOOLEAN("fix_binfmt_elf_mmap", 1), - AA_SFS_FILE_STRING("version", "1.2"), - { } -@@ -2175,6 +2176,8 @@ static struct aa_sfs_entry aa_sfs_entry_features[] = { - - static struct aa_sfs_entry aa_sfs_entry_apparmor[] = { - AA_SFS_FILE_FOPS(".access", 0640, &aa_sfs_access), -+ AA_SFS_FILE_FOPS(".stacked", 0444, &seq_ns_stacked_fops), -+ AA_SFS_FILE_FOPS(".ns_stacked", 0444, &seq_ns_nsstacked_fops), - AA_SFS_FILE_FOPS(".ns_level", 0666, &seq_ns_level_fops), - AA_SFS_FILE_FOPS(".ns_name", 0640, &seq_ns_name_fops), - AA_SFS_FILE_FOPS("profiles", 0440, &aa_sfs_profiles_fops), -diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c -index 0f7c5c2be732..867bcd154c7e 100644 ---- a/security/apparmor/lsm.c -+++ b/security/apparmor/lsm.c -@@ -580,11 +580,16 @@ static int apparmor_setprocattr(const char *name, void *value, - error = aa_change_profile(args, AA_CHANGE_NOFLAGS); - } else if (strcmp(command, "permprofile") == 0) { - error = aa_change_profile(args, AA_CHANGE_TEST); -+ } else if (strcmp(command, "stack") == 0) { -+ error = aa_change_profile(args, AA_CHANGE_STACK); - } else - goto fail; - } else if (strcmp(name, "exec") == 0) { - if (strcmp(command, "exec") == 0) - error = aa_change_profile(args, AA_CHANGE_ONEXEC); -+ else if (strcmp(command, "stack") == 0) -+ error = aa_change_profile(args, (AA_CHANGE_ONEXEC | -+ AA_CHANGE_STACK)); - else - goto fail; - } else --- -2.12.3 - diff --git a/patches.apparmor/0064-apparmor-export-that-basic-profile-namespaces-are-su.patch b/patches.apparmor/0064-apparmor-export-that-basic-profile-namespaces-are-su.patch deleted file mode 100644 index 6e599ab..0000000 --- a/patches.apparmor/0064-apparmor-export-that-basic-profile-namespaces-are-su.patch +++ /dev/null @@ -1,46 +0,0 @@ -From f8613ce96619201ec9038082903b70899f6a107f Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Fri, 9 Jun 2017 17:25:03 -0700 -Subject: [PATCH 64/65] apparmor: export that basic profile namespaces are - supported -Git-commit: 33f2eadabba59cf1c763c46c4470279ec2054099 -Patch-mainline: v4.13-rc1 -References: FATE#323500 - -Allow userspace to detect that basic profile policy namespaces are -available. - -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/apparmorfs.c | 7 +++++++ - 1 file changed, 7 insertions(+) - -diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c -index 229845009a95..853c2ec8e0c9 100644 ---- a/security/apparmor/apparmorfs.c -+++ b/security/apparmor/apparmorfs.c -@@ -2151,6 +2151,12 @@ static struct aa_sfs_entry aa_sfs_entry_policy[] = { - { } - }; - -+static struct aa_sfs_entry aa_sfs_entry_ns[] = { -+ AA_SFS_FILE_BOOLEAN("profile", 1), -+ AA_SFS_FILE_BOOLEAN("pivot_root", 1), -+ { } -+}; -+ - static struct aa_sfs_entry aa_sfs_entry_query_label[] = { - AA_SFS_FILE_STRING("perms", "allow deny audit quiet"), - AA_SFS_FILE_BOOLEAN("data", 1), -@@ -2166,6 +2172,7 @@ static struct aa_sfs_entry aa_sfs_entry_features[] = { - AA_SFS_DIR("policy", aa_sfs_entry_policy), - AA_SFS_DIR("domain", aa_sfs_entry_domain), - AA_SFS_DIR("file", aa_sfs_entry_file), -+ AA_SFS_DIR("namespaces", aa_sfs_entry_ns), - AA_SFS_FILE_U64("capability", VFS_CAP_FLAGS_MASK), - AA_SFS_DIR("rlimit", aa_sfs_entry_rlimit), - AA_SFS_DIR("caps", aa_sfs_entry_caps), --- -2.12.3 - diff --git a/patches.apparmor/0065-apparmor-put-back-designators-in-struct-initialisers.patch b/patches.apparmor/0065-apparmor-put-back-designators-in-struct-initialisers.patch deleted file mode 100644 index 892f9b9..0000000 --- a/patches.apparmor/0065-apparmor-put-back-designators-in-struct-initialisers.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 47c8757fb4c9bf4906ebb1f9fa8b341035aa031f Mon Sep 17 00:00:00 2001 -From: Stephen Rothwell -Date: Tue, 20 Jun 2017 14:50:36 +1000 -Subject: [PATCH 65/65] apparmor: put back designators in struct initialisers -Patch-mainline: v4.13-rc1 -References: FATE#323500 -Git-commit: c4758fa59285fe4dbfeab4364a6957936d040fbf - -Fixes: 8014370f1257 ("apparmor: move path_link mediation to using labels") -Acked-by: Goldwyn Rodrigues -Signed-off-by: Stephen Rothwell -Acked-by: John Johansen -Acked-by: Kees Cook -Signed-off-by: James Morris ---- - security/apparmor/file.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/security/apparmor/file.c b/security/apparmor/file.c -index b6e8e5b11e05..3382518b87fa 100644 ---- a/security/apparmor/file.c -+++ b/security/apparmor/file.c -@@ -472,8 +472,8 @@ static int profile_path_link(struct aa_profile *profile, - int aa_path_link(struct aa_label *label, struct dentry *old_dentry, - const struct path *new_dir, struct dentry *new_dentry) - { -- struct path link = { new_dir->mnt, new_dentry }; -- struct path target = { new_dir->mnt, old_dentry }; -+ struct path link = { .mnt = new_dir->mnt, .dentry = new_dentry }; -+ struct path target = { .mnt = new_dir->mnt, .dentry = old_dentry }; - struct path_cond cond = { - d_backing_inode(old_dentry)->i_uid, - d_backing_inode(old_dentry)->i_mode --- -2.12.3 - diff --git a/patches.apparmor/apparmor-Fix-regression-in-profile-conflict-logic.patch b/patches.apparmor/apparmor-Fix-regression-in-profile-conflict-logic.patch deleted file mode 100644 index 6c2c8e1..0000000 --- a/patches.apparmor/apparmor-Fix-regression-in-profile-conflict-logic.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 1a3881d305592d947ed47887306919d50112394d Mon Sep 17 00:00:00 2001 -From: Matthew Garrett -Date: Thu Jan 11 13:07:54 2018 -0800 -Subject: [PATCH] apparmor: Fix regression in profile conflict logic -Git-commit: 1a3881d305592d947ed47887306919d50112394d -References: bsc#1106427 -Patch-mainline: v4.15-rc8 - -The intended behaviour in apparmor profile matching is to flag a -conflict if two profiles match equally well. However, right now a -conflict is generated if another profile has the same match length even -if that profile doesn't actually match. Fix the logic so we only -generate a conflict if the profiles match. - -Fixes: 844b8292b631 ("apparmor: ensure that undecidable profile attachments fail") -Cc: Stable -Signed-off-by: Matthew Garrett -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues - -diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c -index 04ba9d0..6a54d2f 100644 - ---- a/security/apparmor/domain.c -+++ b/security/apparmor/domain.c -@@ -330,10 +330,7 @@ static struct aa_profile *__attach_match(const char *name, - continue; - - if (profile->xmatch) { -- if (profile->xmatch_len == len) { -- conflict = true; -- continue; -- } else if (profile->xmatch_len > len) { -+ if (profile->xmatch_len >= len) { - unsigned int state; - u32 perm; - -@@ -342,6 +339,10 @@ static struct aa_profile *__attach_match(const char *name, - perm = dfa_user_allow(profile->xmatch, state); - /* any accepting state means a valid match. */ - if (perm & MAY_EXEC) { -+ if (profile->xmatch_len == len) { -+ conflict = true; -+ continue; -+ } - candidate = profile; - len = profile->xmatch_len; - conflict = false; diff --git a/patches.apparmor/apparmor-basic-networking-rules-4.11-rc1.patch b/patches.apparmor/apparmor-basic-networking-rules-4.11-rc1.patch index 6b4aa88..5983ce5 100644 --- a/patches.apparmor/apparmor-basic-networking-rules-4.11-rc1.patch +++ b/patches.apparmor/apparmor-basic-networking-rules-4.11-rc1.patch @@ -1,6 +1,5 @@ From: Jeff Mahoney Subject: apparmor: update apparmor-basic-networking-rules for 4.11-rc1 - Patch-mainline: depends on apparmor-basic-networking-rules.patch References: FATE#300516 @@ -13,32 +12,28 @@ the gfp_t parameter from aa_audit. Signed-off-by: Jeff Mahoney --- - security/apparmor/include/net.h | 4 ++-- - security/apparmor/lsm.c | 2 +- - security/apparmor/net.c | 39 ++++++++++++++++++++------------------- - 3 files changed, 23 insertions(+), 22 deletions(-) + security/apparmor/include/net.h | 4 ++-- + security/apparmor/lsm.c | 2 +- + security/apparmor/net.c | 40 +++++++++++++++++++++------------------- + 3 files changed, 24 insertions(+), 22 deletions(-) -diff --git a/security/apparmor/include/net.h b/security/apparmor/include/net.h -index 5223318b6c81..6710a5369380 100644 --- a/security/apparmor/include/net.h +++ b/security/apparmor/include/net.h @@ -32,9 +32,9 @@ struct aa_net { - extern struct aa_sfs_entry aa_sfs_entry_network[]; + extern struct aa_fs_entry aa_fs_entry_network[]; --int aa_net_perm(int op, struct aa_profile *profile, u16 family, -+int aa_net_perm(const char *op, struct aa_profile *profile, u16 family, +-extern int aa_net_perm(int op, struct aa_profile *profile, u16 family, ++extern int aa_net_perm(const char *op, struct aa_profile *profile, u16 family, int type, int protocol, struct sock *sk); --int aa_revalidate_sk(int op, struct sock *sk); -+int aa_revalidate_sk(const char *op, struct sock *sk); +-extern int aa_revalidate_sk(int op, struct sock *sk); ++extern int aa_revalidate_sk(const char *op, struct sock *sk); static inline void aa_free_net_rules(struct aa_net *new) { -diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c -index b78842ad43b4..9f5f0fe5c15b 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c -@@ -833,7 +833,7 @@ static int apparmor_socket_shutdown(struct socket *sock, int how) +@@ -683,7 +683,7 @@ static int apparmor_socket_shutdown(stru { struct sock *sk = sock->sk; @@ -47,11 +42,9 @@ index b78842ad43b4..9f5f0fe5c15b 100644 } static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = { -diff --git a/security/apparmor/net.c b/security/apparmor/net.c -index fe675807d6cf..913456ba79b0 100644 --- a/security/apparmor/net.c +++ b/security/apparmor/net.c -@@ -38,12 +38,12 @@ static void audit_cb(struct audit_buffer *ab, void *va) +@@ -37,12 +37,12 @@ static void audit_cb(struct audit_buffer audit_log_format(ab, "\"unknown(%d)\"", sa->u.net->family); } audit_log_format(ab, " sock_type="); @@ -68,7 +61,7 @@ index fe675807d6cf..913456ba79b0 100644 } /** -@@ -58,8 +58,9 @@ static void audit_cb(struct audit_buffer *ab, void *va) +@@ -57,8 +57,9 @@ static void audit_cb(struct audit_buffer * * Returns: %0 or sa->error else other errorcode on failure */ @@ -80,11 +73,12 @@ index fe675807d6cf..913456ba79b0 100644 { int audit_type = AUDIT_APPARMOR_AUTO; struct common_audit_data sa; -@@ -71,25 +72,25 @@ static int audit_net(struct aa_profile *profile, int op, u16 family, int type, +@@ -70,25 +71,26 @@ static int audit_net(struct aa_profile * sa.type = LSM_AUDIT_DATA_NONE; } /* todo fill in socket addr info */ - sa.aad = &aad; ++ + aad(&sa) = &aad; sa.u.net = &net; - sa.aad->op = op, @@ -110,11 +104,11 @@ index fe675807d6cf..913456ba79b0 100644 u16 quiet_mask = profile->net.quiet[sa.u.net->family]; u16 kill_mask = 0; - u16 denied = (1 << sa.aad->net.type); -+ u16 denied = (1 << aad(&sa)->net.type); ++ u16 denied = (1 << aad(&sa)->net.type) & ~quiet_mask; if (denied & kill_mask) audit_type = AUDIT_APPARMOR_KILL; -@@ -97,10 +98,10 @@ static int audit_net(struct aa_profile *profile, int op, u16 family, int type, +@@ -96,10 +98,10 @@ static int audit_net(struct aa_profile * if ((denied & quiet_mask) && AUDIT_MODE(profile) != AUDIT_NOQUIET && AUDIT_MODE(profile) != AUDIT_ALL) @@ -127,7 +121,7 @@ index fe675807d6cf..913456ba79b0 100644 } /** -@@ -113,8 +114,8 @@ static int audit_net(struct aa_profile *profile, int op, u16 family, int type, +@@ -112,8 +114,8 @@ static int audit_net(struct aa_profile * * * Returns: %0 else error if permission denied */ @@ -138,15 +132,12 @@ index fe675807d6cf..913456ba79b0 100644 { u16 family_mask; int error; -@@ -143,7 +144,7 @@ int aa_net_perm(int op, struct aa_profile *profile, u16 family, int type, +@@ -142,7 +144,7 @@ int aa_net_perm(int op, struct aa_profil * * Returns: %0 else error if permission denied */ -int aa_revalidate_sk(int op, struct sock *sk) +int aa_revalidate_sk(const char *op, struct sock *sk) { - struct aa_label *label; + struct aa_profile *profile; int error = 0; --- -2.14.2 - diff --git a/patches.apparmor/apparmor-basic-networking-rules.patch b/patches.apparmor/apparmor-basic-networking-rules.patch index 1aaea5a..214ec3a 100644 --- a/patches.apparmor/apparmor-basic-networking-rules.patch +++ b/patches.apparmor/apparmor-basic-networking-rules.patch @@ -1,7 +1,6 @@ From: John Johansen Date: Mon, 4 Oct 2010 15:03:36 -0700 Subject: AppArmor: basic networking rules - Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jj/linux-apparmor.git Git-commit: 09aa4788d6052c6dc423d939319334ebb5d00847 Patch-mainline: Queued in subsystem maintainer repo @@ -12,20 +11,22 @@ Base support for network mediation. Signed-off-by: John Johansen Acked-by: Jeff Mahoney --- - security/apparmor/.gitignore | 1 - security/apparmor/Makefile | 40 ++++++++- - security/apparmor/apparmorfs.c | 1 - security/apparmor/include/audit.h | 4 - security/apparmor/include/net.h | 44 +++++++++ - security/apparmor/include/policy.h | 3 - security/apparmor/lsm.c | 113 +++++++++++++++++++++++++ - security/apparmor/net.c | 164 +++++++++++++++++++++++++++++++++++++ - security/apparmor/policy.c | 1 - security/apparmor/policy_unpack.c | 46 ++++++++++ - 10 files changed, 416 insertions(+), 1 deletion(-) + security/apparmor/.gitignore | 1 + + security/apparmor/Makefile | 42 +++++++++- + security/apparmor/apparmorfs.c | 1 + + security/apparmor/include/audit.h | 4 + + security/apparmor/include/net.h | 44 ++++++++++ + security/apparmor/include/policy.h | 3 + + security/apparmor/lsm.c | 112 +++++++++++++++++++++++++ + security/apparmor/net.c | 162 +++++++++++++++++++++++++++++++++++++ + security/apparmor/policy.c | 1 + + security/apparmor/policy_unpack.c | 46 +++++++++++ + 10 files changed, 414 insertions(+), 2 deletions(-) create mode 100644 security/apparmor/include/net.h create mode 100644 security/apparmor/net.c +diff --git a/security/apparmor/.gitignore b/security/apparmor/.gitignore +index 9cdec70d72b8..d5b291e94264 100644 --- a/security/apparmor/.gitignore +++ b/security/apparmor/.gitignore @@ -1,5 +1,6 @@ @@ -35,18 +36,24 @@ Acked-by: Jeff Mahoney +net_names.h capability_names.h rlim_names.h +diff --git a/security/apparmor/Makefile b/security/apparmor/Makefile +index ad369a7aac24..a7dc10be232d 100644 --- a/security/apparmor/Makefile +++ b/security/apparmor/Makefile -@@ -4,7 +4,7 @@ obj-$(CONFIG_SECURITY_APPARMOR) += appar +@@ -4,10 +4,10 @@ obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o apparmor-y := apparmorfs.o audit.o capability.o context.o ipc.o lib.o match.o \ path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \ -- resource.o secid.o file.o policy_ns.o label.o mount.o -+ resource.o secid.o file.o policy_ns.o label.o mount.o net.o +- resource.o secid.o file.o policy_ns.o ++ resource.o secid.o file.o policy_ns.o net.o apparmor-$(CONFIG_SECURITY_APPARMOR_HASH) += crypto.o - clean-files := capability_names.h rlim_names.h -@@ -25,6 +25,38 @@ cmd_make-caps = echo "static const char +-clean-files := capability_names.h rlim_names.h ++clean-files := capability_names.h rlim_names.h net_names.h + + + # Build a lower case string table of capability names +@@ -25,6 +25,38 @@ cmd_make-caps = echo "static const char *const capability_names[] = {" > $@ ;\ -e 's/^\#define[ \t]+CAP_([A-Z0-9_]+)[ \t]+([0-9]+)/\L\1/p' | \ tr '\n' ' ' | sed -e 's/ $$/"\n/' >> $@ @@ -68,7 +75,7 @@ Acked-by: Jeff Mahoney + sed $< >>$@ -r -n -e "/AF_MAX/d" -e "/AF_LOCAL/d" -e \ + 's/^\#define[ \t]+AF_([A-Z0-9_]+)[ \t]+([0-9]+)(.*)/[\2] = "\L\1",/p';\ + echo "};" >> $@ ;\ -+ echo -n '\#define AA_SFS_AF_MASK "' >> $@ ;\ ++ echo -n '\#define AA_FS_AF_MASK "' >> $@ ;\ + sed -r -n 's/^\#define[ \t]+AF_([A-Z0-9_]+)[ \t]+([0-9]+)(.*)/\L\1/p'\ + $< | tr '\n' ' ' | sed -e 's/ $$/"\n/' >> $@ + @@ -85,7 +92,7 @@ Acked-by: Jeff Mahoney # Build a lower case string table of rlimit names. # Transforms lines from -@@ -61,6 +93,7 @@ cmd_make-rlim = echo "static const char +@@ -61,6 +93,7 @@ cmd_make-rlim = echo "static const char *const rlim_names[RLIM_NLIMITS] = {" \ tr '\n' ' ' | sed -e 's/ $$/"\n/' >> $@ $(obj)/capability.o : $(obj)/capability_names.h @@ -93,7 +100,7 @@ Acked-by: Jeff Mahoney $(obj)/resource.o : $(obj)/rlim_names.h $(obj)/capability_names.h : $(srctree)/include/uapi/linux/capability.h \ $(src)/Makefile -@@ -68,3 +101,8 @@ $(obj)/capability_names.h : $(srctree)/i +@@ -68,3 +101,8 @@ $(obj)/capability_names.h : $(srctree)/include/uapi/linux/capability.h \ $(obj)/rlim_names.h : $(srctree)/include/uapi/asm-generic/resource.h \ $(src)/Makefile $(call cmd,make-rlim) @@ -102,29 +109,36 @@ Acked-by: Jeff Mahoney + $(src)/Makefile + $(call cmd,make-af) + $(call cmd,make-sock) +diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c +index 4f6ac9dbc65d..4b121211e5e7 100644 --- a/security/apparmor/apparmorfs.c +++ b/security/apparmor/apparmorfs.c -@@ -2202,6 +2202,7 @@ static struct aa_sfs_entry aa_sfs_entry_ - AA_SFS_DIR("policy", aa_sfs_entry_policy), - AA_SFS_DIR("domain", aa_sfs_entry_domain), - AA_SFS_DIR("file", aa_sfs_entry_file), -+ AA_SFS_DIR("network", aa_sfs_entry_network), - AA_SFS_DIR("mount", aa_sfs_entry_mount), - AA_SFS_DIR("namespaces", aa_sfs_entry_ns), - AA_SFS_FILE_U64("capability", VFS_CAP_FLAGS_MASK), +@@ -1209,6 +1209,7 @@ static struct aa_fs_entry aa_fs_entry_features[] = { + AA_FS_DIR("policy", aa_fs_entry_policy), + AA_FS_DIR("domain", aa_fs_entry_domain), + AA_FS_DIR("file", aa_fs_entry_file), ++ AA_FS_DIR("network", aa_fs_entry_network), + AA_FS_FILE_U64("capability", VFS_CAP_FLAGS_MASK), + AA_FS_DIR("rlimit", aa_fs_entry_rlimit), + AA_FS_DIR("caps", aa_fs_entry_caps), +diff --git a/security/apparmor/include/audit.h b/security/apparmor/include/audit.h +index fdc4774318ba..947b0447c9bf 100644 --- a/security/apparmor/include/audit.h +++ b/security/apparmor/include/audit.h -@@ -132,6 +132,10 @@ struct apparmor_audit_data { - } rlim; - int signal; - }; +@@ -117,6 +117,10 @@ struct apparmor_audit_data { + u32 denied; + kuid_t ouid; + } fs; + struct { + int type, protocol; + struct sock *sk; + } net; }; struct { - struct aa_profile *profile; + const char *name; +diff --git a/security/apparmor/include/net.h b/security/apparmor/include/net.h +new file mode 100644 +index 000000000000..cb8a12109b7a --- /dev/null +++ b/security/apparmor/include/net.h @@ -0,0 +1,44 @@ @@ -160,11 +174,11 @@ Acked-by: Jeff Mahoney + u16 quiet[AF_MAX]; +}; + -+extern struct aa_sfs_entry aa_sfs_entry_network[]; ++extern struct aa_fs_entry aa_fs_entry_network[]; + -+int aa_net_perm(int op, struct aa_profile *profile, u16 family, ++extern int aa_net_perm(int op, struct aa_profile *profile, u16 family, + int type, int protocol, struct sock *sk); -+int aa_revalidate_sk(int op, struct sock *sk); ++extern int aa_revalidate_sk(int op, struct sock *sk); + +static inline void aa_free_net_rules(struct aa_net *new) +{ @@ -172,6 +186,8 @@ Acked-by: Jeff Mahoney +} + +#endif /* __AA_NET_H */ +diff --git a/security/apparmor/include/policy.h b/security/apparmor/include/policy.h +index 67bc96afe541..a3d18ea8d730 100644 --- a/security/apparmor/include/policy.h +++ b/security/apparmor/include/policy.h @@ -28,6 +28,7 @@ @@ -180,9 +196,9 @@ Acked-by: Jeff Mahoney #include "file.h" +#include "net.h" #include "lib.h" - #include "label.h" - #include "perms.h" -@@ -111,6 +112,7 @@ struct aa_data { + #include "resource.h" + +@@ -132,6 +133,7 @@ struct aa_data { * @policy: general match rules governing policy * @file: The set of rules governing basic file access and domain transitions * @caps: capabilities for the profile @@ -190,7 +206,7 @@ Acked-by: Jeff Mahoney * @rlimits: rlimits for the profile * * @dents: dentries for the profiles file entries in apparmorfs -@@ -148,6 +150,7 @@ struct aa_profile { +@@ -174,6 +176,7 @@ struct aa_profile { struct aa_policydb policy; struct aa_file_rules file; struct aa_caps caps; @@ -198,6 +214,8 @@ Acked-by: Jeff Mahoney struct aa_rlimit rlimits; struct aa_loaddata *rawdata; +diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c +index 8f3c0f7aca5a..b83cbd494e17 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c @@ -33,6 +33,7 @@ @@ -206,25 +224,24 @@ Acked-by: Jeff Mahoney #include "include/ipc.h" +#include "include/net.h" #include "include/path.h" - #include "include/label.h" #include "include/policy.h" -@@ -736,6 +737,105 @@ static int apparmor_task_kill(struct tas + #include "include/policy_ns.h" +@@ -587,6 +588,104 @@ static int apparmor_task_setrlimit(struct task_struct *task, return error; } +static int apparmor_socket_create(int family, int type, int protocol, int kern) +{ -+ struct aa_label *label; ++ struct aa_profile *profile; + int error = 0; + + if (kern) + return 0; + -+ label = __begin_current_label_crit_section(); -+ if (!unconfined(label)) -+ error = aa_net_perm(OP_CREATE, labels_profile(label), -+ family, type, protocol, NULL); -+ __end_current_label_crit_section(label); ++ profile = __aa_current_profile(); ++ if (!unconfined(profile)) ++ error = aa_net_perm(OP_CREATE, profile, family, type, protocol, ++ NULL); + return error; +} + @@ -314,7 +331,7 @@ Acked-by: Jeff Mahoney static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = { LSM_HOOK_INIT(ptrace_access_check, apparmor_ptrace_access_check), LSM_HOOK_INIT(ptrace_traceme, apparmor_ptrace_traceme), -@@ -770,6 +870,19 @@ static struct security_hook_list apparmo +@@ -616,6 +715,19 @@ static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = { LSM_HOOK_INIT(getprocattr, apparmor_getprocattr), LSM_HOOK_INIT(setprocattr, apparmor_setprocattr), @@ -334,9 +351,12 @@ Acked-by: Jeff Mahoney LSM_HOOK_INIT(cred_alloc_blank, apparmor_cred_alloc_blank), LSM_HOOK_INIT(cred_free, apparmor_cred_free), LSM_HOOK_INIT(cred_prepare, apparmor_cred_prepare), +diff --git a/security/apparmor/net.c b/security/apparmor/net.c +new file mode 100644 +index 000000000000..003dd18c61a5 --- /dev/null +++ b/security/apparmor/net.c -@@ -0,0 +1,164 @@ +@@ -0,0 +1,162 @@ +/* + * AppArmor security module + * @@ -354,14 +374,13 @@ Acked-by: Jeff Mahoney +#include "include/apparmor.h" +#include "include/audit.h" +#include "include/context.h" -+#include "include/label.h" +#include "include/net.h" +#include "include/policy.h" + +#include "net_names.h" + -+struct aa_sfs_entry aa_sfs_entry_network[] = { -+ AA_SFS_FILE_STRING("af_mask", AA_SFS_AF_MASK), ++struct aa_fs_entry aa_fs_entry_network[] = { ++ AA_FS_FILE_STRING("af_mask", AA_FS_AF_MASK), + { } +}; + @@ -484,7 +503,7 @@ Acked-by: Jeff Mahoney + */ +int aa_revalidate_sk(int op, struct sock *sk) +{ -+ struct aa_label *label; ++ struct aa_profile *profile; + int error = 0; + + /* aa_revalidate_sk should not be called from interrupt context @@ -493,17 +512,18 @@ Acked-by: Jeff Mahoney + if (in_interrupt()) + return 0; + -+ label = __begin_current_label_crit_section(); -+ if (!unconfined(label)) -+ error = aa_net_perm(op, labels_profile(label), sk->sk_family, -+ sk->sk_type, sk->sk_protocol, sk); -+ __end_current_label_crit_section(label); ++ profile = __aa_current_profile(); ++ if (!unconfined(profile)) ++ error = aa_net_perm(op, profile, sk->sk_family, sk->sk_type, ++ sk->sk_protocol, sk); + + return error; +} +diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c +index cf9d670dca94..0eea92aeb02d 100644 --- a/security/apparmor/policy.c +++ b/security/apparmor/policy.c -@@ -225,6 +225,7 @@ void aa_free_profile(struct aa_profile * +@@ -237,6 +237,7 @@ void aa_free_profile(struct aa_profile *profile) aa_free_file_rules(&profile->file); aa_free_cap_rules(&profile->caps); @@ -511,9 +531,11 @@ Acked-by: Jeff Mahoney aa_free_rlimit_rules(&profile->rlimits); kzfree(profile->dirname); +diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c +index f3422a91353c..92d02d77c0d6 100644 --- a/security/apparmor/policy_unpack.c +++ b/security/apparmor/policy_unpack.c -@@ -275,6 +275,19 @@ fail: +@@ -217,6 +217,19 @@ static bool unpack_nameX(struct aa_ext *e, enum aa_code code, const char *name) return 0; } @@ -533,7 +555,7 @@ Acked-by: Jeff Mahoney static bool unpack_u32(struct aa_ext *e, u32 *data, const char *name) { if (unpack_nameX(e, AA_U32, name)) { -@@ -591,6 +604,7 @@ static struct aa_profile *unpack_profile +@@ -526,6 +539,7 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name) int i, error = -EPROTO; kernel_cap_t tmpcap; u32 tmp; @@ -541,9 +563,9 @@ Acked-by: Jeff Mahoney *ns_name = NULL; -@@ -717,6 +731,38 @@ static struct aa_profile *unpack_profile +@@ -635,6 +649,38 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name) + if (!unpack_rlimits(e, profile)) goto fail; - } + size = unpack_array(e, "net_allowed_af"); + if (size) { @@ -579,4 +601,7 @@ Acked-by: Jeff Mahoney + if (unpack_nameX(e, AA_STRUCT, "policydb")) { /* generic policy dfa - optional and may be NULL */ - info = "failed to unpack policydb"; + profile->policy.dfa = unpack_dfa(e); +-- +2.13.0 + diff --git a/patches.apparmor/apparmor-check-all-net-profiles.patch b/patches.apparmor/apparmor-check-all-net-profiles.patch deleted file mode 100644 index cd85131..0000000 --- a/patches.apparmor/apparmor-check-all-net-profiles.patch +++ /dev/null @@ -1,97 +0,0 @@ -From: Goldwyn Rodrigues -Subject: [PATCH] Check all profiles attached to the label -Patch-mainline: Never, depends on apparmor-basic-networking-rules -References: bsc#1085996 - -This one fixes patches.suse/0001-AppArmor-basic-networking-rules.patch - -While porting apparmor net patch to the newer kernel, I missed on -iterating over the profiles attached to the labels and used -labels_profile(). This missed checking the rest of the profiles attached -to the label. - -While we are at it, use wrapper function begin_current_label_crit_section() -as opposed to the __begin_current_label_crit_section(). - -Signed-off-by: Goldwyn Rodrigues - -diff --git a/security/apparmor/include/net.h b/security/apparmor/include/net.h -index 6710a5369380..580232f20047 100644 ---- a/security/apparmor/include/net.h -+++ b/security/apparmor/include/net.h -@@ -32,7 +32,7 @@ struct aa_net { - - extern struct aa_sfs_entry aa_sfs_entry_network[]; - --int aa_net_perm(const char *op, struct aa_profile *profile, u16 family, -+int aa_label_net_perm(struct aa_label *label, const char *op, u16 family, - int type, int protocol, struct sock *sk); - int aa_revalidate_sk(const char *op, struct sock *sk); - -diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c -index e62b06241476..0007fb2eed29 100644 ---- a/security/apparmor/lsm.c -+++ b/security/apparmor/lsm.c -@@ -745,11 +745,11 @@ static int apparmor_socket_create(int family, int type, int protocol, int kern) - if (kern) - return 0; - -- label = __begin_current_label_crit_section(); -+ label = begin_current_label_crit_section(); - if (!unconfined(label)) -- error = aa_net_perm(OP_CREATE, labels_profile(label), -+ error = aa_label_net_perm(label, OP_CREATE, - family, type, protocol, NULL); -- __end_current_label_crit_section(label); -+ end_current_label_crit_section(label); - return error; - } - -diff --git a/security/apparmor/net.c b/security/apparmor/net.c -index 48e66a61b9c6..95d6e3b9c71d 100644 ---- a/security/apparmor/net.c -+++ b/security/apparmor/net.c -@@ -114,7 +114,7 @@ static int audit_net(struct aa_profile *profile, const char *op, - * - * Returns: %0 else error if permission denied - */ --int aa_net_perm(const char *op, struct aa_profile *profile, u16 family, -+static int aa_net_perm(const char *op, struct aa_profile *profile, u16 family, - int type, int protocol, struct sock *sk) - { - u16 family_mask; -@@ -137,6 +137,18 @@ int aa_net_perm(const char *op, struct aa_profile *profile, u16 family, - return audit_net(profile, op, family, type, protocol, sk, error); - } - -+int aa_label_net_perm(struct aa_label *label, const char *op, u16 family, -+ int type, int protocol, struct sock *sk) -+{ -+ struct aa_profile *profile; -+ -+ if (!unconfined(label)) -+ return 0; -+ -+ return fn_for_each_confined(label, profile, -+ aa_net_perm(op, profile, family, type, protocol, sk)); -+} -+ - /** - * aa_revalidate_sk - Revalidate access to a sock - * @op: operation being checked -@@ -155,11 +167,10 @@ int aa_revalidate_sk(const char *op, struct sock *sk) - if (in_interrupt()) - return 0; - -- label = __begin_current_label_crit_section(); -- if (!unconfined(label)) -- error = aa_net_perm(op, labels_profile(label), sk->sk_family, -- sk->sk_type, sk->sk_protocol, sk); -- __end_current_label_crit_section(label); -+ label = begin_current_label_crit_section(); -+ error = aa_label_net_perm(label, op, sk->sk_family, sk->sk_type, -+ sk->sk_protocol, sk); -+ end_current_label_crit_section(label); - - return error; - } diff --git a/patches.apparmor/apparmor-ensure-that-undecidable-profile-attachments-fail.patch b/patches.apparmor/apparmor-ensure-that-undecidable-profile-attachments-fail.patch deleted file mode 100644 index 0bf39ad..0000000 --- a/patches.apparmor/apparmor-ensure-that-undecidable-profile-attachments-fail.patch +++ /dev/null @@ -1,138 +0,0 @@ -From 844b8292b6311ecd30ae63db1471edb26e01d895 Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Fri Nov 17 17:42:42 2017 -0800 -Subject: [PATCH] apparmor: ensure that undecidable profile attachments fail -Git-commit: 844b8292b6311ecd30ae63db1471edb26e01d895 -References: bsc#1106427 -Patch-mainline: v4.15-rc1 - -Profiles that have an undecidable overlap in their attachments are -being incorrectly handled. Instead of failing to attach the first one -encountered is being used. - -eg. - profile A /** { .. } - profile B /*foo { .. } - -have an unresolvable longest left attachment, they both have an exact -match on / and then have an overlapping expression that has no clear -winner. - -Currently the winner will be the profile that is loaded first which -can result in non-deterministic behavior. Instead in this situation -the exec should fail. - -Fixes: 898127c34ec0 ("AppArmor: functions for domain transitions") -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues - -diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c -index dd754b7..9527adc 100644 - ---- a/security/apparmor/domain.c -+++ b/security/apparmor/domain.c -@@ -305,6 +305,7 @@ static int change_profile_perms(struct aa_profile *profile, - * __attach_match_ - find an attachment match - * @name - to match against (NOT NULL) - * @head - profile list to walk (NOT NULL) -+ * @info - info message if there was an error (NOT NULL) - * - * Do a linear search on the profiles in the list. There is a matching - * preference where an exact match is preferred over a name which uses -@@ -316,28 +317,44 @@ static int change_profile_perms(struct aa_profile *profile, - * Returns: profile or NULL if no match found - */ - static struct aa_profile *__attach_match(const char *name, -- struct list_head *head) -+ struct list_head *head, -+ const char **info) - { - int len = 0; -+ bool conflict = false; - struct aa_profile *profile, *candidate = NULL; - - list_for_each_entry_rcu(profile, head, base.list) { - if (profile->label.flags & FLAG_NULL) - continue; -- if (profile->xmatch && profile->xmatch_len > len) { -- unsigned int state = aa_dfa_match(profile->xmatch, -- DFA_START, name); -- u32 perm = dfa_user_allow(profile->xmatch, state); -- /* any accepting state means a valid match. */ -- if (perm & MAY_EXEC) { -- candidate = profile; -- len = profile->xmatch_len; -+ if (profile->xmatch) { -+ if (profile->xmatch_len == len) { -+ conflict = true; -+ continue; -+ } else if (profile->xmatch_len > len) { -+ unsigned int state; -+ u32 perm; -+ -+ state = aa_dfa_match(profile->xmatch, -+ DFA_START, name); -+ perm = dfa_user_allow(profile->xmatch, state); -+ /* any accepting state means a valid match. */ -+ if (perm & MAY_EXEC) { -+ candidate = profile; -+ len = profile->xmatch_len; -+ conflict = false; -+ } - } - } else if (!strcmp(profile->base.name, name)) - /* exact non-re match, no more searching required */ - return profile; - } - -+ if (conflict) { -+ *info = "conflicting profile attachments"; -+ return NULL; -+ } -+ - return candidate; - } - -@@ -346,16 +363,17 @@ static struct aa_profile *__attach_match(const char *name, - * @ns: the current namespace (NOT NULL) - * @list: list to search (NOT NULL) - * @name: the executable name to match against (NOT NULL) -+ * @info: info message if there was an error - * - * Returns: label or NULL if no match found - */ - static struct aa_label *find_attach(struct aa_ns *ns, struct list_head *list, -- const char *name) -+ const char *name, const char **info) - { - struct aa_profile *profile; - - rcu_read_lock(); -- profile = aa_get_profile(__attach_match(name, list)); -+ profile = aa_get_profile(__attach_match(name, list, info)); - rcu_read_unlock(); - - return profile ? &profile->label : NULL; -@@ -448,11 +466,11 @@ static struct aa_label *x_to_label(struct aa_profile *profile, - if (xindex & AA_X_CHILD) - /* released by caller */ - new = find_attach(ns, &profile->base.profiles, -- name); -+ name, info); - else - /* released by caller */ - new = find_attach(ns, &ns->base.profiles, -- name); -+ name, info); - *lookupname = name; - break; - } -@@ -516,7 +534,7 @@ static struct aa_label *profile_transition(struct aa_profile *profile, - - if (profile_unconfined(profile)) { - new = find_attach(profile->ns, &profile->ns->base.profiles, -- name); -+ name, &info); - if (new) { - AA_DEBUG("unconfined attached to new label"); - return new; diff --git a/patches.apparmor/apparmor-fix-an-error-code-in-__aa_create_ns.patch b/patches.apparmor/apparmor-fix-an-error-code-in-__aa_create_ns.patch deleted file mode 100644 index e86b5c2..0000000 --- a/patches.apparmor/apparmor-fix-an-error-code-in-__aa_create_ns.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0a6b29230ec336189bab32498df3f06c8a6944d8 Mon Sep 17 00:00:00 2001 -From: Dan Carpenter -Date: Thu Aug 2 11:38:23 2018 +0300 -Subject: [PATCH] apparmor: fix an error code in __aa_create_ns() -Git-commit: 0a6b29230ec336189bab32498df3f06c8a6944d8 -References: bsc#1106427 -Patch-mainline: v4.19-rc1 - -We should return error pointers in this function. Returning NULL -results in a NULL dereference in the caller. - -Fixes: 73688d1ed0b8 ("apparmor: refactor prepare_ns() and make usable from different views") -Signed-off-by: Dan Carpenter -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues - -diff --git a/security/apparmor/policy_ns.c b/security/apparmor/policy_ns.c -index b0f9dc3..1a7cec5 100644 - ---- a/security/apparmor/policy_ns.c -+++ b/security/apparmor/policy_ns.c -@@ -255,7 +255,7 @@ static struct aa_ns *__aa_create_ns(struct aa_ns *parent, const char *name, - - ns = alloc_ns(parent->base.hname, name); - if (!ns) -- return NULL; -+ return ERR_PTR(-ENOMEM); - ns->level = parent->level + 1; - mutex_lock_nested(&ns->lock, ns->level); - error = __aafs_ns_mkdir(ns, ns_subns_dir(parent), name, dir); diff --git a/patches.apparmor/apparmor-fix-dangling-symlinks-to-policy-rawdata-aft.patch b/patches.apparmor/apparmor-fix-dangling-symlinks-to-policy-rawdata-aft.patch deleted file mode 100644 index a2ce9f4..0000000 --- a/patches.apparmor/apparmor-fix-dangling-symlinks-to-policy-rawdata-aft.patch +++ /dev/null @@ -1,215 +0,0 @@ -From 1180b4c757aab5506f1be367000364dd5cf5cd02 Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Thu, 15 Mar 2018 22:31:38 -0700 -Subject: [PATCH] apparmor: fix dangling symlinks to policy rawdata after replacement -Git-commit: 1180b4c757aab5506f1be367000364dd5cf5cd02 -Patch-mainline: v4.17-rc1 -References: bsc#1095893 - -When policy replacement occurs the symlinks in the profile directory -need to be updated to point to the new rawdata, otherwise once the -old rawdata is removed the symlink becomes broken. - -Fix this by dynamically generating the symlink everytime it is read. -These links are used enough that their value needs to be cached and -this way we can avoid needing locking to read and update the link -value. - -Fixes: a481f4d917835 ("apparmor: add custom apparmorfs that will be used by policy namespace files") -Buglink: http://bugs.launchpad.net/bugs/1755563 -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues - ---- - security/apparmor/apparmorfs.c | 126 +++++++++++++++++++++++++++++++---------- - 1 file changed, 95 insertions(+), 31 deletions(-) - -diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c -index dd12acb70af6..ea37330c2a02 100644 ---- a/security/apparmor/apparmorfs.c -+++ b/security/apparmor/apparmorfs.c -@@ -313,6 +313,7 @@ static struct dentry *aafs_create_dir(const char *name, struct dentry *parent) - * @name: name of dentry to create - * @parent: parent directory for this dentry - * @target: if symlink, symlink target string -+ * @private: private data - * @iops: struct of inode_operations that should be used - * - * If @target parameter is %NULL, then the @iops parameter needs to be -@@ -321,17 +322,17 @@ static struct dentry *aafs_create_dir(const char *name, struct dentry *parent) - static struct dentry *aafs_create_symlink(const char *name, - struct dentry *parent, - const char *target, -+ void *private, - const struct inode_operations *iops) - { - struct dentry *dent; - char *link = NULL; - - if (target) { -- link = kstrdup(target, GFP_KERNEL); - if (!link) - return ERR_PTR(-ENOMEM); - } -- dent = aafs_create(name, S_IFLNK | 0444, parent, NULL, link, NULL, -+ dent = aafs_create(name, S_IFLNK | 0444, parent, private, link, NULL, - iops); - if (IS_ERR(dent)) - kfree(link); -@@ -1482,26 +1483,95 @@ static int profile_depth(struct aa_profile *profile) - return depth; - } - --static int gen_symlink_name(char *buffer, size_t bsize, int depth, -- const char *dirname, const char *fname) -+static char *gen_symlink_name(int depth, const char *dirname, const char *fname) - { -+ char *buffer, *s; - int error; -+ int size = depth * 6 + strlen(dirname) + strlen(fname) + 11; -+ -+ s = buffer = kmalloc(size, GFP_KERNEL); -+ if (!buffer) -+ return ERR_PTR(-ENOMEM); - - for (; depth > 0; depth--) { -- if (bsize < 7) -- return -ENAMETOOLONG; -- strcpy(buffer, "../../"); -- buffer += 6; -- bsize -= 6; -+ strcpy(s, "../../"); -+ s += 6; -+ size -= 6; - } - -- error = snprintf(buffer, bsize, "raw_data/%s/%s", dirname, fname); -- if (error >= bsize || error < 0) -- return -ENAMETOOLONG; -+ error = snprintf(s, size, "raw_data/%s/%s", dirname, fname); -+ if (error >= size || error < 0) -+ return ERR_PTR(-ENAMETOOLONG); - -- return 0; -+ return buffer; -+} -+ -+static void rawdata_link_cb(void *arg) -+{ -+ kfree(arg); -+} -+ -+static const char *rawdata_get_link_base(struct dentry *dentry, -+ struct inode *inode, -+ struct delayed_call *done, -+ const char *name) -+{ -+ struct aa_proxy *proxy = inode->i_private; -+ struct aa_label *label; -+ struct aa_profile *profile; -+ char *target; -+ int depth; -+ -+ if (!dentry) -+ return ERR_PTR(-ECHILD); -+ -+ label = aa_get_label_rcu(&proxy->label); -+ profile = labels_profile(label); -+ depth = profile_depth(profile); -+ target = gen_symlink_name(depth, profile->rawdata->name, name); -+ aa_put_label(label); -+ -+ if (IS_ERR(target)) -+ return target; -+ -+ set_delayed_call(done, rawdata_link_cb, target); -+ -+ return target; - } - -+static const char *rawdata_get_link_sha1(struct dentry *dentry, -+ struct inode *inode, -+ struct delayed_call *done) -+{ -+ return rawdata_get_link_base(dentry, inode, done, "sha1"); -+} -+ -+static const char *rawdata_get_link_abi(struct dentry *dentry, -+ struct inode *inode, -+ struct delayed_call *done) -+{ -+ return rawdata_get_link_base(dentry, inode, done, "abi"); -+} -+ -+static const char *rawdata_get_link_data(struct dentry *dentry, -+ struct inode *inode, -+ struct delayed_call *done) -+{ -+ return rawdata_get_link_base(dentry, inode, done, "raw_data"); -+} -+ -+static const struct inode_operations rawdata_link_sha1_iops = { -+ .get_link = rawdata_get_link_sha1, -+}; -+ -+static const struct inode_operations rawdata_link_abi_iops = { -+ .get_link = rawdata_get_link_abi, -+}; -+static const struct inode_operations rawdata_link_data_iops = { -+ .get_link = rawdata_get_link_data, -+}; -+ -+ - /* - * Requires: @profile->ns->lock held - */ -@@ -1572,34 +1642,28 @@ int __aafs_profile_mkdir(struct aa_profile *profile, struct dentry *parent) - } - - if (profile->rawdata) { -- char target[64]; -- int depth = profile_depth(profile); -- -- error = gen_symlink_name(target, sizeof(target), depth, -- profile->rawdata->name, "sha1"); -- if (error < 0) -- goto fail2; -- dent = aafs_create_symlink("raw_sha1", dir, target, NULL); -+ dent = aafs_create_symlink("raw_sha1", dir, NULL, -+ profile->label.proxy, -+ &rawdata_link_sha1_iops); - if (IS_ERR(dent)) - goto fail; -+ aa_get_proxy(profile->label.proxy); - profile->dents[AAFS_PROF_RAW_HASH] = dent; - -- error = gen_symlink_name(target, sizeof(target), depth, -- profile->rawdata->name, "abi"); -- if (error < 0) -- goto fail2; -- dent = aafs_create_symlink("raw_abi", dir, target, NULL); -+ dent = aafs_create_symlink("raw_abi", dir, NULL, -+ profile->label.proxy, -+ &rawdata_link_abi_iops); - if (IS_ERR(dent)) - goto fail; -+ aa_get_proxy(profile->label.proxy); - profile->dents[AAFS_PROF_RAW_ABI] = dent; - -- error = gen_symlink_name(target, sizeof(target), depth, -- profile->rawdata->name, "raw_data"); -- if (error < 0) -- goto fail2; -- dent = aafs_create_symlink("raw_data", dir, target, NULL); -+ dent = aafs_create_symlink("raw_data", dir, NULL, -+ profile->label.proxy, -+ &rawdata_link_data_iops); - if (IS_ERR(dent)) - goto fail; -+ aa_get_proxy(profile->label.proxy); - profile->dents[AAFS_PROF_RAW_DATA] = dent; - } - --- -2.16.3 - diff --git a/patches.apparmor/apparmor-fix-display-of-.ns_name-for-containers.patch b/patches.apparmor/apparmor-fix-display-of-.ns_name-for-containers.patch deleted file mode 100644 index 1b025b7..0000000 --- a/patches.apparmor/apparmor-fix-display-of-.ns_name-for-containers.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 040d9e2bce0a5b321c402b79ee43a8e8d2fd3b06 Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Tue, 23 Jan 2018 01:47:42 -0800 -Subject: [PATCH] apparmor: fix display of .ns_name for containers -Git-commit: 040d9e2bce0a5b321c402b79ee43a8e8d2fd3b06 -Patch-mainline: v4.17-rc1 -References: bsc#1095893 - -The .ns_name should not be virtualized by the current ns view. It -needs to report the ns base name as that is being used during startup -as part of determining apparmor policy namespace support. - -Buglink: http://bugs.launchpad.net/bugs/1746463 -Fixes: d9f02d9c237aa ("apparmor: fix display of ns name") -Cc: Stable -Reported-by: Serge Hallyn -Tested-by: Serge Hallyn -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/apparmorfs.c | 4 +--- - 1 file changed, 1 insertion(+), 3 deletions(-) - -diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c -index 1ccd0139a088..dd12acb70af6 100644 ---- a/security/apparmor/apparmorfs.c -+++ b/security/apparmor/apparmorfs.c -@@ -1189,9 +1189,7 @@ static int seq_ns_level_show(struct seq_file *seq, void *v) - static int seq_ns_name_show(struct seq_file *seq, void *v) - { - struct aa_label *label = begin_current_label_crit_section(); -- -- seq_printf(seq, "%s\n", aa_ns_name(labels_ns(label), -- labels_ns(label), true)); -+ seq_printf(seq, "%s\n", labels_ns(label)->base.name); - end_current_label_crit_section(label); - - return 0; --- -2.16.3 - diff --git a/patches.apparmor/apparmor-fix-logging-of-the-existence-test-for-signa.patch b/patches.apparmor/apparmor-fix-logging-of-the-existence-test-for-signa.patch deleted file mode 100644 index 5d8c7de..0000000 --- a/patches.apparmor/apparmor-fix-logging-of-the-existence-test-for-signa.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 588558eb6d0e0b6edfa65a67e906c2ffeba63ff1 Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Thu, 1 Feb 2018 11:24:10 +0100 -Subject: [PATCH 3/6] apparmor: fix logging of the existence test for signals -Git-commit: 588558eb6d0e0b6edfa65a67e906c2ffeba63ff1 -Patch-mainline: v4.17-rc1 -References: bsc#1095893 - -The existence test is not being properly logged as the signal mapping -maps it to the last entry in the named signal table. This is done -to help catch bugs by making the 0 mapped signal value invalid so -that we can catch the signal value not being filled in. - -When fixing the off-by-one comparision logic the reporting of the -existence test was broken, because the logic behind the mapped named -table was hidden. Fix this by adding a define for the name lookup -and using it. - -Cc: Stable -Fixes: f7dc4c9a855a1 ("apparmor: fix off-by-one comparison on MAXMAPPED_SIG") -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/include/sig_names.h | 4 +++- - security/apparmor/ipc.c | 2 +- - 2 files changed, 4 insertions(+), 2 deletions(-) - -diff --git a/security/apparmor/include/sig_names.h b/security/apparmor/include/sig_names.h -index 92e62fe95292..5ca47c50dfa7 100644 ---- a/security/apparmor/include/sig_names.h -+++ b/security/apparmor/include/sig_names.h -@@ -2,6 +2,8 @@ - - #define SIGUNKNOWN 0 - #define MAXMAPPED_SIG 35 -+#define MAXMAPPED_SIGNAME (MAXMAPPED_SIG + 1) -+ - /* 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 -@@ -56,7 +58,7 @@ static const int sig_map[MAXMAPPED_SIG] = { - }; - - /* this table is ordered post sig_map[sig] mapping */ --static const char *const sig_names[MAXMAPPED_SIG + 1] = { -+static const char *const sig_names[MAXMAPPED_SIGNAME] = { - "unknown", - "hup", - "int", -diff --git a/security/apparmor/ipc.c b/security/apparmor/ipc.c -index b40678f3c1d5..586facd35f7c 100644 ---- a/security/apparmor/ipc.c -+++ b/security/apparmor/ipc.c -@@ -174,7 +174,7 @@ static void audit_signal_cb(struct audit_buffer *ab, void *va) - audit_signal_mask(ab, aad(sa)->denied); - } - } -- if (aad(sa)->signal < MAXMAPPED_SIG) -+ if (aad(sa)->signal < MAXMAPPED_SIGNAME) - audit_log_format(ab, " signal=%s", sig_names[aad(sa)->signal]); - else - audit_log_format(ab, " signal=rtmin+%d", --- -2.16.3 - diff --git a/patches.apparmor/apparmor-fix-memory-leak-on-buffer-on-error-exit-path.patch b/patches.apparmor/apparmor-fix-memory-leak-on-buffer-on-error-exit-path.patch deleted file mode 100644 index e2e25df..0000000 --- a/patches.apparmor/apparmor-fix-memory-leak-on-buffer-on-error-exit-path.patch +++ /dev/null @@ -1,34 +0,0 @@ -From: Colin Ian King -Date: Tue Mar 27 14:35:58 2018 +0100 -Subject: apparmor: fix memory leak on buffer on error exit path -Git-commit: 588558eb6d0e0b6edfa65a67e906c2ffeba63ff1 -Patch-mainline: v4.17-rc1 -References: bsc#1095893 - -Currently on the error exit path the allocated buffer is not free'd -causing a memory leak. Fix this by kfree'ing it. - -Detected by CoverityScan, CID#1466876 ("Resource leaks") - -Fixes: 1180b4c757aa ("apparmor: fix dangling symlinks to policy rawdata after replacement") -Signed-off-by: Colin Ian King -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues - -diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c -index 62301ddbbe5e..f4308683c0af 100644 - ---- a/security/apparmor/apparmorfs.c -+++ b/security/apparmor/apparmorfs.c -@@ -1497,8 +1497,10 @@ static char *gen_symlink_name(int depth, const char *dirname, const char *fname) - } - - error = snprintf(s, size, "raw_data/%s/%s", dirname, fname); -- if (error >= size || error < 0) -+ if (error >= size || error < 0) { -+ kfree(buffer); - return ERR_PTR(-ENAMETOOLONG); -+ } - - return buffer; - } diff --git a/patches.apparmor/apparmor-fix-oops-in-audit_signal_cb-hook.patch b/patches.apparmor/apparmor-fix-oops-in-audit_signal_cb-hook.patch deleted file mode 100644 index cae03b5..0000000 --- a/patches.apparmor/apparmor-fix-oops-in-audit_signal_cb-hook.patch +++ /dev/null @@ -1,136 +0,0 @@ -From a3ec3e8612f5d614d290626011e78b0aea1db5a5 Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Wed, 22 Nov 2017 07:33:38 -0800 -Subject: [PATCH] apparmor: fix oops in audit_signal_cb hook -References: Git-fixes, bsc#1070227 -Git-commit: b12cbb21586277f72533769832c24cc6c1d60ab3 -Patch-mainline: v4.15-rc2 - -The apparmor_audit_data struct ordering got messed up during a merge -conflict, resulting in the signal integer and peer pointer being in -a union instead of a struct together. - -For most of the 4.13 and 4.14 life cycle, this was hidden by commit -651e28c5537abb39076d3949fb7618536f1d242e which fixed the -apparmor_audit_data struct when its data was added. When that commit -was reverted in -rc7 the signal audit bug was exposed, and -unfortunately it never showed up in any of the testing until after -4.14 was released, and Shaun Khan, Zephaniah E. Loss-Cutler-Hull filed -nearly simultaneous bug reports (with different oopes, the smaller of -which is included below). - -Full credit goes to Tetsuo Handa for jumping on this as well and -noticing the audit data struct problem and reporting it. - -Alright, trying again, this time with my mail settings to actually send -as plain text, and with some more detail. - -I am running Ubuntu 16.04, with a mainline 4.14 kernel. - -[ 76.178568] BUG: unable to handle kernel paging request at -ffffffff0eee3bc0 -[ 76.178579] IP: audit_signal_cb+0x6c/0xe0 -[ 76.178581] PGD 1a640a067 P4D 1a640a067 PUD 0 -[ 76.178586] Oops: 0000 [#1] PREEMPT SMP -[ 76.178589] Modules linked in: fuse rfcomm bnep usblp uvcvideo btusb -btrtl btbcm btintel bluetooth ecdh_generic ip6table_filter ip6_tables -xt_tcpudp nf_conntrack_ipv4 nf_defrag_ipv4 xt_conntrack nf_conntrack -iptable_filter ip_tables x_tables intel_rapl joydev wmi_bmof serio_raw -iwldvm iwlwifi shpchp kvm_intel kvm irqbypass autofs4 algif_skcipher -nls_iso8859_1 nls_cp437 crc32_pclmul ghash_clmulni_intel -[ 76.178620] CPU: 0 PID: 10675 Comm: pidgin Not tainted -4.14.0-f1-dirty #135 -[ 76.178623] Hardware name: Hewlett-Packard HP EliteBook Folio -9470m/18DF, BIOS 68IBD Ver. F.62 10/22/2015 -[ 76.178625] task: ffff9c7a94c31dc0 task.stack: ffffa09b02a4c000 -[ 76.178628] RIP: 0010:audit_signal_cb+0x6c/0xe0 -[ 76.178631] RSP: 0018:ffffa09b02a4fc08 EFLAGS: 00010292 -[ 76.178634] RAX: ffffa09b02a4fd60 RBX: ffff9c7aee0741f8 RCX: -0000000000000000 -[ 76.178636] RDX: ffffffffee012290 RSI: 0000000000000006 RDI: -ffff9c7a9493d800 -[ 76.178638] RBP: ffffa09b02a4fd40 R08: 000000000000004d R09: -ffffa09b02a4fc46 -[ 76.178641] R10: ffffa09b02a4fcb8 R11: ffff9c7ab44f5072 R12: -ffffa09b02a4fd40 -[ 76.178643] R13: ffffffff9e447be0 R14: ffff9c7a94c31dc0 R15: -0000000000000001 -[ 76.178646] FS: 00007f8b11ba2a80(0000) GS:ffff9c7afea00000(0000) -knlGS:0000000000000000 -[ 76.178648] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 -[ 76.178650] CR2: ffffffff0eee3bc0 CR3: 00000003d5209002 CR4: -00000000001606f0 -[ 76.178652] Call Trace: -[ 76.178660] common_lsm_audit+0x1da/0x780 -[ 76.178665] ? d_absolute_path+0x60/0x90 -[ 76.178669] ? aa_check_perms+0xcd/0xe0 -[ 76.178672] aa_check_perms+0xcd/0xe0 -[ 76.178675] profile_signal_perm.part.0+0x90/0xa0 -[ 76.178679] aa_may_signal+0x16e/0x1b0 -[ 76.178686] apparmor_task_kill+0x51/0x120 -[ 76.178690] security_task_kill+0x44/0x60 -[ 76.178695] group_send_sig_info+0x25/0x60 -[ 76.178699] kill_pid_info+0x36/0x60 -[ 76.178703] SYSC_kill+0xdb/0x180 -[ 76.178707] ? preempt_count_sub+0x92/0xd0 -[ 76.178712] ? _raw_write_unlock_irq+0x13/0x30 -[ 76.178716] ? task_work_run+0x6a/0x90 -[ 76.178720] ? exit_to_usermode_loop+0x80/0xa0 -[ 76.178723] entry_SYSCALL_64_fastpath+0x13/0x94 -[ 76.178727] RIP: 0033:0x7f8b0e58b767 -[ 76.178729] RSP: 002b:00007fff19efd4d8 EFLAGS: 00000206 ORIG_RAX: -000000000000003e -[ 76.178732] RAX: ffffffffffffffda RBX: 0000557f3e3c2050 RCX: -00007f8b0e58b767 -[ 76.178735] RDX: 0000000000000000 RSI: 0000000000000000 RDI: -000000000000263b -[ 76.178737] RBP: 0000000000000000 R08: 0000557f3e3c2270 R09: -0000000000000001 -[ 76.178739] R10: 000000000000022d R11: 0000000000000206 R12: -0000000000000000 -[ 76.178741] R13: 0000000000000001 R14: 0000557f3e3c13c0 R15: -0000000000000000 -[ 76.178745] Code: 48 8b 55 18 48 89 df 41 b8 20 00 08 01 5b 5d 48 8b -42 10 48 8b 52 30 48 63 48 4c 48 8b 44 c8 48 31 c9 48 8b 70 38 e9 f4 fd -00 00 <48> 8b 14 d5 40 27 e5 9e 48 c7 c6 7d 07 19 9f 48 89 df e8 fd 35 -[ 76.178794] RIP: audit_signal_cb+0x6c/0xe0 RSP: ffffa09b02a4fc08 -[ 76.178796] CR2: ffffffff0eee3bc0 -[ 76.178799] ---[ end trace 514af9529297f1a3 ]--- - -Fixes: cd1dbf76b23d ("apparmor: add the ability to mediate signals") -Reported-by: Zephaniah E. Loss-Cutler-Hull -Reported-by: Shuah Khan -Reported-by: Tetsuo Handa -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/include/audit.h | 12 +++++++----- - 1 file changed, 7 insertions(+), 5 deletions(-) - ---- a/security/apparmor/include/audit.h -+++ b/security/apparmor/include/audit.h -@@ -121,17 +121,19 @@ struct apparmor_audit_data { - /* these entries require a custom callback fn */ - struct { - struct aa_label *peer; -- struct { -- const char *target; -- kuid_t ouid; -- } fs; -+ union { -+ struct { -+ const char *target; -+ kuid_t ouid; -+ } fs; -+ int signal; -+ }; - }; - struct { - struct aa_profile *profile; - const char *ns; - long pos; - } iface; -- int signal; - struct { - int rlim; - unsigned long max; diff --git a/patches.apparmor/apparmor-fix-possible-recursive-lock-warning-in-__aa.patch b/patches.apparmor/apparmor-fix-possible-recursive-lock-warning-in-__aa.patch deleted file mode 100644 index 1d846f9..0000000 --- a/patches.apparmor/apparmor-fix-possible-recursive-lock-warning-in-__aa.patch +++ /dev/null @@ -1,303 +0,0 @@ -From 8c104f26fd3064f4af002cccaf9758742aa918ea Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Mon, 20 Nov 2017 23:24:09 -0800 -Subject: [PATCH] apparmor: fix possible recursive lock warning in __aa_create_ns -References: Git-fixes, bsc#1079834 -Git-commit: feb3c766a3ab32d233aaff7db13afd9ba5bc142d -Patch-mainline: v4.15-rc1 - -Use mutex_lock_nested to provide lockdep the parent child lock ordering of -the tree. - -This fixes the lockdep Warning -[ 305.275177] ============================================ -[ 305.275178] WARNING: possible recursive locking detected -[ 305.275179] 4.14.0-rc7+ #320 Not tainted -[ 305.275180] -------------------------------------------- -[ 305.275181] apparmor_parser/1339 is trying to acquire lock: -[ 305.275182] (&ns->lock){+.+.}, at: [] __aa_create_ns+0x6d/0x1e0 -[ 305.275187] - but task is already holding lock: -[ 305.275187] (&ns->lock){+.+.}, at: [] aa_prepare_ns+0x3d/0xd0 -[ 305.275190] - other info that might help us debug this: -[ 305.275191] Possible unsafe locking scenario: - -[ 305.275192] CPU0 -[ 305.275193] ---- -[ 305.275193] lock(&ns->lock); -[ 305.275194] lock(&ns->lock); -[ 305.275195] - *** DEADLOCK *** - -[ 305.275196] May be due to missing lock nesting notation - -[ 305.275198] 2 locks held by apparmor_parser/1339: -[ 305.275198] #0: (sb_writers#10){.+.+}, at: [] vfs_write+0x1a7/0x1d0 -[ 305.275202] #1: (&ns->lock){+.+.}, at: [] aa_prepare_ns+0x3d/0xd0 -[ 305.275205] - stack backtrace: -[ 305.275207] CPU: 1 PID: 1339 Comm: apparmor_parser Not tainted 4.14.0-rc7+ #320 -[ 305.275208] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.1-1ubuntu1 04/01/2014 -[ 305.275209] Call Trace: -[ 305.275212] dump_stack+0x85/0xcb -[ 305.275214] __lock_acquire+0x141c/0x1460 -[ 305.275216] ? __aa_create_ns+0x6d/0x1e0 -[ 305.275218] ? ___slab_alloc+0x183/0x540 -[ 305.275219] ? ___slab_alloc+0x183/0x540 -[ 305.275221] lock_acquire+0xed/0x1e0 -[ 305.275223] ? lock_acquire+0xed/0x1e0 -[ 305.275224] ? __aa_create_ns+0x6d/0x1e0 -[ 305.275227] __mutex_lock+0x89/0x920 -[ 305.275228] ? __aa_create_ns+0x6d/0x1e0 -[ 305.275230] ? trace_hardirqs_on_caller+0x11f/0x190 -[ 305.275231] ? __aa_create_ns+0x6d/0x1e0 -[ 305.275233] ? __lockdep_init_map+0x57/0x1d0 -[ 305.275234] ? lockdep_init_map+0x9/0x10 -[ 305.275236] ? __rwlock_init+0x32/0x60 -[ 305.275238] mutex_lock_nested+0x1b/0x20 -[ 305.275240] ? mutex_lock_nested+0x1b/0x20 -[ 305.275241] __aa_create_ns+0x6d/0x1e0 -[ 305.275243] aa_prepare_ns+0xc2/0xd0 -[ 305.275245] aa_replace_profiles+0x168/0xf30 -[ 305.275247] ? __might_fault+0x85/0x90 -[ 305.275250] policy_update+0xb9/0x380 -[ 305.275252] profile_load+0x7e/0x90 -[ 305.275254] __vfs_write+0x28/0x150 -[ 305.275256] ? rcu_read_lock_sched_held+0x72/0x80 -[ 305.275257] ? rcu_sync_lockdep_assert+0x2f/0x60 -[ 305.275259] ? __sb_start_write+0xdc/0x1c0 -[ 305.275261] ? vfs_write+0x1a7/0x1d0 -[ 305.275262] vfs_write+0xca/0x1d0 -[ 305.275264] ? trace_hardirqs_on_caller+0x11f/0x190 -[ 305.275266] SyS_write+0x49/0xa0 -[ 305.275268] entry_SYSCALL_64_fastpath+0x23/0xc2 -[ 305.275271] RIP: 0033:0x7fa6b22e8c74 -[ 305.275272] RSP: 002b:00007ffeaaee6288 EFLAGS: 00000246 ORIG_RAX: 0000000000000001 -[ 305.275273] RAX: ffffffffffffffda RBX: 00007ffeaaee62a4 RCX: 00007fa6b22e8c74 -[ 305.275274] RDX: 0000000000000a51 RSI: 00005566a8198c10 RDI: 0000000000000004 -[ 305.275275] RBP: 0000000000000a39 R08: 0000000000000a51 R09: 0000000000000000 -[ 305.275276] R10: 0000000000000000 R11: 0000000000000246 R12: 00005566a8198c10 -[ 305.275277] R13: 0000000000000004 R14: 00005566a72ecb88 R15: 00005566a72ec3a8 - -Fixes: 73688d1ed0b8 ("apparmor: refactor prepare_ns() and make usable from different views") -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/apparmorfs.c | 22 +++++++++++----------- - security/apparmor/label.c | 2 +- - security/apparmor/policy.c | 8 ++++---- - security/apparmor/policy_ns.c | 8 ++++---- - security/apparmor/policy_unpack.c | 2 +- - 5 files changed, 21 insertions(+), 21 deletions(-) - -diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c -index 518d5928661b..1ccd0139a088 100644 ---- a/security/apparmor/apparmorfs.c -+++ b/security/apparmor/apparmorfs.c -@@ -533,7 +533,7 @@ static ssize_t ns_revision_read(struct file *file, char __user *buf, - long last_read; - int avail; - -- mutex_lock(&rev->ns->lock); -+ mutex_lock_nested(&rev->ns->lock, rev->ns->level); - last_read = rev->last_read; - if (last_read == rev->ns->revision) { - mutex_unlock(&rev->ns->lock); -@@ -543,7 +543,7 @@ static ssize_t ns_revision_read(struct file *file, char __user *buf, - last_read != - READ_ONCE(rev->ns->revision))) - return -ERESTARTSYS; -- mutex_lock(&rev->ns->lock); -+ mutex_lock_nested(&rev->ns->lock, rev->ns->level); - } - - avail = sprintf(buffer, "%ld\n", rev->ns->revision); -@@ -577,7 +577,7 @@ static unsigned int ns_revision_poll(struct file *file, poll_table *pt) - unsigned int mask = 0; - - if (rev) { -- mutex_lock(&rev->ns->lock); -+ mutex_lock_nested(&rev->ns->lock, rev->ns->level); - poll_wait(file, &rev->ns->wait, pt); - if (rev->last_read < rev->ns->revision) - mask |= POLLIN | POLLRDNORM; -@@ -1643,7 +1643,7 @@ static int ns_mkdir_op(struct inode *dir, struct dentry *dentry, umode_t mode) - */ - inode_unlock(dir); - error = simple_pin_fs(&aafs_ops, &aafs_mnt, &aafs_count); -- mutex_lock(&parent->lock); -+ mutex_lock_nested(&parent->lock, parent->level); - inode_lock_nested(dir, I_MUTEX_PARENT); - if (error) - goto out; -@@ -1692,7 +1692,7 @@ static int ns_rmdir_op(struct inode *dir, struct dentry *dentry) - inode_unlock(dir); - inode_unlock(dentry->d_inode); - -- mutex_lock(&parent->lock); -+ mutex_lock_nested(&parent->lock, parent->level); - ns = aa_get_ns(__aa_findn_ns(&parent->sub_ns, dentry->d_name.name, - dentry->d_name.len)); - if (!ns) { -@@ -1747,7 +1747,7 @@ void __aafs_ns_rmdir(struct aa_ns *ns) - __aafs_profile_rmdir(child); - - list_for_each_entry(sub, &ns->sub_ns, base.list) { -- mutex_lock(&sub->lock); -+ mutex_lock_nested(&sub->lock, sub->level); - __aafs_ns_rmdir(sub); - mutex_unlock(&sub->lock); - } -@@ -1877,7 +1877,7 @@ int __aafs_ns_mkdir(struct aa_ns *ns, struct dentry *parent, const char *name, - - /* subnamespaces */ - list_for_each_entry(sub, &ns->sub_ns, base.list) { -- mutex_lock(&sub->lock); -+ mutex_lock_nested(&sub->lock, sub->level); - error = __aafs_ns_mkdir(sub, ns_subns_dir(ns), NULL, NULL); - mutex_unlock(&sub->lock); - if (error) -@@ -1921,7 +1921,7 @@ static struct aa_ns *__next_ns(struct aa_ns *root, struct aa_ns *ns) - /* is next namespace a child */ - if (!list_empty(&ns->sub_ns)) { - next = list_first_entry(&ns->sub_ns, typeof(*ns), base.list); -- mutex_lock(&next->lock); -+ mutex_lock_nested(&next->lock, next->level); - return next; - } - -@@ -1931,7 +1931,7 @@ static struct aa_ns *__next_ns(struct aa_ns *root, struct aa_ns *ns) - mutex_unlock(&ns->lock); - next = list_next_entry(ns, base.list); - if (!list_entry_is_head(next, &parent->sub_ns, base.list)) { -- mutex_lock(&next->lock); -+ mutex_lock_nested(&next->lock, next->level); - return next; - } - ns = parent; -@@ -2039,7 +2039,7 @@ static void *p_start(struct seq_file *f, loff_t *pos) - f->private = root; - - /* find the first profile */ -- mutex_lock(&root->lock); -+ mutex_lock_nested(&root->lock, root->level); - profile = __first_profile(root, root); - - /* skip to position */ -@@ -2492,7 +2492,7 @@ static int __init aa_create_aafs(void) - ns_subrevision(root_ns) = dent; - - /* policy tree referenced by magic policy symlink */ -- mutex_lock(&root_ns->lock); -+ mutex_lock_nested(&root_ns->lock, root_ns->level); - error = __aafs_ns_mkdir(root_ns, aafs_mnt->mnt_root, ".policy", - aafs_mnt->mnt_root); - mutex_unlock(&root_ns->lock); -diff --git a/security/apparmor/label.c b/security/apparmor/label.c -index c5b99b954580..f5df9eaba4df 100644 ---- a/security/apparmor/label.c -+++ b/security/apparmor/label.c -@@ -2115,7 +2115,7 @@ void __aa_labelset_update_subtree(struct aa_ns *ns) - __labelset_update(ns); - - list_for_each_entry(child, &ns->sub_ns, base.list) { -- mutex_lock(&child->lock); -+ mutex_lock_nested(&child->lock, child->level); - __aa_labelset_update_subtree(child); - mutex_unlock(&child->lock); - } -diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c -index 877983014b5b..a6e84d19bc0b 100644 ---- a/security/apparmor/policy.c -+++ b/security/apparmor/policy.c -@@ -546,7 +546,7 @@ struct aa_profile *aa_new_null_profile(struct aa_profile *parent, bool hat, - profile->file.dfa = aa_get_dfa(nulldfa); - profile->policy.dfa = aa_get_dfa(nulldfa); - -- mutex_lock(&profile->ns->lock); -+ mutex_lock_nested(&profile->ns->lock, profile->ns->level); - p = __find_child(&parent->base.profiles, bname); - if (p) { - aa_free_profile(profile); -@@ -907,7 +907,7 @@ ssize_t aa_replace_profiles(struct aa_ns *policy_ns, struct aa_label *label, - } else - ns = aa_get_ns(policy_ns ? policy_ns : labels_ns(label)); - -- mutex_lock(&ns->lock); -+ mutex_lock_nested(&ns->lock, ns->level); - /* check for duplicate rawdata blobs: space and file dedup */ - list_for_each_entry(rawdata_ent, &ns->rawdata_list, list) { - if (aa_rawdata_eq(rawdata_ent, udata)) { -@@ -1118,13 +1118,13 @@ ssize_t aa_remove_profiles(struct aa_ns *policy_ns, struct aa_label *subj, - - if (!name) { - /* remove namespace - can only happen if fqname[0] == ':' */ -- mutex_lock(&ns->parent->lock); -+ mutex_lock_nested(&ns->parent->lock, ns->level); - __aa_remove_ns(ns); - __aa_bump_ns_revision(ns); - mutex_unlock(&ns->parent->lock); - } else { - /* remove profile */ -- mutex_lock(&ns->lock); -+ mutex_lock_nested(&ns->lock, ns->level); - profile = aa_get_profile(__lookup_profile(&ns->base, name)); - if (!profile) { - error = -ENOENT; -diff --git a/security/apparmor/policy_ns.c b/security/apparmor/policy_ns.c -index 62a3589c62ab..b1e629cba70b 100644 ---- a/security/apparmor/policy_ns.c -+++ b/security/apparmor/policy_ns.c -@@ -256,7 +256,8 @@ static struct aa_ns *__aa_create_ns(struct aa_ns *parent, const char *name, - ns = alloc_ns(parent->base.hname, name); - if (!ns) - return NULL; -- mutex_lock(&ns->lock); -+ ns->level = parent->level + 1; -+ mutex_lock_nested(&ns->lock, ns->level); - error = __aafs_ns_mkdir(ns, ns_subns_dir(parent), name, dir); - if (error) { - AA_ERROR("Failed to create interface for ns %s\n", -@@ -266,7 +267,6 @@ static struct aa_ns *__aa_create_ns(struct aa_ns *parent, const char *name, - return ERR_PTR(error); - } - ns->parent = aa_get_ns(parent); -- ns->level = parent->level + 1; - list_add_rcu(&ns->base.list, &parent->sub_ns); - /* add list ref */ - aa_get_ns(ns); -@@ -313,7 +313,7 @@ struct aa_ns *aa_prepare_ns(struct aa_ns *parent, const char *name) - { - struct aa_ns *ns; - -- mutex_lock(&parent->lock); -+ mutex_lock_nested(&parent->lock, parent->level); - /* try and find the specified ns and if it doesn't exist create it */ - /* released by caller */ - ns = aa_get_ns(__aa_find_ns(&parent->sub_ns, name)); -@@ -336,7 +336,7 @@ static void destroy_ns(struct aa_ns *ns) - if (!ns) - return; - -- mutex_lock(&ns->lock); -+ mutex_lock_nested(&ns->lock, ns->level); - /* release all profiles in this namespace */ - __aa_profile_list_release(&ns->base.profiles); - -diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c -index c02e2b9472bb..2b51fca5057d 100644 ---- a/security/apparmor/policy_unpack.c -+++ b/security/apparmor/policy_unpack.c -@@ -157,7 +157,7 @@ static void do_loaddata_free(struct work_struct *work) - struct aa_ns *ns = aa_get_ns(d->ns); - - if (ns) { -- mutex_lock(&ns->lock); -+ mutex_lock_nested(&ns->lock, ns->level); - __aa_fs_remove_rawdata(d); - mutex_unlock(&ns->lock); - aa_put_ns(ns); --- -2.16.1 - diff --git a/patches.apparmor/apparmor-fix-ptrace-label-match-when-matching-stacke.patch b/patches.apparmor/apparmor-fix-ptrace-label-match-when-matching-stacke.patch deleted file mode 100644 index fac7972..0000000 --- a/patches.apparmor/apparmor-fix-ptrace-label-match-when-matching-stacke.patch +++ /dev/null @@ -1,140 +0,0 @@ -From 3addea85ea9b192e6dc39ec0acd7ee401262f7e7 Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Fri, 8 Dec 2017 17:43:18 -0800 -Subject: [PATCH] apparmor: fix ptrace label match when matching stacked labels -References: Git-fixes, bsc#1079851 -Git-commit: 0dda0b3fb255048a221f736c8a2a24c674da8bf3 -Patch-mainline: v4.15-rc8 - - -Given a label with a profile stack of - A//&B or A//&C ... - -A ptrace rule should be able to specify a generic trace pattern with -a rule like - - ptrace trace A//&**, - -however this is failing because while the correct label match routine -is called, it is being done post label decomposition so it is always -being done against a profile instead of the stacked label. - -To fix this refactor the cross check to pass the full peer label in to -the label_match. - -Fixes: 290f458a4f16 ("apparmor: allow ptrace checks to be finer grained than just capability") -Cc: Stable -Reported-by: Matthew Garrett -Tested-by: Matthew Garrett -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/include/perms.h | 3 +++ - security/apparmor/ipc.c | 53 +++++++++++++++++++++++---------------- - 2 files changed, 35 insertions(+), 21 deletions(-) - -diff --git a/security/apparmor/include/perms.h b/security/apparmor/include/perms.h -index 2b27bb79aec4..d7b7e7115160 100644 ---- a/security/apparmor/include/perms.h -+++ b/security/apparmor/include/perms.h -@@ -133,6 +133,9 @@ extern struct aa_perms allperms; - #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, const char *chrs, u32 mask); - void aa_audit_perm_names(struct audit_buffer *ab, const char **names, u32 mask); -diff --git a/security/apparmor/ipc.c b/security/apparmor/ipc.c -index 7ca0032e7ba9..b40678f3c1d5 100644 ---- a/security/apparmor/ipc.c -+++ b/security/apparmor/ipc.c -@@ -64,40 +64,48 @@ static void audit_ptrace_cb(struct audit_buffer *ab, void *va) - FLAGS_NONE, GFP_ATOMIC); - } - -+/* assumes check for PROFILE_MEDIATES is already done */ - /* TODO: conditionals */ - static int profile_ptrace_perm(struct aa_profile *profile, -- struct aa_profile *peer, u32 request, -- struct common_audit_data *sa) -+ struct aa_label *peer, u32 request, -+ struct common_audit_data *sa) - { - struct aa_perms perms = { }; - -- /* need because of peer in cross check */ -- if (profile_unconfined(profile) || -- !PROFILE_MEDIATES(profile, AA_CLASS_PTRACE)) -- return 0; -- -- aad(sa)->peer = &peer->label; -- aa_profile_match_label(profile, &peer->label, AA_CLASS_PTRACE, request, -+ aad(sa)->peer = peer; -+ aa_profile_match_label(profile, peer, AA_CLASS_PTRACE, request, - &perms); - aa_apply_modes_to_perms(profile, &perms); - return aa_check_perms(profile, &perms, request, sa, audit_ptrace_cb); - } - --static int cross_ptrace_perm(struct aa_profile *tracer, -- struct aa_profile *tracee, u32 request, -- struct common_audit_data *sa) -+static int profile_tracee_perm(struct aa_profile *tracee, -+ struct aa_label *tracer, u32 request, -+ struct common_audit_data *sa) - { -+ if (profile_unconfined(tracee) || unconfined(tracer) || -+ !PROFILE_MEDIATES(tracee, AA_CLASS_PTRACE)) -+ return 0; -+ -+ return profile_ptrace_perm(tracee, tracer, request, sa); -+} -+ -+static int profile_tracer_perm(struct aa_profile *tracer, -+ struct aa_label *tracee, u32 request, -+ struct common_audit_data *sa) -+{ -+ if (profile_unconfined(tracer)) -+ return 0; -+ - if (PROFILE_MEDIATES(tracer, AA_CLASS_PTRACE)) -- return xcheck(profile_ptrace_perm(tracer, tracee, request, sa), -- profile_ptrace_perm(tracee, tracer, -- request << PTRACE_PERM_SHIFT, -- sa)); -- /* policy uses the old style capability check for ptrace */ -- if (profile_unconfined(tracer) || tracer == tracee) -+ return profile_ptrace_perm(tracer, tracee, request, sa); -+ -+ /* profile uses the old style capability check for ptrace */ -+ if (&tracer->label == tracee) - return 0; - - aad(sa)->label = &tracer->label; -- aad(sa)->peer = &tracee->label; -+ aad(sa)->peer = tracee; - aad(sa)->request = 0; - aad(sa)->error = aa_capable(&tracer->label, CAP_SYS_PTRACE, 1); - -@@ -115,10 +123,13 @@ static int cross_ptrace_perm(struct aa_profile *tracer, - int aa_may_ptrace(struct aa_label *tracer, struct aa_label *tracee, - u32 request) - { -+ struct aa_profile *profile; -+ u32 xrequest = request << PTRACE_PERM_SHIFT; - DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, OP_PTRACE); - -- return xcheck_labels_profiles(tracer, tracee, cross_ptrace_perm, -- request, &sa); -+ return xcheck_labels(tracer, tracee, profile, -+ profile_tracer_perm(profile, tracee, request, &sa), -+ profile_tracee_perm(profile, tracer, xrequest, &sa)); - } - - --- -2.16.1 - diff --git a/patches.apparmor/apparmor-fix-regression-in-mount-mediation-when-feat.patch b/patches.apparmor/apparmor-fix-regression-in-mount-mediation-when-feat.patch deleted file mode 100644 index c547164..0000000 --- a/patches.apparmor/apparmor-fix-regression-in-mount-mediation-when-feat.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 70e0616663ebca615bd1c431060f067d70c59d1d Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Thu, 7 Dec 2017 00:28:27 -0800 -Subject: [PATCH] apparmor: fix regression in mount mediation when feature set is pinned -Git-commit: 5b9f57cf47b87f07210875d6a24776b4496b818d -Patch-mainline: v4.15-rc7 -References: Git-fixes, bsc#1079828 - -When the mount code was refactored for Labels it was not correctly -updated to check whether policy supported mediation of the mount -class. This causes a regression when the kernel feature set is -reported as supporting mount and policy is pinned to a feature set -that does not support mount mediation. - -BugLink: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=882697#41 -Fixes: 2ea3ffb7782a ("apparmor: add mount mediation") -Reported-by: Fabian Grünbichler -Cc: Stable -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues ---- - security/apparmor/mount.c | 12 +++++++++++- - 1 file changed, 11 insertions(+), 1 deletion(-) - -diff --git a/security/apparmor/mount.c b/security/apparmor/mount.c -index 82a64b58041d..e395137ecff1 100644 ---- a/security/apparmor/mount.c -+++ b/security/apparmor/mount.c -@@ -330,6 +330,9 @@ static int match_mnt_path_str(struct aa_profile *profile, - AA_BUG(!mntpath); - AA_BUG(!buffer); - -+ if (!PROFILE_MEDIATES(profile, AA_CLASS_MOUNT)) -+ return 0; -+ - error = aa_path_name(mntpath, path_flags(profile, mntpath), buffer, - &mntpnt, &info, profile->disconnected); - if (error) -@@ -381,6 +384,9 @@ static int match_mnt(struct aa_profile *profile, const struct path *path, - AA_BUG(!profile); - AA_BUG(devpath && !devbuffer); - -+ if (!PROFILE_MEDIATES(profile, AA_CLASS_MOUNT)) -+ return 0; -+ - if (devpath) { - error = aa_path_name(devpath, path_flags(profile, devpath), - devbuffer, &devname, &info, -@@ -559,6 +565,9 @@ static int profile_umount(struct aa_profile *profile, struct path *path, - AA_BUG(!profile); - AA_BUG(!path); - -+ if (!PROFILE_MEDIATES(profile, AA_CLASS_MOUNT)) -+ return 0; -+ - error = aa_path_name(path, path_flags(profile, path), buffer, &name, - &info, profile->disconnected); - if (error) -@@ -614,7 +623,8 @@ static struct aa_label *build_pivotroot(struct aa_profile *profile, - AA_BUG(!new_path); - AA_BUG(!old_path); - -- if (profile_unconfined(profile)) -+ if (profile_unconfined(profile) || -+ !PROFILE_MEDIATES(profile, AA_CLASS_MOUNT)) - return aa_get_newest_label(&profile->label); - - error = aa_path_name(old_path, path_flags(profile, old_path), --- -2.16.1 - diff --git a/patches.apparmor/apparmor-fix-resource-audit-messages-when-auditing-peer.patch b/patches.apparmor/apparmor-fix-resource-audit-messages-when-auditing-peer.patch deleted file mode 100644 index e8da66b..0000000 --- a/patches.apparmor/apparmor-fix-resource-audit-messages-when-auditing-peer.patch +++ /dev/null @@ -1,46 +0,0 @@ -From: John Johansen -Date: Fri Feb 9 04:57:39 2018 -0800 -Subject: apparmor: fix resource audit messages when auditing peer -Patch-mainline: v4.17-rc1 -Git-commit: b5beb07ad32ab533027aa988d96a44965ec116f7 -References: bsc#1084839 - -Resource auditing is using the peer field which is not available -when the rlim data struct is used, because it is a different element -of the same union. Accessing peer during resource auditing could -cause garbage log entries or even oops the kernel. - -Move the rlim data block into the same struct as the peer field -so they can be used together. - -CC: -Fixes: 86b92cb782b3 ("apparmor: move resource checks to using labels") -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues - -diff --git a/security/apparmor/include/audit.h b/security/apparmor/include/audit.h -index 4ac095118717..2ebc00a579fd 100644 ---- a/security/apparmor/include/audit.h -+++ b/security/apparmor/include/audit.h -@@ -126,6 +126,10 @@ struct apparmor_audit_data { - const char *target; - kuid_t ouid; - } fs; -+ struct { -+ int rlim; -+ unsigned long max; -+ } rlim; - int signal; - }; - }; -@@ -134,10 +138,6 @@ struct apparmor_audit_data { - const char *ns; - long pos; - } iface; -- struct { -- int rlim; -- unsigned long max; -- } rlim; - struct { - const char *src_name; - const char *type; diff --git a/patches.apparmor/apparmor-remove-no-op-permission-check-in-policy_unpack.patch b/patches.apparmor/apparmor-remove-no-op-permission-check-in-policy_unpack.patch deleted file mode 100644 index 287dc9c..0000000 --- a/patches.apparmor/apparmor-remove-no-op-permission-check-in-policy_unpack.patch +++ /dev/null @@ -1,102 +0,0 @@ -From c037bd615885f1d9d3bdb48531bace79fae1505d Mon Sep 17 00:00:00 2001 -From: John Johansen -Date: Tue Aug 21 17:19:53 2018 -0700 -Subject: [PATCH] apparmor: remove no-op permission check in policy_unpack -Git-commit: c037bd615885f1d9d3bdb48531bace79fae1505d -References: bsc#1106427 -Patch-mainline: v4.19-rc1 - -The patch 736ec752d95e: "AppArmor: policy routines for loading and -unpacking policy" from Jul 29, 2010, leads to the following static -checker warning: - - security/apparmor/policy_unpack.c:410 verify_accept() - warn: bitwise AND condition is false here - - security/apparmor/policy_unpack.c:413 verify_accept() - warn: bitwise AND condition is false here - -security/apparmor/policy_unpack.c - 392 #define DFA_VALID_PERM_MASK 0xffffffff - 393 #define DFA_VALID_PERM2_MASK 0xffffffff - 394 - 395 /** - 396 * verify_accept - verify the accept tables of a dfa - 397 * @dfa: dfa to verify accept tables of (NOT NULL) - 398 * @flags: flags governing dfa - 399 * - 400 * Returns: 1 if valid accept tables else 0 if error - 401 */ - 402 static bool verify_accept(struct aa_dfa *dfa, int flags) - 403 { - 404 int i; - 405 - 406 /* verify accept permissions */ - 407 for (i = 0; i < dfa->tables[YYTD_ID_ACCEPT]->td_lolen; i++) { - 408 int mode = ACCEPT_TABLE(dfa)[i]; - 409 - 410 if (mode & ~DFA_VALID_PERM_MASK) - 411 return 0; - 412 - 413 if (ACCEPT_TABLE2(dfa)[i] & ~DFA_VALID_PERM2_MASK) - 414 return 0; - -Fixes: 736ec752d95e ("AppArmor: policy routines for loading and unpacking policy") -Reported-by: Dan Carpenter -Signed-off-by: John Johansen -Acked-by: Goldwyn Rodrigues - -diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c -index 0e566a0..21cb384 100644 - ---- a/security/apparmor/policy_unpack.c -+++ b/security/apparmor/policy_unpack.c -@@ -389,32 +389,6 @@ static int unpack_strdup(struct aa_ext *e, char **string, const char *name) - return res; - } - --#define DFA_VALID_PERM_MASK 0xffffffff --#define DFA_VALID_PERM2_MASK 0xffffffff -- --/** -- * verify_accept - verify the accept tables of a dfa -- * @dfa: dfa to verify accept tables of (NOT NULL) -- * @flags: flags governing dfa -- * -- * Returns: 1 if valid accept tables else 0 if error -- */ --static bool verify_accept(struct aa_dfa *dfa, int flags) --{ -- int i; -- -- /* verify accept permissions */ -- for (i = 0; i < dfa->tables[YYTD_ID_ACCEPT]->td_lolen; i++) { -- int mode = ACCEPT_TABLE(dfa)[i]; -- -- if (mode & ~DFA_VALID_PERM_MASK) -- return 0; -- -- if (ACCEPT_TABLE2(dfa)[i] & ~DFA_VALID_PERM2_MASK) -- return 0; -- } -- return 1; --} - - /** - * unpack_dfa - unpack a file rule dfa -@@ -445,15 +419,9 @@ static struct aa_dfa *unpack_dfa(struct aa_ext *e) - if (IS_ERR(dfa)) - return dfa; - -- if (!verify_accept(dfa, flags)) -- goto fail; - } - - return dfa; -- --fail: -- aa_put_dfa(dfa); -- return ERR_PTR(-EPROTO); - } - - /** diff --git a/series.conf b/series.conf index d7ca2b7..62cb45f 100644 --- a/series.conf +++ b/series.conf @@ -1320,7 +1320,6 @@ patches.drivers/0025-thunderbolt-Add-support-for-host-and-device-NVM-firm.patch patches.drivers/0026-thunderbolt-fix-spelling-mistake-missmatch-mismatch.patch patches.drivers/drivers-fsi-Add-module-license-to-core-driver.patch - patches.apparmor/0003-doc-ReSTify-apparmor.txt.patch patches.drivers/net-skbuff.h-properly-escape-a-macro-name-on-kernel-.patch patches.drivers/net-fix-some-identation-issues-at-kernel-doc-markups.patch patches.drivers/kernel-doc-describe-the-literal-syntax.patch @@ -1362,69 +1361,6 @@ patches.drivers/0022-clk-rockchip-add-ids-for-camera-on-rk3399.patch patches.drivers/soc-tegra-flowctrl-Fix-error-handling patches.drivers/firmware-tegra-Fix-locking-bugs-in-BPMP - patches.apparmor/0002-apparmorfs-Combine-two-function-calls-into-one-in-aa.patch - patches.apparmor/0004-apparmorfs-Use-seq_putc-in-two-functions.patch - patches.apparmor/0005-apparmor-Fix-error-cod-in-__aa_fs_profile_mkdir.patch - patches.apparmor/0006-security-apparmor-Use-POSIX-compatible-printf-s.patch - patches.apparmor/0007-apparmor-move-file-context-into-file.h.patch - patches.apparmor/0008-apparmor-make-internal-lib-fn-skipn_spaces-available.patch - patches.apparmor/0009-apparmor-allow-profiles-to-provide-info-to-disconnec.patch - patches.apparmor/0010-apparmor-Move-path-lookup-to-using-preallocated-buff.patch - patches.apparmor/0001-securityfs-add-the-ability-to-support-symlinks.patch - patches.apparmor/0011-apparmor-move-to-per-loaddata-files-instead-of-repli.patch - patches.apparmor/0012-apparmor-use-macro-template-to-simplify-profile-seq_.patch - patches.apparmor/0013-apparmor-use-macro-template-to-simplify-namespace-se.patch - patches.apparmor/0014-apparmor-add-custom-apparmorfs-that-will-be-used-by-.patch - patches.apparmor/0015-apparmor-rename-apparmor-file-fns-and-data-to-indica.patch - patches.apparmor/0016-apparmor-allow-specifying-an-already-created-dir-to-.patch - patches.apparmor/0017-apparmor-convert-from-securityfs-to-apparmorfs-for-p.patch - patches.apparmor/0018-apparmor-move-permissions-into-their-own-file-to-be-.patch - patches.apparmor/0019-apparmor-rework-perm-mapping-to-a-slightly-broader-s.patch - patches.apparmor/0020-apparmor-provide-finer-control-over-policy-managemen.patch - patches.apparmor/0021-apparmor-add-policy-revision-file-interface.patch - patches.apparmor/0022-apparmor-add-mkdir-rmdir-interface-to-manage-policy-.patch - patches.apparmor/0023-apparmor-add-label-data-availability-to-the-feature-.patch - patches.apparmor/0024-apparmor-speed-up-transactional-queries.patch - patches.apparmor/0025-apparmor-add-fn-to-test-if-profile-supports-a-given-.patch - patches.apparmor/0026-apparmor-add-gerneric-permissions-struct-and-support.patch - patches.apparmor/0027-apparmor-switch-from-file_perms-to-aa_perms.patch - patches.apparmor/0028-apparmor-add-profile-permission-query-ability.patch - patches.apparmor/0029-apparmor-provide-information-about-path-buffer-size-.patch - patches.apparmor/0030-apparmor-cleanup-__find_child.patch - patches.apparmor/0031-apparmor-add-namespace-lookup-fns.patch - patches.apparmor/0032-apparmor-fix-policy-load-remove-semantics.patch - patches.apparmor/0033-apparmor-fix-apparmor_query-data.patch - patches.apparmor/0034-apparmor-fix-display-of-ns-name.patch - patches.apparmor/0035-apparmor-move-bprm_committing_creds-committed_creds-.patch - patches.apparmor/0036-apparmor-convert-to-profile-block-critical-sections.patch - patches.apparmor/0037-apparmor-share-profile-name-on-replacement.patch - patches.apparmor/0038-apparmor-refactor-updating-profiles-to-the-newest-pa.patch - patches.apparmor/0039-apparmor-cleanup-remove-unused-and-not-fully-impleme.patch - patches.apparmor/0040-apparmor-convert-aa_change_XXX-bool-parameters-to-fl.patch - patches.apparmor/0041-apparmor-cleanup-rename-XXX_file_context-to-XXX_file.patch - patches.apparmor/0042-apparmor-revalidate-files-during-exec.patch - patches.apparmor/0043-apparmor-add-the-base-fns-for-domain-labels.patch - patches.apparmor/0044-apparmor-switch-from-profiles-to-using-labels-on-con.patch - patches.apparmor/0045-apparmor-switch-getprocattr-to-using-label_print-fns.patch - patches.apparmor/0046-apparmor-update-query-interface-to-support-label-que.patch - patches.apparmor/0047-apparmor-move-capability-checks-to-using-labels.patch - patches.apparmor/0048-apparmor-move-resource-checks-to-using-labels.patch - patches.apparmor/0049-apparmor-add-cross-check-permission-helper-macros.patch - patches.apparmor/0050-apparmor-move-ptrace-checks-to-using-labels.patch - patches.apparmor/0051-apparmor-allow-ptrace-checks-to-be-finer-grained-tha.patch - patches.apparmor/0052-apparmor-move-aa_file_perm-to-use-labels.patch - patches.apparmor/0053-apparmor-update-aa_audit_file-to-use-labels.patch - patches.apparmor/0054-apparmor-refactor-path-name-lookup-and-permission-ch.patch - patches.apparmor/0055-apparmor-move-path_link-mediation-to-using-labels.patch - patches.apparmor/0056-apparmor-rework-file-permission-to-cache-file-access.patch - patches.apparmor/0057-apparmor-mediate-files-when-they-are-received.patch - patches.apparmor/0058-apparmor-support-v7-transition-format-compatible-wit.patch - patches.apparmor/0059-apparmor-move-exec-domain-mediation-to-using-labels.patch - patches.apparmor/0060-apparmor-move-change_hat-mediation-to-using-labels.patch - patches.apparmor/0061-apparmor-move-change_profile-mediation-to-using-labe.patch - patches.apparmor/0062-apparmor-add-domain-label-stacking-info-to-apparmorf.patch - patches.apparmor/0063-apparmor-add-stacked-domain-labels-interface.patch - patches.apparmor/0064-apparmor-export-that-basic-profile-namespaces-are-su.patch patches.drivers/tpm-177-tis-Fix-IRQ-autoprobing-when-using-platform_devi.patch patches.drivers/tpm-178-tis-Use-platform_get_irq.patch patches.drivers/tpm-Introduce-flag-TPM_TRANSMIT_RAW.patch @@ -1434,7 +1370,6 @@ patches.drivers/IB-core-Enforce-PKey-security-on-QPs.patch patches.drivers/selinux-lsm-IB-core-Implement-LSM-notification-syste.patch patches.drivers/IB-core-Enforce-security-on-management-datagrams.patch - patches.apparmor/0065-apparmor-put-back-designators-in-struct-initialisers.patch patches.drivers/Fix-English-in-description-of-GCC_PLUGIN_STRUCTLEAK patches.drivers/crypto-sha512-mb-add-some-missing-unlock-on-error patches.suse/crypto-dh-fix-memleak-in-setkey.patch @@ -6927,22 +6862,6 @@ patches.drivers/driver-core-Fix-link-to-device-power-management-docu patches.drivers/PM-docs-Drop-an-excess-character-from-devices.rst patches.drivers/ACPI-watchdog-properly-initialize-resources - patches.apparmor/0001-apparmor-Fix-shadowed-local-variable-in-unpack_trans.patch - patches.apparmor/0002-apparmor-Fix-logical-error-in-verify_header.patch - patches.apparmor/0003-apparmor-Fix-an-error-code-in-aafs_create.patch - patches.apparmor/0004-apparmor-Redundant-condition-prev_ns.-in-label.c-149.patch - patches.apparmor/0005-apparmor-add-the-ability-to-mediate-signals.patch - patches.apparmor/0006-apparmor-add-mount-mediation.patch - patches.apparmor/0007-apparmor-cleanup-conditional-check-for-label-in-labe.patch - patches.apparmor/0008-apparmor-add-support-for-absolute-root-view-based-la.patch - patches.apparmor/0009-apparmor-make-policy_unpack-able-to-audit-different-.patch - patches.apparmor/0010-apparmor-add-more-debug-asserts-to-apparmorfs.patch - patches.apparmor/0012-apparmor-move-new_null_profile-to-after-profile-look.patch - patches.apparmor/0013-apparmor-fix-race-condition-in-null-profile-creation.patch - patches.apparmor/0014-apparmor-ensure-unconfined-profiles-have-dfas-initia.patch - patches.apparmor/0015-apparmor-fix-incorrect-type-assignment-when-freeing-.patch - patches.apparmor/0016-apparmor-fix-build-failure-on-sparc-caused-by-undecl.patch - patches.apparmor/0017-apparmor-fix-apparmorfs-DAC-access-permissions.patch patches.fixes/udpv6-Fix-the-checksum-computation-when-HW-checksum-.patch patches.suse/ip6_gre-skb_push-ipv6hdr-before-packing-the-header-i.patch patches.suse/net-phy-Fix-mask-value-write-on-gmii2rgmii-converter.patch @@ -7706,7 +7625,6 @@ patches.drivers/crypto-ccm-preserve-the-IV-buffer patches.fixes/workqueue-Fix-NULL-pointer-dereference.patch patches.drivers/Revert-scsi-make-state-device-attribute-pollable.patch - patches.apparmor/0004-apparmor-fix-off-by-one-comparison-on-MAXMAPPED_SIG.patch patches.fixes/keys-fix-null-pointer-dereference-during-asn-1-parsing patches.arch/44-x86-mm-Unbreak-modules-that-rely-on-external-PAGE_KERNEL-availability.patch patches.drivers/cxgb4-update-latest-firmware-version-supported.patch @@ -10033,11 +9951,6 @@ patches.fixes/rtc-set-the-alarm-to-the-next-expiring-timer patches.drivers/rtc-pl031-make-interrupt-optional patches.drivers/rtc-pcf8563-fix-output-clock-rate - patches.apparmor/0002-apparmor-fix-leak-of-null-profile-name-if-profile-al.patch - patches.apparmor/apparmor-ensure-that-undecidable-profile-attachments-fail.patch - patches.apparmor/0001-apparmor-fix-profile-attachment-for-special-unconfin.patch - patches.apparmor/0003-apparmor-fix-locking-when-creating-a-new-complain-pr.patch - patches.apparmor/apparmor-fix-possible-recursive-lock-warning-in-__aa.patch patches.drivers/drm-amdgpu-Remove-check-which-is-not-valid-for-certa patches.drivers/drm-amdgpu-Properly-allocate-VM-invalidate-eng-v2 patches.drivers/drm-fsl-dcu-Don-t-set-connector-DPMS-property @@ -10227,7 +10140,6 @@ patches.drivers/0004-cpufreq-mediatek-add-missing-MODULE_DESCRIPTION-AUTH.patch patches.drivers/ACPI-bus-Leave-modalias-empty-for-devices-which-are- patches.drivers/ACPI-EC-Fix-regression-related-to-PM-ops-support-in- - patches.apparmor/apparmor-fix-oops-in-audit_signal_cb-hook.patch patches.drivers/nvme-fabrics-introduce-init-command-check-for-a-queu.patch patches.drivers/nvme-fc-check-if-queue-is-ready-in-queue_rq.patch patches.drivers/nvme-loop-check-if-queue-is-ready-in-queue_rq.patch @@ -10897,7 +10809,6 @@ patches.drivers/KVM-s390-prevent-buffer-overrun-on-memory-hotplug-du.patch patches.fixes/sget-handle-failures-of-register_shrinker.patch patches.drivers/leds-core-Fix-regression-caused-by-commit-2b83ff96f5 - patches.apparmor/apparmor-fix-regression-in-mount-mediation-when-feat.patch patches.fixes/cgroup-avoid-copying-strings-longer-than-the-buffers.patch patches.fixes/cgroup-Fix-deadlock-in-cpu-hotplug-path.patch patches.drivers/platform-x86-wmi-Call-acpi_wmi_init-later @@ -10987,8 +10898,6 @@ patches.fixes/x86-microcode-intel-extend-bdw-late-loading-with-a-revision-check.patch patches.fixes/kdump-write-correct-address-of-mem_section-into-vmco.patch patches.suse/tools-objtool-Makefile-don-t-assume-sync-check.sh-is.patch - patches.apparmor/apparmor-fix-ptrace-label-match-when-matching-stacke.patch - patches.apparmor/apparmor-Fix-regression-in-profile-conflict-logic.patch patches.fixes/Bluetooth-Prevent-stack-info-leak-from-the-EFS-element.patch patches.fixes/0001-usbip-fix-vudc_rx-harden-CMD_SUBMIT-path-to-handle-m.patch patches.fixes/0001-usbip-remove-kernel-addresses-from-usb-device-and-ur.patch @@ -14943,11 +14852,6 @@ patches.drivers/nvmet-fix-space-padding-in-serial-number.patch patches.drivers/nvme-Use-admin-command-effects-for-admin-commands.patch patches.drivers/nvme-expand-nvmf_check_if_ready-checks.patch - patches.apparmor/apparmor-fix-display-of-.ns_name-for-containers.patch - patches.apparmor/apparmor-fix-resource-audit-messages-when-auditing-peer.patch - patches.apparmor/apparmor-fix-dangling-symlinks-to-policy-rawdata-aft.patch - patches.apparmor/apparmor-fix-logging-of-the-existence-test-for-signa.patch - patches.apparmor/apparmor-fix-memory-leak-on-buffer-on-error-exit-path.patch patches.drivers/watchdog-f71808e_wdt-Fix-WD_EN-register-read patches.drivers/pwm-stm32-Remove-unused-struct-device patches.drivers/pwm-rcar-Fix-a-condition-to-prevent-mismatch-value-s @@ -17343,8 +17247,6 @@ patches.arch/powerpc-topology-Get-topology-for-shared-processors-.patch patches.arch/KVM-PPC-Book3S-Fix-guest-DMA-when-guest-partially-ba.patch patches.arch/powerpc-mce-Fix-SLB-rebolting-during-MCE-recovery-pa.patch - patches.apparmor/apparmor-fix-an-error-code-in-__aa_create_ns.patch - patches.apparmor/apparmor-remove-no-op-permission-check-in-policy_unpack.patch patches.drivers/iommu-amd-make-sure-tlb-to-be-flushed-before-iova-freed patches.drivers/0001-x86-irq_remapping-move-irq-remapping-mode-enum patches.drivers/0002-iommu-amd-add-support-for-higher-64-bit-iommu-control-register @@ -17944,7 +17846,6 @@ patches.apparmor/apparmor-basic-networking-rules.patch patches.apparmor/apparmor-fix-quieting-of-audit-messages-for-network-mediation.patch patches.apparmor/apparmor-basic-networking-rules-4.11-rc1.patch - patches.apparmor/apparmor-check-all-net-profiles.patch ######################################################## # Lock down functions for UEFI secure boot , FATE#314486