Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Dynamic Users with systemd (0pointer.net)
9 points by XJ0OYtjb on Oct 6, 2017 | hide | past | favorite | 6 comments



The underlying premises upon which the rest is based are somewhat questionable, in my experience. I have a lot of dedicated user accounts for services, including dedicated user accounts for log services, far more than there are on any systemd system. My highest UID is 1468. I am a mere 2% of the distance to exhausting even the 16-bit ID space, let alone the full 32-bit ID space that the operating system actually has. And that 2% figure is without taking into account that on that particular machine these accounts have been assigned IDs starting from 1003.

All of these are dealt with by the package installation/deinstallation mechanisms, and my experience is that those are what needs attention, with better, or at least widespread, mechanisms for handling dedicated user accounts as part of the installation/deinstallation process. The OpenBSD package manager provides a @newuser mechanism for this, which does all of the work of allocating and deallocating dedicated user accounts for services. On other package managers, the process is a more involved and explicitly written one, involving combinations of getent, pw, userdel, and useradd. These package managers would benefit from tools that enable the same sort of one-liners for this stuff that OpenBSD's package manager does. (I've written a library of shell functions for my packages.)

Addressed this way, one still gets services running under the aegides of dedicated user accounts that only own and can modify little to no part of the filesystem, but with all of the allocation/deallocation and file/directory ownership work done once, statically, at installation/deinstallation time; rather than time and again dynamically at runtime.

It's a parallel of the Do not parse configuration at runtime. principle. Do not do package management tasks, such as per-package user ID assignment and per-package directory creation/deletion, at runtime.


That's cool, though FWIW the idea of using a random UID isn't original; it's how some well-written daemons achieve privilege separation, preventing unprivileged slaves from being able to interact with each other without having to resort to unportable (and often non-existent) capability extensions. You don't need init to do this for you; you can literally just do setuid(arc4random_uniform(5000) + 60000), perhaps after doing the common startup tasks that often require privileges. (The problem with the systemd approach is that you're already unprivileged when you're invoked, which can be a major hurdle for non-trivial services which require unnecessarily complex workarounds--e.g. resorting to D-Bus machinations for otherwise simple privileged operations that you only needed in the first 30 lines of main().)

And a far simpler solution than bind mounts for achieving persistent files is to use the traditional setgid bit on the shared directory with a persistent group[1]. For example,

  mkdir /var/foo
  chown root:somegroup /var/foo
  chmod u=rwx,g=rwxs,o=rx /var/foo
You then either make that group the service process's GID or its supplementary GID if want to randomize the GID. And make sure process umasks are set correctly so newly created files are group writeable.

Altogether this is like three or four lines of code: 1) setgid or setgid + setgroup, 2) setuid, and 3) umask.

You can do all of this, today, on any Unix, with any init system. You end up with files owned by random UIDs, but systemd has no better solution than just periodically chown'ing them.

[1] If you want persistent files then there's really no burden in having a persistent group. It just makes sense.


> setuid(arc4random_uniform(5000) + 60000)

You really want something to keep track of that UID, and not re-use it, especially with that small a random space to work with. Better to allocate than just choose at random and hope for no collision.


Unless you need two such programs on the same machine, in which case they need to coordinate somehow. Perhaps by having a third service which hands out the ids as needed.


... or by having a shared-memory account database in a tmpfs at /run/systemd/dynamic-uid/ . (-:

That idea, by the way, was invented more fully and more generally about a decade and a half ago by Daniel Rench, who named it "userdir".


What a breathtakingly stupid idea. It doesn't actually solve any of the underlying problems with UID limitations, and it removes the possibility of static analysis.




Consider applying for YC's Fall 2025 batch! Applications are open till Aug 4

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: