Closed Bug 1321134 Opened 5 years ago Closed 5 years ago

WebRTC and PulseAudio want and/or need write access to $XDG_RUNTIME_DIR on some systems


(Core :: Security: Process Sandboxing, defect)

Not set



Tracking Status
firefox53 --- wontfix
firefox54 --- wontfix
firefox55 --- fixed


(Reporter: jld, Assigned: jld)


(Blocks 1 open bug)


(Whiteboard: [sb+, webrtc])


(1 file)

I have a VM that runs Ubuntu 14.04, but I'm using fvwm rather than the normal Ubuntu desktop environment, and trying to use WebRTC runs into two problems with sandboxing: writing to /run/user/NNN/dconf/user (which seems to have something to do with WebRTC invoking the Necko proxy server component and trying to access the systemwide proxy config) and trying to create the directory /run/user/NNN/pulse (which already exists; pulseaudio is already running), where NNN is the uid in decimal.

I don't know what the security implications are of allowing write/create/etc. access to this /run/user directory in general or even to those two places in particular, but it's probably bad.  I also don't know why it's broken for me and not lots of other users.

I still need to see if this reproduces on any version of stock Ubuntu, but I don't have an unmodified 14.04 VM lying around.  It *does* reproduce with the official Nightly build as well as a local m-c build.

The test page I'm using is, as usual,; when affected, clicking the Start button doesn't even prompt for input devices.
(ni? to me to see how reproducible this is)
Flags: needinfo?(jld)
It's not reproducible on regular Ubuntu, and the difference is that normal Ubuntu autostarts pulseaudio with a wrapper that loads the `x11-publish` module (among others), which publishes the server info as X11 root window properties; this seems to make the pulseaudio client library just connect instead of first trying create the directory that already exists.

I do still see errors about dconf on my setup, and don't with regular Ubuntu, but that doesn't break WebRTC; not sure what's going on with that.

Also, this directory is available in the environment as XDG_RUNTIME_DIR, so if it does wind up needing special treatment it's probably better to use that than hard-code /run/user.
Flags: needinfo?(jld)
Summary: WebRTC and PulseAudio need access to /run/user on some systems → WebRTC and PulseAudio want and/or need write access to $XDG_RUNTIME_DIR on some systems
Whiteboard: sb+
Whiteboard: sb+ → sb+, webrtc
Whiteboard: sb+, webrtc → [sb+, webrtc]
See Also: → 1335329
A non WebRTC/PulseAudio case falling on the same problem is opening directory indexes (ftp://, resource:// listings).

I ended up in my_glib_log_func with the error "unable to create file '/run/user/1000/dconf/user': Permission denied" with this backtrace:

#0  my_glib_log_func (log_domain=0x7fbb75dfa0fb "dconf", log_level=G_LOG_LEVEL_CRITICAL, 
    message=0x7fbb752edd60 "unable to create file '/run/user/1000/dconf/user': 許可がありません.  dconf will not work properly.", user_data=0x0) at /home/glandium/gecko-push/toolkit/xre/nsSigHandlers.cpp:142
#1  0x00007fbba00055c4 in g_logv () from /lib/x86_64-linux-gnu/
#2  0x00007fbba00057cf in g_log () from /lib/x86_64-linux-gnu/
#3  0x00007fbb75df9abe in ?? () from /usr/lib/x86_64-linux-gnu/gio/modules/
#4  0x00007fbb75df72fb in ?? () from /usr/lib/x86_64-linux-gnu/gio/modules/
#5  0x00007fbb75df6ffc in ?? () from /usr/lib/x86_64-linux-gnu/gio/modules/
#6  0x00007fbb75df525d in ?? () from /usr/lib/x86_64-linux-gnu/gio/modules/
#7  0x00007fbb75df5e87 in ?? () from /usr/lib/x86_64-linux-gnu/gio/modules/
#8  0x00007fbba061f332 in ?? () from /usr/lib/x86_64-linux-gnu/
#9  0x00007fbba0623675 in ?? () from /usr/lib/x86_64-linux-gnu/
#10 0x00007fbba0624a12 in g_settings_get_user_value () from /usr/lib/x86_64-linux-gnu/
#11 0x00007fbb973da8b6 in HourCycle () at /home/glandium/gecko-push/intl/locale/gtk/OSPreferences_gtk.cpp:85
#12 mozilla::intl::OSPreferences::ReadDateTimePattern (this=this@entry=0x7fbb775b5720, 
    aTimeStyle=aTimeStyle@entry=mozilla::intl::OSPreferences::DateTimeFormatStyle::Long, aLocale=..., aRetVal=...)
    at /home/glandium/gecko-push/intl/locale/gtk/OSPreferences_gtk.cpp:132
#13 0x00007fbb973d76f8 in mozilla::intl::OSPreferences::GetDateTimePattern (this=0x7fbb775b5720, aDateFormatStyle=<optimized out>, 
    aTimeFormatStyle=<optimized out>, aLocale=..., aRetVal=...) at /home/glandium/gecko-push/intl/locale/OSPreferences.cpp:382
#14 0x00007fbb973d8a17 in mozilla::DateTimeFormat::FormatUDateTime (aDateFormatSelector=<optimized out>, aTimeFormatSelector=1, 
    aUDateTime=1495677810000, aTimeParameters=0x0, aStringOut=...) at /home/glandium/gecko-push/intl/locale/DateTimeFormat.cpp:173
#15 0x00007fbb97593e2f in nsIndexedToHTML::OnIndexAvailable (this=0x7fbb74efee80, aRequest=0x7fbb8c54e980, aCtxt=0x0, 
    aIndex=0x7fbb73f960e0) at /home/glandium/gecko-push/netwerk/streamconv/converters/nsIndexedToHTML.cpp:847
#16 0x00007fbb9758b000 in nsDirIndexParser::ProcessData (this=0x7fbb752edac0, aRequest=0x7fbb8c54e980, aCtxt=0x0)
    at /home/glandium/gecko-push/netwerk/streamconv/converters/nsDirIndexParser.cpp:405
#17 0x00007fbb9758b15d in nsDirIndexParser::OnDataAvailable (this=0x7fbb752edac0, aRequest=0x7fbb8c54e980, aCtxt=0x0, 
    aStream=0x7fbb74ef7b80, aSourceOffset=<optimized out>, aCount=24977)
    at /home/glandium/gecko-push/netwerk/streamconv/converters/nsDirIndexParser.cpp:343
#18 0x00007fbb9740ae4b in nsBaseChannel::OnDataAvailable (this=0x7fbb8c54e940, request=<optimized out>, ctxt=<optimized out>, 
    stream=0x7fbb74ef7b80, offset=0, count=24977) at /home/glandium/gecko-push/netwerk/base/nsBaseChannel.cpp:888
#19 0x00007fbb9741a6d7 in nsInputStreamPump::OnStateTransfer (this=this@entry=0x7fbb74e2f9c0)
    at /home/glandium/gecko-push/netwerk/base/nsInputStreamPump.cpp:621
#20 0x00007fbb9741a856 in nsInputStreamPump::OnInputStreamReady (this=0x7fbb74e2f9c0, stream=<optimized out>)
    at /home/glandium/gecko-push/netwerk/base/nsInputStreamPump.cpp:444
#21 0x00007fbb9739fdcc in nsInputStreamReadyEvent::Run (this=0x7fbb74ef9560)
    at /home/glandium/gecko-push/xpcom/io/nsStreamUtils.cpp:96
#22 0x00007fbb973abb68 in mozilla::SchedulerGroup::Runnable::Run (this=0x7fbb74eb3d30)
    at /home/glandium/gecko-push/xpcom/threads/SchedulerGroup.cpp:359

It's funny that getting preferences from dconf requires some kind of write access.
It's also funny that it somehow doesn't fail on one of the tests it does before that on the parent directories (it stat()s and access()s all of /run, /run/user, /run/user/1000 and /run/user/1000/dconf first, all of which fail with "Bad system call")
Backtrace with dconf/glib symbols, at the open() point:
#0  0x00007f2fe7c8a83d in open64 () at ../sysdeps/unix/syscall-template.S:84
#1  0x00007f2fb82f9a1a in open (__oflag=66, __path=0x7f2fb6373d80 "/run/user/1000/dconf/user")
    at /usr/include/x86_64-linux-gnu/bits/fcntl2.h:53
#2  0x00007f2fb82f9a1a in dconf_shm_open (name=0x7f2fb9afaad0 "user") at dconf-shm.c:67
#3  0x00007f2fb82f72fb in dconf_engine_source_user_reopen (source=0x7f2fb956c380) at dconf-engine-source-user.c:76
#4  0x00007f2fb82f6ffc in dconf_engine_source_refresh (source=0x7f2fb956c380) at dconf-engine-source.c:57
#5  0x00007f2fb82f525d in dconf_engine_acquire_sources (engine=engine@entry=0x7f2fb98c0c10) at dconf-engine.c:203
#6  0x00007f2fb82f6311 in dconf_engine_get_state (engine=0x7f2fb98c0c10) at dconf-engine.c:314
#7  0x00007f2fb82f6311 in dconf_engine_watch_fast (engine=0x7f2fb98c0c10, path=0x7f2fb638f540 "/org/gnome/desktop/interface/")
    at dconf-engine.c:857
#8  0x00007f2fe2773777 in g_object_new_internal (class=class@entry=0x7f2fb9c97790, params=params@entry=0x7fffca75db80, n_params=n_params@entry=1) at ././gobject/gobject.c:1823
#9  0x00007f2fe277510e in g_object_new_valist (object_type=object_type@entry=139842951294464, first_property_name=first_property_name@entry=0x7f2fe2af478f "schema-id", var_args=var_args@entry=0x7fffca75dcd0) at ././gobject/gobject.c:2042
#10 0x00007f2fe27753b1 in g_object_new (object_type=139842951294464, first_property_name=first_property_name@entry=0x7f2fe2af478f "schema-id") at ././gobject/gobject.c:1626
#11 0x00007f2fe2aba4e5 in g_settings_new (schema_id=schema_id@entry=0x7f2fdc40e9ca "org.gnome.desktop.interface")
    at ././gio/gsettings.c:965
#12 0x00007f2fd9870847 in HourCycle () at /home/glandium/gecko-push/intl/locale/gtk/OSPreferences_gtk.cpp:73

So that's what it wants write access for, shared memory.
(In reply to Mike Hommey [:glandium] from comment #4)
> So that's what it wants write access for, shared memory.

Specifically, a single bit of shared memory — but clients that only read that bit will still open the file for writing and write a 0 to the second byte.  This is to work around bugs in posix_fallocate, according to comments in

Also, the leaf filename isn't necessarily "user"; it's configurable when using a non-default dconf profile.  See for details.  It's also possible to store the database itself in $XDG_RUNTIME_DIR, but according to the source it uses the subdirectory "dconf-service", not "dconf", so it seems that we could safely allow subtree write access to $XDG_RUNTIME_DIR/dconf even in that case.

Incidentally, because I didn't actually say this when I added it to this bug's See Also: The PulseAudio part of comment #0 was fixed in bug 1335329.
All those things are implementation details... should the sandbox work around those, or should we just make our calls to dconf from sandboxed processes go the parent process via ipc?
(In reply to Mike Hommey [:glandium] from comment #6)
> All those things are implementation details... should the sandbox work
> around those, or should we just make our calls to dconf from sandboxed
> processes go the parent process via ipc?

They are and we should.  There's a question of whether that should happen at the GSettings level or individual users — as far as I know there's currently just this and the WebRTC proxy thing (which supports GConf as well as DConf and might wind up in a different process eventually anyway — bug 1287225) — but I can file a followup bug anyway.

(But then sandboxing kind of inherently means intervening in implementation details, at least on OSes designed for coarse-grained ambient authority.)
I've tested the file listing use case and it seems that dconf actually does work despite the errors, in the sense that it is able to read the pref setting.  What it can't do is cache the values it reads.

The shared memory files are used to signal that the file storing the actual prefs has changed: readers create it (with the first byte being 0) if needed, and the writer sets the first byte to 1 and unlinks it.  This way existing readers will see the change and know to reload the data, while future readers get a fresh flag that starts at 0.

If the reader failed to open or commit space for the file, dconf_shm_is_flagged() always return true, so every pref read will reread and reparse the file.

So the result of this is to (1) make long file listings slower to load, because every directory entry is a call to HourCycle() and a re-read of the dconf storage, and (2) print stuff to stderr that people will probably, and quite understandably, file bugs about.  (And/or it will mislead people who are investigating actual bugs; this kind of thing has happened before.)
No longer depends on: 1325242
See Also: → 1325242
See Also: → 1369118
Comment on attachment 8872865 [details]
Bug 1321134 - Allow access to dconf shared-memory flags.

Seems over-broad but is the simplest thing to do short of implementing an IPC proxy for dconf (or higher level on gecko side).
Attachment #8872865 - Flags: review?(mh+mozilla) → review+
Assignee: nobody → jld
Comment on attachment 8872865 [details]
Bug 1321134 - Allow access to dconf shared-memory flags.
Attachment #8872865 - Flags: review?(gpascutto) → review+
Pushed by
Allow access to dconf shared-memory flags. r=gcp,glandium
This wouldn't be eligible for uplift to 54 at this point, since there's no functional regression.
Closed: 5 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla55
Blocks: sb-audio
No longer depends on: sb-audio
See Also: → 1714018
You need to log in before you can comment on or make changes to this bug.