Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Container issues with Ubuntu Oracular systemd version 256-1ubuntu1 #13810

Closed
2 of 4 tasks
mihalicyn opened this issue Jul 23, 2024 · 10 comments · Fixed by #13820
Closed
2 of 4 tasks

Container issues with Ubuntu Oracular systemd version 256-1ubuntu1 #13810

mihalicyn opened this issue Jul 23, 2024 · 10 comments · Fixed by #13820
Assignees
Labels
Bug Confirmed to be a bug
Milestone

Comments

@mihalicyn
Copy link
Member

mihalicyn commented Jul 23, 2024

Investigate and fix all the issues

TODO list:

See also:
#13807
#12698
https://bugs.launchpad.net/ubuntu/+source/systemd/+bug/2046486
#13844
#13860

@mihalicyn mihalicyn added the Bug Confirmed to be a bug label Jul 23, 2024
@mihalicyn mihalicyn self-assigned this Jul 23, 2024
@tomponline tomponline added this to the lxd-6.2 milestone Jul 23, 2024
@tomponline
Copy link
Member

For now the workaround is to do lxc config set <instance> security.nesting=true and restart container.

mihalicyn added a commit to mihalicyn/lxd that referenced this issue Jul 25, 2024
tomponline added a commit that referenced this issue Jul 25, 2024
It turns out, that a ruleset:
```
{{- if .feature_mount_nosymfollow }}
  # see #12698
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /[^spd]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /d[^e]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /de[^v]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /dev/.[^l]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /dev/.l[^x]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /dev/.lx[^c]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /dev/.lxc?*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /dev/[^.]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /dev?*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /p[^r]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /pr[^o]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /pro[^c]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /proc?*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /s[^y]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /sy[^s]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /sys?*{,/**},
{{- end }}
```

is not enough to allow nosymfollow. We still getting AppArmor denials
like this:
```
[110841.647871] audit: type=1400 audit(1721910063.197:1611): apparmor="DENIED" operation="mount" class="mount" info="failed flags match" error=-13 profile="lxd-secure-oriole_</var/snap/lxd/common/lxd>" name="/dev/shm/" pid=712867 comm="(sd-mkdcreds)" flags="ro, nosuid, nodev, noexec, remount, bind"
```

First of all, there is no "nosymfollow" in the kernel log. Which is a
bug and should be fixed by:
https://lore.kernel.org/all/[email protected]/

Secondly, it looks like these rules in the form of mount
options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /some/path,

just does not work at all. At least in AppArmor 4.0+ (have not yet
tested with older ones).

During my local experiments, I found that working variant of it might
be: mount
```
options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) -> /some/path,
```

or wider:
```
mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow),
```

Let's just add a wider variant of the rule in addition to what we
already have for unprivileged containers. But keep in mind that
something is wrong with these rules in their more restrictive form (with
path specifier). This is a matter of a futher investigation, because
it's important for privileged containers case.

See also:
#12698

Closes #12698
May close #13810
@tomponline tomponline reopened this Jul 25, 2024
@tomponline
Copy link
Member

tomponline commented Jul 25, 2024

Reopens for privilege use case.

mihalicyn added a commit to mihalicyn/lxd that referenced this issue Jul 26, 2024
While investigating canonical#13810 I found that all ro+remount rules in the form:

mount options=(ro,remount,bind,A,B,C) /some_pattern{,/**},

just does not work at all. This remount+bind case is a very special one,
and we should rewrite all rules in this form:

mount options=(ro,remount,bind,A,B,C) -> /some_pattern{,/**},

This syntax is not new. This change should be compatible with very old
AppArmor versions including 2.11.

Explanation why it was not noticed for years is that for unprivileged
container case we have analogical rule but in a wider form:

mount options=(ro,remount,bind,nodev,A,B,C),

which masks the issue. But for privileged containers it's not.

So, let's fix this for correctness.

Signed-off-by: Alexander Mikhalitsyn <[email protected]>
tomponline added a commit that referenced this issue Jul 26, 2024
While investigating #13810 I found that all ro+remount rules in the
form:

```
mount options=(ro,remount,bind,A,B,C) /some_pattern{,/**},
```

just does not work at all. This remount+bind case is a very special one,
and we should rewrite all rules in this form:

```
mount options=(ro,remount,bind,A,B,C) -> /some_pattern{,/**},
```

This syntax is not new. This change should be compatible with very old
AppArmor versions including 2.11.

Explanation why it was not noticed for years is that for unprivileged
container case we have analogical rule but in a wider form:

```
mount options=(ro,remount,bind,nodev,A,B,C),
```

which masks the issue. But for privileged containers it's not.

So, let's fix this for correctness.
@mihalicyn
Copy link
Member Author

Ok, what we have about privileged containers:

  • jammy works
  • noble doesn't
  • oracular too

What we have in the audit logs:

[15669.318153] audit: type=1400 audit(1721991292.665:4813): apparmor="DENIED" operation="mount" class="mount" info="failed perms check" error=-13 profile="lxd-no_</var/snap/lxd/common/lxd>" name="/run/systemd/mount-rootfs/" pid=145591 comm="(d-logind)" srcname="/" flags="rw, rbind"
[15669.327424] audit: type=1400 audit(1721991292.673:4814): apparmor="DENIED" operation="mount" class="mount" info="failed perms check" error=-13 profile="lxd-no_</var/snap/lxd/common/lxd>" name="/run/systemd/mount-rootfs/" pid=145595 comm="(d-logind)" srcname="/" flags="rw, rbind"
[15669.336943] audit: type=1400 audit(1721991292.685:4815): apparmor="DENIED" operation="mount" class="mount" info="failed perms check" error=-13 profile="lxd-no_</var/snap/lxd/common/lxd>" name="/run/systemd/mount-rootfs/" pid=145599 comm="(d-logind)" srcname="/" flags="rw, rbind"
[15669.346912] audit: type=1400 audit(1721991292.693:4816): apparmor="DENIED" operation="mount" class="mount" info="failed perms check" error=-13 profile="lxd-no_</var/snap/lxd/common/lxd>" name="/run/systemd/mount-rootfs/" pid=145603 comm="(d-logind)" srcname="/" flags="rw, rbind"
[15669.357968] audit: type=1400 audit(1721991292.705:4817): apparmor="DENIED" operation="mount" class="mount" info="failed perms check" error=-13 profile="lxd-no_</var/snap/lxd/common/lxd>" name="/run/systemd/mount-rootfs/" pid=145607 comm="(d-logind)" srcname="/" flags="rw, rbind"
[15671.673932] audit: type=1400 audit(1721991295.021:4818): apparmor="DENIED" operation="mount" class="mount" info="failed perms check" error=-13 profile="lxd-or_</var/snap/lxd/common/lxd>" name="/run/systemd/mount-rootfs/" pid=145649 comm="(d-logind)" srcname="/" flags="rw, rbind"
[15671.674044] audit: type=1400 audit(1721991295.021:4819): apparmor="DENIED" operation="mount" class="mount" info="failed perms check" error=-13 profile="lxd-or_</var/snap/lxd/common/lxd>" name="/dev/" pid=145651 comm="(sd-mkdcreds)" flags="rw, rslave"
[15671.683716] audit: type=1400 audit(1721991295.029:4820): apparmor="DENIED" operation="mount" class="mount" info="failed perms check" error=-13 profile="lxd-or_</var/snap/lxd/common/lxd>" name="/run/systemd/mount-rootfs/" pid=145654 comm="(d-logind)" srcname="/" flags="rw, rbind"
[15671.686683] audit: type=1400 audit(1721991295.033:4821): apparmor="DENIED" operation="mount" class="mount" info="failed perms check" error=-13 profile="lxd-or_</var/snap/lxd/common/lxd>" name="/dev/" pid=145658 comm="(sd-mkdcreds)" flags="rw, rslave"
[15671.692154] audit: type=1400 audit(1721991295.037:4822): apparmor="DENIED" operation="mount" class="mount" info="failed perms check" error=-13 profile="lxd-or_</var/snap/lxd/common/lxd>" name="/run/systemd/mount-rootfs/" pid=145659 comm="(d-logind)" srcname="/" flags="rw, rbind"

This thing wants a recursive bind-mount of / to /run/systemd/mount-rootfs/. While it's perfectly safe for unprivileged containers, we can't allow it for privileged ones. It would be a security breach.

We have this commit in our imagebuilder canonical/lxd-imagebuilder@c928d22 and taking into account that images:debian/sid container works with security.privileged=true I would just apply the same quirk to the Ubuntu images.

@tomponline
Copy link
Member

Have asked CPC about being able to apply a similar fix as canonical/lxd-imagebuilder@c928d22 to ubuntu: images.

https://chat.canonical.com/canonical/pl/dygqosfbp3gy3x7hcs5ssergoy

@tomponline
Copy link
Member

@mihalicyn does this fix rely on the apparmor parser version in core24?

@mihalicyn
Copy link
Member Author

mihalicyn commented Jul 26, 2024

@mihalicyn does this fix rely on the apparmor parser version in core24?

yes, but we don't need core24 itself.

Full list of changes we need to backport:

  1. snapcraft: add apparmor part for core22 only (5.0-edge) lxd-pkg-snap#477
  2. Instance: Allow nosymfollow mount flag for container apparmor profile #13681
  3. Container: Allow apparmor nosymfollow mount flag in more cases #13820
    (optional) Container: fix all apparmor ro+remount rules #13826

tomponline pushed a commit to tomponline/lxd that referenced this issue Aug 2, 2024
It turns out, that a ruleset:
{{- if .feature_mount_nosymfollow }}
  # see canonical#12698
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /[^spd]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /d[^e]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /de[^v]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /dev/.[^l]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /dev/.l[^x]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /dev/.lx[^c]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /dev/.lxc?*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /dev/[^.]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /dev?*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /p[^r]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /pr[^o]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /pro[^c]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /proc?*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /s[^y]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /sy[^s]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /sys?*{,/**},
{{- end }}

is not enough to allow nosymfollow. We still getting AppArmor denials like this:
[110841.647871] audit: type=1400 audit(1721910063.197:1611): apparmor="DENIED" operation="mount"
class="mount" info="failed flags match" error=-13 profile="lxd-secure-oriole_</var/snap/lxd/common/lxd>" name="/dev/shm/"
pid=712867 comm="(sd-mkdcreds)" flags="ro, nosuid, nodev, noexec, remount, bind"

First of all, there is no "nosymfollow" in the kernel log. Which is a bug and should be fixed by:
https://lore.kernel.org/all/[email protected]/

Secondly, it looks like these rules in the form of
mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /some/path,

just does not work at all. At least in AppArmor 4.0+ (have not yet tested with older ones).

During my local experiments, I found that working variant of it might be:
mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) -> /some/path,

or wider:
mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow),

Let's just add a wider variant of the rule in addition to what we already
have for unprivileged containers. But keep in mind that something is wrong with
these rules in their more restrictive form (with path specifier). This is a matter
of a futher investigation, because it's important for privileged containers case.

See also:
canonical#12698

Closes canonical#12698
May close canonical#13810

Signed-off-by: Alexander Mikhalitsyn <[email protected]>
tomponline pushed a commit to tomponline/lxd that referenced this issue Aug 2, 2024
While investigating canonical#13810 I found that all ro+remount rules in the form:

mount options=(ro,remount,bind,A,B,C) /some_pattern{,/**},

just does not work at all. This remount+bind case is a very special one,
and we should rewrite all rules in this form:

mount options=(ro,remount,bind,A,B,C) -> /some_pattern{,/**},

This syntax is not new. This change should be compatible with very old
AppArmor versions including 2.11.

Explanation why it was not noticed for years is that for unprivileged
container case we have analogical rule but in a wider form:

mount options=(ro,remount,bind,nodev,A,B,C),

which masks the issue. But for privileged containers it's not.

So, let's fix this for correctness.

Signed-off-by: Alexander Mikhalitsyn <[email protected]>
@tomponline
Copy link
Member

thanks @mihalicyn

I've added the vendored apparmor parser and your fixes as cherry-picks to latest/stable now.

@tomponline tomponline changed the title LXD container issues with Ubuntu Oracular systemd version 256-1ubuntu1 Container issues with Ubuntu Oracular systemd version 256-1ubuntu1 Aug 5, 2024
@tomponline
Copy link
Member

tomponline commented Aug 21, 2024

We are rolling out fixes to 5.21/stable for this now (snap refresh lxd --channel=5.21/stable --cohort="+" will get it by bypassing progressive rollout).

tomponline pushed a commit to tomponline/lxd that referenced this issue Sep 13, 2024
It turns out, that a ruleset:
{{- if .feature_mount_nosymfollow }}
  # see canonical#12698
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /[^spd]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /d[^e]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /de[^v]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /dev/.[^l]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /dev/.l[^x]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /dev/.lx[^c]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /dev/.lxc?*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /dev/[^.]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /dev?*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /p[^r]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /pr[^o]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /pro[^c]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /proc?*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /s[^y]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /sy[^s]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /sys?*{,/**},
{{- end }}

is not enough to allow nosymfollow. We still getting AppArmor denials like this:
[110841.647871] audit: type=1400 audit(1721910063.197:1611): apparmor="DENIED" operation="mount"
class="mount" info="failed flags match" error=-13 profile="lxd-secure-oriole_</var/snap/lxd/common/lxd>" name="/dev/shm/"
pid=712867 comm="(sd-mkdcreds)" flags="ro, nosuid, nodev, noexec, remount, bind"

First of all, there is no "nosymfollow" in the kernel log. Which is a bug and should be fixed by:
https://lore.kernel.org/all/[email protected]/

Secondly, it looks like these rules in the form of
mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /some/path,

just does not work at all. At least in AppArmor 4.0+ (have not yet tested with older ones).

During my local experiments, I found that working variant of it might be:
mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) -> /some/path,

or wider:
mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow),

Let's just add a wider variant of the rule in addition to what we already
have for unprivileged containers. But keep in mind that something is wrong with
these rules in their more restrictive form (with path specifier). This is a matter
of a futher investigation, because it's important for privileged containers case.

See also:
canonical#12698

Closes canonical#12698
May close canonical#13810

Signed-off-by: Alexander Mikhalitsyn <[email protected]>
tomponline pushed a commit to tomponline/lxd that referenced this issue Sep 13, 2024
While investigating canonical#13810 I found that all ro+remount rules in the form:

mount options=(ro,remount,bind,A,B,C) /some_pattern{,/**},

just does not work at all. This remount+bind case is a very special one,
and we should rewrite all rules in this form:

mount options=(ro,remount,bind,A,B,C) -> /some_pattern{,/**},

This syntax is not new. This change should be compatible with very old
AppArmor versions including 2.11.

Explanation why it was not noticed for years is that for unprivileged
container case we have analogical rule but in a wider form:

mount options=(ro,remount,bind,nodev,A,B,C),

which masks the issue. But for privileged containers it's not.

So, let's fix this for correctness.

Signed-off-by: Alexander Mikhalitsyn <[email protected]>
tomponline pushed a commit to tomponline/lxd that referenced this issue Sep 13, 2024
It turns out, that a ruleset:
{{- if .feature_mount_nosymfollow }}
  # see canonical#12698
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /[^spd]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /d[^e]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /de[^v]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /dev/.[^l]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /dev/.l[^x]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /dev/.lx[^c]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /dev/.lxc?*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /dev/[^.]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /dev?*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /p[^r]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /pr[^o]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /pro[^c]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /proc?*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /s[^y]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /sy[^s]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /sys?*{,/**},
{{- end }}

is not enough to allow nosymfollow. We still getting AppArmor denials like this:
[110841.647871] audit: type=1400 audit(1721910063.197:1611): apparmor="DENIED" operation="mount"
class="mount" info="failed flags match" error=-13 profile="lxd-secure-oriole_</var/snap/lxd/common/lxd>" name="/dev/shm/"
pid=712867 comm="(sd-mkdcreds)" flags="ro, nosuid, nodev, noexec, remount, bind"

First of all, there is no "nosymfollow" in the kernel log. Which is a bug and should be fixed by:
https://lore.kernel.org/all/[email protected]/

Secondly, it looks like these rules in the form of
mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /some/path,

just does not work at all. At least in AppArmor 4.0+ (have not yet tested with older ones).

During my local experiments, I found that working variant of it might be:
mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) -> /some/path,

or wider:
mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow),

Let's just add a wider variant of the rule in addition to what we already
have for unprivileged containers. But keep in mind that something is wrong with
these rules in their more restrictive form (with path specifier). This is a matter
of a futher investigation, because it's important for privileged containers case.

See also:
canonical#12698

Closes canonical#12698
May close canonical#13810

Signed-off-by: Alexander Mikhalitsyn <[email protected]>
tomponline pushed a commit to tomponline/lxd that referenced this issue Sep 13, 2024
While investigating canonical#13810 I found that all ro+remount rules in the form:

mount options=(ro,remount,bind,A,B,C) /some_pattern{,/**},

just does not work at all. This remount+bind case is a very special one,
and we should rewrite all rules in this form:

mount options=(ro,remount,bind,A,B,C) -> /some_pattern{,/**},

This syntax is not new. This change should be compatible with very old
AppArmor versions including 2.11.

Explanation why it was not noticed for years is that for unprivileged
container case we have analogical rule but in a wider form:

mount options=(ro,remount,bind,nodev,A,B,C),

which masks the issue. But for privileged containers it's not.

So, let's fix this for correctness.

Signed-off-by: Alexander Mikhalitsyn <[email protected]>
tomponline pushed a commit to tomponline/lxd that referenced this issue Sep 13, 2024
It turns out, that a ruleset:
{{- if .feature_mount_nosymfollow }}
  # see canonical#12698
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /[^spd]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /d[^e]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /de[^v]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /dev/.[^l]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /dev/.l[^x]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /dev/.lx[^c]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /dev/.lxc?*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /dev/[^.]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /dev?*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /p[^r]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /pr[^o]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /pro[^c]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /proc?*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /s[^y]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /sy[^s]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /sys?*{,/**},
{{- end }}

is not enough to allow nosymfollow. We still getting AppArmor denials like this:
[110841.647871] audit: type=1400 audit(1721910063.197:1611): apparmor="DENIED" operation="mount"
class="mount" info="failed flags match" error=-13 profile="lxd-secure-oriole_</var/snap/lxd/common/lxd>" name="/dev/shm/"
pid=712867 comm="(sd-mkdcreds)" flags="ro, nosuid, nodev, noexec, remount, bind"

First of all, there is no "nosymfollow" in the kernel log. Which is a bug and should be fixed by:
https://lore.kernel.org/all/[email protected]/

Secondly, it looks like these rules in the form of
mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /some/path,

just does not work at all. At least in AppArmor 4.0+ (have not yet tested with older ones).

During my local experiments, I found that working variant of it might be:
mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) -> /some/path,

or wider:
mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow),

Let's just add a wider variant of the rule in addition to what we already
have for unprivileged containers. But keep in mind that something is wrong with
these rules in their more restrictive form (with path specifier). This is a matter
of a futher investigation, because it's important for privileged containers case.

See also:
canonical#12698

Closes canonical#12698
May close canonical#13810

Signed-off-by: Alexander Mikhalitsyn <[email protected]>
tomponline pushed a commit to tomponline/lxd that referenced this issue Sep 13, 2024
While investigating canonical#13810 I found that all ro+remount rules in the form:

mount options=(ro,remount,bind,A,B,C) /some_pattern{,/**},

just does not work at all. This remount+bind case is a very special one,
and we should rewrite all rules in this form:

mount options=(ro,remount,bind,A,B,C) -> /some_pattern{,/**},

This syntax is not new. This change should be compatible with very old
AppArmor versions including 2.11.

Explanation why it was not noticed for years is that for unprivileged
container case we have analogical rule but in a wider form:

mount options=(ro,remount,bind,nodev,A,B,C),

which masks the issue. But for privileged containers it's not.

So, let's fix this for correctness.

Signed-off-by: Alexander Mikhalitsyn <[email protected]>
tomponline pushed a commit to tomponline/lxd that referenced this issue Sep 13, 2024
It turns out, that a ruleset:
{{- if .feature_mount_nosymfollow }}
  # see canonical#12698
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /[^spd]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /d[^e]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /de[^v]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /dev/.[^l]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /dev/.l[^x]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /dev/.lx[^c]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /dev/.lxc?*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /dev/[^.]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /dev?*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /p[^r]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /pr[^o]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /pro[^c]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /proc?*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /s[^y]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /sy[^s]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /sys?*{,/**},
{{- end }}

is not enough to allow nosymfollow. We still getting AppArmor denials like this:
[110841.647871] audit: type=1400 audit(1721910063.197:1611): apparmor="DENIED" operation="mount"
class="mount" info="failed flags match" error=-13 profile="lxd-secure-oriole_</var/snap/lxd/common/lxd>" name="/dev/shm/"
pid=712867 comm="(sd-mkdcreds)" flags="ro, nosuid, nodev, noexec, remount, bind"

First of all, there is no "nosymfollow" in the kernel log. Which is a bug and should be fixed by:
https://lore.kernel.org/all/[email protected]/

Secondly, it looks like these rules in the form of
mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /some/path,

just does not work at all. At least in AppArmor 4.0+ (have not yet tested with older ones).

During my local experiments, I found that working variant of it might be:
mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) -> /some/path,

or wider:
mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow),

Let's just add a wider variant of the rule in addition to what we already
have for unprivileged containers. But keep in mind that something is wrong with
these rules in their more restrictive form (with path specifier). This is a matter
of a futher investigation, because it's important for privileged containers case.

See also:
canonical#12698

Closes canonical#12698
May close canonical#13810

Signed-off-by: Alexander Mikhalitsyn <[email protected]>
tomponline pushed a commit to tomponline/lxd that referenced this issue Sep 13, 2024
While investigating canonical#13810 I found that all ro+remount rules in the form:

mount options=(ro,remount,bind,A,B,C) /some_pattern{,/**},

just does not work at all. This remount+bind case is a very special one,
and we should rewrite all rules in this form:

mount options=(ro,remount,bind,A,B,C) -> /some_pattern{,/**},

This syntax is not new. This change should be compatible with very old
AppArmor versions including 2.11.

Explanation why it was not noticed for years is that for unprivileged
container case we have analogical rule but in a wider form:

mount options=(ro,remount,bind,nodev,A,B,C),

which masks the issue. But for privileged containers it's not.

So, let's fix this for correctness.

Signed-off-by: Alexander Mikhalitsyn <[email protected]>
tomponline pushed a commit to tomponline/lxd that referenced this issue Sep 13, 2024
It turns out, that a ruleset:
{{- if .feature_mount_nosymfollow }}
  # see canonical#12698
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /[^spd]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /d[^e]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /de[^v]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /dev/.[^l]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /dev/.l[^x]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /dev/.lx[^c]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /dev/.lxc?*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /dev/[^.]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /dev?*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /p[^r]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /pr[^o]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /pro[^c]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /proc?*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /s[^y]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /sy[^s]*{,/**},
  mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /sys?*{,/**},
{{- end }}

is not enough to allow nosymfollow. We still getting AppArmor denials like this:
[110841.647871] audit: type=1400 audit(1721910063.197:1611): apparmor="DENIED" operation="mount"
class="mount" info="failed flags match" error=-13 profile="lxd-secure-oriole_</var/snap/lxd/common/lxd>" name="/dev/shm/"
pid=712867 comm="(sd-mkdcreds)" flags="ro, nosuid, nodev, noexec, remount, bind"

First of all, there is no "nosymfollow" in the kernel log. Which is a bug and should be fixed by:
https://lore.kernel.org/all/[email protected]/

Secondly, it looks like these rules in the form of
mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) /some/path,

just does not work at all. At least in AppArmor 4.0+ (have not yet tested with older ones).

During my local experiments, I found that working variant of it might be:
mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow) -> /some/path,

or wider:
mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow),

Let's just add a wider variant of the rule in addition to what we already
have for unprivileged containers. But keep in mind that something is wrong with
these rules in their more restrictive form (with path specifier). This is a matter
of a futher investigation, because it's important for privileged containers case.

See also:
canonical#12698

Closes canonical#12698
May close canonical#13810

Signed-off-by: Alexander Mikhalitsyn <[email protected]>
(cherry picked from commit 86c3d51)
tomponline pushed a commit to tomponline/lxd that referenced this issue Sep 13, 2024
While investigating canonical#13810 I found that all ro+remount rules in the form:

mount options=(ro,remount,bind,A,B,C) /some_pattern{,/**},

just does not work at all. This remount+bind case is a very special one,
and we should rewrite all rules in this form:

mount options=(ro,remount,bind,A,B,C) -> /some_pattern{,/**},

This syntax is not new. This change should be compatible with very old
AppArmor versions including 2.11.

Explanation why it was not noticed for years is that for unprivileged
container case we have analogical rule but in a wider form:

mount options=(ro,remount,bind,nodev,A,B,C),

which masks the issue. But for privileged containers it's not.

So, let's fix this for correctness.

Signed-off-by: Alexander Mikhalitsyn <[email protected]>
(cherry picked from commit 047d3f5)
@tomponline
Copy link
Member

@mihalicyn please can you verify that Oracular is working on Jammy host with 5.0/edge channel, if so then we can close this as the fix will be included in LXD 5.0.4 Thanks

@mihalicyn
Copy link
Member Author

I can confirm that it works for me well on 5.0/edge with Ubuntu Jammy host.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug Confirmed to be a bug
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants