mirror of
https://gitlab.com/apparmor/apparmor.git
synced 2025-03-04 00:14:44 +01:00
Add the patches for 4.13 and 4.14. These are based on security-next for 4.14
The old out of tree patchseries has been completely dropped. v4.13 has most of the newer apparmor 3.x code in it. v4.14 has the rest except the af_unix mediation which is included as the last patch
This commit is contained in:
parent
26a12fd9ac
commit
6260deec9a
20 changed files with 6318 additions and 0 deletions
|
@ -0,0 +1,41 @@
|
|||
From 00c72bc198aa85e5da02de2c0c4cc423c82a54f1 Mon Sep 17 00:00:00 2001
|
||||
From: Fedora Kernel Team <kernel-team@fedoraproject.org>
|
||||
Date: Thu, 3 Aug 2017 13:46:51 -0500
|
||||
Subject: [PATCH 01/17] UBUNTU: SAUCE: (efi-lockdown) MODSIGN: Fix module
|
||||
signature verification
|
||||
|
||||
BugLink: http://bugs.launchpad.net/bugs/1712168
|
||||
|
||||
Currently mod_verify_sig() calls verify_pkcs_7_signature() with
|
||||
trusted_keys=NULL, which causes only the builtin keys to be used
|
||||
to verify the signature. This breaks self-signing of modules with
|
||||
a MOK, as the MOK is loaded into the secondary trusted keyring.
|
||||
Fix this by passing the spacial value trusted_keys=(void *)1UL,
|
||||
which tells verify_pkcs_7_signature() to use the secondary
|
||||
keyring instead.
|
||||
|
||||
(cherry picked from commit cff4523d65b848f9c41c9e998a735ae2a820da2d
|
||||
git://git.kernel.org/pub/scm/linux/kernel/git/jwboyer/fedora.git)
|
||||
[ saf: Taken from fedora commit without authorship information or much
|
||||
of a commit message; modified so that commit will describe the
|
||||
problem being fixed. ]
|
||||
Signed-off-by: Seth Forshee <seth.forshee@canonical.com>
|
||||
---
|
||||
kernel/module_signing.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/kernel/module_signing.c b/kernel/module_signing.c
|
||||
index 937c844bee4a..d3d6f95a96b4 100644
|
||||
--- a/kernel/module_signing.c
|
||||
+++ b/kernel/module_signing.c
|
||||
@@ -81,6 +81,6 @@ int mod_verify_sig(const void *mod, unsigned long *_modlen)
|
||||
}
|
||||
|
||||
return verify_pkcs7_signature(mod, modlen, mod + modlen, sig_len,
|
||||
- NULL, VERIFYING_MODULE_SIGNATURE,
|
||||
+ (void *)1UL, VERIFYING_MODULE_SIGNATURE,
|
||||
NULL, NULL);
|
||||
}
|
||||
--
|
||||
2.11.0
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
From c6cad5e65a23dcafa1821ca381901297664d9c64 Mon Sep 17 00:00:00 2001
|
||||
From: Geert Uytterhoeven <geert@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@linux-m68k.org>
|
||||
Reviewed-by: Serge Hallyn <serge@hallyn.com>
|
||||
Signed-off-by: John Johansen <john.johansen@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
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
From 9934296cba701d429a0fc0cf071a40c8c3a1587e Mon Sep 17 00:00:00 2001
|
||||
From: Christos Gkekas <chris.gekas@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@gmail.com>
|
||||
Signed-off-by: John Johansen <john.johansen@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
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
From 8b3851c7b83f32f2be9d4b48371ddf033afedf62 Mon Sep 17 00:00:00 2001
|
||||
From: Dan Carpenter <dan.carpenter@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@oracle.com>
|
||||
Acked-by: Serge Hallyn <serge@hallyn.com>
|
||||
Signed-off-by: John Johansen <john.johansen@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
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
From 4b56e146905bbad2c79ea92e3f49e210ca527572 Mon Sep 17 00:00:00 2001
|
||||
From: John Johansen <john.johansen@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@hotmail.com>
|
||||
Signed-off-by: John Johansen <john.johansen@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
|
||||
|
|
@ -0,0 +1,397 @@
|
|||
From f9e20353a6c5726775867db81b6085e8ab425a36 Mon Sep 17 00:00:00 2001
|
||||
From: John Johansen <john.johansen@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@canonical.com>
|
||||
Acked-by: Seth Arnold <seth.arnold@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
|
||||
|
1051
kernel-patches/v4.13/0007-apparmor-add-mount-mediation.patch
Normal file
1051
kernel-patches/v4.13/0007-apparmor-add-mount-mediation.patch
Normal file
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,71 @@
|
|||
From 763d17c9a18b0df7dbec2740f10dc40d378e3cc1 Mon Sep 17 00:00:00 2001
|
||||
From: John Johansen <john.johansen@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@canonical.com>
|
||||
Acked-by: Seth Arnold <seth.arnold@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
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
From 6b092bbbf9e17b10f709d11b3bc2d7e493617934 Mon Sep 17 00:00:00 2001
|
||||
From: John Johansen <john.johansen@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@canonical.com>
|
||||
Acked-by: Seth Arnold <seth.arnold@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
|
||||
|
|
@ -0,0 +1,219 @@
|
|||
From aa4b6bded85552bc5f9f22d2e18ce86c5c17947c Mon Sep 17 00:00:00 2001
|
||||
From: John Johansen <john.johansen@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@canonical.com>
|
||||
Acked-by: Seth Arnold <seth.arnold@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
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
From ba3f778a2ef31454032c2ca9c99d9212feb4dcf1 Mon Sep 17 00:00:00 2001
|
||||
From: John Johansen <john.johansen@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@canonical.com>
|
||||
Acked-by: Seth Arnold <seth.arnold@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
|
||||
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,194 @@
|
|||
From 50d30adbef98a0b6cc531a9413d05f564eb633ee Mon Sep 17 00:00:00 2001
|
||||
From: John Johansen <john.johansen@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@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
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
From ab3b869791b6122c7be7e68ca4c08e2c2e8815ac Mon Sep 17 00:00:00 2001
|
||||
From: John Johansen <john.johansen@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@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
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
From 7f2cdd6453518ff76c3855255c91306a2b928c9a Mon Sep 17 00:00:00 2001
|
||||
From: John Johansen <john.johansen@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@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
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
From 8daf877473653c06a28c86bf72d63ce7e5c1d542 Mon Sep 17 00:00:00 2001
|
||||
From: John Johansen <john.johansen@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@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
|
||||
|
File diff suppressed because it is too large
Load diff
5
kernel-patches/v4.13/README
Normal file
5
kernel-patches/v4.13/README
Normal file
|
@ -0,0 +1,5 @@
|
|||
The old out of tree patches have been dropped.
|
||||
|
||||
This series is a backport of the patches currently in security-next
|
||||
scheduled for 4.14, with the exception of the last patch for af_unix
|
||||
mediation.
|
File diff suppressed because it is too large
Load diff
4
kernel-patches/v4.14/README
Normal file
4
kernel-patches/v4.14/README
Normal file
|
@ -0,0 +1,4 @@
|
|||
This series is based on what is currently in linux-next scheduled for
|
||||
inclusion in 4.14
|
||||
|
||||
af_unix-mediation is the last remaining patch that is out of tree
|
Loading…
Add table
Reference in a new issue