diff mbox series

sanity: check for working user namespaces

Message ID 20240912165736.1531460-1-ross.burton@arm.com
State New
Headers show
Series sanity: check for working user namespaces | expand

Commit Message

Ross Burton Sept. 12, 2024, 4:57 p.m. UTC
If user namespaces are not available (typically because AppArmor is
blocking them), alert the user.

We consider network isolation sufficiently important that this is a fatal
error, and the user will need to configure AppArmor to allow bitbake to
create a user namespace.

[ YOCTO #15592 ]

Signed-off-by: Ross Burton <ross.burton@arm.com>
---
 meta/classes-global/sanity.bbclass | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

Comments

Ross Burton Sept. 12, 2024, 4:59 p.m. UTC | #1
Note that in its final form this isn’t had any testing on an Ubuntu machine, so testing would be appreciated if anyone has an Ubuntu 24.x machine (not a container, need their kernel) with apparmor enabled.

Thanks,
Ross

> On 12 Sep 2024, at 17:57, Ross Burton via lists.openembedded.org <ross.burton=arm.com@lists.openembedded.org> wrote:
> 
> If user namespaces are not available (typically because AppArmor is
> blocking them), alert the user.
> 
> We consider network isolation sufficiently important that this is a fatal
> error, and the user will need to configure AppArmor to allow bitbake to
> create a user namespace.
> 
> [ YOCTO #15592 ]
> 
> Signed-off-by: Ross Burton <ross.burton@arm.com>
> ---
> meta/classes-global/sanity.bbclass | 24 ++++++++++++++++++++++++
> 1 file changed, 24 insertions(+)
> 
> diff --git a/meta/classes-global/sanity.bbclass b/meta/classes-global/sanity.bbclass
> index 1d242f0f0a0..72dab0fea2b 100644
> --- a/meta/classes-global/sanity.bbclass
> +++ b/meta/classes-global/sanity.bbclass
> @@ -475,6 +475,29 @@ def check_wsl(d):
>             bb.warn("You are running bitbake under WSLv2, this works properly but you should optimize your VHDX file eventually to avoid running out of storage space")
>     return None
> 
> +def check_userns():
> +    """
> +    Check that user namespaces are functional, as they're used for network isolation.
> +    """
> +
> +    # There is a known failure case with AppAmrmor where the unshare() call
> +    # succeeds (at which point the uid is nobody) but writing to the uid_map
> +    # fails (so the uid isn't reset back to the user's uid). We can detect this.
> +    parentuid = os.getuid()
> +    pid = os.fork()
> +    if not pid:
> +        try:
> +            bb.utils.disable_network()
> +        except:
> +            pass
> +        os._exit(parentuid != os.getuid())
> +
> +    ret = os.waitpid(pid, 0)[1]
> +    if ret:
> +        bb.fatal("User namespaces are not usable by BitBake, possibly due to AppArmor.\n"
> +                 "See https://discourse.ubuntu.com/t/ubuntu-24-04-lts-noble-numbat-release-notes/39890#unprivileged-user-namespace-restrictions for more information.")
> +
> +
> # Require at least gcc version 8.0
> #
> # This can be fixed on CentOS-7 with devtoolset-6+
> @@ -641,6 +664,7 @@ def check_sanity_version_change(status, d):
>     status.addresult(check_git_version(d))
>     status.addresult(check_perl_modules(d))
>     status.addresult(check_wsl(d))
> +    status.addresult(check_userns())
> 
>     missing = ""
> 
> -- 
> 2.34.1
> 
> 
> -=-=-=-=-=-=-=-=-=-=-=-
> Links: You receive all messages sent to this group.
> View/Reply Online (#204449): https://lists.openembedded.org/g/openembedded-core/message/204449
> Mute This Topic: https://lists.openembedded.org/mt/108416977/6875888
> Group Owner: openembedded-core+owner@lists.openembedded.org
> Unsubscribe: https://lists.openembedded.org/g/openembedded-core/unsub [ross.burton@arm.com]
> -=-=-=-=-=-=-=-=-=-=-=-
>
Martin Jansa Sept. 12, 2024, 5:22 p.m. UTC | #2
Works as expected, the build failed :).

openembedded-core/build$ bitbake -k zlib-native
ERROR: User namespaces are not usable by BitBake, possibly due to AppArmor.
See https://discourse.ubuntu.com/t/ubuntu-24-04-lts-noble-numbat-release-notes/39890#unprivileged-user-namespace-restrictions
for more information.

The only issue might be that these checks are executed only once, so
if you have existing TMPDIR (where it was failing) then it will
continue failing with:

ERROR: PermissionError: [Errno 1] Operation not permitted

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/martin/work/bitbake/bin/bitbake-worker", line 278, in child
    bb.utils.disable_network(uid, gid)
  File "/home/martin/work/bitbake/lib/bb/utils.py", line 1696, in
disable_network
    with open("/proc/self/uid_map", "w") as f:
PermissionError: [Errno 1] Operation not permitted

until TMPDIR is removed and sanity re-executed.

On Thu, Sep 12, 2024 at 6:59 PM Ross Burton via lists.openembedded.org
<ross.burton=arm.com@lists.openembedded.org> wrote:
>
> Note that in its final form this isn’t had any testing on an Ubuntu machine, so testing would be appreciated if anyone has an Ubuntu 24.x machine (not a container, need their kernel) with apparmor enabled.
>
> Thanks,
> Ross
>
> > On 12 Sep 2024, at 17:57, Ross Burton via lists.openembedded.org <ross.burton=arm.com@lists.openembedded.org> wrote:
> >
> > If user namespaces are not available (typically because AppArmor is
> > blocking them), alert the user.
> >
> > We consider network isolation sufficiently important that this is a fatal
> > error, and the user will need to configure AppArmor to allow bitbake to
> > create a user namespace.
> >
> > [ YOCTO #15592 ]
> >
> > Signed-off-by: Ross Burton <ross.burton@arm.com>
> > ---
> > meta/classes-global/sanity.bbclass | 24 ++++++++++++++++++++++++
> > 1 file changed, 24 insertions(+)
> >
> > diff --git a/meta/classes-global/sanity.bbclass b/meta/classes-global/sanity.bbclass
> > index 1d242f0f0a0..72dab0fea2b 100644
> > --- a/meta/classes-global/sanity.bbclass
> > +++ b/meta/classes-global/sanity.bbclass
> > @@ -475,6 +475,29 @@ def check_wsl(d):
> >             bb.warn("You are running bitbake under WSLv2, this works properly but you should optimize your VHDX file eventually to avoid running out of storage space")
> >     return None
> >
> > +def check_userns():
> > +    """
> > +    Check that user namespaces are functional, as they're used for network isolation.
> > +    """
> > +
> > +    # There is a known failure case with AppAmrmor where the unshare() call
> > +    # succeeds (at which point the uid is nobody) but writing to the uid_map
> > +    # fails (so the uid isn't reset back to the user's uid). We can detect this.
> > +    parentuid = os.getuid()
> > +    pid = os.fork()
> > +    if not pid:
> > +        try:
> > +            bb.utils.disable_network()
> > +        except:
> > +            pass
> > +        os._exit(parentuid != os.getuid())
> > +
> > +    ret = os.waitpid(pid, 0)[1]
> > +    if ret:
> > +        bb.fatal("User namespaces are not usable by BitBake, possibly due to AppArmor.\n"
> > +                 "See https://discourse.ubuntu.com/t/ubuntu-24-04-lts-noble-numbat-release-notes/39890#unprivileged-user-namespace-restrictions for more information.")
> > +
> > +
> > # Require at least gcc version 8.0
> > #
> > # This can be fixed on CentOS-7 with devtoolset-6+
> > @@ -641,6 +664,7 @@ def check_sanity_version_change(status, d):
> >     status.addresult(check_git_version(d))
> >     status.addresult(check_perl_modules(d))
> >     status.addresult(check_wsl(d))
> > +    status.addresult(check_userns())
> >
> >     missing = ""
> >
> > --
> > 2.34.1
> >
> >
> >
> >
>
>
> -=-=-=-=-=-=-=-=-=-=-=-
> Links: You receive all messages sent to this group.
> View/Reply Online (#204450): https://lists.openembedded.org/g/openembedded-core/message/204450
> Mute This Topic: https://lists.openembedded.org/mt/108416977/3617156
> Group Owner: openembedded-core+owner@lists.openembedded.org
> Unsubscribe: https://lists.openembedded.org/g/openembedded-core/unsub [martin.jansa@gmail.com]
> -=-=-=-=-=-=-=-=-=-=-=-
>
Ross Burton Sept. 12, 2024, 5:28 p.m. UTC | #3
By which do you mean the build failed gracefully, whereas previously it would have exploded?

Ross

> On 12 Sep 2024, at 18:22, Martin Jansa <martin.jansa@gmail.com> wrote:
> 
> Works as expected, the build failed :).
> 
> openembedded-core/build$ bitbake -k zlib-native
> ERROR: User namespaces are not usable by BitBake, possibly due to AppArmor.
> See https://discourse.ubuntu.com/t/ubuntu-24-04-lts-noble-numbat-release-notes/39890#unprivileged-user-namespace-restrictions
> for more information.
> 
> The only issue might be that these checks are executed only once, so
> if you have existing TMPDIR (where it was failing) then it will
> continue failing with:
> 
> ERROR: PermissionError: [Errno 1] Operation not permitted
> 
> During handling of the above exception, another exception occurred:
> 
> Traceback (most recent call last):
>  File "/home/martin/work/bitbake/bin/bitbake-worker", line 278, in child
>    bb.utils.disable_network(uid, gid)
>  File "/home/martin/work/bitbake/lib/bb/utils.py", line 1696, in
> disable_network
>    with open("/proc/self/uid_map", "w") as f:
> PermissionError: [Errno 1] Operation not permitted
> 
> until TMPDIR is removed and sanity re-executed.
> 
> On Thu, Sep 12, 2024 at 6:59 PM Ross Burton via lists.openembedded.org
> <ross.burton=arm.com@lists.openembedded.org> wrote:
>> 
>> Note that in its final form this isn’t had any testing on an Ubuntu machine, so testing would be appreciated if anyone has an Ubuntu 24.x machine (not a container, need their kernel) with apparmor enabled.
>> 
>> Thanks,
>> Ross
>> 
>>> On 12 Sep 2024, at 17:57, Ross Burton via lists.openembedded.org <ross.burton=arm.com@lists.openembedded.org> wrote:
>>> 
>>> If user namespaces are not available (typically because AppArmor is
>>> blocking them), alert the user.
>>> 
>>> We consider network isolation sufficiently important that this is a fatal
>>> error, and the user will need to configure AppArmor to allow bitbake to
>>> create a user namespace.
>>> 
>>> [ YOCTO #15592 ]
>>> 
>>> Signed-off-by: Ross Burton <ross.burton@arm.com>
>>> ---
>>> meta/classes-global/sanity.bbclass | 24 ++++++++++++++++++++++++
>>> 1 file changed, 24 insertions(+)
>>> 
>>> diff --git a/meta/classes-global/sanity.bbclass b/meta/classes-global/sanity.bbclass
>>> index 1d242f0f0a0..72dab0fea2b 100644
>>> --- a/meta/classes-global/sanity.bbclass
>>> +++ b/meta/classes-global/sanity.bbclass
>>> @@ -475,6 +475,29 @@ def check_wsl(d):
>>>            bb.warn("You are running bitbake under WSLv2, this works properly but you should optimize your VHDX file eventually to avoid running out of storage space")
>>>    return None
>>> 
>>> +def check_userns():
>>> +    """
>>> +    Check that user namespaces are functional, as they're used for network isolation.
>>> +    """
>>> +
>>> +    # There is a known failure case with AppAmrmor where the unshare() call
>>> +    # succeeds (at which point the uid is nobody) but writing to the uid_map
>>> +    # fails (so the uid isn't reset back to the user's uid). We can detect this.
>>> +    parentuid = os.getuid()
>>> +    pid = os.fork()
>>> +    if not pid:
>>> +        try:
>>> +            bb.utils.disable_network()
>>> +        except:
>>> +            pass
>>> +        os._exit(parentuid != os.getuid())
>>> +
>>> +    ret = os.waitpid(pid, 0)[1]
>>> +    if ret:
>>> +        bb.fatal("User namespaces are not usable by BitBake, possibly due to AppArmor.\n"
>>> +                 "See https://discourse.ubuntu.com/t/ubuntu-24-04-lts-noble-numbat-release-notes/39890#unprivileged-user-namespace-restrictions for more information.")
>>> +
>>> +
>>> # Require at least gcc version 8.0
>>> #
>>> # This can be fixed on CentOS-7 with devtoolset-6+
>>> @@ -641,6 +664,7 @@ def check_sanity_version_change(status, d):
>>>    status.addresult(check_git_version(d))
>>>    status.addresult(check_perl_modules(d))
>>>    status.addresult(check_wsl(d))
>>> +    status.addresult(check_userns())
>>> 
>>>    missing = ""
>>> 
>>> --
>>> 2.34.1
>>> 
>>> 
>>> 
>>> 
>> 
>> 
>> -=-=-=-=-=-=-=-=-=-=-=-
>> Links: You receive all messages sent to this group.
>> View/Reply Online (#204450): https://lists.openembedded.org/g/openembedded-core/message/204450
>> Mute This Topic: https://lists.openembedded.org/mt/108416977/3617156
>> Group Owner: openembedded-core+owner@lists.openembedded.org
>> Unsubscribe: https://lists.openembedded.org/g/openembedded-core/unsub [martin.jansa@gmail.com]
>> -=-=-=-=-=-=-=-=-=-=-=-
Jose Quaresma Sept. 12, 2024, 5:29 p.m. UTC | #4
Ross Burton via lists.openembedded.org <ross.burton=
arm.com@lists.openembedded.org> escreveu (quinta, 12/09/2024 à(s) 17:57):

> If user namespaces are not available (typically because AppArmor is
> blocking them), alert the user.
>
> We consider network isolation sufficiently important that this is a fatal
> error, and the user will need to configure AppArmor to allow bitbake to
> create a user namespace.
>
> [ YOCTO #15592 ]
>
> Signed-off-by: Ross Burton <ross.burton@arm.com>
> ---
>  meta/classes-global/sanity.bbclass | 24 ++++++++++++++++++++++++
>  1 file changed, 24 insertions(+)
>
> diff --git a/meta/classes-global/sanity.bbclass
> b/meta/classes-global/sanity.bbclass
> index 1d242f0f0a0..72dab0fea2b 100644
> --- a/meta/classes-global/sanity.bbclass
> +++ b/meta/classes-global/sanity.bbclass
> @@ -475,6 +475,29 @@ def check_wsl(d):
>              bb.warn("You are running bitbake under WSLv2, this works
> properly but you should optimize your VHDX file eventually to avoid running
> out of storage space")
>      return None
>
> +def check_userns():
> +    """
> +    Check that user namespaces are functional, as they're used for
> network isolation.
> +    """
> +
> +    # There is a known failure case with AppAmrmor where the unshare()
> call
> +    # succeeds (at which point the uid is nobody) but writing to the
> uid_map
> +    # fails (so the uid isn't reset back to the user's uid). We can
> detect this.
> +    parentuid = os.getuid()
> +    pid = os.fork()
> +    if not pid:
> +        try:
> +            bb.utils.disable_network()
> +        except:
> +            pass
> +        os._exit(parentuid != os.getuid())
> +
> +    ret = os.waitpid(pid, 0)[1]
> +    if ret:
> +        bb.fatal("User namespaces are not usable by BitBake, possibly due
> to AppArmor.\n"
> +                 "See
> https://discourse.ubuntu.com/t/ubuntu-24-04-lts-noble-numbat-release-notes/39890#unprivileged-user-namespace-restrictions
> for more information.")
>

The error message could be better imo.
It will also happen inside a docker container that runs without the
NET_ADMIN capability, which is the default.
https://docs.docker.com/engine/containers/run/#runtime-privilege-and-linux-capabilities

Jose


> +
> +
>  # Require at least gcc version 8.0
>  #
>  # This can be fixed on CentOS-7 with devtoolset-6+
> @@ -641,6 +664,7 @@ def check_sanity_version_change(status, d):
>      status.addresult(check_git_version(d))
>      status.addresult(check_perl_modules(d))
>      status.addresult(check_wsl(d))
> +    status.addresult(check_userns())
>
>      missing = ""
>
> --
> 2.34.1
>
>
> -=-=-=-=-=-=-=-=-=-=-=-
> Links: You receive all messages sent to this group.
> View/Reply Online (#204449):
> https://lists.openembedded.org/g/openembedded-core/message/204449
> Mute This Topic: https://lists.openembedded.org/mt/108416977/5052612
> Group Owner: openembedded-core+owner@lists.openembedded.org
> Unsubscribe: https://lists.openembedded.org/g/openembedded-core/unsub [
> quaresma.jose@gmail.com]
> -=-=-=-=-=-=-=-=-=-=-=-
>
>
Ross Burton Sept. 12, 2024, 5:31 p.m. UTC | #5
> On 12 Sep 2024, at 18:29, Jose Quaresma <quaresma.jose@gmail.com> wrote:
> The error message could be better imo.
> It will also happen inside a docker container that runs without the NET_ADMIN capability, which is the default.
> https://docs.docker.com/engine/containers/run/#runtime-privilege-and-linux-capabilities

Do you have a suggestion for better wording?  Also do you have an example of it failing before this patch, in case we can extend the check to actually handle this case specifically.

Ross
Martin Jansa Sept. 12, 2024, 5:32 p.m. UTC | #6
On Thu, Sep 12, 2024 at 7:28 PM Ross Burton <Ross.Burton@arm.com> wrote:
>
> By which do you mean the build failed gracefully, whereas previously it would have exploded?

Without existing TMPDIR it failed with just the error from sanity
check (as expected).

With existing TMPDIR (where sanity check was already executed before
your change) or without your change applied it fails with many
PermissionError exceptions.

I forgot to mention that I did another zlib-native build after
echo 0 > /proc/sys/kernel/apparmor_restrict_unprivileged_userns
and that didn't fail sanity check nor in build (as expected).

> > On 12 Sep 2024, at 18:22, Martin Jansa <martin.jansa@gmail.com> wrote:
> >
> > Works as expected, the build failed :).
> >
> > openembedded-core/build$ bitbake -k zlib-native
> > ERROR: User namespaces are not usable by BitBake, possibly due to AppArmor.
> > See https://discourse.ubuntu.com/t/ubuntu-24-04-lts-noble-numbat-release-notes/39890#unprivileged-user-namespace-restrictions
> > for more information.
> >
> > The only issue might be that these checks are executed only once, so
> > if you have existing TMPDIR (where it was failing) then it will
> > continue failing with:
> >
> > ERROR: PermissionError: [Errno 1] Operation not permitted
> >
> > During handling of the above exception, another exception occurred:
> >
> > Traceback (most recent call last):
> >  File "/home/martin/work/bitbake/bin/bitbake-worker", line 278, in child
> >    bb.utils.disable_network(uid, gid)
> >  File "/home/martin/work/bitbake/lib/bb/utils.py", line 1696, in
> > disable_network
> >    with open("/proc/self/uid_map", "w") as f:
> > PermissionError: [Errno 1] Operation not permitted
> >
> > until TMPDIR is removed and sanity re-executed.
> >
> > On Thu, Sep 12, 2024 at 6:59 PM Ross Burton via lists.openembedded.org
> > <ross.burton=arm.com@lists.openembedded.org> wrote:
> >>
> >> Note that in its final form this isn’t had any testing on an Ubuntu machine, so testing would be appreciated if anyone has an Ubuntu 24.x machine (not a container, need their kernel) with apparmor enabled.
> >>
> >> Thanks,
> >> Ross
> >>
> >>> On 12 Sep 2024, at 17:57, Ross Burton via lists.openembedded.org <ross.burton=arm.com@lists.openembedded.org> wrote:
> >>>
> >>> If user namespaces are not available (typically because AppArmor is
> >>> blocking them), alert the user.
> >>>
> >>> We consider network isolation sufficiently important that this is a fatal
> >>> error, and the user will need to configure AppArmor to allow bitbake to
> >>> create a user namespace.
> >>>
> >>> [ YOCTO #15592 ]
> >>>
> >>> Signed-off-by: Ross Burton <ross.burton@arm.com>
> >>> ---
> >>> meta/classes-global/sanity.bbclass | 24 ++++++++++++++++++++++++
> >>> 1 file changed, 24 insertions(+)
> >>>
> >>> diff --git a/meta/classes-global/sanity.bbclass b/meta/classes-global/sanity.bbclass
> >>> index 1d242f0f0a0..72dab0fea2b 100644
> >>> --- a/meta/classes-global/sanity.bbclass
> >>> +++ b/meta/classes-global/sanity.bbclass
> >>> @@ -475,6 +475,29 @@ def check_wsl(d):
> >>>            bb.warn("You are running bitbake under WSLv2, this works properly but you should optimize your VHDX file eventually to avoid running out of storage space")
> >>>    return None
> >>>
> >>> +def check_userns():
> >>> +    """
> >>> +    Check that user namespaces are functional, as they're used for network isolation.
> >>> +    """
> >>> +
> >>> +    # There is a known failure case with AppAmrmor where the unshare() call
> >>> +    # succeeds (at which point the uid is nobody) but writing to the uid_map
> >>> +    # fails (so the uid isn't reset back to the user's uid). We can detect this.
> >>> +    parentuid = os.getuid()
> >>> +    pid = os.fork()
> >>> +    if not pid:
> >>> +        try:
> >>> +            bb.utils.disable_network()
> >>> +        except:
> >>> +            pass
> >>> +        os._exit(parentuid != os.getuid())
> >>> +
> >>> +    ret = os.waitpid(pid, 0)[1]
> >>> +    if ret:
> >>> +        bb.fatal("User namespaces are not usable by BitBake, possibly due to AppArmor.\n"
> >>> +                 "See https://discourse.ubuntu.com/t/ubuntu-24-04-lts-noble-numbat-release-notes/39890#unprivileged-user-namespace-restrictions for more information.")
> >>> +
> >>> +
> >>> # Require at least gcc version 8.0
> >>> #
> >>> # This can be fixed on CentOS-7 with devtoolset-6+
> >>> @@ -641,6 +664,7 @@ def check_sanity_version_change(status, d):
> >>>    status.addresult(check_git_version(d))
> >>>    status.addresult(check_perl_modules(d))
> >>>    status.addresult(check_wsl(d))
> >>> +    status.addresult(check_userns())
> >>>
> >>>    missing = ""
> >>>
> >>> --
> >>> 2.34.1
> >>>
> >>>
> >>>
> >>>
> >>
> >>
> >> -=-=-=-=-=-=-=-=-=-=-=-
> >> Links: You receive all messages sent to this group.
> >> View/Reply Online (#204450): https://lists.openembedded.org/g/openembedded-core/message/204450
> >> Mute This Topic: https://lists.openembedded.org/mt/108416977/3617156
> >> Group Owner: openembedded-core+owner@lists.openembedded.org
> >> Unsubscribe: https://lists.openembedded.org/g/openembedded-core/unsub [martin.jansa@gmail.com]
> >> -=-=-=-=-=-=-=-=-=-=-=-
>
>
Jose Quaresma Sept. 12, 2024, 5:45 p.m. UTC | #7
Ross Burton <Ross.Burton@arm.com> escreveu (quinta, 12/09/2024 à(s) 18:32):

>
>
> > On 12 Sep 2024, at 18:29, Jose Quaresma <quaresma.jose@gmail.com> wrote:
> > The error message could be better imo.
> > It will also happen inside a docker container that runs without the
> NET_ADMIN capability, which is the default.
> >
> https://docs.docker.com/engine/containers/run/#runtime-privilege-and-linux-capabilities
>
> Do you have a suggestion for better wording?  Also do you have an example
> of it failing before this patch, in case we can extend the check to
> actually handle this case specifically.
>

No, I don't.
Maybe we can suggest if the build runs inside a container, it need to run
with: --cap-add NET_ADMIN or --privileged
Inside a docker container without the above args and before the patch,
the unshare() call fail but since this is not fatal
nothing happens and the build continues without creating the new network
space.

Jose


>
> Ross
Richard Purdie Sept. 12, 2024, 8:37 p.m. UTC | #8
On Thu, 2024-09-12 at 18:29 +0100, Jose Quaresma via
lists.openembedded.org wrote:
> 
> 
> Ross Burton via lists.openembedded.org
> <ross.burton=arm.com@lists.openembedded.org> escreveu (quinta,
> 12/09/2024 à(s) 17:57):
> > If user namespaces are not available (typically because AppArmor is
> > blocking them), alert the user.
> > 
> > We consider network isolation sufficiently important that this is a
> > fatal
> > error, and the user will need to configure AppArmor to allow
> > bitbake to
> > create a user namespace.
> > 
> > [ YOCTO #15592 ]
> > 
> > Signed-off-by: Ross Burton <ross.burton@arm.com>
> > ---
> >  meta/classes-global/sanity.bbclass | 24 ++++++++++++++++++++++++
> >  1 file changed, 24 insertions(+)
> > 
> > diff --git a/meta/classes-global/sanity.bbclass b/meta/classes-
> > global/sanity.bbclass
> > index 1d242f0f0a0..72dab0fea2b 100644
> > --- a/meta/classes-global/sanity.bbclass
> > +++ b/meta/classes-global/sanity.bbclass
> > @@ -475,6 +475,29 @@ def check_wsl(d):
> >              bb.warn("You are running bitbake under WSLv2, this
> > works properly but you should optimize your VHDX file eventually to
> > avoid running out of storage space")
> >      return None
> > 
> > +def check_userns():
> > +    """
> > +    Check that user namespaces are functional, as they're used for
> > network isolation.
> > +    """
> > +
> > +    # There is a known failure case with AppAmrmor where the
> > unshare() call
> > +    # succeeds (at which point the uid is nobody) but writing to
> > the uid_map
> > +    # fails (so the uid isn't reset back to the user's uid). We
> > can detect this.
> > +    parentuid = os.getuid()
> > +    pid = os.fork()
> > +    if not pid:
> > +        try:
> > +            bb.utils.disable_network()
> > +        except:
> > +            pass
> > +        os._exit(parentuid != os.getuid())
> > +
> > +    ret = os.waitpid(pid, 0)[1]
> > +    if ret:
> > +        bb.fatal("User namespaces are not usable by BitBake,
> > possibly due to AppArmor.\n"
> > +                 "See
> > https://discourse.ubuntu.com/t/ubuntu-24-04-lts-noble-numbat-release-notes/39890#unprivileged-user-namespace-restrictions
> >  for more information.")
> > 
> 
> 
> The error message could be better imo.
> It will also happen inside a docker container that runs without the
> NET_ADMIN capability, which is the default.
> https://docs.docker.com/engine/containers/run/#runtime-privilege-and-linux-capabilities

Did you actually observe that?

If the unshare() fails, the uids will still match and I don't think the
error message will trigger but I could be wrong.

What we want to detect is where the unshare() works but the uid mapping
then fails which is the annoying apparmor corner case.

Cheers,

Richard
Jose Quaresma Sept. 13, 2024, 10:01 a.m. UTC | #9
Richard Purdie <richard.purdie@linuxfoundation.org> escreveu (quinta,
12/09/2024 à(s) 21:37):

> On Thu, 2024-09-12 at 18:29 +0100, Jose Quaresma via
> lists.openembedded.org wrote:
> >
> >
> > Ross Burton via lists.openembedded.org
> > <ross.burton=arm.com@lists.openembedded.org> escreveu (quinta,
> > 12/09/2024 à(s) 17:57):
> > > If user namespaces are not available (typically because AppArmor is
> > > blocking them), alert the user.
> > >
> > > We consider network isolation sufficiently important that this is a
> > > fatal
> > > error, and the user will need to configure AppArmor to allow
> > > bitbake to
> > > create a user namespace.
> > >
> > > [ YOCTO #15592 ]
> > >
> > > Signed-off-by: Ross Burton <ross.burton@arm.com>
> > > ---
> > >  meta/classes-global/sanity.bbclass | 24 ++++++++++++++++++++++++
> > >  1 file changed, 24 insertions(+)
> > >
> > > diff --git a/meta/classes-global/sanity.bbclass b/meta/classes-
> > > global/sanity.bbclass
> > > index 1d242f0f0a0..72dab0fea2b 100644
> > > --- a/meta/classes-global/sanity.bbclass
> > > +++ b/meta/classes-global/sanity.bbclass
> > > @@ -475,6 +475,29 @@ def check_wsl(d):
> > >              bb.warn("You are running bitbake under WSLv2, this
> > > works properly but you should optimize your VHDX file eventually to
> > > avoid running out of storage space")
> > >      return None
> > >
> > > +def check_userns():
> > > +    """
> > > +    Check that user namespaces are functional, as they're used for
> > > network isolation.
> > > +    """
> > > +
> > > +    # There is a known failure case with AppAmrmor where the
> > > unshare() call
> > > +    # succeeds (at which point the uid is nobody) but writing to
> > > the uid_map
> > > +    # fails (so the uid isn't reset back to the user's uid). We
> > > can detect this.
> > > +    parentuid = os.getuid()
> > > +    pid = os.fork()
> > > +    if not pid:
> > > +        try:
> > > +            bb.utils.disable_network()
> > > +        except:
> > > +            pass
> > > +        os._exit(parentuid != os.getuid())
> > > +
> > > +    ret = os.waitpid(pid, 0)[1]
> > > +    if ret:
> > > +        bb.fatal("User namespaces are not usable by BitBake,
> > > possibly due to AppArmor.\n"
> > > +                 "See
> > >
> https://discourse.ubuntu.com/t/ubuntu-24-04-lts-noble-numbat-release-notes/39890#unprivileged-user-namespace-restrictions
> > >  for more information.")
> > >
> >
> >
> > The error message could be better imo.
> > It will also happen inside a docker container that runs without the
> > NET_ADMIN capability, which is the default.
> >
> https://docs.docker.com/engine/containers/run/#runtime-privilege-and-linux-capabilities
>
> Did you actually observe that?
>

No, I have not tested the patch.


>
> If the unshare() fails, the uids will still match and I don't think the
> error message will trigger but I could be wrong.


> What we want to detect is where the unshare() works but the uid mapping
> then fails which is the annoying apparmor corner case.
>

Right, when I first read it I thought the error would be when it failed to
create the
network namespace and not for things related to the user namespace.
So probably what I said doesn't make sense, however it is still impossible
to create the network namespace under the conditions I mentioned.

I Understand now and will play a bit with the patch to check.

Thanks for the clarification.

Jose


> Cheers,
>
> Richard
>
diff mbox series

Patch

diff --git a/meta/classes-global/sanity.bbclass b/meta/classes-global/sanity.bbclass
index 1d242f0f0a0..72dab0fea2b 100644
--- a/meta/classes-global/sanity.bbclass
+++ b/meta/classes-global/sanity.bbclass
@@ -475,6 +475,29 @@  def check_wsl(d):
             bb.warn("You are running bitbake under WSLv2, this works properly but you should optimize your VHDX file eventually to avoid running out of storage space")
     return None
 
+def check_userns():
+    """
+    Check that user namespaces are functional, as they're used for network isolation.
+    """
+
+    # There is a known failure case with AppAmrmor where the unshare() call
+    # succeeds (at which point the uid is nobody) but writing to the uid_map
+    # fails (so the uid isn't reset back to the user's uid). We can detect this.
+    parentuid = os.getuid()
+    pid = os.fork()
+    if not pid:
+        try:
+            bb.utils.disable_network()
+        except:
+            pass
+        os._exit(parentuid != os.getuid())
+
+    ret = os.waitpid(pid, 0)[1]
+    if ret:
+        bb.fatal("User namespaces are not usable by BitBake, possibly due to AppArmor.\n"
+                 "See https://discourse.ubuntu.com/t/ubuntu-24-04-lts-noble-numbat-release-notes/39890#unprivileged-user-namespace-restrictions for more information.")
+
+
 # Require at least gcc version 8.0
 #
 # This can be fixed on CentOS-7 with devtoolset-6+
@@ -641,6 +664,7 @@  def check_sanity_version_change(status, d):
     status.addresult(check_git_version(d))
     status.addresult(check_perl_modules(d))
     status.addresult(check_wsl(d))
+    status.addresult(check_userns())
 
     missing = ""