[v2] tests: gracefully handle AppArmor userns containment

Message ID 20240206105932.127820-1-simon.chopin@canonical.com
State Superseded
Delegated to: Maxim Kuvyrkov
Headers
Series [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

Simon Chopin Feb. 6, 2024, 10:59 a.m. UTC
  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

Maxim Kuvyrkov Feb. 13, 2024, 7:36 a.m. UTC | #1
> 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
  
Florian Weimer Feb. 14, 2024, 7:53 a.m. UTC | #2
* 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
  
Simon Chopin Feb. 16, 2024, 3:57 p.m. UTC | #3
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
>
>
  

Patch

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 */
+    { "/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));
 	}
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");
 	  }