-
-
Notifications
You must be signed in to change notification settings - Fork 3.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
core: do not enforce PrivateTmp with DynamicUser if /tmp and /var/tmp are already private tmpfs #32724
base: main
Are you sure you want to change the base?
Conversation
Important An -rc1 tag has been created and a release is being prepared, so please note that PRs introducing new features and APIs will be held back until the new version has been released. |
20c1844
to
8e1acb1
Compare
8e1acb1
to
35570fa
Compare
35570fa
to
cf0dd4e
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we also check InaccessiblePaths=
, BindReadOnlyPaths=
??
cf0dd4e
to
8234797
Compare
src/core/unit.c
Outdated
|
||
if (!tmp_found || !var_tmp_found) | ||
ec->private_tmp = true; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that said, maybe a simple fix is to not imply PrivateTmp= in case of DynamicUser=1 but instead imply TemporaryFileSystem=/tmp /var/tmp?
wouldn't that be better and simpler?
i mean, there definitely is value in keeping dynamic uids/gids local to file systems that are destroyed when the service is dead, hence changing the logic liek that would make sense to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok I've applied this change, it's slightly backward incompatible unlike the original version but if that's what it takes
or well, i generally think that things such as PrivateTmp=1 as high-level knobs are the way to go, and they should abstract what happens in the bg a bit. so i think we should just make sure it has a different effect in case DynamicUser=1 is used, i.e. make it act like TemporaryFs=/tmp + Bind=/var/tmp:/tmp |
07f51a2
to
772b5b8
Compare
This is logically equivalent to your comment above - we do want to enforce that private tmpfses are used with DynamicUser=yes, so the PrivateTmp knob becomes essentially meaningless in that case - whether it's enabled or disabled, same result applies I am not making /tmp an alias of /var/tmp as that changes too much the existing setup, where they are different directories, we can't just change that from one version to another as it is most likely going to break things, DynamicUser is used by hundreds of units in Debian alone, plus it's the default for portables |
772b5b8
to
7cc35c8
Compare
… are tmpfs DynamicUser= enables PrivateTmp= implicitly to avoid files owned by reusable uids leaking into the host. Configuring TemporaryFileSystem=/tmp/ /var/ also ensures this, so allow it as an alternative, since it has less impactful semantics with respect to PrivateTmp=yes, which links the mount namespace to the host's /tmp instead.
It is already implied by DynamicUser=yes if not set, but dropping it allows users to instead define TemporaryFileSystem=/tmp/ /var/tmp/ in their portable services, which has fewer side effects.
7cc35c8
to
bf4784a
Compare
We explicitly support that /tmp and /var/tmp is the same thing, and it's what I keep telling people: if they really want a persistent /tmp, then they should bind mount them, and not make them separate. Apps must be able to deal with the fact that /tmp + /var/tmp are a shared namespace, they must be ready to deal with concurrent access and other tools creating files there. Hence they should not be surprised at all if a conflicting inode appears any time. Hence, please, let's share the superblock there. and make one a bind mount of the other. |
@@ -4279,7 +4279,6 @@ int unit_patch_contexts(Unit *u) { | |||
* UID/GID around in the file system or on IPC objects. Hence enforce a strict | |||
* sandbox. */ | |||
|
|||
ec->private_tmp = true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i'd still imply this, it's prettier that way, because it tells external tools that we do not share the regular /tmp/ on these services
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I removed it to avoid triggering all the machinery that sets up the directories in the host filesystem, passes the pipes, adds the tracking, etc since it's not needed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And actually given the exact semantics on PrivateTmp, where the storage is actually on the host and it is visible to root there, and it can be shared, I think we should not toggle this, because it would not correspond to what actually happens, and suddenly it could mean either the new thing or the old thing.
Where is that documented? |
I checked the following: docs/TEMPORARY_DIRECTORIES.md (most comprehensive writeup we have for tmp and var/tmp) All of these mention that /tmp and /var/tmp are different, and have different semantics (persistent vs volatile, large file vs small files, etc), and nowhere it says they can be the same. |
DynamicUser=
enablesPrivateTmp=
implicitly to avoid files owned by reusable uidsleaking into the host. Configuring
TemporaryFileSystem=/tmp/ /var/
also ensuresthis, so allow it as an alternative, since it has less impactful semantics with
respect to
PrivateTmp=yes
, which links the mount namespace to the host's /tmp/instead.