XDG_SESSION_TMPDIR

Lennart Poettering mzkqt at 0pointer.de
Sat Apr 24 18:44:24 PDT 2010


On Fri, 23.04.10 17:19, Ryan Lortie (desrt at desrt.ca) wrote:

> Hi,

heya,
 
> I'd like to propose a new freedesktop spec that creates an environment
> variable for a secure session-scoped temporary directory.

I am very interested in seeing this implemented and had actually planned
to submit a very similar proposal on XDG, though more something along
the lines of a per-user/per-session /var/run/, which however I guess
boils down to similar effects.

> The main use case here is to allow a directory through which to
> synchronise intra-session IPC that for one reason or another doesn't use
> DBus.  A few examples:
> 
>   - dconf will store a journal file here of outstanding changes not yet
>     written to the database stored in the user's home directory
> 
>   - gvfs metadata storage wants to do the same
> 
>   - give a well-known location for unix sockets for session-scoped
>     services
> 
> It's conceivable that even the session D-Bus would want to create its
> socket in this directory.

Yepp, I am especially in favour of this due to all the problems people
run into when writing their own code for /tmp, where they tend to ignore
the various security implications, and lack of namespacing there. Only
very very few people get this right.

Personally, I'd really like to see such a directory for use in PA. The
code necessary to implement something like this in /tmp is just
incredibly complex.

I think instead of doing a seperate spec it would be more appropriate to
update the XDG basedir spec, however.

> --

Dude, please don't add two dashes on a single line into your
mails. That's how most mailers seperate signatures from the mail body,
and my mailer automatically cuts everything after it when I press
reply. (see RFC3676)

> For application authors:

> All processes belonging to the same session share the XDG_SESSION_TMPDIR
> environment variable (set or unset).  Specifically, any processes
> activated by the session D-Bus must have this variable set or unset
> accordingly.

I'd argue that XDG_SESSION_RUNTIME_DIR is a more appropriate name, since
I think the data you pointed out above is more like /var/run than it is
what /tmp should be used for. 

Also, there already is XDG_CACHE_HOME, which is better aligned with what
traditional /tmp does. Your XDG_SESSION_TMPDIR kinda overlaps with that,
doesn't it?

> If XDG_SESSION_TMPDIR is unset, applications must behave by falling back
> to an alternative mode of operation (which may be slower).

Hmm, they way I envisioned XDG_SESSION_RUNTIME_DIR I would actually
would have mandated that the fallback is $XDG_CACHE_HOME, and hence
~/.cache (or some subdir of that). It would then be up to the admin to
guarantee that ~/.cache is a directory capable of AF_UNIX sockets and
POSIX locking and the like, if he chooses not to set
XDG_SESSION_RUNTIME_DIR.

Of course, most reasonable distros would set XDG_SESSION_RUNTIME_DIR,
but if some minimal distributions don't want that, we'd fallback to
/home, which should be safe since those minimal distros don't tend to
have NFS home and suchlike.

The problem with putting stuff in /tmp is that it's not namespaced, and
the code to work around that is hard to get right. So to make sure that
developers don't fall in that trap I'd rather see them fall back to
$HOME then to /tmp, if XDG_SESSION_TMPDIR/XDG_SESSION_RUNTIME_DIR is
not set.

> Assuming XDG_SESSION_TMPDIR is set, it refers to a directory of mode
> 0700 that is owned by the current user.  This directory was empty at the
> start of the session (ignoring any files used by the implementation) and
> the same directory is never used by more than one session at one time.

Well, for the PA case and most other user software I can think of that
currently puts a socket in /tmp (i.e. ssh-agent, and suchlike) is
actually more interested in a per-user than a per-session dir.

> The directory is always on a native local (read: not NFS or FUSE)
> filesystem.  The directory may be on a memory-backed (read: tmpfs)
> filesystem so it is essential that the directory not be used for storage
> of large amounts of data.

I'd also mandate that it is capable of accepting AF_UNIX sockets as well
as that it is capable of POSIX file locking, and imposes no limit on the
charset for filenames. Also I'd recommend (but not mandate) that every
possible file system feature the OS supports is available on the dir
(xattrs, ...).

> Creating the directory on a memory-backed filesystem is preferred simply
> because it's faster.

Well, that's an implementation detail, and I am not sure it even is
true. Also, on 32bit archs using tmpfs is a bit problematic in some
cases, since the limited address space also limits the size of the
tmpfs. I'd not mention that in the spec.

> One possible method is to have a small program that runs as part of the
> session.  This program creates a session directory at a predictable
> location and opens a ".lock" file within that directory.  If it can
> acquire a write lock on this file then it ensures that the directory is
> empty (ie: "rm *") and uses the directory as the XDG_SESSION_TMPDIR.
> If any of this fails, the program attempts to use less predictable
> names.  If all attempts fail, the program doesn't set the environment
> variable.  The program then forks and launches the rest of the session,
> watching for SIGCHLD and cleaning up the directory when the session
> exits.

Hmpf. What I had in mind here is actually have something that is
enforced by CK when creating a session. I.e. on login, create a directory
/var/run/users/lennart-$XDG_SESSION_COOKIE or such like, which is created
and removed by priviliged CK code, and hence needs no complex locking or
privilege control. By doing management of that dir from priviliged code
things would become a lot simpler, since we can actually enforce policy
on it.

Distributions should probably mount the entire /var/run as tmpfs, and by
putting these user dirs beneath that hierarchy we'd just inherit from
that.

> Periodically a cleanup process can run to check that there are no stale
> session directories (ie: by trying to acquire the lock on them and
> deleting them if they are unlocked).

Well, that's probably something CK should take care of. I am no fan of
periodic cleanups.

> I used /dev/shm since that's a world-writable tmpfs that's available on
> most Linux boxes these days.  I don't know if that's a good idea, but it
> works.

Well, I think something below /var/run/ is more approproate.

> In order to use this, just create a file in /etc/X11/Xsession.d *after*
> where D-Bus gets launched (ie: higher number) containing:

>   STARTUP="/path/to/xdg-session-tmpdir $STARTUP"

Meh, chaining processes like this (and ssh-agent, and dbus-launch)
enforces serialized startup. Please stop coming up with systems like
this. It's evil.

> Pending discussion/flaming, I'll write this spec up properly and create
> a git repository for a simple implementation (which may or may not look
> like the one I've attached here) and start doing releases.  After that
> it should be fairly trivial to vendors to start providing this.

My recommendation → integrate this into the XDG basedir spec and into
CK. Don't write a new spec, don't write seperate code for this.

> One topic for discussion that I can see popping up is if we should have
> per-user temporary directories in addition to session-scoped ones.  I
> personally think that this is a little bit bogus.  Every now and then
> the "per-user D-Bus" discussion pops up and the consensus there seems to
> be that having more than one logged-in session of a given user is a bit
> of a fringe case and can be handled just fine in the same way that we
> handle multiple logins (on different machines) sharing an NFS home
> directory.

Well, stuff like ssh-agent and the like allow people to share ssh keys
between their logins. I'd really try to cover for this use case.

That said while I previously was behind the per-user bus idea, I changed
sides and now support Colin's ideas on this: make the session bus
something that is shared between multiple logins, so that a session is
no longer the time between one login and its logout, but instead between
the time of the first login until the last logout (i.e. the bus is
ref-counted). That way you could say that login and logout would just
add/remove a display to the session. We should encourage sharing between
sessions of the same user, not hinder it. Hence minimize seperation
between displays, not emphasize it. This is very similar to how MacOS'
launchd life-cycle is tied to ssh/gui logins. And I think it makes a lot
of sense to learn from MacOS there, because it just makes a lot of
sense. But all of this is probably something we should discuss another
time.

Anyway, I completely agree that we want something like you suggest.

Lennart

-- 
Lennart Poettering                        Red Hat, Inc.
lennart [at] poettering [dot] net
http://0pointer.net/lennart/           GnuPG 0x1A015CC4


More information about the xdg mailing list