← Back to team overview

touch-packages team mailing list archive

[Bug 1327426] Re: scopes runner should set various confinement variables

 

> > XDG_RUNTIME_DIR and TMPDIR need to be the same anyway, because
TMPDIR has to be a sub-directory of /run/user/<uid>, and the scope can't
write to locations "above" that, so it doesn't make sense to set
XDG_RUNTIME_DIR to anything but TMPDIR.

> Actually, on Ubuntu XDG_RUNTIME_DIR is set to /run/user/`id -u` as part of the user's login session. This should not be set to
> something else (and only explicitly set to '/run/user/`id -u`' it it isn't already.

At the moment, I'm not setting it at all. It's set whatever we get from
our calling environment. But I'm a bit puzzled here: unless I
misunderstand something, a confined scope can't write to this directory,
only to sub-directories of XDG_RUNTIME_DIR as set by the Apparmor
policy. I'm wondering whether that might not be surprising for the scope
if XDG_RUNTIME_DIR is not writable? (But see below, scope-specific env
vars are not an option anyway.)

>I think this is troublesome to only implement this method without
setting TMPDIR. We set TMPDIR because well-written (ie, our system)
libraries respect this. Not setting this and only offering
tmp_directory() will make it so the developer has to know to set this
separately if using some library or similar that is creating a temporary
file.

We are really running into a much deeper issue here. Environment
variables are an idea that is three decades old, and they do not play at
all well with threads and plug-in architectures. For one, there is no
way for a thread to retrieve the value of an environment variable
without risking a crash because getenv() and setenv() are not thread-
safe. Second, environment variables affect the entire process, but that
destroys the notion of having more than one run time in the same process
because the setting would have to be scope-specific. (Note that this is
entirely orthogonal to confinement.)

> Well, again, this is all about consistency for developing on Ubuntu.
If when writing an app you get PATH set, but don't for a scope, that
seems inconsistent. I guess I just figured that all this would happen
after the fork() but before the exec() of the scope-runner or the
binary. It isn't clear to me why this would affect siblings or
parents....

The issue is that several scopes can share a single process. This is not
so much because that would be an essential feature, but a software
design decision: things in libraries must have a well-defined life cycle
and must not share any hidden state. Environment variables effectively
are global variables that tie otherwise separate run time instances
together in an invisible way.

The problem here is not my design decision, the problem is TMPDIR. In a
well-defined threaded execution environment (especially when thinking
about sand-boxing) *no* library should *ever* have to read an
environment variable to decide anything. (Of course, I'm aware that
there are historical reasons for all this. But the assumptions that were
valid when TMPDIR was invented are becoming increasingly less valid, as
we are changing the security models for UNIX, and threads didn't exist
back then.)

>> That leaves UBUNTU_APPLICATION_ISOLATION. I did a Google search and
couldn't find any doc on that specific variable. But is it really
needed? It is understood that scopes are confined. If a scope really
needs to find out whether it is currently under some Apparmor profile,
it can just try doing something that won't work if confined. If the
attempt fails, the scope knows it's currently confined.

> https://wiki.ubuntu.com/SecurityTeam/Specifications/ApplicationConfinement#Launching_applications
> http://developer.ubuntu.com/publish/apps/security-policy-for-click-packages/ (see 'Runtime Environment')

Thanks for the links!

I'm immediately having problems with UBUNTU_APPLICATION_ISOLATION after
reading this and following the link to the glib patch.

While I can see that this was a pragmatic fix to an immediate problem,
it is wrong in principle:

- There is a completely invisible environment variable that is being
read in the guts of a system library in order to change the way an API
call behaves in the presence of confinement.

- The variable is set by upstart, so every process that applies an
Apparmor profile before exec'ing now also needs to set the environment
variable.

Why doesn't the system call that sets the Apparmor profile set the
environment variable automatically? And, more importantly, why is
confinement being communicated by an environment variable when it really
should be a system call? I don't read an environment variable to find
out what my umask value is; I shouldn't read an environment variable to
find out whether my process is confined.

> Also, I just want to restate that none of this is a security concern
when a scope is confined since apparmor will make sure the scope is
confined regardless of environment. I filed this bug in the hopes of
making things consistent for the developer.

Jamie, I totally understand, and thanks for raising this! I'm learning
heaps as we go along :-)

Basically, I don't want to allow anything into the run time that
requires environment variables whose values are scope-specific, because
that closes the door to having multiple run times in a single address
space without tying them together with shared global state.

The UBUNTU_APPLICATION_ISOLATION variable is a hack, IMO, and we should
nip it in the bud before it contaminates anything else. If a process
needs to find out whether it is confined or not, that should be done via
a system call, not by reading an environment variable, or the process
should do it by trying something harmless that will fail if the process
is confined.

-- 
You received this bug notification because you are a member of Ubuntu
Touch seeded packages, which is subscribed to unity-scopes-api in
Ubuntu.
https://bugs.launchpad.net/bugs/1327426

Title:
  scopes runner should set various confinement variables

Status in API for Unity scopes integration:
  Triaged
Status in “unity-scopes-api” package in Ubuntu:
  New

Bug description:
  Click apps started with ubuntu-app-launch (or via aa-exec-click via legacy desktop files) have a number of environment variables set. Eg, for a test app of mine with APP_ID of 'com.ubuntu.developer.jdstrand.click-env_click-env_0.1', the following are set by ubuntu-app-launch:
  APP_ID=com.ubuntu.developer.jdstrand.click-env_click-env_0.1
  __GL_SHADER_DISK_CACHE_PATH=/home/phablet/.cache/com.ubuntu.developer.jdstrand.click-env
  LD_LIBRARY_PATH=/opt/click.ubuntu.com/.click/users/phablet/com.ubuntu.developer.jdstrand.click-env/lib/arm-linux-gnueabihf:/opt/click.ubuntu.com/.click/users/phablet/com.ubuntu.developer.jdstrand.click-env/lib
  PATH=/opt/click.ubuntu.com/.click/users/phablet/com.ubuntu.developer.jdstrand.click-env/lib/arm-linux-gnueabihf/bin:/opt/click.ubuntu.com/.click/users/phablet/com.ubuntu.developer.jdstrand.click-env:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
  QML2_IMPORT_PATH=/opt/click.ubuntu.com/.click/users/phablet/com.ubuntu.developer.jdstrand.click-env/lib/arm-linux-gnueabihf
  TMPDIR=/run/user/32011/confined/com.ubuntu.developer.jdstrand.click-env
  UBUNTU_APPLICATION_ISOLATION=1
  XDG_CACHE_HOME=/home/phablet/.cache
  XDG_CONFIG_HOME=/home/phablet/.config
  XDG_DATA_DIRS=/opt/click.ubuntu.com/.click/users/phablet/com.ubuntu.developer.jdstrand.click-env:/usr/share
  XDG_DATA_HOME=/home/phablet/.local/share
  XDG_RUNTIME_DIR=/run/user/32011

  For scopes, we should probably do the same thing. I suggest the following:
    APP_ID=<apparmor profile name>
    LD_LIBRARY_PATH=<click install directory>/lib/$multiarch:<click install directory>/lib
    PATH=<click install directory>/lib/$multiarch/bin:<click install directory>:$PATH
    UBUNTU_APPLICATION_ISOLATION=1
    XDG_DATA_DIRS=<click install directory>:/usr/share
    XDG_DATA_HOME=$HOME/.local/share
    XDG_RUNTIME_DIR=/run/user/$UID

  APP_ID may not strictly be needed since these are scopes and not
  subject to application lifecycle, etc, but if it is provided
  developers will have a consistent environment when developing apps and
  scopes and it might make it easier for them to programmatically
  determine the location of certain directories, specifically their
  scope-specific writable area. Eg:

    my_pkgname = $APP_ID.split('_')[0]
    my_writable_dir = $XDG_DATA_HOME/unity-scopes/leaf-net/$my_pkgname

  You could also just provide an API to determine these directories (as
  was discussed at the sprint).

  TMPDIR is not listed above, but probably should be since apparmor policy does not allow access to /tmp. If you want to provide that, I suggest:
    TMPDIR=/run/user/$UID/confined-scopes/leaf-net/<'name' from click manifest>

  Note, 'leaf-net' is used for the same reason here as it is in
  {HOME}/.local/share/unity-scopes/leaf-net/@{APP_PKGNAME}/ in the
  policy: to prevent other scope types from having overlapped writable
  directories which could lead to information disclosure (see bug
  1326105 for a description of the attack). 'leaf-net' should be used
  with scopes that use the ubuntu-scope-network apparmor template and
  'leafs-fs' for scopes that use the (currently unavailable) ubuntu-
  scope-local-content apparmor template.

To manage notifications about this bug go to:
https://bugs.launchpad.net/unity-scopes-api/+bug/1327426/+subscriptions