Address AppArmor incompatibilities
This change fixes the AppArmor incompatibility issues with the stock Proxmox kernel. Since the stock kernel includes some patches from Ubuntu, its AppArmor feature set is incompatible with the one offered by this project. We address this by also including these patches in our build, so users do not need to manually intervene to update the apparmor_parser configuration.
This commit is contained in:
parent
c75ca2a30d
commit
ed134665cb
7 changed files with 1523 additions and 10 deletions
15
README.md
15
README.md
|
@ -44,19 +44,14 @@ Then, you can install the package as follows:
|
|||
apt install ./pve-kernel-VERSION_amd64.deb
|
||||
```
|
||||
|
||||
## AppArmor issues
|
||||
When using these kernels, Proxmox's AppArmor profiles may fail to load since it
|
||||
uses an older AppArmor feature set which is not supported by these kernels anymore.
|
||||
This issue also appears when launching LXC containers.
|
||||
To fix this, tell AppArmor to use the stock features file as opposed to
|
||||
Proxmox's features file, which is done by updating `/etc/apparmor/parser.conf` as follows:
|
||||
|
||||
## AppArmor intervention
|
||||
Previously, these kernels required changing the AppArmor feature file to a non-default version.
|
||||
This issue has been fixed since version 5.16.
|
||||
If you have used the workaround, please update back to the default configuration in `/etc/apparmor/parser.conf` as follows:
|
||||
```
|
||||
## Pin feature set (avoid regressions when policy is lagging behind
|
||||
## the kernel)
|
||||
# lxc-pve diverts to old feature file that is incompatible with kernel
|
||||
# features-file=/usr/share/apparmor-features/features
|
||||
features-file=/usr/share/apparmor-features/features.stock
|
||||
features-file=/usr/share/apparmor-features/features
|
||||
```
|
||||
|
||||
## Building manually
|
||||
|
|
1
debian/changelog
vendored
1
debian/changelog
vendored
|
@ -2,6 +2,7 @@ pve-kernel (5.16.0-1) edge; urgency=medium
|
|||
|
||||
* Disable UBNSAN (see issue #164 and #200).
|
||||
* Update to ZFS 2.1.2
|
||||
* Fix AppArmor incompatibilities
|
||||
|
||||
-- Fabian Mastenbroek <mail.fabianm@gmail.com> Wed, 10 Nov 2021 10:15:00 +0000
|
||||
|
||||
|
|
250
debian/patches/pve/0006-apparmor-compatibility-v2.x-net-rules.patch
vendored
Normal file
250
debian/patches/pve/0006-apparmor-compatibility-v2.x-net-rules.patch
vendored
Normal file
|
@ -0,0 +1,250 @@
|
|||
From f153f512ed7a81e9b92a04d49869cffebf714f52 Mon Sep 17 00:00:00 2001
|
||||
From: John Johansen <john.johansen@canonical.com>
|
||||
Date: Sun, 17 Jun 2018 03:56:25 -0700
|
||||
Subject: UBUNTU: SAUCE: apparmor: patch to provide compatibility with v2.x net
|
||||
rules
|
||||
|
||||
The networking rules upstreamed in 4.17 have a deliberate abi break
|
||||
with the older 2.x network rules.
|
||||
|
||||
This patch provides compatibility with the older rules for those
|
||||
still using an apparmor 2.x userspace and still want network rules
|
||||
to work on a newer kernel.
|
||||
|
||||
Signed-off-by: John Johansen <john.johansen@canonical.com>
|
||||
[ saf: resolve conflicts when rebasing to 4.20 ]
|
||||
Signed-off-by: Seth Forshee <seth.forshee@canonical.com>
|
||||
---
|
||||
security/apparmor/apparmorfs.c | 1 +
|
||||
security/apparmor/include/apparmor.h | 2 +-
|
||||
security/apparmor/include/net.h | 11 ++++++++
|
||||
security/apparmor/include/policy.h | 2 ++
|
||||
security/apparmor/net.c | 31 ++++++++++++++++-----
|
||||
security/apparmor/policy.c | 1 +
|
||||
security/apparmor/policy_unpack.c | 54 ++++++++++++++++++++++++++++++++++--
|
||||
7 files changed, 92 insertions(+), 10 deletions(-)
|
||||
|
||||
(limited to 'security/apparmor')
|
||||
|
||||
diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
|
||||
index 2ee3b3d..0aef8e3 100644
|
||||
--- a/security/apparmor/apparmorfs.c
|
||||
+++ b/security/apparmor/apparmorfs.c
|
||||
@@ -2362,6 +2362,7 @@ static struct aa_sfs_entry aa_sfs_entry_features[] = {
|
||||
AA_SFS_DIR("domain", aa_sfs_entry_domain),
|
||||
AA_SFS_DIR("file", aa_sfs_entry_file),
|
||||
AA_SFS_DIR("network_v8", aa_sfs_entry_network),
|
||||
+ AA_SFS_DIR("network", aa_sfs_entry_network_compat),
|
||||
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),
|
||||
diff --git a/security/apparmor/include/apparmor.h b/security/apparmor/include/apparmor.h
|
||||
index 1fbabdb..5870de2 100644
|
||||
--- a/security/apparmor/include/apparmor.h
|
||||
+++ b/security/apparmor/include/apparmor.h
|
||||
@@ -20,7 +20,7 @@
|
||||
#define AA_CLASS_UNKNOWN 1
|
||||
#define AA_CLASS_FILE 2
|
||||
#define AA_CLASS_CAP 3
|
||||
-#define AA_CLASS_DEPRECATED 4
|
||||
+#define AA_CLASS_NET_COMPAT 4
|
||||
#define AA_CLASS_RLIMITS 5
|
||||
#define AA_CLASS_DOMAIN 6
|
||||
#define AA_CLASS_MOUNT 7
|
||||
diff --git a/security/apparmor/include/net.h b/security/apparmor/include/net.h
|
||||
index aadb4b2..98a42ef 100644
|
||||
--- a/security/apparmor/include/net.h
|
||||
+++ b/security/apparmor/include/net.h
|
||||
@@ -68,6 +68,16 @@ struct aa_sk_ctx {
|
||||
DEFINE_AUDIT_NET(NAME, OP, SK, (SK)->sk_family, (SK)->sk_type, \
|
||||
(SK)->sk_protocol)
|
||||
|
||||
+/* struct aa_net - network confinement data
|
||||
+ * @allow: basic network families permissions
|
||||
+ * @audit: which network permissions to force audit
|
||||
+ * @quiet: which network permissions to quiet rejects
|
||||
+ */
|
||||
+struct aa_net_compat {
|
||||
+ u16 allow[AF_MAX];
|
||||
+ u16 audit[AF_MAX];
|
||||
+ u16 quiet[AF_MAX];
|
||||
+};
|
||||
|
||||
#define af_select(FAMILY, FN, DEF_FN) \
|
||||
({ \
|
||||
@@ -87,6 +97,7 @@ struct aa_secmark {
|
||||
};
|
||||
|
||||
extern struct aa_sfs_entry aa_sfs_entry_network[];
|
||||
+extern struct aa_sfs_entry aa_sfs_entry_network_compat[];
|
||||
|
||||
void audit_net_cb(struct audit_buffer *ab, void *va);
|
||||
int aa_profile_af_perm(struct aa_profile *profile, struct common_audit_data *sa,
|
||||
diff --git a/security/apparmor/include/policy.h b/security/apparmor/include/policy.h
|
||||
index b5b4b81..f904105 100644
|
||||
--- a/security/apparmor/include/policy.h
|
||||
+++ b/security/apparmor/include/policy.h
|
||||
@@ -108,6 +108,7 @@ struct aa_data {
|
||||
* @policy: general match rules governing policy
|
||||
* @file: The set of rules governing basic file access and domain transitions
|
||||
* @caps: capabilities for the profile
|
||||
+ * @net_compat: v2 compat network controls for the profile
|
||||
* @rlimits: rlimits for the profile
|
||||
*
|
||||
* @dents: dentries for the profiles file entries in apparmorfs
|
||||
@@ -145,6 +146,7 @@ struct aa_profile {
|
||||
struct aa_policydb policy;
|
||||
struct aa_file_rules file;
|
||||
struct aa_caps caps;
|
||||
+ struct aa_net_compat *net_compat;
|
||||
|
||||
int xattr_count;
|
||||
char **xattrs;
|
||||
diff --git a/security/apparmor/net.c b/security/apparmor/net.c
|
||||
index e0c1b50..e693df8 100644
|
||||
--- a/security/apparmor/net.c
|
||||
+++ b/security/apparmor/net.c
|
||||
@@ -24,6 +24,11 @@ struct aa_sfs_entry aa_sfs_entry_network[] = {
|
||||
{ }
|
||||
};
|
||||
|
||||
+struct aa_sfs_entry aa_sfs_entry_network_compat[] = {
|
||||
+ AA_SFS_FILE_STRING("af_mask", AA_SFS_AF_MASK),
|
||||
+ { }
|
||||
+};
|
||||
+
|
||||
static const char * const net_mask_names[] = {
|
||||
"unknown",
|
||||
"send",
|
||||
@@ -118,14 +123,26 @@ int aa_profile_af_perm(struct aa_profile *profile, struct common_audit_data *sa,
|
||||
if (profile_unconfined(profile))
|
||||
return 0;
|
||||
state = PROFILE_MEDIATES(profile, AA_CLASS_NET);
|
||||
- if (!state)
|
||||
+ if (state) {
|
||||
+ if (!state)
|
||||
+ return 0;
|
||||
+ buffer[0] = cpu_to_be16(family);
|
||||
+ buffer[1] = cpu_to_be16((u16) type);
|
||||
+ state = aa_dfa_match_len(profile->policy.dfa, state,
|
||||
+ (char *) &buffer, 4);
|
||||
+ aa_compute_perms(profile->policy.dfa, state, &perms);
|
||||
+ } else if (profile->net_compat) {
|
||||
+ /* 2.x socket mediation compat */
|
||||
+ perms.allow = (profile->net_compat->allow[family] & (1 << type)) ?
|
||||
+ ALL_PERMS_MASK : 0;
|
||||
+ perms.audit = (profile->net_compat->audit[family] & (1 << type)) ?
|
||||
+ ALL_PERMS_MASK : 0;
|
||||
+ perms.quiet = (profile->net_compat->quiet[family] & (1 << type)) ?
|
||||
+ ALL_PERMS_MASK : 0;
|
||||
+
|
||||
+ } else {
|
||||
return 0;
|
||||
-
|
||||
- buffer[0] = cpu_to_be16(family);
|
||||
- buffer[1] = cpu_to_be16((u16) type);
|
||||
- state = aa_dfa_match_len(profile->policy.dfa, state, (char *) &buffer,
|
||||
- 4);
|
||||
- aa_compute_perms(profile->policy.dfa, state, &perms);
|
||||
+ }
|
||||
aa_apply_modes_to_perms(profile, &perms);
|
||||
|
||||
return aa_check_perms(profile, &perms, request, sa, audit_net_cb);
|
||||
diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c
|
||||
index 4c010c9..a00e39b 100644
|
||||
--- a/security/apparmor/policy.c
|
||||
+++ b/security/apparmor/policy.c
|
||||
@@ -222,6 +222,7 @@ void aa_free_profile(struct aa_profile *profile)
|
||||
aa_free_file_rules(&profile->file);
|
||||
aa_free_cap_rules(&profile->caps);
|
||||
aa_free_rlimit_rules(&profile->rlimits);
|
||||
+ kfree_sensitive(profile->net_compat);
|
||||
|
||||
for (i = 0; i < profile->xattr_count; i++)
|
||||
kfree_sensitive(profile->xattrs[i]);
|
||||
diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c
|
||||
index 4e1f96b..aedfecc 100644
|
||||
--- a/security/apparmor/policy_unpack.c
|
||||
+++ b/security/apparmor/policy_unpack.c
|
||||
@@ -34,7 +34,7 @@
|
||||
|
||||
#define v5 5 /* base version */
|
||||
#define v6 6 /* per entry policydb mediation check */
|
||||
-#define v7 7
|
||||
+#define v7 7 /* v2 compat networking */
|
||||
#define v8 8 /* full network masking */
|
||||
|
||||
/*
|
||||
@@ -314,6 +314,19 @@ fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
+static bool unpack_u16(struct aa_ext *e, u16 *data, const char *name)
|
||||
+{
|
||||
+ if (unpack_nameX(e, AA_U16, name)) {
|
||||
+ if (!inbounds(e, sizeof(u16)))
|
||||
+ return 0;
|
||||
+ if (data)
|
||||
+ *data = le16_to_cpu(get_unaligned((__le16 *) e->pos));
|
||||
+ e->pos += sizeof(u16);
|
||||
+ return 1;
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static bool unpack_u32(struct aa_ext *e, u32 *data, const char *name)
|
||||
{
|
||||
void *pos = e->pos;
|
||||
@@ -676,7 +689,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;
|
||||
+ size_t size = 0, ns_len;
|
||||
struct rhashtable_params params = { 0 };
|
||||
char *key = NULL;
|
||||
struct aa_data *data;
|
||||
@@ -823,6 +836,43 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
+ size = unpack_array(e, "net_allowed_af");
|
||||
+ if (size || VERSION_LT(e->version, v8)) {
|
||||
+ profile->net_compat = kzalloc(sizeof(struct aa_net_compat), GFP_KERNEL);
|
||||
+ if (!profile->net_compat) {
|
||||
+ info = "out of memory";
|
||||
+ goto fail;
|
||||
+ }
|
||||
+ for (i = 0; i < size; i++) {
|
||||
+ /* discard extraneous rules that this kernel will
|
||||
+ * never request
|
||||
+ */
|
||||
+ if (i >= AF_MAX) {
|
||||
+ u16 tmp;
|
||||
+
|
||||
+ if (!unpack_u16(e, &tmp, NULL) ||
|
||||
+ !unpack_u16(e, &tmp, NULL) ||
|
||||
+ !unpack_u16(e, &tmp, NULL))
|
||||
+ goto fail;
|
||||
+ continue;
|
||||
+ }
|
||||
+ if (!unpack_u16(e, &profile->net_compat->allow[i], NULL))
|
||||
+ goto fail;
|
||||
+ if (!unpack_u16(e, &profile->net_compat->audit[i], NULL))
|
||||
+ goto fail;
|
||||
+ if (!unpack_u16(e, &profile->net_compat->quiet[i], NULL))
|
||||
+ goto fail;
|
||||
+ }
|
||||
+ if (size && !unpack_nameX(e, AA_ARRAYEND, NULL))
|
||||
+ goto fail;
|
||||
+ if (VERSION_LT(e->version, v7)) {
|
||||
+ /* pre v7 policy always allowed these */
|
||||
+ profile->net_compat->allow[AF_UNIX] = 0xffff;
|
||||
+ profile->net_compat->allow[AF_NETLINK] = 0xffff;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+
|
||||
if (unpack_nameX(e, AA_STRUCT, "policydb")) {
|
||||
/* generic policy dfa - optional and may be NULL */
|
||||
info = "failed to unpack policydb";
|
1168
debian/patches/pve/0007-apparmor-af_unix-mediation.patch
vendored
Normal file
1168
debian/patches/pve/0007-apparmor-af_unix-mediation.patch
vendored
Normal file
File diff suppressed because it is too large
Load diff
38
debian/patches/pve/0008-apparmor-fix-apparmor-mediating-locking-non-fs-unix-sockets.patch
vendored
Normal file
38
debian/patches/pve/0008-apparmor-fix-apparmor-mediating-locking-non-fs-unix-sockets.patch
vendored
Normal file
|
@ -0,0 +1,38 @@
|
|||
From d7410054784d8aa0e313f9eeb6110a791420f3d3 Mon Sep 17 00:00:00 2001
|
||||
From: John Johansen <john.johansen@canonical.com>
|
||||
Date: Mon, 30 Jul 2018 13:55:30 -0700
|
||||
Subject: UBUNTU SAUCE: apparmor: fix apparmor mediating locking non-fs, unix
|
||||
sockets
|
||||
|
||||
The apparmor policy language current does not allow expressing of the
|
||||
locking permission for no-fs unix sockets. However the kernel is
|
||||
enforcing mediation.
|
||||
|
||||
Add the AA_MAY_LOCK perm to the computed perm mask which will grant
|
||||
permission for all current abi profiles, but still allow specifying
|
||||
auditing of the operation if needed.
|
||||
|
||||
BugLink: http://bugs.launchpad.net/bugs/1780227
|
||||
Signed-off-by: John Johansen <john.johansen@canonical.com>
|
||||
Acked-by: Acked-by: Stefan Bader <stefan.bader@canonical.com>
|
||||
Acked-by: Acked-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com>
|
||||
Signed-off-by: Seth Forshee <seth.forshee@canonical.com>
|
||||
---
|
||||
security/apparmor/lib.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
(limited to 'security/apparmor')
|
||||
|
||||
diff --git a/security/apparmor/lib.c b/security/apparmor/lib.c
|
||||
index fa49b81..bf72843 100644
|
||||
--- a/security/apparmor/lib.c
|
||||
+++ b/security/apparmor/lib.c
|
||||
@@ -334,7 +334,7 @@ void aa_compute_perms(struct aa_dfa *dfa, unsigned int state,
|
||||
/* for v5 perm mapping in the policydb, the other set is used
|
||||
* to extend the general perm set
|
||||
*/
|
||||
- perms->allow |= map_other(dfa_other_allow(dfa, state));
|
||||
+ perms->allow |= map_other(dfa_other_allow(dfa, state)) | AA_MAY_LOCK;
|
||||
perms->audit |= map_other(dfa_other_audit(dfa, state));
|
||||
perms->quiet |= map_other(dfa_other_quiet(dfa, state));
|
||||
// perms->xindex = dfa_user_xindex(dfa, state);
|
57
debian/patches/pve/0009-apparmor-fix-use-after-free-in-sk_peer_label.patch
vendored
Normal file
57
debian/patches/pve/0009-apparmor-fix-use-after-free-in-sk_peer_label.patch
vendored
Normal file
|
@ -0,0 +1,57 @@
|
|||
From e9243f6a285589f49161faf0f96f4cf15c1dafae Mon Sep 17 00:00:00 2001
|
||||
From: John Johansen <john.johansen@canonical.com>
|
||||
Date: Tue, 26 Jun 2018 20:19:19 -0700
|
||||
Subject: UBUNTU: SAUCE: apparmor: fix use after free in sk_peer_label
|
||||
|
||||
BugLink: http://bugs.launchpad.net/bugs/1778646
|
||||
Signed-off-by: John Johansen <john.johansen@canonical.com>
|
||||
Signed-off-by: Seth Forshee <seth.forshee@canonical.com>
|
||||
---
|
||||
security/apparmor/lsm.c | 11 +++++++----
|
||||
1 file changed, 7 insertions(+), 4 deletions(-)
|
||||
|
||||
(limited to 'security/apparmor')
|
||||
|
||||
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
|
||||
index 59a8ddd..b1216ee 100644
|
||||
--- a/security/apparmor/lsm.c
|
||||
+++ b/security/apparmor/lsm.c
|
||||
@@ -1162,9 +1162,10 @@ static struct aa_label *sk_peer_label(struct sock *sk)
|
||||
{
|
||||
struct sock *peer_sk;
|
||||
struct aa_sk_ctx *ctx = SK_CTX(sk);
|
||||
+ struct aa_label *label = ERR_PTR(-ENOPROTOOPT);
|
||||
|
||||
if (ctx->peer)
|
||||
- return ctx->peer;
|
||||
+ return aa_get_label(ctx->peer);
|
||||
|
||||
if (sk->sk_family != PF_UNIX)
|
||||
return ERR_PTR(-ENOPROTOOPT);
|
||||
@@ -1172,14 +1173,15 @@ static struct aa_label *sk_peer_label(struct sock *sk)
|
||||
/* check for sockpair peering which does not go through
|
||||
* security_unix_stream_connect
|
||||
*/
|
||||
- peer_sk = unix_peer(sk);
|
||||
+ peer_sk = unix_peer_get(sk);
|
||||
if (peer_sk) {
|
||||
ctx = SK_CTX(peer_sk);
|
||||
if (ctx->label)
|
||||
- return ctx->label;
|
||||
+ label = aa_get_label(ctx->label);
|
||||
+ sock_put(peer_sk);
|
||||
}
|
||||
|
||||
- return ERR_PTR(-ENOPROTOOPT);
|
||||
+ return label;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1223,6 +1225,7 @@ out:
|
||||
|
||||
}
|
||||
|
||||
+ aa_put_label(peer);
|
||||
done:
|
||||
end_current_label_crit_section(label);
|
||||
|
4
debian/patches/series.linux
vendored
4
debian/patches/series.linux
vendored
|
@ -3,3 +3,7 @@ pve/0002-bridge-keep-MAC-of-first-assigned-port.patch
|
|||
pve/0003-pci-Enable-overrides-for-missing-ACS-capabilities-4..patch
|
||||
pve/0004-kvm-disable-default-dynamic-halt-polling-growth.patch
|
||||
pve/0005-net-core-downgrade-unregister_netdevice-refcount-lea.patch
|
||||
pve/0006-apparmor-compatibility-v2.x-net-rules.patch
|
||||
pve/0007-apparmor-af_unix-mediation.patch
|
||||
pve/0008-apparmor-fix-apparmor-mediating-locking-non-fs-unix-sockets.patch
|
||||
pve/0009-apparmor-fix-use-after-free-in-sk_peer_label.patch
|
||||
|
|
Loading…
Reference in a new issue