[packages/kernel] - initial 4.14.0
arekm
arekm at pld-linux.org
Sun Nov 12 23:03:33 CET 2017
commit 8b6a494719f4150ce54b9e4d30810ece069c1c73
Author: Arkadiusz Miśkiewicz <arekm at maven.pl>
Date: Sun Nov 12 23:03:17 2017 +0100
- initial 4.14.0
...1-UBUNTU-SAUCE-apparmor-af_unix-mediation.patch | 0
...x-shadowed-local-variable-in-unpack_trans.patch | 51 -
...parmor-Fix-logical-error-in-verify_header.patch | 32 -
...apparmor-Fix-an-error-code-in-aafs_create.patch | 37 -
...dundant-condition-prev_ns.-in-label.c-149.patch | 29 -
...parmor-add-the-ability-to-mediate-signals.patch | 397 ---
0007-apparmor-add-mount-mediation.patch | 1051 ------
...eanup-conditional-check-for-label-in-labe.patch | 71 -
...d-support-for-absolute-root-view-based-la.patch | 63 -
...ke-policy_unpack-able-to-audit-different-.patch | 219 --
...rmor-add-more-debug-asserts-to-apparmorfs.patch | 78 -
...ve-new_null_profile-to-after-profile-look.patch | 194 --
...x-race-condition-in-null-profile-creation.patch | 60 -
...sure-unconfined-profiles-have-dfas-initia.patch | 36 -
...x-incorrect-type-assignment-when-freeing-.patch | 39 -
kernel-aufs4.patch | 3520 +++++++++++++++-----
kernel.spec | 47 +-
17 files changed, 2750 insertions(+), 3174 deletions(-)
---
diff --git a/kernel.spec b/kernel.spec
index 41ffc068..93ecbd27 100644
--- a/kernel.spec
+++ b/kernel.spec
@@ -69,9 +69,9 @@
%define have_pcmcia 0
%endif
-%define rel 1
-%define basever 4.13
-%define postver .12
+%define rel 0.1
+%define basever 4.14
+%define postver .0
# define this to '-%{basever}' for longterm branch
%define versuffix %{nil}
@@ -120,7 +120,7 @@ Epoch: 3
License: GPL v2
Group: Base/Kernel
Source0: https://www.kernel.org/pub/linux/kernel/v4.x/linux-%{basever}.tar.xz
-# Source0-md5: ab1a2abc6f37b752dd2595338bec4e78
+# Source0-md5: bacdb9ffdcd922aa069a5e1520160e24
%if "%{postver}" != ".0"
Patch0: https://www.kernel.org/pub/linux/kernel/v4.x/patch-%{version}.xz
# Patch0-md5: 665b55e1f24ec56de55f7d0302d7c4f5
@@ -197,10 +197,9 @@ Patch101: kernel-vserver-fixes.patch
# Patch creation:
# git clone git://github.com/sfjro/aufs4-standalone.git
# cd aufs4-standalone
-# git checkout -b aufs4.12 origin/aufs4.12
+# git checkout -b aufs4.14 origin/aufs4.14
# cat aufs4-kbuild.patch aufs4-base.patch aufs4-mmap.patch aufs4-standalone.patch > ~/rpm/packages/kernel/kernel-aufs4.patch
-# rm -rf linux && mkdir linux
-# cp -a Documentation fs include linux
+# rm -rf linux && mkdir linux; cp -a Documentation fs include linux
# diff -urN /usr/share/empty linux | filterdiff -x linux/include/uapi/linux/Kbuild >> ~/rpm/packages/kernel/kernel-aufs4.patch
# cat aufs4-loopback.patch >> ~/rpm/packages/kernel/kernel-aufs4.patch
#
@@ -218,23 +217,9 @@ Patch2000: kernel-small_fixes.patch
Patch2001: kernel-pwc-uncompress.patch
Patch2003: kernel-regressions.patch
-# http://bazaar.launchpad.net/~apparmor-dev/apparmor/master/files/head:/kernel-patches/v4.13/
-Patch5001: 0002-apparmor-Fix-shadowed-local-variable-in-unpack_trans.patch
-Patch5002: 0003-apparmor-Fix-logical-error-in-verify_header.patch
-Patch5003: 0004-apparmor-Fix-an-error-code-in-aafs_create.patch
-Patch5004: 0005-apparmor-Redundant-condition-prev_ns.-in-label.c-149.patch
-Patch5005: 0006-apparmor-add-the-ability-to-mediate-signals.patch
-Patch5006: 0007-apparmor-add-mount-mediation.patch
-Patch5007: 0008-apparmor-cleanup-conditional-check-for-label-in-labe.patch
-Patch5008: 0009-apparmor-add-support-for-absolute-root-view-based-la.patch
-Patch5009: 0010-apparmor-make-policy_unpack-able-to-audit-different-.patch
-Patch5010: 0011-apparmor-add-more-debug-asserts-to-apparmorfs.patch
-Patch5011: 0012-apparmor-add-base-infastructure-for-socket-mediation.patch
-Patch5012: 0013-apparmor-move-new_null_profile-to-after-profile-look.patch
-Patch5013: 0014-apparmor-fix-race-condition-in-null-profile-creation.patch
-Patch5014: 0015-apparmor-ensure-unconfined-profiles-have-dfas-initia.patch
-Patch5015: 0016-apparmor-fix-incorrect-type-assignment-when-freeing-.patch
-Patch5016: 0017-UBUNTU-SAUCE-apparmor-af_unix-mediation.patch
+# https://gitlab.com/apparmor/apparmor/tree/master/kernel-patches/v4.14
+Patch5001: 0012-apparmor-add-base-infastructure-for-socket-mediation.patch
+Patch5002: 0001-UBUNTU-SAUCE-apparmor-af_unix-mediation.patch
# for rescuecd
# based on ftp://ftp.leg.uct.ac.za/pub/linux/rip/tmpfs_root-2.6.30.diff.gz
@@ -706,20 +691,6 @@ rm -f localversion-rt
%if %{with apparmor}
%patch5001 -p1
%patch5002 -p1
-%patch5003 -p1
-%patch5004 -p1
-%patch5005 -p1
-%patch5006 -p1
-%patch5007 -p1
-%patch5008 -p1
-%patch5009 -p1
-%patch5010 -p1
-%patch5011 -p1
-%patch5012 -p1
-%patch5013 -p1
-%patch5014 -p1
-%patch5015 -p1
-%patch5016 -p1
%endif
%patch250 -p1
diff --git a/0017-UBUNTU-SAUCE-apparmor-af_unix-mediation.patch b/0001-UBUNTU-SAUCE-apparmor-af_unix-mediation.patch
similarity index 100%
rename from 0017-UBUNTU-SAUCE-apparmor-af_unix-mediation.patch
rename to 0001-UBUNTU-SAUCE-apparmor-af_unix-mediation.patch
diff --git a/0002-apparmor-Fix-shadowed-local-variable-in-unpack_trans.patch b/0002-apparmor-Fix-shadowed-local-variable-in-unpack_trans.patch
deleted file mode 100644
index 4d9836d9..00000000
--- a/0002-apparmor-Fix-shadowed-local-variable-in-unpack_trans.patch
+++ /dev/null
@@ -1,51 +0,0 @@
-From c6cad5e65a23dcafa1821ca381901297664d9c64 Mon Sep 17 00:00:00 2001
-From: Geert Uytterhoeven <geert at linux-m68k.org>
-Date: Thu, 6 Jul 2017 10:56:21 +0200
-Subject: [PATCH 02/17] apparmor: Fix shadowed local variable in
- unpack_trans_table()
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-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 <geert at linux-m68k.org>
-Reviewed-by: Serge Hallyn <serge at hallyn.com>
-Signed-off-by: John Johansen <john.johansen at canonical.com>
-(cherry picked from commit 966d631935a578fadb5770f17a957ee1a969d868)
----
- 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.11.0
-
diff --git a/0003-apparmor-Fix-logical-error-in-verify_header.patch b/0003-apparmor-Fix-logical-error-in-verify_header.patch
deleted file mode 100644
index be4f854c..00000000
--- a/0003-apparmor-Fix-logical-error-in-verify_header.patch
+++ /dev/null
@@ -1,32 +0,0 @@
-From 9934296cba701d429a0fc0cf071a40c8c3a1587e Mon Sep 17 00:00:00 2001
-From: Christos Gkekas <chris.gekas at gmail.com>
-Date: Sat, 8 Jul 2017 20:50:21 +0100
-Subject: [PATCH 03/17] apparmor: Fix logical error in verify_header()
-
-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 <chris.gekas at gmail.com>
-Signed-off-by: John Johansen <john.johansen at canonical.com>
-(cherry picked from commit c54a2175e3a6bf6c697d249bba1aa729e06c7ba8)
----
- 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.11.0
-
diff --git a/0004-apparmor-Fix-an-error-code-in-aafs_create.patch b/0004-apparmor-Fix-an-error-code-in-aafs_create.patch
deleted file mode 100644
index 4e937e00..00000000
--- a/0004-apparmor-Fix-an-error-code-in-aafs_create.patch
+++ /dev/null
@@ -1,37 +0,0 @@
-From 8b3851c7b83f32f2be9d4b48371ddf033afedf62 Mon Sep 17 00:00:00 2001
-From: Dan Carpenter <dan.carpenter at oracle.com>
-Date: Thu, 13 Jul 2017 10:39:20 +0300
-Subject: [PATCH 04/17] apparmor: Fix an error code in aafs_create()
-
-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 <dan.carpenter at oracle.com>
-Acked-by: Serge Hallyn <serge at hallyn.com>
-Signed-off-by: John Johansen <john.johansen at canonical.com>
-(cherry picked from commit aee58bf341db52a3a3563c6b972bfd4fc2d41e46)
----
- 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.11.0
-
diff --git a/0005-apparmor-Redundant-condition-prev_ns.-in-label.c-149.patch b/0005-apparmor-Redundant-condition-prev_ns.-in-label.c-149.patch
deleted file mode 100644
index beea3de9..00000000
--- a/0005-apparmor-Redundant-condition-prev_ns.-in-label.c-149.patch
+++ /dev/null
@@ -1,29 +0,0 @@
-From 4b56e146905bbad2c79ea92e3f49e210ca527572 Mon Sep 17 00:00:00 2001
-From: John Johansen <john.johansen at canonical.com>
-Date: Mon, 31 Jul 2017 23:44:37 -0700
-Subject: [PATCH 05/17] apparmor: Redundant condition: prev_ns. in
- [label.c:1498]
-
-Reported-by: David Binderman <dcb314 at hotmail.com>
-Signed-off-by: John Johansen <john.johansen at canonical.com>
-(cherry picked from commit d323d2c17cfcc54b6845bfc1d13bca5cef210fc7)
----
- 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.11.0
-
diff --git a/0006-apparmor-add-the-ability-to-mediate-signals.patch b/0006-apparmor-add-the-ability-to-mediate-signals.patch
deleted file mode 100644
index ee3672db..00000000
--- a/0006-apparmor-add-the-ability-to-mediate-signals.patch
+++ /dev/null
@@ -1,397 +0,0 @@
-From f9e20353a6c5726775867db81b6085e8ab425a36 Mon Sep 17 00:00:00 2001
-From: John Johansen <john.johansen at canonical.com>
-Date: Tue, 18 Jul 2017 22:56:22 -0700
-Subject: [PATCH 06/17] apparmor: add the ability to mediate signals
-
-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 <john.johansen at canonical.com>
-Acked-by: Seth Arnold <seth.arnold at canonical.com>
-(cherry picked from commit c6bf1adaecaa719d7c56338cc43b2982214f2f44)
----
- 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 <linux/signal.h>
-+
-+#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 <profile, profile, perm> */
-+ 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.11.0
-
diff --git a/0007-apparmor-add-mount-mediation.patch b/0007-apparmor-add-mount-mediation.patch
deleted file mode 100644
index 99dac5c1..00000000
--- a/0007-apparmor-add-mount-mediation.patch
+++ /dev/null
@@ -1,1051 +0,0 @@
-From f37356d0a41499f9222f9f2b9c0147b500ae4285 Mon Sep 17 00:00:00 2001
-From: John Johansen <john.johansen at canonical.com>
-Date: Tue, 18 Jul 2017 23:04:47 -0700
-Subject: [PATCH 07/17] apparmor: add mount mediation
-
-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 <john.johansen at canonical.com>
-Acked-by: Seth Arnold <seth.arnold at canonical.com>
-(cherry picked from commit fa488437d0f95b2e5db1e624341fe0d5a233f729)
----
- 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 <linux/binfmts.h>
- #include <linux/types.h>
-
-+#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 <linux/fs.h>
-+#include <linux/path.h>
-+
-+#include "domain.h"
-+#include "policy.h"
-+
-+/* mount perms */
-+#define AA_MAY_PIVOTROOT 0x01
-+#define AA_MAY_MOUNT 0x02
-+#define AA_MAY_UMOUNT 0x04
-+#define AA_AUDIT_DATA 0x40
-+#define AA_MNT_CONT_MATCH 0x40
-+
-+#define AA_MS_IGNORE_MASK (MS_KERNMOUNT | MS_NOSEC | MS_ACTIVE | MS_BORN)
-+
-+int aa_remount(struct aa_label *label, const struct path *path,
-+ unsigned long flags, void *data);
-+
-+int aa_bind_mount(struct aa_label *label, const struct path *path,
-+ const char *old_name, unsigned long flags);
-+
-+
-+int aa_mount_change_type(struct aa_label *label, const struct path *path,
-+ unsigned long flags);
-+
-+int aa_move_mount(struct aa_label *label, const struct path *path,
-+ const char *old_name);
-+
-+int aa_new_mount(struct aa_label *label, const char *dev_name,
-+ const struct path *path, const char *type, unsigned long flags,
-+ void *data);
-+
-+int aa_umount(struct aa_label *label, struct vfsmount *mnt, int flags);
-+
-+int aa_pivotroot(struct aa_label *label, const struct path *old_path,
-+ const struct path *new_path);
-+
-+#endif /* __AA_MOUNT_H */
-diff --git a/security/apparmor/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 <linux/fs.h>
-+#include <linux/mount.h>
-+#include <linux/namei.h>
-+
-+#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.11.0
-
diff --git a/0008-apparmor-cleanup-conditional-check-for-label-in-labe.patch b/0008-apparmor-cleanup-conditional-check-for-label-in-labe.patch
deleted file mode 100644
index 20892df4..00000000
--- a/0008-apparmor-cleanup-conditional-check-for-label-in-labe.patch
+++ /dev/null
@@ -1,71 +0,0 @@
-From 763d17c9a18b0df7dbec2740f10dc40d378e3cc1 Mon Sep 17 00:00:00 2001
-From: John Johansen <john.johansen at canonical.com>
-Date: Sun, 6 Aug 2017 05:36:40 -0700
-Subject: [PATCH 08/17] apparmor: cleanup conditional check for label in
- label_print
-
-Signed-off-by: John Johansen <john.johansen at canonical.com>
-Acked-by: Seth Arnold <seth.arnold at canonical.com>
-(cherry picked from commit 7e57939b9d67dcfc2c8348fd0e2c76a2f0349c75)
----
- 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.11.0
-
diff --git a/0009-apparmor-add-support-for-absolute-root-view-based-la.patch b/0009-apparmor-add-support-for-absolute-root-view-based-la.patch
deleted file mode 100644
index 84ee7a1d..00000000
--- a/0009-apparmor-add-support-for-absolute-root-view-based-la.patch
+++ /dev/null
@@ -1,63 +0,0 @@
-From 6b092bbbf9e17b10f709d11b3bc2d7e493617934 Mon Sep 17 00:00:00 2001
-From: John Johansen <john.johansen at canonical.com>
-Date: Sun, 6 Aug 2017 05:39:08 -0700
-Subject: [PATCH 09/17] apparmor: add support for absolute root view based
- labels
-
-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 <john.johansen at canonical.com>
-Acked-by: Seth Arnold <seth.arnold at canonical.com>
-(cherry picked from commit eadfbf0898eda94cee0d982626aa24a3146db48b)
----
- 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.11.0
-
diff --git a/0010-apparmor-make-policy_unpack-able-to-audit-different-.patch b/0010-apparmor-make-policy_unpack-able-to-audit-different-.patch
deleted file mode 100644
index 7e481b28..00000000
--- a/0010-apparmor-make-policy_unpack-able-to-audit-different-.patch
+++ /dev/null
@@ -1,219 +0,0 @@
-From aa4b6bded85552bc5f9f22d2e18ce86c5c17947c Mon Sep 17 00:00:00 2001
-From: John Johansen <john.johansen at canonical.com>
-Date: Tue, 18 Jul 2017 23:37:18 -0700
-Subject: [PATCH 10/17] apparmor: make policy_unpack able to audit different
- info messages
-
-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 <john.johansen at canonical.com>
-Acked-by: Seth Arnold <seth.arnold at canonical.com>
-(cherry picked from commit 1489d896c5649e9ce1b6000b4857f8baa7a6ab63)
----
- 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.11.0
-
diff --git a/0011-apparmor-add-more-debug-asserts-to-apparmorfs.patch b/0011-apparmor-add-more-debug-asserts-to-apparmorfs.patch
deleted file mode 100644
index 85eafc85..00000000
--- a/0011-apparmor-add-more-debug-asserts-to-apparmorfs.patch
+++ /dev/null
@@ -1,78 +0,0 @@
-From ba3f778a2ef31454032c2ca9c99d9212feb4dcf1 Mon Sep 17 00:00:00 2001
-From: John Johansen <john.johansen at canonical.com>
-Date: Tue, 18 Jul 2017 23:41:13 -0700
-Subject: [PATCH 11/17] apparmor: add more debug asserts to apparmorfs
-
-Signed-off-by: John Johansen <john.johansen at canonical.com>
-Acked-by: Seth Arnold <seth.arnold at canonical.com>
-(cherry picked from commit 52c9542126fb04df1f12c605b6c22719c9096794)
----
- 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.11.0
-
diff --git a/0013-apparmor-move-new_null_profile-to-after-profile-look.patch b/0013-apparmor-move-new_null_profile-to-after-profile-look.patch
deleted file mode 100644
index f1337f3c..00000000
--- a/0013-apparmor-move-new_null_profile-to-after-profile-look.patch
+++ /dev/null
@@ -1,194 +0,0 @@
-From 50d30adbef98a0b6cc531a9413d05f564eb633ee Mon Sep 17 00:00:00 2001
-From: John Johansen <john.johansen at canonical.com>
-Date: Wed, 16 Aug 2017 08:59:57 -0700
-Subject: [PATCH 13/17] apparmor: move new_null_profile to after profile lookup
- fns()
-
-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 <john.johansen at canonical.com>
-(cherry picked from commit cf1e50dfc6f627bc2989b57076b129c330fb3f0a)
----
- 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 */
-
- /**
-@@ -559,6 +480,85 @@ struct aa_profile *aa_fqlookupn_profile(struct aa_label *base,
- }
-
- /**
-+ * 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)
- * @noreplace: true if replacement shouldn't be allowed but addition is okay
---
-2.11.0
-
diff --git a/0014-apparmor-fix-race-condition-in-null-profile-creation.patch b/0014-apparmor-fix-race-condition-in-null-profile-creation.patch
deleted file mode 100644
index ae57b4bd..00000000
--- a/0014-apparmor-fix-race-condition-in-null-profile-creation.patch
+++ /dev/null
@@ -1,60 +0,0 @@
-From ab3b869791b6122c7be7e68ca4c08e2c2e8815ac Mon Sep 17 00:00:00 2001
-From: John Johansen <john.johansen at canonical.com>
-Date: Wed, 16 Aug 2017 05:40:49 -0700
-Subject: [PATCH 14/17] apparmor: fix race condition in null profile creation
-
-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 <john.johansen at canonical.com>
-(cherry picked from commit 3aa3de2a4fb8f33ec62b00998bc6b6c6850d41b1)
----
- 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.11.0
-
diff --git a/0015-apparmor-ensure-unconfined-profiles-have-dfas-initia.patch b/0015-apparmor-ensure-unconfined-profiles-have-dfas-initia.patch
deleted file mode 100644
index 1ceb9900..00000000
--- a/0015-apparmor-ensure-unconfined-profiles-have-dfas-initia.patch
+++ /dev/null
@@ -1,36 +0,0 @@
-From 7f2cdd6453518ff76c3855255c91306a2b928c9a Mon Sep 17 00:00:00 2001
-From: John Johansen <john.johansen at canonical.com>
-Date: Wed, 16 Aug 2017 05:48:06 -0700
-Subject: [PATCH 15/17] apparmor: ensure unconfined profiles have dfas
- initialized
-
-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 <john.johansen at canonical.com>
-(cherry picked from commit 034ad2d248927722bdcd1aedb62634cdc2049113)
----
- 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.11.0
-
diff --git a/0016-apparmor-fix-incorrect-type-assignment-when-freeing-.patch b/0016-apparmor-fix-incorrect-type-assignment-when-freeing-.patch
deleted file mode 100644
index 9ff09f80..00000000
--- a/0016-apparmor-fix-incorrect-type-assignment-when-freeing-.patch
+++ /dev/null
@@ -1,39 +0,0 @@
-From 8daf877473653c06a28c86bf72d63ce7e5c1d542 Mon Sep 17 00:00:00 2001
-From: John Johansen <john.johansen at canonical.com>
-Date: Wed, 16 Aug 2017 09:33:48 -0700
-Subject: [PATCH 16/17] apparmor: fix incorrect type assignment when freeing
- proxies
-
-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] <asn:4>*label
-../security/apparmor/label.c:52:30: got struct aa_label *<noident>
-
-fix with RCU_INIT_POINTER as this is one of those cases where
-rcu_assign_pointer() is not needed.
-
-Signed-off-by: John Johansen <john.johansen at canonical.com>
-(cherry picked from commit 76e22e212a850bbd16cf49f9c586d4635507e0b5)
----
- 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.11.0
-
diff --git a/kernel-aufs4.patch b/kernel-aufs4.patch
index e0eb9ca1..d11a0aa1 100644
--- a/kernel-aufs4.patch
+++ b/kernel-aufs4.patch
@@ -24,10 +24,10 @@ index 7bbaca9..a026491 100644
aufs4.x-rcN base patch
diff --git a/MAINTAINERS b/MAINTAINERS
-index 1c3feff..1a12137 100644
+index af0cb69..d360d2e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
-@@ -2392,6 +2392,19 @@ F: include/linux/audit.h
+@@ -2465,6 +2465,19 @@ F: include/linux/audit.h
F: include/uapi/linux/audit.h
F: kernel/audit*
@@ -48,10 +48,10 @@ index 1c3feff..1a12137 100644
M: Miguel Ojeda Sandonis <miguel.ojeda.sandonis at gmail.com>
W: http://miguelojeda.es/auxdisplay.htm
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
-index f321b96..10707c3 100644
+index 85de673..d44de9d 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
-@@ -700,6 +700,24 @@ static inline int is_loop_device(struct file *file)
+@@ -686,6 +686,24 @@ static inline int is_loop_device(struct file *file)
return i && S_ISBLK(i->i_mode) && MAJOR(i->i_rdev) == LOOP_MAJOR;
}
@@ -90,7 +90,7 @@ index f901413..e3719a5 100644
void (*finish)(void *))
{
diff --git a/fs/fcntl.c b/fs/fcntl.c
-index 3b01b64..659760e 100644
+index 448a111..f51c2cf 100644
--- a/fs/fcntl.c
+++ b/fs/fcntl.c
@@ -31,7 +31,7 @@
@@ -112,10 +112,10 @@ index 3b01b64..659760e 100644
return error;
diff --git a/fs/inode.c b/fs/inode.c
-index 5037059..73820bf 100644
+index d1e35b5..f7800d6 100644
--- a/fs/inode.c
+++ b/fs/inode.c
-@@ -1641,7 +1641,7 @@ EXPORT_SYMBOL(generic_update_time);
+@@ -1655,7 +1655,7 @@ EXPORT_SYMBOL(generic_update_time);
* This does the actual work of updating an inodes time or version. Must have
* had called mnt_want_write() before calling this.
*/
@@ -124,13 +124,30 @@ index 5037059..73820bf 100644
{
int (*update_time)(struct inode *, struct timespec *, int);
+diff --git a/fs/namespace.c b/fs/namespace.c
+index d18deb4..e5a4a7f 100644
+--- a/fs/namespace.c
++++ b/fs/namespace.c
+@@ -846,6 +846,12 @@ static inline int check_mnt(struct mount *mnt)
+ return mnt->mnt_ns == current->nsproxy->mnt_ns;
+ }
+
++/* for aufs, CONFIG_AUFS_BR_FUSE */
++int is_current_mnt_ns(struct vfsmount *mnt)
++{
++ return check_mnt(real_mount(mnt));
++}
++
+ /*
+ * vfsmount lock must be held for write
+ */
diff --git a/fs/read_write.c b/fs/read_write.c
-index 0cc7033..6e542f0 100644
+index f0d4b16..6aa8c7a 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
-@@ -473,6 +473,28 @@ ssize_t __vfs_write(struct file *file, const char __user *p, size_t count,
+@@ -483,6 +483,28 @@ ssize_t __vfs_write(struct file *file, const char __user *p, size_t count,
+ return -EINVAL;
}
- EXPORT_SYMBOL(__vfs_write);
+vfs_readf_t vfs_readf(struct file *file)
+{
@@ -154,14 +171,14 @@ index 0cc7033..6e542f0 100644
+ return ERR_PTR(-ENOSYS);
+}
+
- ssize_t __kernel_write(struct file *file, const char *buf, size_t count, loff_t *pos)
+ ssize_t __kernel_write(struct file *file, const void *buf, size_t count, loff_t *pos)
{
mm_segment_t old_fs;
diff --git a/fs/splice.c b/fs/splice.c
-index ae41201..9753304 100644
+index f3084cc..eb888c6 100644
--- a/fs/splice.c
+++ b/fs/splice.c
-@@ -853,8 +853,8 @@ EXPORT_SYMBOL(generic_splice_sendpage);
+@@ -837,8 +837,8 @@ EXPORT_SYMBOL(generic_splice_sendpage);
/*
* Attempt to initiate a splice from pipe to file.
*/
@@ -172,7 +189,7 @@ index ae41201..9753304 100644
{
ssize_t (*splice_write)(struct pipe_inode_info *, struct file *,
loff_t *, size_t, unsigned int);
-@@ -870,9 +870,9 @@ static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
+@@ -854,9 +854,9 @@ static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
/*
* Attempt to initiate a splice from a file to a pipe.
*/
@@ -186,7 +203,7 @@ index ae41201..9753304 100644
ssize_t (*splice_read)(struct file *, loff_t *,
struct pipe_inode_info *, size_t, unsigned int);
diff --git a/fs/sync.c b/fs/sync.c
-index 2a54c1f..7a5fa3f 100644
+index a576aa2..eb61780 100644
--- a/fs/sync.c
+++ b/fs/sync.c
@@ -27,7 +27,7 @@
@@ -211,10 +228,10 @@ index 61eb82c..e700888 100644
static inline void fput_light(struct file *file, int fput_needed)
{
diff --git a/include/linux/fs.h b/include/linux/fs.h
-index cbfe127..9b21bb5 100644
+index 13dab19..8ab6566 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
-@@ -1262,6 +1262,7 @@ extern void fasync_free(struct fasync_struct *);
+@@ -1264,6 +1264,7 @@ extern void fasync_free(struct fasync_struct *);
/* can be called from interrupts */
extern void kill_fasync(struct fasync_struct **, int, int);
@@ -222,7 +239,7 @@ index cbfe127..9b21bb5 100644
extern void __f_setown(struct file *filp, struct pid *, enum pid_type, int force);
extern int f_setown(struct file *filp, unsigned long arg, int force);
extern void f_delown(struct file *filp);
-@@ -1683,6 +1684,7 @@ struct file_operations {
+@@ -1710,6 +1711,7 @@ struct file_operations {
ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
int (*check_flags)(int);
@@ -230,7 +247,7 @@ index cbfe127..9b21bb5 100644
int (*flock) (struct file *, int, struct file_lock *);
ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);
ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);
-@@ -1753,6 +1755,12 @@ ssize_t rw_copy_check_uvector(int type, const struct iovec __user * uvector,
+@@ -1780,6 +1782,12 @@ ssize_t rw_copy_check_uvector(int type, const struct iovec __user * uvector,
struct iovec *fast_pointer,
struct iovec **ret_pointer);
@@ -241,9 +258,9 @@ index cbfe127..9b21bb5 100644
+vfs_writef_t vfs_writef(struct file *file);
+
extern ssize_t __vfs_read(struct file *, char __user *, size_t, loff_t *);
- extern ssize_t __vfs_write(struct file *, const char __user *, size_t, loff_t *);
extern ssize_t vfs_read(struct file *, char __user *, size_t, loff_t *);
-@@ -2157,6 +2165,7 @@ extern int current_umask(void);
+ extern ssize_t vfs_write(struct file *, const char __user *, size_t, loff_t *);
+@@ -2182,6 +2190,7 @@ extern int current_umask(void);
extern void ihold(struct inode * inode);
extern void iput(struct inode *);
extern int generic_update_time(struct inode *, struct timespec *, int);
@@ -251,7 +268,7 @@ index cbfe127..9b21bb5 100644
/* /sys/fs */
extern struct kobject *fs_kobj;
-@@ -2437,6 +2446,7 @@ static inline bool sb_is_blkdev_sb(struct super_block *sb)
+@@ -2462,6 +2471,7 @@ static inline bool sb_is_blkdev_sb(struct super_block *sb)
return false;
}
#endif
@@ -259,6 +276,46 @@ index cbfe127..9b21bb5 100644
extern int sync_filesystem(struct super_block *);
extern const struct file_operations def_blk_fops;
extern const struct file_operations def_chr_fops;
+diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h
+index bfa8e0b..728d810 100644
+--- a/include/linux/lockdep.h
++++ b/include/linux/lockdep.h
+@@ -405,6 +405,8 @@ static inline int lockdep_match_key(struct lockdep_map *lock,
+ return lock->key == key;
+ }
+
++struct lock_class *lockdep_hlock_class(struct held_lock *hlock);
++
+ /*
+ * Acquire a lock.
+ *
+@@ -529,6 +531,7 @@ struct lock_class_key { };
+
+ #define lockdep_depth(tsk) (0)
+
++#define lockdep_is_held(lock) (1)
+ #define lockdep_is_held_type(l, r) (1)
+
+ #define lockdep_assert_held(l) do { (void)(l); } while (0)
+diff --git a/include/linux/mnt_namespace.h b/include/linux/mnt_namespace.h
+index 12b2ab5..8b810d1 100644
+--- a/include/linux/mnt_namespace.h
++++ b/include/linux/mnt_namespace.h
+@@ -5,11 +5,14 @@
+ struct mnt_namespace;
+ struct fs_struct;
+ struct user_namespace;
++struct vfsmount;
+
+ extern struct mnt_namespace *copy_mnt_ns(unsigned long, struct mnt_namespace *,
+ struct user_namespace *, struct fs_struct *);
+ extern void put_mnt_ns(struct mnt_namespace *ns);
+
++extern int is_current_mnt_ns(struct vfsmount *mnt);
++
+ extern const struct file_operations proc_mounts_operations;
+ extern const struct file_operations proc_mountinfo_operations;
+ extern const struct file_operations proc_mountstats_operations;
diff --git a/include/linux/splice.h b/include/linux/splice.h
index db42746..12f3a5a 100644
--- a/include/linux/splice.h
@@ -274,13 +331,34 @@ index db42746..12f3a5a 100644
+ struct pipe_inode_info *pipe, size_t len,
+ unsigned int flags);
#endif
+diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c
+index e36e652..bc97a97 100644
+--- a/kernel/locking/lockdep.c
++++ b/kernel/locking/lockdep.c
+@@ -144,7 +144,7 @@ static struct lock_list list_entries[MAX_LOCKDEP_ENTRIES];
+ unsigned long nr_lock_classes;
+ static struct lock_class lock_classes[MAX_LOCKDEP_KEYS];
+
+-static inline struct lock_class *hlock_class(struct held_lock *hlock)
++inline struct lock_class *lockdep_hlock_class(struct held_lock *hlock)
+ {
+ if (!hlock->class_idx) {
+ /*
+@@ -155,6 +155,7 @@ static inline struct lock_class *hlock_class(struct held_lock *hlock)
+ }
+ return lock_classes + hlock->class_idx - 1;
+ }
++#define hlock_class(hlock) lockdep_hlock_class(hlock)
+
+ #ifdef CONFIG_LOCK_STAT
+ static DEFINE_PER_CPU(struct lock_class_stats[MAX_LOCKDEP_KEYS], cpu_lock_stats);
aufs4.x-rcN mmap patch
diff --git a/fs/proc/base.c b/fs/proc/base.c
-index 719c2e9..a1b7968 100644
+index ad3b076..ad4a50d 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
-@@ -1986,7 +1986,7 @@ static int map_files_get_link(struct dentry *dentry, struct path *path)
+@@ -1987,7 +1987,7 @@ static int map_files_get_link(struct dentry *dentry, struct path *path)
down_read(&mm->mmap_sem);
vma = find_exact_vma(mm, vm_start, vm_end);
if (vma && vma->vm_file) {
@@ -306,10 +384,10 @@ index 7563437..7c0dc0f 100644
ino = inode->i_ino;
}
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
-index fe8f326..b2f7f1a 100644
+index 5589b4b..f60aea2 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
-@@ -293,7 +293,10 @@ show_map_vma(struct seq_file *m, struct vm_area_struct *vma, int is_pid)
+@@ -309,7 +309,10 @@ show_map_vma(struct seq_file *m, struct vm_area_struct *vma, int is_pid)
const char *name = NULL;
if (file) {
@@ -321,7 +399,7 @@ index fe8f326..b2f7f1a 100644
dev = inode->i_sb->s_dev;
ino = inode->i_ino;
pgoff = ((loff_t)vma->vm_pgoff) << PAGE_SHIFT;
-@@ -1640,7 +1643,7 @@ static int show_numa_map(struct seq_file *m, void *v, int is_pid)
+@@ -1734,7 +1737,7 @@ static int show_numa_map(struct seq_file *m, void *v, int is_pid)
struct proc_maps_private *proc_priv = &numa_priv->proc_maps;
struct vm_area_struct *vma = v;
struct numa_maps *md = &numa_priv->md;
@@ -331,10 +409,10 @@ index fe8f326..b2f7f1a 100644
struct mm_walk walk = {
.hugetlb_entry = gather_hugetlb_stats,
diff --git a/fs/proc/task_nommu.c b/fs/proc/task_nommu.c
-index 23266694..58e59b6 100644
+index b00b7660..93e8a86 100644
--- a/fs/proc/task_nommu.c
+++ b/fs/proc/task_nommu.c
-@@ -157,7 +157,10 @@ static int nommu_vma_show(struct seq_file *m, struct vm_area_struct *vma,
+@@ -155,7 +155,10 @@ static int nommu_vma_show(struct seq_file *m, struct vm_area_struct *vma,
file = vma->vm_file;
if (file) {
@@ -347,10 +425,10 @@ index 23266694..58e59b6 100644
ino = inode->i_ino;
pgoff = (loff_t)vma->vm_pgoff << PAGE_SHIFT;
diff --git a/include/linux/mm.h b/include/linux/mm.h
-index 46b9ac5..62ba1c3 100644
+index 065d99d..04486c3 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
-@@ -1306,6 +1306,28 @@ static inline int fixup_user_fault(struct task_struct *tsk,
+@@ -1348,6 +1348,28 @@ static inline int fixup_user_fault(struct task_struct *tsk,
}
#endif
@@ -380,10 +458,10 @@ index 46b9ac5..62ba1c3 100644
unsigned int gup_flags);
extern int access_remote_vm(struct mm_struct *mm, unsigned long addr,
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
-index 3cadee0..d0142c1 100644
+index 1861ea8..d85a914 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
-@@ -259,6 +259,7 @@ struct vm_region {
+@@ -260,6 +260,7 @@ struct vm_region {
unsigned long vm_top; /* region allocated to here */
unsigned long vm_pgoff; /* the offset in vm_file corresponding to vm_start */
struct file *vm_file; /* the backing file or NULL */
@@ -391,19 +469,19 @@ index 3cadee0..d0142c1 100644
int vm_usage; /* region usage count (access under nommu_region_sem) */
bool vm_icache_flushed : 1; /* true if the icache has been flushed for
-@@ -333,6 +334,7 @@ struct vm_area_struct {
+@@ -334,6 +335,7 @@ struct vm_area_struct {
unsigned long vm_pgoff; /* Offset (within vm_file) in PAGE_SIZE
units */
struct file * vm_file; /* File we map to (can be NULL). */
+ struct file *vm_prfile; /* shadow of vm_file */
void * vm_private_data; /* was vm_pte (shared mem) */
- #ifndef CONFIG_MMU
+ atomic_long_t swap_readahead_info;
diff --git a/kernel/fork.c b/kernel/fork.c
-index cbbea27..f0fd8a1 100644
+index 07cc743..b1d2b43 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
-@@ -663,7 +663,7 @@ static __latent_entropy int dup_mmap(struct mm_struct *mm,
+@@ -676,7 +676,7 @@ static __latent_entropy int dup_mmap(struct mm_struct *mm,
struct inode *inode = file_inode(file);
struct address_space *mapping = file->f_mapping;
@@ -413,7 +491,7 @@ index cbbea27..f0fd8a1 100644
atomic_dec(&inode->i_writecount);
i_mmap_lock_write(mapping);
diff --git a/mm/Makefile b/mm/Makefile
-index 411bd24..e7de927 100644
+index e3ac3ae..745b26c 100644
--- a/mm/Makefile
+++ b/mm/Makefile
@@ -39,7 +39,7 @@ obj-y := filemap.o mempool.o oom_kill.o \
@@ -426,10 +504,10 @@ index 411bd24..e7de927 100644
obj-y += init-mm.o
diff --git a/mm/filemap.c b/mm/filemap.c
-index 0b41c8c..c5262ff 100644
+index 594d73f..7183aef 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
-@@ -2543,7 +2543,7 @@ int filemap_page_mkwrite(struct vm_fault *vmf)
+@@ -2590,7 +2590,7 @@ int filemap_page_mkwrite(struct vm_fault *vmf)
int ret = VM_FAULT_LOCKED;
sb_start_pagefault(inode->i_sb);
@@ -439,10 +517,10 @@ index 0b41c8c..c5262ff 100644
if (page->mapping != inode->i_mapping) {
unlock_page(page);
diff --git a/mm/mmap.c b/mm/mmap.c
-index f19efcf..7fdd59e 100644
+index 680506f..081406a 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
-@@ -170,7 +170,7 @@ static struct vm_area_struct *remove_vma(struct vm_area_struct *vma)
+@@ -171,7 +171,7 @@ static struct vm_area_struct *remove_vma(struct vm_area_struct *vma)
if (vma->vm_ops && vma->vm_ops->close)
vma->vm_ops->close(vma);
if (vma->vm_file)
@@ -451,7 +529,7 @@ index f19efcf..7fdd59e 100644
mpol_put(vma_policy(vma));
kmem_cache_free(vm_area_cachep, vma);
return next;
-@@ -895,7 +895,7 @@ int __vma_adjust(struct vm_area_struct *vma, unsigned long start,
+@@ -896,7 +896,7 @@ int __vma_adjust(struct vm_area_struct *vma, unsigned long start,
if (remove_next) {
if (file) {
uprobe_munmap(next, next->vm_start, next->vm_end);
@@ -460,7 +538,7 @@ index f19efcf..7fdd59e 100644
}
if (next->anon_vma)
anon_vma_merge(vma, next);
-@@ -1745,8 +1745,8 @@ unsigned long mmap_region(struct file *file, unsigned long addr,
+@@ -1746,8 +1746,8 @@ unsigned long mmap_region(struct file *file, unsigned long addr,
return addr;
unmap_and_free_vma:
@@ -470,7 +548,7 @@ index f19efcf..7fdd59e 100644
/* Undo any partial mapping done by a device driver. */
unmap_region(mm, vma, prev, vma->vm_start, vma->vm_end);
-@@ -2568,7 +2568,7 @@ int __split_vma(struct mm_struct *mm, struct vm_area_struct *vma,
+@@ -2569,7 +2569,7 @@ int __split_vma(struct mm_struct *mm, struct vm_area_struct *vma,
goto out_free_mpol;
if (new->vm_file)
@@ -479,7 +557,7 @@ index f19efcf..7fdd59e 100644
if (new->vm_ops && new->vm_ops->open)
new->vm_ops->open(new);
-@@ -2587,7 +2587,7 @@ int __split_vma(struct mm_struct *mm, struct vm_area_struct *vma,
+@@ -2588,7 +2588,7 @@ int __split_vma(struct mm_struct *mm, struct vm_area_struct *vma,
if (new->vm_ops && new->vm_ops->close)
new->vm_ops->close(new);
if (new->vm_file)
@@ -488,7 +566,7 @@ index f19efcf..7fdd59e 100644
unlink_anon_vmas(new);
out_free_mpol:
mpol_put(vma_policy(new));
-@@ -2741,7 +2741,7 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size,
+@@ -2750,7 +2750,7 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size,
struct vm_area_struct *vma;
unsigned long populate = 0;
unsigned long ret = -EINVAL;
@@ -497,7 +575,7 @@ index f19efcf..7fdd59e 100644
pr_warn_once("%s (%d) uses deprecated remap_file_pages() syscall. See Documentation/vm/remap_file_pages.txt.\n",
current->comm, current->pid);
-@@ -2816,10 +2816,27 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size,
+@@ -2825,10 +2825,27 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size,
}
}
@@ -526,7 +604,7 @@ index f19efcf..7fdd59e 100644
out:
up_write(&mm->mmap_sem);
if (populate)
-@@ -3110,7 +3127,7 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap,
+@@ -3136,7 +3153,7 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap,
if (anon_vma_clone(new_vma, vma))
goto out_free_mempol;
if (new_vma->vm_file)
@@ -536,7 +614,7 @@ index f19efcf..7fdd59e 100644
new_vma->vm_ops->open(new_vma);
vma_link(mm, new_vma, prev, rb_link, rb_parent);
diff --git a/mm/nommu.c b/mm/nommu.c
-index fc184f5..637ea81 100644
+index 17c00d9..4bcdf94 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -641,7 +641,7 @@ static void __put_nommu_region(struct vm_region *region)
@@ -557,7 +635,7 @@ index fc184f5..637ea81 100644
put_nommu_region(vma->vm_region);
kmem_cache_free(vm_area_cachep, vma);
}
-@@ -1326,7 +1326,7 @@ unsigned long do_mmap(struct file *file,
+@@ -1321,7 +1321,7 @@ unsigned long do_mmap(struct file *file,
goto error_just_free;
}
}
@@ -566,7 +644,7 @@ index fc184f5..637ea81 100644
kmem_cache_free(vm_region_jar, region);
region = pregion;
result = start;
-@@ -1401,10 +1401,10 @@ unsigned long do_mmap(struct file *file,
+@@ -1396,10 +1396,10 @@ unsigned long do_mmap(struct file *file,
up_write(&nommu_region_sem);
error:
if (region->vm_file)
@@ -693,7 +771,7 @@ index e3719a5..3203470 100644
/**
* d_ancestor - search for an ancestor
diff --git a/fs/exec.c b/fs/exec.c
-index 62175cb..f0b6fdd 100644
+index 3e14ba2..6818b01 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -109,6 +109,7 @@ bool path_noexec(const struct path *path)
@@ -705,7 +783,7 @@ index 62175cb..f0b6fdd 100644
#ifdef CONFIG_USELIB
/*
diff --git a/fs/fcntl.c b/fs/fcntl.c
-index 659760e..5c37087 100644
+index f51c2cf..58bf222 100644
--- a/fs/fcntl.c
+++ b/fs/fcntl.c
@@ -84,6 +84,7 @@ int setfl(int fd, struct file * filp, unsigned long arg)
@@ -717,7 +795,7 @@ index 659760e..5c37087 100644
static void f_modown(struct file *filp, struct pid *pid, enum pid_type type,
int force)
diff --git a/fs/file_table.c b/fs/file_table.c
-index 72e861a..01ae52f 100644
+index 61517f5..c6bab39c 100644
--- a/fs/file_table.c
+++ b/fs/file_table.c
@@ -148,6 +148,7 @@ struct file *get_empty_filp(void)
@@ -728,7 +806,7 @@ index 72e861a..01ae52f 100644
/**
* alloc_file - allocate and initialize a 'struct file'
-@@ -260,6 +261,7 @@ void flush_delayed_fput(void)
+@@ -258,6 +259,7 @@ void flush_delayed_fput(void)
{
delayed_fput(NULL);
}
@@ -736,7 +814,7 @@ index 72e861a..01ae52f 100644
static DECLARE_DELAYED_WORK(delayed_fput_work, delayed_fput);
-@@ -302,6 +304,7 @@ void __fput_sync(struct file *file)
+@@ -300,6 +302,7 @@ void __fput_sync(struct file *file)
}
EXPORT_SYMBOL(fput);
@@ -744,19 +822,19 @@ index 72e861a..01ae52f 100644
void put_filp(struct file *file)
{
-@@ -310,6 +313,7 @@ void put_filp(struct file *file)
+@@ -308,6 +311,7 @@ void put_filp(struct file *file)
file_free(file);
}
}
+EXPORT_SYMBOL_GPL(put_filp);
void __init files_init(void)
- {
+ {
diff --git a/fs/inode.c b/fs/inode.c
-index 73820bf..7db829e 100644
+index f7800d6..f31a6c7 100644
--- a/fs/inode.c
+++ b/fs/inode.c
-@@ -1650,6 +1650,7 @@ int update_time(struct inode *inode, struct timespec *time, int flags)
+@@ -1664,6 +1664,7 @@ int update_time(struct inode *inode, struct timespec *time, int flags)
return update_time(inode, time, flags);
}
@@ -765,10 +843,10 @@ index 73820bf..7db829e 100644
/**
* touch_atime - update the access time
diff --git a/fs/namespace.c b/fs/namespace.c
-index f8893dc..c55d949 100644
+index e5a4a7f..6d0c376 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
-@@ -463,6 +463,7 @@ void __mnt_drop_write(struct vfsmount *mnt)
+@@ -517,6 +517,7 @@ void __mnt_drop_write(struct vfsmount *mnt)
mnt_dec_writers(real_mount(mnt));
preempt_enable();
}
@@ -776,7 +854,15 @@ index f8893dc..c55d949 100644
/**
* mnt_drop_write - give up write access to a mount
-@@ -1823,6 +1824,7 @@ int iterate_mounts(int (*f)(struct vfsmount *, void *), void *arg,
+@@ -851,6 +852,7 @@ int is_current_mnt_ns(struct vfsmount *mnt)
+ {
+ return check_mnt(real_mount(mnt));
+ }
++EXPORT_SYMBOL_GPL(is_current_mnt_ns);
+
+ /*
+ * vfsmount lock must be held for write
+@@ -1887,6 +1889,7 @@ int iterate_mounts(int (*f)(struct vfsmount *, void *), void *arg,
}
return 0;
}
@@ -857,7 +943,7 @@ index 9991f88..117042c 100644
/*
* Destroy all marks in destroy_list, waits for SRCU period to finish before
diff --git a/fs/open.c b/fs/open.c
-index 35bb784..92e08c5 100644
+index 7ea1184..6e2e241 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -64,6 +64,7 @@ int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
@@ -877,10 +963,18 @@ index 35bb784..92e08c5 100644
static int do_dentry_open(struct file *f,
struct inode *inode,
diff --git a/fs/read_write.c b/fs/read_write.c
-index 6e542f0..c6fa090 100644
+index 6aa8c7a..b5d392e 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
-@@ -483,6 +483,7 @@ vfs_readf_t vfs_readf(struct file *file)
+@@ -453,6 +453,7 @@ ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
+
+ return ret;
+ }
++EXPORT_SYMBOL_GPL(vfs_read);
+
+ static ssize_t new_sync_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos)
+ {
+@@ -493,6 +494,7 @@ vfs_readf_t vfs_readf(struct file *file)
return new_sync_read;
return ERR_PTR(-ENOSYS);
}
@@ -888,19 +982,27 @@ index 6e542f0..c6fa090 100644
vfs_writef_t vfs_writef(struct file *file)
{
-@@ -494,6 +495,7 @@ vfs_writef_t vfs_writef(struct file *file)
+@@ -504,6 +506,7 @@ vfs_writef_t vfs_writef(struct file *file)
return new_sync_write;
return ERR_PTR(-ENOSYS);
}
+EXPORT_SYMBOL_GPL(vfs_writef);
- ssize_t __kernel_write(struct file *file, const char *buf, size_t count, loff_t *pos)
+ ssize_t __kernel_write(struct file *file, const void *buf, size_t count, loff_t *pos)
+ {
+@@ -573,6 +576,7 @@ ssize_t vfs_write(struct file *file, const char __user *buf, size_t count, loff_
+
+ return ret;
+ }
++EXPORT_SYMBOL_GPL(vfs_write);
+
+ static inline loff_t file_pos_read(struct file *file)
{
diff --git a/fs/splice.c b/fs/splice.c
-index 9753304..b38e036 100644
+index eb888c6..7ab89d2 100644
--- a/fs/splice.c
+++ b/fs/splice.c
-@@ -866,6 +866,7 @@ long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
+@@ -850,6 +850,7 @@ long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
return splice_write(pipe, out, ppos, len, flags);
}
@@ -908,7 +1010,7 @@ index 9753304..b38e036 100644
/*
* Attempt to initiate a splice from a file to a pipe.
-@@ -895,6 +896,7 @@ long do_splice_to(struct file *in, loff_t *ppos,
+@@ -879,6 +880,7 @@ long do_splice_to(struct file *in, loff_t *ppos,
return splice_read(in, ppos, pipe, len, flags);
}
@@ -917,7 +1019,7 @@ index 9753304..b38e036 100644
/**
* splice_direct_to_actor - splices data directly between two non-pipes
diff --git a/fs/sync.c b/fs/sync.c
-index 7a5fa3f..c9b9d46 100644
+index eb61780..32c5a05 100644
--- a/fs/sync.c
+++ b/fs/sync.c
@@ -38,6 +38,7 @@ int __sync_filesystem(struct super_block *sb, int wait)
@@ -929,10 +1031,10 @@ index 7a5fa3f..c9b9d46 100644
/*
* Write out and wait upon all dirty data associated with this
diff --git a/fs/xattr.c b/fs/xattr.c
-index 464c94b..0234d49 100644
+index 61cd28b..35570cd 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
-@@ -296,6 +296,7 @@ vfs_getxattr_alloc(struct dentry *dentry, const char *name, char **xattr_value,
+@@ -297,6 +297,7 @@ vfs_getxattr_alloc(struct dentry *dentry, const char *name, char **xattr_value,
*xattr_value = value;
return error;
}
@@ -940,20 +1042,32 @@ index 464c94b..0234d49 100644
ssize_t
__vfs_getxattr(struct dentry *dentry, struct inode *inode, const char *name,
+diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c
+index bc97a97..895a1ba 100644
+--- a/kernel/locking/lockdep.c
++++ b/kernel/locking/lockdep.c
+@@ -155,6 +155,7 @@ inline struct lock_class *lockdep_hlock_class(struct held_lock *hlock)
+ }
+ return lock_classes + hlock->class_idx - 1;
+ }
++EXPORT_SYMBOL_GPL(lockdep_hlock_class);
+ #define hlock_class(hlock) lockdep_hlock_class(hlock)
+
+ #ifdef CONFIG_LOCK_STAT
diff --git a/kernel/task_work.c b/kernel/task_work.c
-index d513051..e056d54 100644
+index 836a72a..aa00d49 100644
--- a/kernel/task_work.c
+++ b/kernel/task_work.c
-@@ -119,3 +119,4 @@ void task_work_run(void)
+@@ -115,3 +115,4 @@ void task_work_run(void)
} while (work);
}
}
+EXPORT_SYMBOL_GPL(task_work_run);
diff --git a/security/commoncap.c b/security/commoncap.c
-index 7abebd7..c079ce4 100644
+index fc46f5b..90543ef 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
-@@ -1062,12 +1062,14 @@ int cap_mmap_addr(unsigned long addr)
+@@ -1270,12 +1270,14 @@ int cap_mmap_addr(unsigned long addr)
}
return ret;
}
@@ -989,10 +1103,10 @@ index 03c1652..f88c84b 100644
int devcgroup_inode_mknod(int mode, dev_t dev)
{
diff --git a/security/security.c b/security/security.c
-index 3013237..342ce8b 100644
+index 4bf0f57..b30d1e1 100644
--- a/security/security.c
+++ b/security/security.c
-@@ -535,6 +535,7 @@ int security_path_rmdir(const struct path *dir, struct dentry *dentry)
+@@ -530,6 +530,7 @@ int security_path_rmdir(const struct path *dir, struct dentry *dentry)
return 0;
return call_int_hook(path_rmdir, 0, dir, dentry);
}
@@ -1000,7 +1114,7 @@ index 3013237..342ce8b 100644
int security_path_unlink(const struct path *dir, struct dentry *dentry)
{
-@@ -551,6 +552,7 @@ int security_path_symlink(const struct path *dir, struct dentry *dentry,
+@@ -546,6 +547,7 @@ int security_path_symlink(const struct path *dir, struct dentry *dentry,
return 0;
return call_int_hook(path_symlink, 0, dir, dentry, old_name);
}
@@ -1008,7 +1122,7 @@ index 3013237..342ce8b 100644
int security_path_link(struct dentry *old_dentry, const struct path *new_dir,
struct dentry *new_dentry)
-@@ -559,6 +561,7 @@ int security_path_link(struct dentry *old_dentry, const struct path *new_dir,
+@@ -554,6 +556,7 @@ int security_path_link(struct dentry *old_dentry, const struct path *new_dir,
return 0;
return call_int_hook(path_link, 0, old_dentry, new_dir, new_dentry);
}
@@ -1016,7 +1130,7 @@ index 3013237..342ce8b 100644
int security_path_rename(const struct path *old_dir, struct dentry *old_dentry,
const struct path *new_dir, struct dentry *new_dentry,
-@@ -586,6 +589,7 @@ int security_path_truncate(const struct path *path)
+@@ -581,6 +584,7 @@ int security_path_truncate(const struct path *path)
return 0;
return call_int_hook(path_truncate, 0, path);
}
@@ -1024,7 +1138,7 @@ index 3013237..342ce8b 100644
int security_path_chmod(const struct path *path, umode_t mode)
{
-@@ -593,6 +597,7 @@ int security_path_chmod(const struct path *path, umode_t mode)
+@@ -588,6 +592,7 @@ int security_path_chmod(const struct path *path, umode_t mode)
return 0;
return call_int_hook(path_chmod, 0, path, mode);
}
@@ -1032,7 +1146,7 @@ index 3013237..342ce8b 100644
int security_path_chown(const struct path *path, kuid_t uid, kgid_t gid)
{
-@@ -600,6 +605,7 @@ int security_path_chown(const struct path *path, kuid_t uid, kgid_t gid)
+@@ -595,6 +600,7 @@ int security_path_chown(const struct path *path, kuid_t uid, kgid_t gid)
return 0;
return call_int_hook(path_chown, 0, path, uid, gid);
}
@@ -1040,7 +1154,7 @@ index 3013237..342ce8b 100644
int security_path_chroot(const struct path *path)
{
-@@ -685,6 +691,7 @@ int security_inode_readlink(struct dentry *dentry)
+@@ -680,6 +686,7 @@ int security_inode_readlink(struct dentry *dentry)
return 0;
return call_int_hook(inode_readlink, 0, dentry);
}
@@ -1048,7 +1162,7 @@ index 3013237..342ce8b 100644
int security_inode_follow_link(struct dentry *dentry, struct inode *inode,
bool rcu)
-@@ -700,6 +707,7 @@ int security_inode_permission(struct inode *inode, int mask)
+@@ -695,6 +702,7 @@ int security_inode_permission(struct inode *inode, int mask)
return 0;
return call_int_hook(inode_permission, 0, inode, mask);
}
@@ -1056,7 +1170,7 @@ index 3013237..342ce8b 100644
int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
{
-@@ -871,6 +879,7 @@ int security_file_permission(struct file *file, int mask)
+@@ -866,6 +874,7 @@ int security_file_permission(struct file *file, int mask)
return fsnotify_perm(file, mask);
}
@@ -1064,7 +1178,7 @@ index 3013237..342ce8b 100644
int security_file_alloc(struct file *file)
{
-@@ -930,6 +939,7 @@ int security_mmap_file(struct file *file, unsigned long prot,
+@@ -925,6 +934,7 @@ int security_mmap_file(struct file *file, unsigned long prot,
return ret;
return ima_file_mmap(file, prot);
}
@@ -1163,7 +1277,7 @@ diff -urN /usr/share/empty/Documentation/ABI/testing/sysfs-aufs linux/Documentat
+ will be empty. About XINO files, see the aufs manual.
diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/01intro.txt linux/Documentation/filesystems/aufs/design/01intro.txt
--- /usr/share/empty/Documentation/filesystems/aufs/design/01intro.txt 1970-01-01 01:00:00.000000000 +0100
-+++ linux/Documentation/filesystems/aufs/design/01intro.txt 2017-09-05 10:42:11.038754821 +0200
++++ linux/Documentation/filesystems/aufs/design/01intro.txt 2017-11-12 22:24:42.257509799 +0100
@@ -0,0 +1,171 @@
+
+# Copyright (C) 2005-2017 Junjiro R. Okajima
@@ -1950,6 +2064,147 @@ diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/05wbr_policy.tx
+ where the source and the target exists and selects the higher
+ one. If the selected branch is readonly, then aufs follows the
+ copyup policy.
+diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/06dirren.dot linux/Documentation/filesystems/aufs/design/06dirren.dot
+--- /usr/share/empty/Documentation/filesystems/aufs/design/06dirren.dot 1970-01-01 01:00:00.000000000 +0100
++++ linux/Documentation/filesystems/aufs/design/06dirren.dot 2017-11-12 22:24:44.694244127 +0100
+@@ -0,0 +1,31 @@
++
++// to view this graph, run dot(1) command in GRAPHVIZ.
++
++digraph G {
++node [shape=box];
++whinfo [label="detailed info file\n(lower_brid_root-hinum, h_inum, namelen, old name)"];
++
++node [shape=oval];
++
++aufs_rename -> whinfo [label="store/remove"];
++
++node [shape=oval];
++inode_list [label="h_inum list in branch\ncache"];
++
++node [shape=box];
++whinode [label="h_inum list file"];
++
++node [shape=oval];
++brmgmt [label="br_add/del/mod/umount"];
++
++brmgmt -> inode_list [label="create/remove"];
++brmgmt -> whinode [label="load/store"];
++
++inode_list -> whinode [style=dashed,dir=both];
++
++aufs_rename -> inode_list [label="add/del"];
++
++aufs_lookup -> inode_list [label="search"];
++
++aufs_lookup -> whinfo [label="load/remove"];
++}
+diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/06dirren.txt linux/Documentation/filesystems/aufs/design/06dirren.txt
+--- /usr/share/empty/Documentation/filesystems/aufs/design/06dirren.txt 1970-01-01 01:00:00.000000000 +0100
++++ linux/Documentation/filesystems/aufs/design/06dirren.txt 2017-11-12 22:24:44.694244127 +0100
+@@ -0,0 +1,102 @@
++
++# Copyright (C) 2017 Junjiro R. Okajima
++#
++# 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; either version 2 of the License, or
++# (at your option) any later version.
++#
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++# GNU General Public License for more details.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program. If not, see <http://www.gnu.org/licenses/>.
++
++Special handling for renaming a directory (DIRREN)
++----------------------------------------------------------------------
++First, let's assume we have a simple usecase.
++
++- /u = /rw + /ro
++- /rw/dirA exists
++- /ro/dirA and /ro/dirA/file exist too
++- there is no dirB on both branches
++- a user issues rename("dirA", "dirB")
++
++Now, what should aufs behave against this rename(2)?
++There are a few possible cases.
++
++A. returns EROFS.
++ since dirA exists on a readonly branch which cannot be renamed.
++B. returns EXDEV.
++ it is possible to copy-up dirA (only the dir itself), but the child
++ entries ("file" in this case) should not be. it must be a bad
++ approach to copy-up recursively.
++C. returns a success.
++ even the branch /ro is readonly, aufs tries renaming it. Obviously it
++ is a violation of aufs' policy.
++D. construct an extra information which indicates that /ro/dirA should
++ be handled as the name of dirB.
++ overlayfs has a similar feature called REDIRECT.
++
++Until now, aufs implements the case B only which returns EXDEV, and
++expects the userspace application behaves like mv(1) which tries
++issueing rename(2) recursively.
++
++A new aufs feature called DIRREN is introduced which implements the case
++D. There are several "extra information" added.
++
++1. detailed info per renamed directory
++ path: /rw/dirB/$AUFS_WH_DR_INFO_PFX.<lower branch-id>
++2. the inode-number list of directories on a branch
++ path: /rw/dirB/$AUFS_WH_DR_BRHINO
++
++The filename of "detailed info per directory" represents the lower
++branch, and its format is
++- a type of the branch id
++ one of these.
++ + uuid (not implemented yet)
++ + fsid
++ + dev
++- the inode-number of the branch root dir
++
++And it contains these info in a single regular file.
++- magic number
++- branch's inode-number of the logically renamed dir
++- the name of the before-renamed dir
++
++The "detailed info per directory" file is created in aufs rename(2), and
++loaded in any lookup.
++The info is considered in lookup for the matching case only. Here
++"matching" means that the root of branch (in the info filename) is same
++to the current looking-up branch. After looking-up the before-renamed
++name, the inode-number is compared. And the matched dentry is used.
++
++The "inode-number list of directories" is a regular file which contains
++simply the inode-numbers on the branch. The file is created or updated
++in removing the branch, and loaded in adding the branch. Its lifetime is
++equal to the branch.
++The list is refered in lookup, and when the current target inode is
++found in the list, the aufs tries loading the "detailed info per
++directory" and get the changed and valid name of the dir.
++
++Theoretically these "extra informaiton" may be able to be put into XATTR
++in the dir inode. But aufs doesn't choose this way because
++1. XATTR may not be supported by the branch (or its configuration)
++2. XATTR may have its size limit.
++3. XATTR may be less easy to convert than a regular file, when the
++ format of the info is changed in the future.
++At the same time, I agree that the regular file approach is much slower
++than XATTR approach. So, in the future, aufs may take the XATTR or other
++better approach.
++
++This DIRREN feature is enabled by aufs configuration, and is activated
++by a new mount option.
++
++For the more complicated case, there is a work with UDBA option, which
++is to dected the direct access to the branches (by-passing aufs) and to
++maintain the cashes in aufs. Since a single cached aufs dentry may
++contains two names, before- and after-rename, the name comparision in
++UDBA handler may not work correctly. In this case, the behaviour will be
++equivalen to udba=reval case.
diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/06fhsm.txt linux/Documentation/filesystems/aufs/design/06fhsm.txt
--- /usr/share/empty/Documentation/filesystems/aufs/design/06fhsm.txt 1970-01-01 01:00:00.000000000 +0100
+++ linux/Documentation/filesystems/aufs/design/06fhsm.txt 2017-07-29 12:14:25.896375188 +0200
@@ -2818,8 +3073,8 @@ diff -urN /usr/share/empty/Documentation/filesystems/aufs/README linux/Documenta
+# End: ;
diff -urN /usr/share/empty/fs/aufs/aufs.h linux/fs/aufs/aufs.h
--- /usr/share/empty/fs/aufs/aufs.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/aufs.h 2017-07-29 12:14:25.896375188 +0200
-@@ -0,0 +1,59 @@
++++ linux/fs/aufs/aufs.h 2017-11-12 22:24:44.697577553 +0100
+@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2005-2017 Junjiro R. Okajima
+ *
@@ -2862,15 +3117,16 @@ diff -urN /usr/share/empty/fs/aufs/aufs.h linux/fs/aufs/aufs.h
+#include "dbgaufs.h"
+#include "dentry.h"
+#include "dir.h"
++#include "dirren.h"
+#include "dynop.h"
+#include "file.h"
+#include "fstype.h"
++#include "hbl.h"
+#include "inode.h"
+#include "loop.h"
+#include "module.h"
+#include "opts.h"
+#include "rwsem.h"
-+#include "spl.h"
+#include "super.h"
+#include "sysaufs.h"
+#include "vfsub.h"
@@ -2881,8 +3137,8 @@ diff -urN /usr/share/empty/fs/aufs/aufs.h linux/fs/aufs/aufs.h
+#endif /* __AUFS_H__ */
diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c
--- /usr/share/empty/fs/aufs/branch.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/branch.c 2017-07-29 12:14:25.896375188 +0200
-@@ -0,0 +1,1422 @@
++++ linux/fs/aufs/branch.c 2017-11-12 22:24:44.697577553 +0100
+@@ -0,0 +1,1432 @@
+/*
+ * Copyright (C) 2005-2017 Junjiro R. Okajima
+ *
@@ -2918,6 +3174,8 @@ diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c
+ struct au_dykey **key;
+
+ au_hnotify_fin_br(br);
++ /* always, regardless the mount option */
++ au_dr_hino_free(&br->br_dirren);
+
+ if (br->br_xino.xi_file)
+ fput(br->br_xino.xi_file);
@@ -3022,7 +3280,7 @@ diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c
+ goto out;
+ add_branch->br_xino.xi_nondir.total = 8; /* initial size */
+ add_branch->br_xino.xi_nondir.array
-+ = kzalloc(sizeof(ino_t) * add_branch->br_xino.xi_nondir.total,
++ = kcalloc(add_branch->br_xino.xi_nondir.total, sizeof(ino_t),
+ GFP_NOFS);
+ if (unlikely(!add_branch->br_xino.xi_nondir.array))
+ goto out_br;
@@ -3286,6 +3544,11 @@ diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c
+ br->br_id = au_new_br_id(sb);
+ AuDebugOn(br->br_id < 0);
+
++ /* always, regardless the given option */
++ err = au_dr_br_init(sb, br, &add->path);
++ if (unlikely(err))
++ goto out_err;
++
+ if (au_br_writable(add->perm)) {
+ err = au_wbr_init(br, sb, add->perm);
+ if (unlikely(err))
@@ -3452,14 +3715,15 @@ diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c
+{
+ unsigned long long n;
+ struct file **p, *f;
-+ struct au_sphlhead *files;
++ struct hlist_bl_head *files;
++ struct hlist_bl_node *pos;
+ struct au_finfo *finfo;
+
+ n = 0;
+ p = a;
+ files = &au_sbi(sb)->si_files;
-+ spin_lock(&files->spin);
-+ hlist_for_each_entry(finfo, &files->head, fi_hlist) {
++ hlist_bl_lock(files);
++ hlist_bl_for_each_entry(finfo, pos, files, fi_hlist) {
+ f = finfo->fi_file;
+ if (file_count(f)
+ && !special_file(file_inode(f)->i_mode)) {
@@ -3469,7 +3733,7 @@ diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c
+ AuDebugOn(n > max);
+ }
+ }
-+ spin_unlock(&files->spin);
++ hlist_bl_unlock(files);
+
+ return n;
+}
@@ -3872,6 +4136,9 @@ diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c
+ au_br_do_del_hip(au_ii(inode), bindex, bbot);
+ au_sbilist_unlock();
+
++ /* ignore an error */
++ au_dr_br_fin(sb, br); /* always, regardless the mount option */
++
+ dput(h_root);
+ iput(h_inode);
+ au_br_do_free(br);
@@ -4281,8 +4548,7 @@ diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c
+ goto out; /* success */
+
+out_bf:
-+ if (bf)
-+ kfree(bf);
++ kfree(bf);
+out:
+ AuTraceErr(err);
+ return err;
@@ -4307,8 +4573,8 @@ diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c
+}
diff -urN /usr/share/empty/fs/aufs/branch.h linux/fs/aufs/branch.h
--- /usr/share/empty/fs/aufs/branch.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/branch.h 2017-07-29 12:14:25.896375188 +0200
-@@ -0,0 +1,321 @@
++++ linux/fs/aufs/branch.h 2017-11-12 22:24:44.697577553 +0100
+@@ -0,0 +1,333 @@
+/*
+ * Copyright (C) 2005-2017 Junjiro R. Okajima
+ *
@@ -4336,6 +4602,7 @@ diff -urN /usr/share/empty/fs/aufs/branch.h linux/fs/aufs/branch.h
+#ifdef __KERNEL__
+
+#include <linux/mount.h>
++#include "dirren.h"
+#include "dynop.h"
+#include "rwsem.h"
+#include "super.h"
@@ -4433,6 +4700,8 @@ diff -urN /usr/share/empty/fs/aufs/branch.h linux/fs/aufs/branch.h
+ /* entries under sysfs per mount-point */
+ struct au_brsysfs br_sysfs[AuBrSysfs_Last];
+#endif
++
++ struct au_dr_br br_dirren;
+};
+
+/* ---------------------------------------------------------------------- */
@@ -4479,7 +4748,7 @@ diff -urN /usr/share/empty/fs/aufs/branch.h linux/fs/aufs/branch.h
+
+static inline int au_br_rdonly(struct au_branch *br)
+{
-+ return ((au_br_sb(br)->s_flags & MS_RDONLY)
++ return (sb_rdonly(au_br_sb(br))
+ || !au_br_writable(br->br_perm))
+ ? -EROFS : 0;
+}
@@ -4599,15 +4868,24 @@ diff -urN /usr/share/empty/fs/aufs/branch.h linux/fs/aufs/branch.h
+
+/* ---------------------------------------------------------------------- */
+
++#define wbr_wh_read_lock(wbr) au_rw_read_lock(&(wbr)->wbr_wh_rwsem)
++#define wbr_wh_write_lock(wbr) au_rw_write_lock(&(wbr)->wbr_wh_rwsem)
++#define wbr_wh_read_trylock(wbr) au_rw_read_trylock(&(wbr)->wbr_wh_rwsem)
++#define wbr_wh_write_trylock(wbr) au_rw_write_trylock(&(wbr)->wbr_wh_rwsem)
+/*
-+ * wbr_wh_read_lock, wbr_wh_write_lock
-+ * wbr_wh_read_unlock, wbr_wh_write_unlock, wbr_wh_downgrade_lock
-+ */
-+AuSimpleRwsemFuncs(wbr_wh, struct au_wbr *wbr, &wbr->wbr_wh_rwsem);
++#define wbr_wh_read_trylock_nested(wbr) \
++ au_rw_read_trylock_nested(&(wbr)->wbr_wh_rwsem)
++#define wbr_wh_write_trylock_nested(wbr) \
++ au_rw_write_trylock_nested(&(wbr)->wbr_wh_rwsem)
++*/
+
-+#define WbrWhMustNoWaiters(wbr) AuRwMustNoWaiters(&wbr->wbr_wh_rwsem)
-+#define WbrWhMustAnyLock(wbr) AuRwMustAnyLock(&wbr->wbr_wh_rwsem)
-+#define WbrWhMustWriteLock(wbr) AuRwMustWriteLock(&wbr->wbr_wh_rwsem)
++#define wbr_wh_read_unlock(wbr) au_rw_read_unlock(&(wbr)->wbr_wh_rwsem)
++#define wbr_wh_write_unlock(wbr) au_rw_write_unlock(&(wbr)->wbr_wh_rwsem)
++#define wbr_wh_downgrade_lock(wbr) au_rw_dgrade_lock(&(wbr)->wbr_wh_rwsem)
++
++#define WbrWhMustNoWaiters(wbr) AuRwMustNoWaiters(&(wbr)->wbr_wh_rwsem)
++#define WbrWhMustAnyLock(wbr) AuRwMustAnyLock(&(wbr)->wbr_wh_rwsem)
++#define WbrWhMustWriteLock(wbr) AuRwMustWriteLock(&(wbr)->wbr_wh_rwsem)
+
+/* ---------------------------------------------------------------------- */
+
@@ -4632,8 +4910,8 @@ diff -urN /usr/share/empty/fs/aufs/branch.h linux/fs/aufs/branch.h
+#endif /* __AUFS_BRANCH_H__ */
diff -urN /usr/share/empty/fs/aufs/conf.mk linux/fs/aufs/conf.mk
--- /usr/share/empty/fs/aufs/conf.mk 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/conf.mk 2017-07-29 12:14:25.899708630 +0200
-@@ -0,0 +1,38 @@
++++ linux/fs/aufs/conf.mk 2017-11-12 22:24:44.704244405 +0100
+@@ -0,0 +1,39 @@
+
+AuConfStr = CONFIG_AUFS_FS=${CONFIG_AUFS_FS}
+
@@ -4650,6 +4928,7 @@ diff -urN /usr/share/empty/fs/aufs/conf.mk linux/fs/aufs/conf.mk
+ XATTR \
+ FHSM \
+ RDU \
++ DIRREN \
+ SHWH \
+ BR_RAMFS \
+ BR_FUSE POLL \
@@ -4674,8 +4953,8 @@ diff -urN /usr/share/empty/fs/aufs/conf.mk linux/fs/aufs/conf.mk
+-include ${srctree}/${src}/conf_priv.mk
diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c
--- /usr/share/empty/fs/aufs/cpup.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/cpup.c 2017-09-05 10:42:11.055421928 +0200
-@@ -0,0 +1,1442 @@
++++ linux/fs/aufs/cpup.c 2017-11-12 22:24:44.704244405 +0100
+@@ -0,0 +1,1443 @@
+/*
+ * Copyright (C) 2005-2017 Junjiro R. Okajima
+ *
@@ -5197,7 +5476,8 @@ diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c
+ else {
+ inode_unlock_shared(h_src_inode);
+ err = vfsub_getattr(&h_path, &h_src_attr->st);
-+ vfsub_inode_lock_shared_nested(h_src_inode, AuLsc_I_CHILD);
++ vfsub_inode_lock_shared_nested(h_src_inode,
++ AuLsc_I_CHILD);
+ }
+ if (unlikely(err)) {
+ inode_unlock_shared(h_src_inode);
@@ -6120,8 +6400,8 @@ diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c
+}
diff -urN /usr/share/empty/fs/aufs/cpup.h linux/fs/aufs/cpup.h
--- /usr/share/empty/fs/aufs/cpup.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/cpup.h 2017-07-29 12:14:25.899708630 +0200
-@@ -0,0 +1,94 @@
++++ linux/fs/aufs/cpup.h 2017-11-12 22:24:44.704244405 +0100
+@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2005-2017 Junjiro R. Okajima
+ *
@@ -6183,6 +6463,11 @@ diff -urN /usr/share/empty/fs/aufs/cpup.h linux/fs/aufs/cpup.h
+#define AuCpup_RWDST (1 << 5) /* force write target even if
+ the branch is marked as RO */
+
++#ifndef CONFIG_AUFS_BR_HFSPLUS
++#undef AuCpup_HOPEN
++#define AuCpup_HOPEN 0
++#endif
++
+#define au_ftest_cpup(flags, name) ((flags) & AuCpup_##name)
+#define au_fset_cpup(flags, name) \
+ do { (flags) |= AuCpup_##name; } while (0)
@@ -6218,8 +6503,8 @@ diff -urN /usr/share/empty/fs/aufs/cpup.h linux/fs/aufs/cpup.h
+#endif /* __AUFS_CPUP_H__ */
diff -urN /usr/share/empty/fs/aufs/dbgaufs.c linux/fs/aufs/dbgaufs.c
--- /usr/share/empty/fs/aufs/dbgaufs.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/dbgaufs.c 2017-07-29 12:14:25.899708630 +0200
-@@ -0,0 +1,438 @@
++++ linux/fs/aufs/dbgaufs.c 2017-11-12 22:24:44.704244405 +0100
+@@ -0,0 +1,437 @@
+/*
+ * Copyright (C) 2005-2017 Junjiro R. Okajima
+ *
@@ -6336,7 +6621,7 @@ diff -urN /usr/share/empty/fs/aufs/dbgaufs.c linux/fs/aufs/dbgaufs.c
+ struct dbgaufs_plink_arg *p;
+ struct au_sbinfo *sbinfo;
+ struct super_block *sb;
-+ struct au_sphlhead *sphl;
++ struct hlist_bl_head *hbl;
+
+ err = -ENOMEM;
+ p = (void *)get_zeroed_page(GFP_NOFS);
@@ -6356,10 +6641,9 @@ diff -urN /usr/share/empty/fs/aufs/dbgaufs.c linux/fs/aufs/dbgaufs.c
+ limit -= n;
+
+ sum = 0;
-+ for (i = 0, sphl = sbinfo->si_plink;
-+ i < AuPlink_NHASH;
-+ i++, sphl++) {
-+ n = au_sphl_count(sphl);
++ for (i = 0, hbl = sbinfo->si_plink; i < AuPlink_NHASH;
++ i++, hbl++) {
++ n = au_hbl_count(hbl);
+ sum += n;
+
+ n = snprintf(p->a + p->n, limit, "%lu ", n);
@@ -6712,7 +6996,7 @@ diff -urN /usr/share/empty/fs/aufs/dbgaufs.h linux/fs/aufs/dbgaufs.h
+#endif /* __DBGAUFS_H__ */
diff -urN /usr/share/empty/fs/aufs/dcsub.c linux/fs/aufs/dcsub.c
--- /usr/share/empty/fs/aufs/dcsub.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/dcsub.c 2017-07-29 12:14:25.899708630 +0200
++++ linux/fs/aufs/dcsub.c 2017-11-12 22:24:42.267510077 +0100
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2005-2017 Junjiro R. Okajima
@@ -7081,7 +7365,7 @@ diff -urN /usr/share/empty/fs/aufs/dcsub.h linux/fs/aufs/dcsub.h
+#endif /* __AUFS_DCSUB_H__ */
diff -urN /usr/share/empty/fs/aufs/debug.c linux/fs/aufs/debug.c
--- /usr/share/empty/fs/aufs/debug.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/debug.c 2017-07-29 12:14:25.899708630 +0200
++++ linux/fs/aufs/debug.c 2017-11-12 22:24:42.267510077 +0100
@@ -0,0 +1,440 @@
+/*
+ * Copyright (C) 2005-2017 Junjiro R. Okajima
@@ -7754,8 +8038,8 @@ diff -urN /usr/share/empty/fs/aufs/debug.h linux/fs/aufs/debug.h
+#endif /* __AUFS_DEBUG_H__ */
diff -urN /usr/share/empty/fs/aufs/dentry.c linux/fs/aufs/dentry.c
--- /usr/share/empty/fs/aufs/dentry.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux/fs/aufs/dentry.c 2017-09-05 10:42:11.055421928 +0200
-@@ -0,0 +1,1130 @@
++++ linux/fs/aufs/dentry.c 2017-11-12 22:24:44.704244405 +0100
+@@ -0,0 +1,1152 @@
+/*
+ * Copyright (C) 2005-2017 Junjiro R. Okajima
+ *
@@ -7780,19 +8064,13 @@ diff -urN /usr/share/empty/fs/aufs/dentry.c linux/fs/aufs/dentry.c
+#include <linux/namei.h>
+#include "aufs.h"
+
-+struct au_do_lookup_args {
-+ unsigned int flags;
-+ mode_t type;
-+};
-+
+/*
+ * returns positive/negative dentry, NULL or an error.
+ * NULL means whiteout-ed or not-found.
+ */
+static struct dentry*
+au_do_lookup(struct dentry *h_parent, struct dentry *dentry,
-+ aufs_bindex_t bindex, struct qstr *wh_name,
-+ struct au_do_lookup_args *args)
++ aufs_bindex_t bindex, struct au_do_lookup_args *args)
+{
+ struct dentry *h_dentry;
+ struct inode *h_inode;
@@ -7807,7 +8085,7 @@ diff -urN /usr/share/empty/fs/aufs/dentry.c linux/fs/aufs/dentry.c
+ br = au_sbr(dentry->d_sb, bindex);
+ wh_able = !!au_br_whable(br->br_perm);
+ if (wh_able)
-+ wh_found = au_wh_test(h_parent, wh_name, ignore_perm);
++ wh_found = au_wh_test(h_parent, &args->whname, ignore_perm);
+ h_dentry = ERR_PTR(wh_found);
+ if (!wh_found)
+ goto real_lookup;
@@ -7822,9 +8100,9 @@ diff -urN /usr/share/empty/fs/aufs/dentry.c linux/fs/aufs/dentry.c
+
+real_lookup:
+ if (!ignore_perm)
-+ h_dentry = vfsub_lkup_one(&dentry->d_name, h_parent);
++ h_dentry = vfsub_lkup_one(args->name, h_parent);
+ else
-+ h_dentry = au_sio_lkup_one(&dentry->d_name, h_parent);
++ h_dentry = au_sio_lkup_one(args->name, h_parent);
+ if (IS_ERR(h_dentry)) {
+ if (PTR_ERR(h_dentry) == -ENAMETOOLONG
+ && !allow_neg)
@@ -7839,6 +8117,13 @@ diff -urN /usr/share/empty/fs/aufs/dentry.c linux/fs/aufs/dentry.c
+ } else if (wh_found
+ || (args->type && args->type != (h_inode->i_mode & S_IFMT)))
+ goto out_neg;
++ else if (au_ftest_lkup(args->flags, DIRREN)
++ /* && h_inode */
++ && !au_dr_lkup_h_ino(args, bindex, h_inode->i_ino)) {
++ AuDbg("b%d %pd ignored hi%llu\n", bindex, h_dentry,
++ (unsigned long long)h_inode->i_ino);
++ goto out_neg;
++ }
+
+ if (au_dbbot(dentry) <= bindex)
+ au_set_dbbot(dentry, bindex);
@@ -7887,26 +8172,28 @@ diff -urN /usr/share/empty/fs/aufs/dentry.c linux/fs/aufs/dentry.c
+{
+ int npositive, err;
+ aufs_bindex_t bindex, btail, bdiropq;
-+ unsigned char isdir, dirperm1;
-+ struct qstr whname;
++ unsigned char isdir, dirperm1, dirren;
+ struct au_do_lookup_args args = {
-+ .flags = flags
++ .flags = flags,
++ .name = &dentry->d_name
+ };
-+ const struct qstr *name = &dentry->d_name;
+ struct dentry *parent;
+ struct super_block *sb;
+
+ sb = dentry->d_sb;
-+ err = au_test_shwh(sb, name);
++ err = au_test_shwh(sb, args.name);
+ if (unlikely(err))
+ goto out;
+
-+ err = au_wh_name_alloc(&whname, name);
++ err = au_wh_name_alloc(&args.whname, args.name);
+ if (unlikely(err))
+ goto out;
+
+ isdir = !!d_is_dir(dentry);
+ dirperm1 = !!au_opt_test(au_mntflags(sb), DIRPERM1);
++ dirren = !!au_opt_test(au_mntflags(sb), DIRREN);
++ if (dirren)
++ au_fset_lkup(args.flags, DIRREN);
+
+ npositive = 0;
+ parent = dget_parent(dentry);
@@ -7914,6 +8201,7 @@ diff -urN /usr/share/empty/fs/aufs/dentry.c linux/fs/aufs/dentry.c
+ for (bindex = btop; bindex <= btail; bindex++) {
+ struct dentry *h_parent, *h_dentry;
+ struct inode *h_inode, *h_dir;
++ struct au_branch *br;
+
+ h_dentry = au_h_dptr(dentry, bindex);
+ if (h_dentry) {
@@ -7925,10 +8213,16 @@ diff -urN /usr/share/empty/fs/aufs/dentry.c linux/fs/aufs/dentry.c
+ if (!h_parent || !d_is_dir(h_parent))
+ continue;
+
++ if (dirren) {
++ /* if the inum matches, then use the prepared name */
++ err = au_dr_lkup_name(&args, bindex);
++ if (unlikely(err))
++ goto out_parent;
++ }
++
+ h_dir = d_inode(h_parent);
+ vfsub_inode_lock_shared_nested(h_dir, AuLsc_I_PARENT);
-+ h_dentry = au_do_lookup(h_parent, dentry, bindex, &whname,
-+ &args);
++ h_dentry = au_do_lookup(h_parent, dentry, bindex, &args);
+ inode_unlock_shared(h_dir);
+ err = PTR_ERR(h_dentry);
+ if (IS_ERR(h_dentry))
@@ -7956,6 +8250,15 @@ diff -urN /usr/share/empty/fs/aufs/dentry.c linux/fs/aufs/dentry.c
+ if (bdiropq >= 0 && bdiropq <= bindex)
+ break;
+ }
++ br = au_sbr(sb, bindex);
++ if (dirren
++ && au_dr_hino_test_add(&br->br_dirren, h_inode->i_ino,
++ /*add_ent*/NULL)) {
++ /* prepare next name to lookup */
++ err = au_dr_lkup(&args, dentry, bindex);
++ if (unlikely(err))
++ goto out_parent;
++ }
+ }
+
+ if (npositive) {
@@ -7972,7 +8275,9 @@ diff -urN /usr/share/empty/fs/aufs/dentry.c linux/fs/aufs/dentry.c
+
+out_parent:
+ dput(parent);
-+ kfree(whname.name);
++ kfree(args.whname.name);
++ if (dirren)
++ au_dr_lkup_fin(&args);
+out:
+ return err;
+}
@@ -8581,7 +8886,7 @@ diff -urN /usr/share/empty/fs/aufs/dentry.c linux/fs/aufs/dentry.c
+
+/* todo: remove this */
+static int h_d_revalidate(struct dentry *dentry, struct inode *inode,
-+ unsigned int flags, int do_udba)
++ unsigned int flags, int do_udba, int dirren)
+{
+ int err;
+ umode_t mode, h_mode;
@@ -8632,7 +8937,7 @@ diff -urN /usr/share/empty/fs/aufs/dentry.c linux/fs/aufs/dentry.c
+ && !is_root
+ && ((!h_nfs
+ && (unhashed != !!d_unhashed(h_dentry)
-+ || (!tmpfile
++ || (!tmpfile && !dirren
+ && !au_qstreq(name, h_name))
+ ))
+ || (h_nfs
@@ -8773,7 +9078,7 @@ diff -urN /usr/share/empty/fs/aufs/dentry.c linux/fs/aufs/dentry.c
+{
+ int valid, err;
+ unsigned int sigen;
<Skipped 4357 lines>
================================================================
---- gitweb:
http://git.pld-linux.org/gitweb.cgi/packages/kernel.git/commitdiff/8b6a494719f4150ce54b9e4d30810ece069c1c73
More information about the pld-cvs-commit
mailing list