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

  1. Start as root
  2. Bind to the privileged port (port < 1024)
  3. Drop privileges, making it unprivileged user, just like any user without root access.
  4. 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

  1. getuid()/geteuid() -> checks if we are running as root. if uid/euid == 0, it is root.
  2. getpwnam() -> check the /etc/passwd to get numeric UID.
  3. getgrnam() -> look up the group in /etc/group numeric GID.
  4. setgid() -> switch to the group first (must happen before setuid).
  5. 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