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

Add --disable-userns switch #452

Closed
wants to merge 1 commit into from
Closed

Add --disable-userns switch #452

wants to merge 1 commit into from

Conversation

alexlarsson
Copy link
Collaborator

Some usecases of bubblewrap want to ensure that the subprocess can't
further re-arrange the filesystem namespace, or do other more complex
namespace modification. This can be limited by --disable-userns,
which makes the kernel unable to create any new user namespaces
for the process hierarchy.

This is done by making a cover of the original root, but running the
process with the origin root as root anyway. This "non-standard" root
means the kernel will not allow creating new user namespaces.

This is more typically done using chroot("/theroot") which would also
mean the root of the namespace ("/") differes from the process current
root ("/theroot)". However, we want to avoid this as in this case symlinks
in /proc/$pid/fd would have a "/theroot" prefix when seen outside the
namespace, which is something that e.g. flatpak doesn't want.

Note, there is a slight cost to this as the covering bind mount
duplicates all the regular mounts in namespace. However, they all
refer to the same mounts so no actual files are duplicated.

Some usecases of bubblewrap want to ensure that the subprocess can't
further re-arrange the filesystem namespace, or do other more complex
namespace modification. This can be limited by --disable-userns,
which makes the kernel unable to create any new user namespaces
for the process hierarchy.

This is done by making a cover of the original root, but running the
process with the origin root as root anyway. This "non-standard" root
means the kernel will not allow creating new user namespaces.

This is more typically done using chroot("/theroot") which would also
mean the root of the namespace ("/") differes from the process current
root ("/theroot)". However, we want to avoid this as in this case symlinks
in /proc/$pid/fd would have a "/theroot" prefix when seen outside the
namespace, which is something that e.g. flatpak doesn't want.

Note, there is a slight cost to this as the covering bind mount
duplicates all the regular mounts in namespace. However, they all
refer to the same mounts so no actual files are duplicated.
@alexlarsson
Copy link
Collaborator Author

@smcv smcv requested a review from cgwalters October 8, 2021 20:13
@smcv
Copy link
Collaborator

smcv commented Oct 8, 2021

Sorry, I don't have the necessary knowledge of kernel subtleties to review this.

{
if (using_userns2)
{
/* If we're not in the main userns, the we don't own the

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

then

Comment on lines +2996 to +2999
/* Mount a bind cover of the root fs. This will trigger
* current_chrooted() in create_user_ns() in the kernel at:
* https://elixir.bootlin.com/linux/v5.14.4/source/kernel/user_namespace.c#L92
* making it impossible for the process to create new user namespaces.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this an API guarantee that we can rely on, or an implementation detail that kernel developers could randomly change in a future version (thus making us vulnerable again)?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this behavior is stable API, because it is fundamental in exposing user namespaces in a secure way.

@lukts30
Copy link

lukts30 commented Feb 18, 2022

Wouldn't it be more straightforward to use the max_user_namespaces sysctl?

If the user namespace is a child of the initial user namespace you could of course bump the max_user_namespaces value from 0 back up if are privileged to write to that sysctl.

But you can create an intermediary user namespace set the limit to 1 and then create the user namespace for the actual program to run in. Inside this user namespace, it is still possible to set the sysctl to some large number but the kernel enforces that any stricter max value in a parent namespace is enforced.

[lukas@PC      ~]$ sysctl user.max_user_namespaces
user.max_user_namespaces = 128026
[lukas@PC      ~]$ unshare -Ur bash
[root@PC      ~]# sysctl user.max_user_namespaces
user.max_user_namespaces = 2147483647
[root@PC      ~]# sysctl -w user.max_user_namespaces=1
user.max_user_namespaces = 1
[root@PC      ~]# unshare -Ur bash
[root@PC      ~]# sysctl user.max_user_namespaces
user.max_user_namespaces = 2147483647
[root@PC      ~]# unshare -Ur bash
unshare: unshare failed: No space left on device

* https://elixir.bootlin.com/linux/v5.14.4/source/kernel/user_namespace.c#L92
* making it impossible for the process to create new user namespaces.
*
* What happens is that the path "/" in the namespace noew
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* What happens is that the path "/" in the namespace noew
* What happens is that the path "/" in the namespace now

@smcv
Copy link
Collaborator

smcv commented Mar 22, 2022

Wouldn't it be more straightforward to use the max_user_namespaces sysctl?

This looks like a simpler way to achieve the same thing. I might try implementing it if you don't get there first.

smcv added a commit to smcv/bubblewrap that referenced this pull request Mar 22, 2022
Some use-cases of bubblewrap want to ensure that the subprocess can't
further re-arrange the filesystem namespace, or do other more complex
namespace modification. For example, Flatpak wants to prevent sandboxed
processes from altering their /proc/$pid/root/.flatpak-info, so that
/.flatpak-info can safely be used as an indicator that a process is part
of a Flatpak app.

This approach was suggested by lukts30 on containers#452.
The sysctl-controlled maximum numbers of namespaces are themselves
namespaced, so we can disable nested user namespaces by setting the
limit to 1 and then entering a new, nested user namespace. The resulting
process loses its privileges in the namespace where the limit was set
to 1, so it is unable to move the limit back up.

Signed-off-by: Simon McVittie <smcv@collabora.com>
@smcv
Copy link
Collaborator

smcv commented Mar 22, 2022

Wouldn't it be more straightforward to use the max_user_namespaces sysctl?

This looks like a simpler way to achieve the same thing.

#488 reimplements this feature with that approach.

smcv added a commit to smcv/bubblewrap that referenced this pull request Mar 22, 2022
Some use-cases of bubblewrap want to ensure that the subprocess can't
further re-arrange the filesystem namespace, or do other more complex
namespace modification. For example, Flatpak wants to prevent sandboxed
processes from altering their /proc/$pid/root/.flatpak-info, so that
/.flatpak-info can safely be used as an indicator that a process is part
of a Flatpak app.

This approach was suggested by lukts30 on containers#452.
The sysctl-controlled maximum numbers of namespaces are themselves
namespaced, so we can disable nested user namespaces by setting the
limit to 1 and then entering a new, nested user namespace. The resulting
process loses its privileges in the namespace where the limit was set
to 1, so it is unable to move the limit back up.

Signed-off-by: Simon McVittie <smcv@collabora.com>
smcv added a commit to smcv/bubblewrap that referenced this pull request Aug 9, 2022
Some use-cases of bubblewrap want to ensure that the subprocess can't
further re-arrange the filesystem namespace, or do other more complex
namespace modification. For example, Flatpak wants to prevent sandboxed
processes from altering their /proc/$pid/root/.flatpak-info, so that
/.flatpak-info can safely be used as an indicator that a process is part
of a Flatpak app.

This approach was suggested by lukts30 on containers#452.
The sysctl-controlled maximum numbers of namespaces are themselves
namespaced, so we can disable nested user namespaces by setting the
limit to 1 and then entering a new, nested user namespace. The resulting
process loses its privileges in the namespace where the limit was set
to 1, so it is unable to move the limit back up.

Signed-off-by: Simon McVittie <smcv@collabora.com>
alexlarsson pushed a commit to smcv/bubblewrap that referenced this pull request Sep 6, 2022
Some use-cases of bubblewrap want to ensure that the subprocess can't
further re-arrange the filesystem namespace, or do other more complex
namespace modification. For example, Flatpak wants to prevent sandboxed
processes from altering their /proc/$pid/root/.flatpak-info, so that
/.flatpak-info can safely be used as an indicator that a process is part
of a Flatpak app.

This approach was suggested by lukts30 on containers#452.
The sysctl-controlled maximum numbers of namespaces are themselves
namespaced, so we can disable nested user namespaces by setting the
limit to 1 and then entering a new, nested user namespace. The resulting
process loses its privileges in the namespace where the limit was set
to 1, so it is unable to move the limit back up.

Signed-off-by: Simon McVittie <smcv@collabora.com>
@alexlarsson
Copy link
Collaborator Author

closing this in favour of #488

@alexlarsson alexlarsson closed this Sep 6, 2022
smcv added a commit to smcv/bubblewrap that referenced this pull request Dec 16, 2022
Some use-cases of bubblewrap want to ensure that the subprocess can't
further re-arrange the filesystem namespace, or do other more complex
namespace modification. For example, Flatpak wants to prevent sandboxed
processes from altering their /proc/$pid/root/.flatpak-info, so that
/.flatpak-info can safely be used as an indicator that a process is part
of a Flatpak app.

This approach was suggested by lukts30 on containers#452.
The sysctl-controlled maximum numbers of namespaces are themselves
namespaced, so we can disable nested user namespaces by setting the
limit to 1 and then entering a new, nested user namespace. The resulting
process loses its privileges in the namespace where the limit was set
to 1, so it is unable to move the limit back up.

Co-authored-by: Alexander Larsson <alexl@redhat.com>
Signed-off-by: Simon McVittie <smcv@collabora.com>
smcv added a commit to smcv/bubblewrap that referenced this pull request Dec 16, 2022
Some use-cases of bubblewrap want to ensure that the subprocess can't
further re-arrange the filesystem namespace, or do other more complex
namespace modification. For example, Flatpak wants to prevent sandboxed
processes from altering their /proc/$pid/root/.flatpak-info, so that
/.flatpak-info can safely be used as an indicator that a process is part
of a Flatpak app.

This approach was suggested by lukts30 on containers#452.
The sysctl-controlled maximum numbers of namespaces are themselves
namespaced, so we can disable nested user namespaces by setting the
limit to 1 and then entering a new, nested user namespace. The resulting
process loses its privileges in the namespace where the limit was set
to 1, so it is unable to move the limit back up.

Co-authored-by: Alexander Larsson <alexl@redhat.com>
Signed-off-by: Simon McVittie <smcv@collabora.com>
smcv added a commit to smcv/bubblewrap that referenced this pull request Dec 16, 2022
Some use-cases of bubblewrap want to ensure that the subprocess can't
further re-arrange the filesystem namespace, or do other more complex
namespace modification. For example, Flatpak wants to prevent sandboxed
processes from altering their /proc/$pid/root/.flatpak-info, so that
/.flatpak-info can safely be used as an indicator that a process is part
of a Flatpak app.

This approach was suggested by lukts30 on containers#452.
The sysctl-controlled maximum numbers of namespaces are themselves
namespaced, so we can disable nested user namespaces by setting the
limit to 1 and then entering a new, nested user namespace. The resulting
process loses its privileges in the namespace where the limit was set
to 1, so it is unable to move the limit back up.

Co-authored-by: Alexander Larsson <alexl@redhat.com>
Signed-off-by: Simon McVittie <smcv@collabora.com>
alexlarsson added a commit that referenced this pull request Jan 3, 2023
Some use-cases of bubblewrap want to ensure that the subprocess can't
further re-arrange the filesystem namespace, or do other more complex
namespace modification. For example, Flatpak wants to prevent sandboxed
processes from altering their /proc/$pid/root/.flatpak-info, so that
/.flatpak-info can safely be used as an indicator that a process is part
of a Flatpak app.

This approach was suggested by lukts30 on #452.
The sysctl-controlled maximum numbers of namespaces are themselves
namespaced, so we can disable nested user namespaces by setting the
limit to 1 and then entering a new, nested user namespace. The resulting
process loses its privileges in the namespace where the limit was set
to 1, so it is unable to move the limit back up.

Co-authored-by: Alexander Larsson <alexl@redhat.com>
Signed-off-by: Simon McVittie <smcv@collabora.com>
brandsimon pushed a commit to brandsimon/bubblewrap that referenced this pull request Mar 19, 2023
Some use-cases of bubblewrap want to ensure that the subprocess can't
further re-arrange the filesystem namespace, or do other more complex
namespace modification. For example, Flatpak wants to prevent sandboxed
processes from altering their /proc/$pid/root/.flatpak-info, so that
/.flatpak-info can safely be used as an indicator that a process is part
of a Flatpak app.

This approach was suggested by lukts30 on containers#452.
The sysctl-controlled maximum numbers of namespaces are themselves
namespaced, so we can disable nested user namespaces by setting the
limit to 1 and then entering a new, nested user namespace. The resulting
process loses its privileges in the namespace where the limit was set
to 1, so it is unable to move the limit back up.

Co-authored-by: Alexander Larsson <alexl@redhat.com>
Signed-off-by: Simon McVittie <smcv@collabora.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants