switch user and group id and exec without passwd, can be used to replace sudo when building container.
This is a simple tool that will simply execute a program with different privileges. The program will be exceuted directly and not run as a child, like su and sudo does, which avoids TTY and signal issues (see below).
Notice that su-exec depends on being run by the root user, non-root users do not have permission to change uid/gid, or you need to setuid on it.
su-exec user-spec command [ arguments... ]
user-spec
is either a user name (e.g. nobody
) or user name and group
name separated with colon (e.g. nobody:ftp
). Numeric uid/gid values
can be used instead of names. Example:
$ su-exec apache:1000 /usr/sbin/httpd -f /opt/www/httpd.conf
If you compile softwares in a container, you probably need sudo
, since compiling with root may not be
a good idea and some Makefile
like lede
even forbidden building as root.
However, sudo
is such a overkill for unattented auto-build of a container since
- It requires dependencies to be installed.
- You need to configure
sudo
to allow password-lesssudo
for your user - You cannot run
sudo apt-get remove -y sudo
to uninstall, you have to somewhat switch to root user withoutsudo
to uninstall it.
So how to replace sudo
with su-exec
for containers? Simple, just execute the following lines with root
:
14.5kb
when building usingglibc2.3
,clang-9.0.0-2
andlld-9.0.0
14.0kb
when building usingmusl-1.2.0
,clang-9.0.0-2
andlld-9.0.0
.53.3kb
when still using the above toolchain, but instead built with-static
.
cd /usr/local/bin/
# For dynamic-linked glibc, 14.5kb
wget https://github.com/NobodyXu/su-exec/releases/download/v0.3.1/su-exec
# For dynamic-linked musl-libc, 14.0kb
wget https://github.com/NobodyXu/su-exec/releases/download/v0.3.1/su-exec-musl
# For static-linked musl-libc, 53.3kb
wget https://github.com/NobodyXu/su-exec/releases/download/v0.3.1/su-exec-static-musl
chmod a+xs su-exec
Removing su-exec
is pretty simple:
su-exec root:root rm /usr/local/bin/su-exec
Notice how su
will make ps
be a child of a shell while su-exec
just executes ps
directly.
$ docker run -it --rm alpine:edge su postgres -c 'ps aux'
PID USER TIME COMMAND
1 postgres 0:00 ash -c ps aux
12 postgres 0:00 ps aux
$ docker run -it --rm -v $PWD/su-exec:/sbin/su-exec:ro alpine:edge su-exec postgres ps aux
PID USER TIME COMMAND
1 postgres 0:00 ps aux
su-exec
is not likesudo
but more likesu
, it does not modify any environment variables other thanHOME
,USER
,LOGNAME
, which might be undesirable. To workaround, usesu-exec env var=val command arg
.
- Due to the fact that
su-exec
does not allocate new tty, it is vulnerable to TTY hijacking and arbitrary code execution. An easy workaround will be tochmod 600 /dev/tty
, but to ensure the change is persistent, you need to modify udev rule.
This does more or less exactly the same thing as gosu but it is only
14.3kb
when building usingglibc2.3
,clang-9.0.0-2
andlld-9.0.0
13.9kb
when building usingmusl-1.2.0
,clang-9.0.0-2
andlld-9.0.0
.45.6kb
when still using the above toolchain, but instead built with-static
.
instead of 1.7MB
, which is running gosu 1.10.1
from apt
.
Both are installed on Intel x86-64
platform.
Run docker build .
where docker
can be replace by podman
, or buildah
.