7

Systemd has a nice feature that is private temporary directory (/tmp). But it is not clear from the dense manual what are the correct ways to use it and implementation gotchas (get the feeling the manual is more a spec for devs and contributors)

Enabling this setting has the side effect of adding Requires= and After= dependencies on all mount units necessary to access /tmp and /var/tmp.

From https://www.freedesktop.org/software/systemd/man/systemd.exec.html#PrivateTmp=

This is a little cryptic for non-systemd-insiders. I am assuming my filesystem, which for simplicity sake let's say i only have /, will receive a Requires=, guess it is left as an exercise to figure out what it will require... maybe i should put the homework tag here? :)

Starting on https://www.freedesktop.org/software/systemd/man/systemd.mount.html#x-systemd.requires=

But that doesn't sound right. It says that Requires= on mount units are only for hierarchy. I guess.

Let's move on to https://www.freedesktop.org/software/systemd/man/systemd.unit.html#Requires=

But this also does not explain anything. It only says that one unit may require another. I guess.

I'm (wildly) guessing it uses https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ReadWritePaths= So in my example the systemd unit mount for / will have a Requires=[BindPaths=[/tmp/systemd-noise,/tmp]] or however one writes that in systemd-speak?

Let's ask systemd

# systemctl show httpd ... Requires=system.slice sysinit.target -.mount tmp.mount ... RequiresMountsFor=/tmp /var/tmp 

Not very helpful either.

I'm trying to wrap my head mostly on:

  1. How exactly systemd denies access to the actual /tmp on the filesystem. And

  2. How the process (let's say a cgi running from a systemd started apache) can figure out where the /tmp it have access to is at?


Edit:

This question was from 2020, by that time systemd had just went ahead and enabled private tmp for all services without much settings or docs besides "it uses file system namespacing and bind mounts."

now in 2023 we do have more settings to control it PrivateTmp=, but the docs still only mention that high level namespaces :)

I will leave this question up in case someone want to dive in the source and document the implementation gotchas

5
  • If your final goal is to access /tmp from the host, that's easy: ls /proc/1234/root/tmp/ (where 1234 is the pid of the process) Commented Apr 1, 2020 at 7:39
  • but that assumes the process is running and that i can get the PID by parsing running processes and matching the cmd line, which is as troublesome to implement as guessing the service directory from the /tmp/systemd.*.$(service) Commented Apr 1, 2020 at 19:34
  • 1
    Related, from systemd.io: Using /tmp/ and /var/tmp/ safely Commented Aug 22, 2023 at 21:46
  • @PabloA sadly, that is mostly useless and covers the very basic concepts, if even that. it doesn't even mention where the actual tmp dirs are moved or how to find them. ...as i said on my question > without much settings or docs besides "it uses file system namespacing and bind mounts." Commented Jun 9, 2024 at 17:57
  • @A.B even with the process running, it's impossible to learn the actual location of that as it messes with bind mounts in ways i still cannot find. yeah i can drop files there at runtime, but that is a far cry from "understanding" things. Commented Jun 9, 2024 at 18:01

1 Answer 1

10

How exactly systemd denies access to the actual /tmp on the filesystem.

It doesn't, really. It just "replaces" /tmp from the perspective of the process.

It runs the process in a mount namespace where the path /tmp is not the same as the global /tmp directory. You can do this yourself with the following sequence of commands:

# run a shell in a new mount namespace unshare -m # create an empty directory mkdir /tmp/my-private-tmp # bind mount that directory on /tmp mount -o bind /tmp/my-private-tmp /tmp 

After running those commands, in the same shell, take a look at /tmp and you'll see it's empty:

# ls /tmp total 0 

Create a file in /tmp:

touch /tmp/testfile 

From a different terminal, you'll see that this was actually created in /tmp/my-private-tmp:

# ls -l /tmp/my-private-tmp 

From a different terminal, you'll see that this was actually created in /tmp/my-private-tmp:

total 0 -rw-r--r-- 1 root root 0 Aug 27 21:53 testfile 

How the process (let's say a CGI running from a systemd started Apache) can figure out where the /tmp it has access to is at?

It just uses /tmp. It doesn't need to know where the actual directory is located.


For more reading on this topic:


how does systemd decides on the new tmp location?

It creates a subdirectory in /tmp named systemd-private-<something>-<unit>-<random hash>...but I don't think that's relevant. It's sufficient to say, "systemd creates a randomly named directory for the service".

when is that decided and when is it created, if not just ephemeraly for each instance?

The directory is created when the service starts.

how is it cleaned?

The directory is removed when the service stops. From the systemd.exec man page:

all temporary files created by a service in these directories will be removed after the service is stopped.

does it respect systemd-tmpfiles commands?

No. Nor should it. systemd-tmpfiles is for creating temporary files/directories when the system boots.

how to share a semi-private tmp between two services?

From the man page:

It is possible to run two or more units within the same private /tmp/ and /var/tmp/ namespace by using the JoinsNamespaceOf= directive, see systemd.unit(5) for details.

3
  • how does systemd decides on the new tmp location? when is that decided and when is it created, if not just ephemeraly for each instance? how is it cleaned? does it respect systemd-tmpfiles commands? how to share a semi-private tmp between two services? ...those are just some questions that just knowing how it works don't answer. the implementation matters and it is not documented very well :( Commented Sep 21, 2023 at 21:13
  • 1
    I've update the answer to address your questions. Commented Sep 21, 2023 at 22:05
  • thank you! So it's still system-wide /tmp, restricted for managed services... something to keep in mind if your org wants least access to sysadmins. Also not respecting systemd-tmpfiles means it will either fill the disk and avoid rotation/cleanup or i will need full systemd utilities (and it's configs) doing that work in each machined instead of just the recommended systemd shim. Commented Sep 22, 2023 at 21:17

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.