• Introducing Dynamic Users

    With systemd dynamic users we hope to make it easier and cheaper to allocate system users on-the-fly, thus significantly increasing the possible uses of this core UNIX security concept.

     

    If you write a systemd service unit file, you may enable the dynamic user logic for it by setting the DynamicUser = option in its [Service] section to yes. If you do a system user is dynamically allocated the instant the service binary is invoked and released again when the service terminates. The user is automatically allocated from the UID range 61184–65519, by looking for a so-far unused UID.

     

    Now you may wonder, how does this concept deal with the sticky user issue discussed above? In order to counter the problem, two strategies easily come to mind:

     

    Prohibit the service from creating any files/directories or IPC objects

     

    Automatically removing the files/directories or IPC objects the service created when it shuts down.

    In systemd we implemented both strategies, but for different parts of the execution environment. Specifically:

     

    Setting DynamicUser = yes implies ProtectSystem = strict and ProtectHome = read-only. These sand-boxing options turn off write access to pretty much the whole OS directory tree, with a few relevant exceptions, such as the API file systems / proc, / sys, and so on, as well as / tmp and / var / tmp. (BTW: setting these two options on your regular services that do not use DynamicUser = is a good idea too, as it drastically reduces the exposure of the system to exploited services.)

     

    Setting DynamicUser = yes implies PrivateTmp = yes. This option sets up / tmp and / var / tmp for the service in a way that it gets its own, disconnected version of these directories, that are not shared by other services, and whose life-cycle is bound to the service's own life- cycle. Thus if the service goes down, the user is removed and all its temporary files and directories with it. (BTW: as above, consider setting this option for your regular services that do not use DynamicUser = too, it's a great way to lock things down security-wise.)

     

    Setting DynamicUser = yes implies RemoveIPC = yes. This option ensures that when the service goes down all SysV and POSIX IPC objects (shared memory, message queues, semaphores) owned by the service's user are removed. Thus, the life-cycle of the IPC objects is bound to the life-cycle of the dynamic user and service, too. (BTW: yes, here too, consider using this in your regular services, too!)

     

    With these four settings in effect, services with dynamic users are nicely sand-boxed. They cannot create files or directories, except in / tmp and / var / tmp, where they will be removed automatically when the service shuts down, as will any IPC objects created. Sticky ownership of files/directories and IPC objects are hence dealt with effectively.

     

    The RuntimeDirectory = option may be used to open up a bit of the sandbox to external programs. If you set it to a directory name of your choice, it will be created below / run when the service is started, and removed in its entirety when it is terminated. The ownership of the directory is assigned to the service's dynamic user. This way, a dynamic user service can expose API interfaces (AF_UNIX sockets,…) to other services at a well-defined place and again bind the life-cycle of it to the service's own run-time. Example: set RuntimeDirectory = foobar in your service, and watch how a directory/run/foobar appears at the moment you start the service, and disappears the moment you stop it again. (BTW: Much like the other settings discussed above, RuntimeDirectory = may be used outside of the DynamicUser = context too, and is a nice way to run any service with a properly owned, life-cycle-managed run-time directory.)

     

    Persistent data

    Of course, a service running in such an environment (although already very useful for many cases!), Has a major limitation: it cannot leave persistent data around it can reuse on a later run. As pretty much the whole OS directory tree is read-only to it, there's simply no place it could put the data that survives from one service invocation to the next.

     

    With systemd 235 this limitation is removed: there are now three new settings: StateDirectory =, LogsDirectory =, and CacheDirectory =. In many ways they operate like RuntimeDirectory =, but create sub-directories below / var / lib, / var / log and / var / cache, respectively. There's a major difference beyond that, however: directories created that way are persistent, they will survive the run-time cycle of a service, and thus may be used to store data that is supposed to stay around between invocations of the service.

     

    Of course, the obvious question to ask now is: how do these three settings deal with the sticky file ownership problem?

     

    For that, we lifted a concept from container managers. Container managers have a very similar problem: each container and the host typically end up using a very similar set of numeric UIDs, and unless user name-spacing is deployed this means that host users might be able to access the data of specific containers that also have a user by the same numeric UID assigned, even though it actually refers to a very different identity in a different context. (Actually, it's even worse than just getting access, due to the existence of setuid file bits, access might translate to privilege elevation.) The way container managers protect the container images from the host (and from each other to some level) is by Placing the container trees below a boundary directory, with very restrictive access modes and ownership (0700 and root: root or so). A host user hence cannot take advantage of the files/directories of a container user of the same UID inside of a local container tree, simply because the boundary directory makes it impossible to even reference files in it. After all on UNIX, in order to get access to a specific path you need access to every single component of it.

     

     

    How is that applied to dynamic user services? Let's say StateDirectory = foobar is set for a service that has DynamicUser = turned off. The instant the service is started, / var/lib/foobar is created as state directory, owned by the service's user, and remains in existence when the service is stopped. If the same service now is run with DynamicUser = turned on, the implementation is slightly altered. Instead of a directory/var/lib/foobar, a symbolic link by the same path is created (owned by root), pointing to / var/lib/private/foobar (the latter being owned by the service's dynamic user). The / var/lib / private directory is created as boundary directory: it's owned by root: root, and has a restrictive access mode of 0700. Both the symlink and the service's state directory will survive the service's life-cycle, but the state directory will remain and continues to be owned by the now disposed of dynamic UID - however it is protected from other host users (and other services which might get the same dynamic UID assigned due to UID recycling) by the boundary directory.

     

    The obvious question to ask now is: but if the boundary directory prohibits access to the directory from unprivileged processes, how can the service itself which runs under its own dynamic UID access it anyway? This is achieved by invoking the service process in a slightly modified mount name-space: it will see most of the file hierarchy the same way as everything else on the system (modulo / tmp and / var / tmp as mentioned above), except for / var/lib / private, which is over-mounted with a read-only tmpfs file system instance, with a slightly more liberal access mode permitting the service read access. Inside of this tmpfs file system instance, another mount is placed: a bind mount to the host's real / var/lib / private / foobar directory, onto the same name. Putting this together with these means that superficially everything looks the same and is available at the same place on the host and from inside the service, but two important changes have been made: the / var/lib / private boundary directory lost its restrictive character inside the service and has been emptied of the state directories of any other service, thus making the protection complete. Note that the symlink/var/lib/foobar hides the fact that the boundary directory is used (making it a little more than an implementation detail), as the directory is available this way under the same name as it would be if DynamicUser = was not used. Long story short: for the daemon and from the view from the host the indirection through / var/lib / private is mostly transparent.

     

    This logic, of course, raises another question: what happens to the state directory if a dynamic user service is started with a state directory configured, gets UID X assigned on this first invocation, then terminates and is restarted and now gets UID Y assigned on the second invocation, with X ≠ Y? On the second invocation the directory - and all the files and directories below it - will still be owned by the original UID X so how could the second instance run as Y access it? Our way out is simple: systemd will recursively change the ownership of the directory and everything contained within it to UID Y before invoking the service's executable.

     

    Of course, such recursive ownership changing (chown () ing) of whole directory trees can become expensive (though according to my experiences, IRL and for most services, it's much cheaper than you might think), hence in order to optimize behavior in this regard, the allocation of dynamic UIDs has been tweaked in two ways to avoid the necessity to do this expensive operation in most cases: firstly, when a dynamic UID is allocated for a service an allocation loop is employed that starts out with a UID hashed from the service's name. This means a service by the same name is likely to always use the same numeric UID. That means that a stable service name translates into a stable dynamic UID, and that means recursive file ownership adjustments can be skipped (of course, after validation). Secondly, if the configured state directory already exists, and is owned by a suitable currently unused dynamic UID, it's preferably used above everything else, thus maximizing the chance we can avoid the chown () ing. (That all said, ultimately we have to face it, the currently available UID space of 4K + is very small still, and conflicts are pretty likely sooner or later, thus a chown () ing to be expected every now and then when this feature is used extensively).

     

    http://omaaa.eklablog.com/
    http://omaaa.eklablog.fr/
    http://dynamic.eklablog.com/


    http://omaaa.ek.la/
    http://dynamic.eklablog.net/
    http://dynamic.eklablog.fr/
    http://dynamic.ek.la/
    http://omaaa.lo.gs/
    http://dynamic.lo.gs/
    http://dynamic.id.st/
    http://omaaa.id.st/
    http://dynamic.cd.st/
    http://dynamic.revolublog.com/
    http://omaaa.cd.st/
    http://dynamic.blogg.org/
    http://omaaa.revolublog.com/
    http://omaaa.blogg.org/
    http://omaaa.kazeo.com/
    http://government-jobs.eklablog.com/
    http://government-jobs.eklablog.net/
    http://government-jobs.eklablog.fr/
    http://government-jobs.ek.la/
    http://government-jobs.lo.gs/
    http://government-jobs.id.st/
    http://foodr.eklablog.net/
    http://government-jobs.cd.st/
    http://foodr.eklablog.fr/
    http://government-jobs.revolublog.com/
    http://government-jobs.blogg.org/
    http://foodr.ek.la/
    http://government-jobs.kazeo.com/
    http://foodr.lo.gs/
    http://foodr.id.st/
    http://foodr.cd.st/
    http://foodr.revolublog.com/
    http://foodr.blogg.org/
    http://foodr.kazeo.com/
    http://astrology.eklablog.net/
    http://astrology.eklablog.fr/
    http://astrology.ek.la/
    http://astrology.lo.gs/
    http://astrology.id.st/
    http://astrology.cd.st/
    http://astrology.revolublog.com/
    http://jobsoo.eklablog.com/
    http://astrology.blogg.org/
    http://astrology.kazeo.com/
    http://jobsoo.eklablog.net/
    http://jobsoo.eklablog.fr/
    http://jobsoo.ek.la/
    http://jobsoo.lo.gs/
    http://sco-service.kazeo.com/
    http://jobsoo.id.st/
    http://sco-service.eklablog.net/
    http://foodr.eklablog.com/
    http://jobsoo.cd.st/
    http://sco-service.eklablog.fr/
    http://jobsoo.revolublog.com/
    http://sco-service.ek.la/
    http://jobsoo.blogg.org/
    http://jobsoo.kazeo.com/
    http://sco-service.lo.gs/
    http://sco-service.cd.st/
    http://sco-service.revolublog.com/
    http://sco-service.blogg.org/
    http://sco-service.id.st/
    http://omaaa.eklablog.net/

     

     

    http://coffee.eklablog.net/
    http://cofee.eklablog.com/
    http://coffee.revolublog.com/
    http://coffee.cd.st/
    http://coffee.blogg.org/
    http://coffee.blogg.org/
    http://coffee.kazeo.com/
    http://coffee.id.st/
    https://coffee.eklablog.fr/
    http://coffee.ek.la/
    http://chocolate.ek.la/
    http://chocolate.kazeo.com/
    http://chocolate.revolublog.com/
    http://chocolate.cd.st/
    http://chocolate.id.st/
    http://chocolate.lo.gs/
    http://chocolate.eklablog.fr/
    http://chocolate.eklablog.net/
    http://chocolate.blogg.org/
    http://chocolate.eklablog.com/
    http://diabtese.eklablog.com/
    http://diabtese.eklablog.net/
    http://diabtese.eklablog.fr/
    http://diabtese.ek.la/
    http://diabtese.lo.gs/
    http://diabtese.id.st/
    http://diabtese.cd.st/
    http://diabtese.revolublog.com/
    http://diabtese.blogg.org/
    http: //diabtese.kazeo.com/ \
    http://coffee.eklablog.net/
    http://cofee.eklablog.com /
    http://coffee.revolublog.com/
    http://coffee.cd.st/
    http://coffee.blogg.org/
    http://coffee.blogg.org/
    http://coffee.kazeo.com /
    http://coffee.id.st/
    https://coffee.eklablog.fr/
    http://coffee.ek.la/
    http://chocolate.ek.la/
    http://chocolate.kazeo.com /
    http://chocolate.revolublog.com/
    http://chocolate.cd.st/
    http://chocolate.id.st/
    http://chocolate.lo.gs/
    http://chocolate.eklablog.fr/
    http://chocolate.eklablog.net/
    http://chocolate.blogg.org/
    http://chocolate.eklablog.com/
    http://diabtese.eklablog.com/
    http://diabtese.eklablog.net/
    http://diabtese.eklablog.fr/
    http://diabtese.ek.la/
    http://diabtese.lo.gs/
    http://diabtese.id.st/
    http://diabtese.cd.st/
    http://diabtese.revolublog.com/
    http://diabtese.blogg.org/
    http://diabtese.kazeo.com/


    votre commentaire



    Suivre le flux RSS des articles
    Suivre le flux RSS des commentaires