[v2] tests: gracefully handle AppArmor userns containment
Checks
Context |
Check |
Description |
redhat-pt-bot/TryBot-apply_patch |
success
|
Patch applied to master at the time it was sent
|
linaro-tcwg-bot/tcwg_glibc_build--master-aarch64 |
success
|
Testing passed
|
redhat-pt-bot/TryBot-32bit |
success
|
Build for i686
|
linaro-tcwg-bot/tcwg_glibc_check--master-aarch64 |
success
|
Testing passed
|
linaro-tcwg-bot/tcwg_glibc_build--master-arm |
success
|
Testing passed
|
linaro-tcwg-bot/tcwg_glibc_check--master-arm |
success
|
Testing passed
|
Commit Message
Recent AppArmor containment allows restricting unprivileged user
namespaces, which is enabled by default on recent Ubuntu systems.
When that happens, the affected tests will now be considered unsupported
rather than simply failing.
Further information:
* https://gitlab.com/apparmor/apparmor/-/wikis/unprivileged_userns_restriction
* https://ubuntu.com/blog/ubuntu-23-10-restricted-unprivileged-user-namespaces
V2:
* Fix duplicated line in check_unshare_hints
* Also handle similar failure in tst-pidfd_getpid
Signed-off-by: Simon Chopin <simon.chopin@canonical.com>
---
support/test-container.c | 7 +++++--
sysdeps/unix/sysv/linux/tst-pidfd_getpid.c | 3 ++-
2 files changed, 7 insertions(+), 3 deletions(-)
base-commit: fa3eb7d5e7d32ca1ad48b48a7eb6d15b8382c3a7
Comments
> On Feb 6, 2024, at 14:59, Simon Chopin <simon.chopin@canonical.com> wrote:
>
> Recent AppArmor containment allows restricting unprivileged user
> namespaces, which is enabled by default on recent Ubuntu systems.
>
> When that happens, the affected tests will now be considered unsupported
> rather than simply failing.
>
> Further information:
>
> * https://gitlab.com/apparmor/apparmor/-/wikis/unprivileged_userns_restriction
> * https://ubuntu.com/blog/ubuntu-23-10-restricted-unprivileged-user-namespaces
>
> V2:
> * Fix duplicated line in check_unshare_hints
> * Also handle similar failure in tst-pidfd_getpid
Looks good, with below comments addressed.
Please CC reviewers of the previous versions of the patch -- Xi Ruoyao in this case.
>
> Signed-off-by: Simon Chopin <simon.chopin@canonical.com>
> ---
> support/test-container.c | 7 +++++--
> sysdeps/unix/sysv/linux/tst-pidfd_getpid.c | 3 ++-
> 2 files changed, 7 insertions(+), 3 deletions(-)
>
> diff --git a/support/test-container.c b/support/test-container.c
> index adf2b30215..af66cece51 100644
> --- a/support/test-container.c
> +++ b/support/test-container.c
> @@ -682,6 +682,8 @@ check_for_unshare_hints (int require_pidns)
> { "/proc/sys/kernel/unprivileged_userns_clone", 0, 1, 0 },
> /* ALT Linux has an alternate way of doing the same. */
> { "/proc/sys/kernel/userns_restrict", 1, 0, 0 },
> + /* AppArmor can also disable unprivileged user namespaces */
GNU coding style is to finish comment sentences with a dot, followed by two spaces. E.g.,
/* My new comment. */
> + { "/proc/sys/kernel/apparmor_restrict_unprivileged_userns", 1, 0, 0 },
> /* Linux kernel >= 4.9 has a configurable limit on the number of
> each namespace. Some distros set the limit to zero to disable the
> corresponding namespace as a "security policy". */
> @@ -1108,10 +1110,11 @@ main (int argc, char **argv)
> {
> /* Older kernels may not support all the options, or security
> policy may block this call. */
> - if (errno == EINVAL || errno == EPERM || errno == ENOSPC)
> + if (errno == EINVAL || errno == EPERM
> + || errno == ENOSPC || errno == EACCES)
Where is EACCES coming from? I could not find documentation mentioning EACCES as a possible error condition for unshare().
> {
> int saved_errno = errno;
> - if (errno == EPERM || errno == ENOSPC)
> + if (errno == EPERM || errno == ENOSPC || errno == EACCES)
> check_for_unshare_hints (require_pidns);
> FAIL_UNSUPPORTED ("unable to unshare user/fs: %s", strerror (saved_errno));
> }
> diff --git a/sysdeps/unix/sysv/linux/tst-pidfd_getpid.c b/sysdeps/unix/sysv/linux/tst-pidfd_getpid.c
> index 0354da5abb..ef62fbe941 100644
> --- a/sysdeps/unix/sysv/linux/tst-pidfd_getpid.c
> +++ b/sysdeps/unix/sysv/linux/tst-pidfd_getpid.c
> @@ -61,7 +61,8 @@ do_test (void)
> {
> /* Older kernels may not support all the options, or security
> policy may block this call. */
> - if (errno == EINVAL || errno == EPERM || errno == ENOSPC)
> + if (errno == EINVAL || errno == EPERM
> + || errno == ENOSPC || errno == EACCES)
> exit (EXIT_UNSUPPORTED);
> FAIL_EXIT1 ("unshare user/fs/pid failed: %m");
> }
>
> base-commit: fa3eb7d5e7d32ca1ad48b48a7eb6d15b8382c3a7
> --
> 2.40.1
>
Thanks,
--
Maxim Kuvyrkov
https://www.linaro.org
* Maxim Kuvyrkov:
> Where is EACCES coming from? I could not find documentation
> mentioning EACCES as a possible error condition for unshare().
Presumably a seccomp filter or a Linux security module. We don't do
that error code translation in the main library (e.g., for clone3), but
it has crept into the test suite over time.
Thanks,
Florian
Hi Maxim,
On mar. 13 févr. 2024 11:36:34, Maxim Kuvyrkov wrote:
> > On Feb 6, 2024, at 14:59, Simon Chopin <simon.chopin@canonical.com> wrote:
> >
> > Recent AppArmor containment allows restricting unprivileged user
> > namespaces, which is enabled by default on recent Ubuntu systems.
> >
> > When that happens, the affected tests will now be considered unsupported
> > rather than simply failing.
> >
> > Further information:
> >
> > * https://gitlab.com/apparmor/apparmor/-/wikis/unprivileged_userns_restriction
> > * https://ubuntu.com/blog/ubuntu-23-10-restricted-unprivileged-user-namespaces
> >
> > V2:
> > * Fix duplicated line in check_unshare_hints
> > * Also handle similar failure in tst-pidfd_getpid
>
> Looks good, with below comments addressed.
>
> Please CC reviewers of the previous versions of the patch -- Xi Ruoyao in this case.
ACK
>
> >
> > Signed-off-by: Simon Chopin <simon.chopin@canonical.com>
> > ---
> > support/test-container.c | 7 +++++--
> > sysdeps/unix/sysv/linux/tst-pidfd_getpid.c | 3 ++-
> > 2 files changed, 7 insertions(+), 3 deletions(-)
> >
> > diff --git a/support/test-container.c b/support/test-container.c
> > index adf2b30215..af66cece51 100644
> > --- a/support/test-container.c
> > +++ b/support/test-container.c
> > @@ -682,6 +682,8 @@ check_for_unshare_hints (int require_pidns)
> > { "/proc/sys/kernel/unprivileged_userns_clone", 0, 1, 0 },
> > /* ALT Linux has an alternate way of doing the same. */
> > { "/proc/sys/kernel/userns_restrict", 1, 0, 0 },
> > + /* AppArmor can also disable unprivileged user namespaces */
>
> GNU coding style is to finish comment sentences with a dot, followed by two spaces. E.g.,
> /* My new comment. */
ACK
>
> > + { "/proc/sys/kernel/apparmor_restrict_unprivileged_userns", 1, 0, 0 },
> > /* Linux kernel >= 4.9 has a configurable limit on the number of
> > each namespace. Some distros set the limit to zero to disable the
> > corresponding namespace as a "security policy". */
> > @@ -1108,10 +1110,11 @@ main (int argc, char **argv)
> > {
> > /* Older kernels may not support all the options, or security
> > policy may block this call. */
> > - if (errno == EINVAL || errno == EPERM || errno == ENOSPC)
> > + if (errno == EINVAL || errno == EPERM
> > + || errno == ENOSPC || errno == EACCES)
>
> Where is EACCES coming from? I could not find documentation mentioning EACCES as a possible error condition for unshare().
This is injected by AppArmor when it prevents a syscall. According to
coworkers it's a fairly standard value for LSM modules, and some cursory
code source sleuthing goes in that sense, but the only instance of
actual documentation that mentions this is a mention in passing in
https://manpages.ubuntu.com/manpages/jammy/man5/apparmor.d.5.html
I'll add some more info about it in the commit log.
>
> > {
> > int saved_errno = errno;
> > - if (errno == EPERM || errno == ENOSPC)
> > + if (errno == EPERM || errno == ENOSPC || errno == EACCES)
> > check_for_unshare_hints (require_pidns);
> > FAIL_UNSUPPORTED ("unable to unshare user/fs: %s", strerror (saved_errno));
> > }
> > diff --git a/sysdeps/unix/sysv/linux/tst-pidfd_getpid.c b/sysdeps/unix/sysv/linux/tst-pidfd_getpid.c
> > index 0354da5abb..ef62fbe941 100644
> > --- a/sysdeps/unix/sysv/linux/tst-pidfd_getpid.c
> > +++ b/sysdeps/unix/sysv/linux/tst-pidfd_getpid.c
> > @@ -61,7 +61,8 @@ do_test (void)
> > {
> > /* Older kernels may not support all the options, or security
> > policy may block this call. */
> > - if (errno == EINVAL || errno == EPERM || errno == ENOSPC)
> > + if (errno == EINVAL || errno == EPERM
> > + || errno == ENOSPC || errno == EACCES)
> > exit (EXIT_UNSUPPORTED);
> > FAIL_EXIT1 ("unshare user/fs/pid failed: %m");
> > }
> >
> > base-commit: fa3eb7d5e7d32ca1ad48b48a7eb6d15b8382c3a7
> > --
> > 2.40.1
> >
>
> Thanks,
>
> --
> Maxim Kuvyrkov
> https://www.linaro.org
>
>
@@ -682,6 +682,8 @@ check_for_unshare_hints (int require_pidns)
{ "/proc/sys/kernel/unprivileged_userns_clone", 0, 1, 0 },
/* ALT Linux has an alternate way of doing the same. */
{ "/proc/sys/kernel/userns_restrict", 1, 0, 0 },
+ /* AppArmor can also disable unprivileged user namespaces */
+ { "/proc/sys/kernel/apparmor_restrict_unprivileged_userns", 1, 0, 0 },
/* Linux kernel >= 4.9 has a configurable limit on the number of
each namespace. Some distros set the limit to zero to disable the
corresponding namespace as a "security policy". */
@@ -1108,10 +1110,11 @@ main (int argc, char **argv)
{
/* Older kernels may not support all the options, or security
policy may block this call. */
- if (errno == EINVAL || errno == EPERM || errno == ENOSPC)
+ if (errno == EINVAL || errno == EPERM
+ || errno == ENOSPC || errno == EACCES)
{
int saved_errno = errno;
- if (errno == EPERM || errno == ENOSPC)
+ if (errno == EPERM || errno == ENOSPC || errno == EACCES)
check_for_unshare_hints (require_pidns);
FAIL_UNSUPPORTED ("unable to unshare user/fs: %s", strerror (saved_errno));
}
@@ -61,7 +61,8 @@ do_test (void)
{
/* Older kernels may not support all the options, or security
policy may block this call. */
- if (errno == EINVAL || errno == EPERM || errno == ENOSPC)
+ if (errno == EINVAL || errno == EPERM
+ || errno == ENOSPC || errno == EACCES)
exit (EXIT_UNSUPPORTED);
FAIL_EXIT1 ("unshare user/fs/pid failed: %m");
}