Dropping Privileges?
In Unix/Linux, when a program need to bind to the previleged port (port below 1024), they must run as root. But, running as root all the time is risky. As if someone exploits the program, they get full system access.
Normal Pattern
- Start as root
- Bind to the privileged port (port < 1024)
- Drop privileges, making it unprivileged user, just like any user without root access.
- Continue running as that unprivileged user with no problems.
This is a standard practise used by Apache, Nginx, Bind and essentially every server that binds with low ports.
How does it work
getuid()/geteuid()-> checks if we are running as root. ifuid/euid == 0, it is root.getpwnam()-> check the /etc/passwd to get numeric UID.getgrnam()-> look up the group in /etc/group numeric GID.setgid()-> switch to the group first (must happen before setuid).setuid()-> switch to user.
After step 5, the process runs as nobody and no longer access the root-only resources.
What is a limux namespace?
A namespace is a feature that isolates a process from the rest of the system. tools like Docker, systemd-nspawn & Deckard (a DNS testing suite) use namespaces.
A 'user namespace' lets you map the process's UID uid 0 (root inside the namespace) to a non-root uid outside the namespace.
Inside, the namespace thinks it is root. But /etc/passwd from the host system isn't visible unless explicitly mapped.
workaround
Set user="root" and set group="root". Works because in user namespace, the root user is always resolvable (it is built into the kernal's UID namespace logic) while any other user names aren't.
Problem in the #3094
The Deckard DNS test suit runs hickory-dns inside a linus user + network namespace :-
- the process appear as root so if
uid == 0, passes. - but when hickory calls
getpwnam("nobody"), it return NULL, because /etc/passwd from host isn't available. - this trigger error in line 818
- server crashes.
Fix
Add a drop_privilege = false config option to skip it.
Verdict
PR merged at #3762