Requirements for CAP_SYS_ADMIN on setns() ?
IIUC, currently, in order to be able to invoke setns() the calling process is required to have CAP_SYS_ADMIN capability. Alternatively with user namespaces, access is allowed if the process' effective uid matches the uid of the owner of the namespace.
I have a scenario though that isn't dealt with by those rules. I have a container that was spawned by uid == 0, and I have an unprivileged process uid != 0 in the initial namespace that I wish to allow to enter the namespaces associated with the container.
With the CAP_SYS_ADMIN rule on setns(), it seems that the unprivileged process will need to execute some setuid binary in order to gain the CAP_SYS_ADMIN capability required to call setns().
Of course you can't call setns() without first obtaining a file descriptor corresponding to the /proc/$CONTAINERPID/ns/XXXX namespace you wish to join. This appears to require elevated privileges too.
Is it not sufficient to rely on the permissions on the /proc/$PID/ns/XXX file to control access to a namespace, and thus allow setns() without
a CAP_SYS_ADMIN check ? ie setns() is basically useless unless you
already have sufficient privileges to get a file descriptor for the namespace, so why does setns need an additional privilege check beyond that done at time of open() on the proc file.
In my scenario this would allow for a privileged daemon to open the /proc/$PID/ns/XXX file, and then pass the file descriptor back to the unprivileged process using SCM_RIGHTS, which could then invoke setns(). This kind of privilege separation is perferrable to requiring the unprivileged process to run some kind of setuid program to gain the CAP_SYS_ADMIN capability.
Regards,
Daniel
Signature · 4 lines
|: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
A message that is not in the archive (sent off-list or not yet received): [email protected]
Quoted 32 lines · Daniel P. Berrange
IIUC, currently, in order to be able to invoke
setns()the calling process is required to haveCAP_SYS_ADMINcapability. Alternatively with user namespaces, access is allowed if the process' effective uid matches the uid of the owner of the namespace.I have a scenario though that isn't dealt with by those rules. I have a container that was spawned by uid == 0, and I have an unprivileged process uid != 0 in the initial namespace that I wish to allow to enter the namespaces associated with the container.
With the
CAP_SYS_ADMINrule onsetns(), it seems that the unprivileged process will need to execute some setuid binary in order to gain theCAP_SYS_ADMINcapability required to callsetns().Of course you can't call
setns()without first obtaining a file descriptor corresponding to the/proc/$CONTAINERPID/ns/XXXXnamespace you wish to join. This appears to require elevated privileges too.Is it not sufficient to rely on the permissions on the
/proc/$PID/ns/XXXfile to control access to a namespace, and thus allowsetns()without
aCAP_SYS_ADMINcheck ? iesetns()is basically useless unless you
already have sufficient privileges to get a file descriptor for the namespace, so why does setns need an additional privilege check beyond that done at time ofopen()on the proc file.In my scenario this would allow for a privileged daemon to open the
/proc/$PID/ns/XXXfile, and then pass the file descriptor back to the unprivileged process usingSCM_RIGHTS, which could then invokesetns(). This kind of privilege separation is perferrable to requiring the unprivileged process to run some kind of setuid program to gain theCAP_SYS_ADMINcapability.
Quoted 2 lines
Regards,
Daniel
Hey Daniel,
it's possible that as things settle down we can find ways to relax this, but note that this behavior was very specifically added by the commit below. Very unfortunate that this is a feature regression over the CONFIG_USER_NS=n case :(
5e4a08476b50fa39210fca82e03325cc46b9c235
Author: Eric W. Biederman <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]> Date: Fri Dec 14 07:55:36 2012 -0800
userns: Require CAP_SYS_ADMIN for most uses of setns.
Andy Lutomirski <[email protected]> found a nasty little bug in
the permissions of setns. With unprivileged user namespaces it
became possible to create new namespaces without privilege.
However the setns calls were relaxed to only require CAP_SYS_ADMIN in
the user nameapce of the targed namespace.
Which made the following nasty sequence possible.
pid = clone(CLONE_NEWUSER | CLONE_NEWNS);
if (pid == 0) { /* child */
system("mount --bind /home/me/passwd /etc/passwd");
}
else if (pid != 0) { /* parent */
char path[PATH_MAX];
snprintf(path, sizeof(path), "/proc/%u/ns/mnt");
fd = open(path, O_RDONLY);
setns(fd, 0);
system("su -");
}
Prevent this possibility by requiring CAP_SYS_ADMIN
in the current user namespace when joing all but the user namespace.Quoted 36 lines · Serge Hallyn
Quoted 32 lines · Daniel P. Berrange
IIUC, currently, in order to be able to invoke
setns()the calling process is required to haveCAP_SYS_ADMINcapability. Alternatively with user namespaces, access is allowed if the process' effective uid matches the uid of the owner of the namespace.I have a scenario though that isn't dealt with by those rules. I have a container that was spawned by uid == 0, and I have an unprivileged process uid != 0 in the initial namespace that I wish to allow to enter the namespaces associated with the container.
With the
CAP_SYS_ADMINrule onsetns(), it seems that the unprivileged process will need to execute some setuid binary in order to gain theCAP_SYS_ADMINcapability required to callsetns().Of course you can't call
setns()without first obtaining a file descriptor corresponding to the/proc/$CONTAINERPID/ns/XXXXnamespace you wish to join. This appears to require elevated privileges too.Is it not sufficient to rely on the permissions on the
/proc/$PID/ns/XXXfile to control access to a namespace, and thus allowsetns()without
aCAP_SYS_ADMINcheck ? iesetns()is basically useless unless you
already have sufficient privileges to get a file descriptor for the namespace, so why does setns need an additional privilege check beyond that done at time ofopen()on the proc file.In my scenario this would allow for a privileged daemon to open the
/proc/$PID/ns/XXXfile, and then pass the file descriptor back to the unprivileged process usingSCM_RIGHTS, which could then invokesetns(). This kind of privilege separation is perferrable to requiring the unprivileged process to run some kind of setuid program to gain theCAP_SYS_ADMINcapability.Quoted 2 lines
Regards,
Daniel
Quoted 6 lines
Hey Daniel,
it's possible that as things settle down we can find ways to relax this, but note that this behavior was very specifically added by the commit below. Very unfortunate that this is a feature regression over the
CONFIG_USER_NS=ncase :(
No this is not a feature regression over the CONFIG_USER_NS=n case. The patch was a setns bug fix. The situation Daniel wants to use is exploitable.
Allowing an unprivileged user to call setns allows confusing suid root processes.
It is completely possible for Daniels situation to work of the unprivileged user calls setns first. That is allowed.
Eric
A message that is not in the archive (sent off-list or not yet received): 87txlb8atb.fsf-aS9lmoZGLiVWk0Htik3J/[email protected]
Quoted 49 lines · Eric W. Biederman
Quoted 36 lines · Serge Hallyn
Quoted 32 lines · Daniel P. Berrange
IIUC, currently, in order to be able to invoke
setns()the calling process is required to haveCAP_SYS_ADMINcapability. Alternatively with user namespaces, access is allowed if the process' effective uid matches the uid of the owner of the namespace.I have a scenario though that isn't dealt with by those rules. I have a container that was spawned by uid == 0, and I have an unprivileged process uid != 0 in the initial namespace that I wish to allow to enter the namespaces associated with the container.
With the
CAP_SYS_ADMINrule onsetns(), it seems that the unprivileged process will need to execute some setuid binary in order to gain theCAP_SYS_ADMINcapability required to callsetns().Of course you can't call
setns()without first obtaining a file descriptor corresponding to the/proc/$CONTAINERPID/ns/XXXXnamespace you wish to join. This appears to require elevated privileges too.Is it not sufficient to rely on the permissions on the
/proc/$PID/ns/XXXfile to control access to a namespace, and thus allowsetns()without
aCAP_SYS_ADMINcheck ? iesetns()is basically useless unless you
already have sufficient privileges to get a file descriptor for the namespace, so why does setns need an additional privilege check beyond that done at time ofopen()on the proc file.In my scenario this would allow for a privileged daemon to open the
/proc/$PID/ns/XXXfile, and then pass the file descriptor back to the unprivileged process usingSCM_RIGHTS, which could then invokesetns(). This kind of privilege separation is perferrable to requiring the unprivileged process to run some kind of setuid program to gain theCAP_SYS_ADMINcapability.Quoted 2 lines
Regards,
DanielQuoted 6 lines
Hey Daniel,
it's possible that as things settle down we can find ways to relax this, but note that this behavior was very specifically added by the commit below. Very unfortunate that this is a feature regression over the
CONFIG_USER_NS=ncase :(No this is not a feature regression over the
CONFIG_USER_NS=ncase. The patch was a setns bug fix. The situation Daniel wants to use is exploitable.
Quoted 5 lines
Allowing an unprivileged user to call setns allows confusing suid root processes.
It is completely possible for Daniels situation to work of the unprivileged user calls setns first. That is allowed.
Oh, hm. I thought that in the thread leading up to this email, the original reporter said that in a kernel with CONFIG_USER_NS=n, an unprivileged user could setns(fd) to an fd sent by a privileged process, whereas the same situation with CONFIG_USER_NS=y was not allowed. I probably misunderstood.
-serge
A message that is not in the archive (sent off-list or not yet received): 20130606164428.GA4687-anj0Drq5vpzx6HRWoRZK3AC/[email protected]
Quoted 7 lines · Serge E. Hallyn
Quoted 6 lines · Eric W. Biederman
Quoted 4 lines · Serge Hallyn
Quoted 3 lines · Daniel P. Berrange
Is it not sufficient to rely on the permissions on the
/proc/$PID/ns/XXXfile to control access to a namespace, and thus allowsetns()without aCAP_SYS_ADMINcheck ?
The permissions on /proc/$PID/ns/XXX are sufficient to control access but they are not ok to allow use.
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
ie
setns()is basically useless unless you
already have sufficient privileges to get a file descriptor for the namespace, so why does setns need an additional privilege check beyond that done at time ofopen()on the proc file.
To be very clear.
setns requires CAP_SYS_ADMIN because changing the namespaces for your children can result in tricking a suid root application and thus lead to privilege escalation.
If you run setns inside a user namespace that you control the privilege escalation is not possible and so setns is allowed.
Eric
A message that is not in the archive (sent off-list or not yet received): 87bo7j6r80.fsf-aS9lmoZGLiVWk0Htik3J/[email protected]
Quoted 18 lines · Eric W. Biederman
Quoted 7 lines · Serge E. Hallyn
Quoted 6 lines · Eric W. Biederman
Quoted 4 lines · Serge Hallyn
Quoted 3 lines · Daniel P. Berrange
Is it not sufficient to rely on the permissions on the
/proc/$PID/ns/XXXfile to control access to a namespace, and thus allowsetns()without aCAP_SYS_ADMINcheck ?The permissions on
/proc/$PID/ns/XXXare sufficient to control access but they are not ok to allow use.Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
ie
setns()is basically useless unless you
already have sufficient privileges to get a file descriptor for the namespace, so why does setns need an additional privilege check beyond that done at time ofopen()on the proc file.
Quoted 5 lines
To be very clear.
setns requires
CAP_SYS_ADMINbecause changing the namespaces for your children can result in tricking a suid root application and thus lead to privilege escalation.
Yep, ok I see that from the example shown earlier in the thread.
Quoted 2 lines
If you run setns inside a user namespace that you control the privilege escalation is not possible and so setns is allowed.
What are the privilege requirements for being able to call setns() on a user namespace FD ?
Thinking some more, if there was a setpidns(pid_t containerpid) syscall which unconditionally joined the caller to all namespaces associated with the target pid, then you'd not have the security risk described, right ?
Daniel
Signature · 4 lines
|: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
A message that is not in the archive (sent off-list or not yet received): [email protected]
Quoted 25 lines · Daniel P. Berrange
Quoted 18 lines · Eric W. Biederman
Quoted 7 lines · Serge E. Hallyn
Quoted 6 lines · Eric W. Biederman
Quoted 4 lines · Serge Hallyn
Quoted 3 lines · Daniel P. Berrange
Is it not sufficient to rely on the permissions on the
/proc/$PID/ns/XXXfile to control access to a namespace, and thus allowsetns()without aCAP_SYS_ADMINcheck ?The permissions on
/proc/$PID/ns/XXXare sufficient to control access but they are not ok to allow use.Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
ie
setns()is basically useless unless you
already have sufficient privileges to get a file descriptor for the namespace, so why does setns need an additional privilege check beyond that done at time ofopen()on the proc file.Quoted 5 lines
To be very clear.
setns requires
CAP_SYS_ADMINbecause changing the namespaces for your children can result in tricking a suid root application and thus lead to privilege escalation.
Quoted 7 lines
Yep, ok I see that from the example shown earlier in the thread.
Quoted 2 lines
If you run setns inside a user namespace that you control the privilege escalation is not possible and so setns is allowed.
What are the privilege requirements for being able to call
setns()on a user namespace FD ?
That you are not threaded and the user namespace is a child of the current user namespace that you have CAP_SYS_ADMIN rights over.
Essentially the requirement is that it is a user namespace that your uid created.
Quoted 3 lines
Thinking some more, if there was a
setpidns(pid_t containerpid)syscall which unconditionally joined the caller to all namespaces associated with the target pid, then you'd not have the security risk described, right ?
The security risk is present unless you join the user namespace, as namespaces can be a bit leaky (fd passing etc). At the same time the user namespace is sufficient to remove the security risk, as privilege escalation is not possible in the user namespace so even if you fool a suid application it does not matter.
Eric
Waaaay behind on my email...
Quoted 12 lines · Daniel P. Berrange
Quoted 2 lines · Eric W. Biederman
"Serge E. Hallyn" <[email protected]> writes:
setns requiresCAP_SYS_ADMINbecause changing the namespaces foryour
Quoted 1 line
children can result in tricking a suid root application and thus
lead
Quoted 1 line
to privilege escalation.
Yep, ok I see that from the example shown earlier in the thread.
Quoted 1 line
If you run setns inside a user namespace that you control the
privilege
Quoted 8 lines
Quoted 1 line
escalation is not possible and so setns is allowed.
What are the privilege requirements for being able to call
setns()on a user namespace FD ?Thinking some more, if there was a
setpidns(pid_t containerpid)syscall which unconditionally joined the caller to all namespaces associated with the target pid, then you'd not have the security risk described, right ?
Sounds like you want a reparent_to_init() that works for a container's init.
Rob
Quoted 27 lines · Rob Landley
Waaaay behind on my email...
Quoted 17 lines · Daniel P. Berrange
Quoted 2 lines · Eric W. Biederman
"Serge E. Hallyn" <[email protected]> writes:
setns requiresCAP_SYS_ADMINbecause changing the namespaces foryour
Quoted 1 line
children can result in tricking a suid root application and thus
lead
Quoted 1 line
to privilege escalation.
Yep, ok I see that from the example shown earlier in the thread.
Quoted 1 line
If you run setns inside a user namespace that you control the
privilege
Quoted 1 line
escalation is not possible and so setns is allowed.
What are the privilege requirements for being able to call
setns()on a user namespace FD ?Quoted 6 lines
Thinking some more, if there was a
setpidns(pid_t containerpid)syscall
which unconditionally joined the caller to all namespaces associated with
the target pid, then you'd not have the security risk described, right ?
Quoted 2 lines
Sounds like you want a
reparent_to_init()that works for a container's init.
setns on all of the namespaces effectively gives you that ability. You probably want to play with cgroups and a few other similar things. And there is a utility in util-linux that automates at least the namespace portion of this called nsenter.
Eric