[Dev] Tizen 3.0 proposal for fixing OSP/WRT/Core hard-coded UID issue
casey.schaufler at intel.com
Fri Oct 11 23:16:42 GMT 2013
> -----Original Message-----
> From: Stéphane Desneux [mailto:stephane.desneux at eurogiciel.fr]
> Sent: Friday, October 11, 2013 3:16 PM
> To: Schaufler, Casey
> Cc: dev at lists.tizen.org
> Subject: Re: [Dev] Tizen 3.0 proposal for fixing OSP/WRT/Core hard-coded UID
> Schaufler, Casey wrote:
> > Dominique and I discussed the underlying problem in some detail and
> > believe that we have a cleaner solution.
> > The plan is to have one launcher that services all requests.
> > The launcher will have to be privileged, but will reduce the
> > capabilities required to the extent possible.
> > The launcher will accept a message from the user session handling
> > portion of systemd that contains the environment information assigned
> > to the user when the session is started.
> > The launcher will accept a similar tear-down message from the systemd
> > user session manager as well.
> > In the future the set of messages accepted by the launcher may be
> > expanded to accommodate modification of the user environment.
> > The systemd user session initialization and tear-down will be modified
> > (extended?) to send the user environment information to the launcher.
> > This is a saner approach than attempting to glean the information from
> > another process. It provides a clean interface and assurance that the
> > information is accurate.
> > It allows for future extension. It works with the systemd model,
> > rather than at odds with it.
> Hello Casey and others listening,
> First, I agree with the plan you found with Dominique: using /proc/PID/xxx to
> retrieve anything is too insecure. On the other side, using SO_PEERCRED or
> SCM_CREDENTIALS to retrieve uids seems correct.
> I've a few points to share with you to go further.
> A) choosing the right environment source: not so easy
> I've checked how the various daemons are launched on the system (for IVI and
> tizen/common in particular - see 2nd sheet on the document previously shared:
> From what I saw, things at startup seem to be done roughly in the following
> order (please adjust if I'm wrong):
> - systemd (root) reaches the default target (say graphical.target)
> - it triggers a user-session.service which launches 'systemd --user'
> - systemd --user opens a PAM session (this is a point where action is possible)
> and then runs as the real user who logs in
You are correct. This is where "action is possible".
After the environment information is gathered but
before the security attributes of the user are set the
message about the new user session is sent to the
Environment information that is set after the real
user logs in (i.e. effective UID is set) cannot be trusted.
Neither can messages received from real user sessions
be trusted to provide accurate environment information.
Therefore the message must be sent here, and only
information that is available prior to the switch to the
real user can be used.
> - systemd --user then runs the required user services to setup everything: dbus
> session, desktop (ex: weston), 'shell' (ex: ivi_shell, E18 or anything like an
> enhanced window manager) and potentially all user related daemons.
> - then in the 'desktop' environment, a user is supposed to launch an application.
> I wanted to point that the right environment to copy/paste into the application
> environment is not the one in systemd --user: this environment is quite dry and
> doesn't contain enough information. For example (taken from various profiles):
> wayland display, wayland seat#, dbus session address, LANG, XXX_KEYRING,
> XAUTHORITY, agents infos, various agents vars (SSH,GPG etc.) ... are *not* set
> at this early time.
> To get an idea, on recent IVI snapshots just compare weston env to systemd
> --user env:
> # tr '\0' '\n' </proc/$(pgrep -u app -f /usr/bin/weston)/environ
> # tr '\0' '\n' </proc/$(pgrep -u app -f /usr/lib/systemd/systemd)/environ
> If we don't want to set a static address for the dbus session address (would it
> be a security hole ?), it may even be more tricky: the DBUS session address will
> be set when libdbus forks dbus--session, i.e. when the first dbus app will
> start. From a security POV, I prefer random sockets but it's even harder to
> define what's the correct environment to paste into the application process.
> Trying to set static environment variables for most services could probably help
> but I'm not sure we can cover *all* services this way.
> So the solution is perhaps not so related to systemd (even if systemd could help
> on some points).
Whether the code of systemd is changed or if the work is
done by something invoked by systemd it should be clear
that systemd is an integral part of the solution, just as it is
part of the problem today.
> B) the launcher agent
> Actually, the primary 'launcher' is the AMD daemon (from aul package),
> by systemd as root, with full caps (some *must* be dropped as Casey
> AMD is responsible for receiving launch requests from userland, make the
> necessary checks and pass the launch request to launchpad daemons (wrt or
> to fork the app inside the user session.
AMD is what needs to be extended to accept notifications
about user sessions being created and destroyed. In the future
it might accept requests to modify a session's environment,
but that's beyond what we're discussing now.
> If I understand your proposal, we should develop a kind of agent, able to
> maintain a proper environment for each user inside the AMD daemon (typically
> send RPCs like: init(uid,[vars]), update (uid,[vars]), exit(uid) )
I don't know that I'd go so far as to call it an agent.
A simple table mapping a UID to an environment should suffice.
> On AMD side:
> - 1 user = 1 environment table (in memory, probably)
> - the rule for launching an app is simple: no|empty environment = no launch.
I love simple! Yes.
> 'good' environment = launch in this environment (propagated to launchpads).
> There is perhaps a security enhancement here, as an app couldn't be run in the
> user environment after logout.
That is supported by the session termination message, which
tells AMD to discard the environment for the UID.
> By extension, an application cannot be run for
> another user (= no 'su' for apps !) Put in another way: I should check if the
> actual AMD and launchpads care about checking what's being run: they
> just setuid() with the appropriate user and run the app. If the user session is
> not open, any app would crash, except if it's some kind of malicious app that
> could inspect user data...
It's easier than that. The launch request comes in, SO_PEERCRED
provides the UID. AMD looks for the environment by UID and if
there is not one it responds with an error and otherwise does
> The 'AMD-agent' would be started inside the user session when needed and
> be responsible for updating the launch environment for this user inside the
> - is transient: the agent runs, sends a message then terminates. It's not a
> daemon as it would just run few times inside the session.
> - is run initially at some point in the session init (by systemd probably at the
> end of init -OR- run at some point by the desktop manager itself because env is
> more rich).
> - is run during the user session when needed (how to trigger ?) to update the
> - pushes some environment init/updates: what if we just push the agent
> environment when it was launched (i.e. the environment created by our parent
> process) ? No need to pass a lot of args... Some vars could be filtered for
> security reasons.
I'm very wary of this. I think we could do selective updates to
the user environment on the fly, but it would require great care.
> - is run at logout time to cleanup things on AMD side (the user shouldn't be
> able to launch anything after this, and env should be zeroed on AMD side).
This is why I want systemd involved. Systemd knows when a user
session goes away. It can trigger sending the message that clears the
environment, and because it's from outside the user session it
should be reliable.
> On the security side, the amd-agent should be privileged to avoid spoofing and
> the amd daemon must authenticate the received RPCs:
> - amd-agent could have the set-user-ID bit to run as root
> - amd/amd-agent could use SO_PEERCRED/SCM_CREDENTIALS for
> authentication base on uid
If, for some reason, we can't use systemd session management
to achieve this we could resort to an agent like you've described.
I think that systemd has all of the bells and whistles needed to
> - use SMACK (best way to secure that ?)
This is another good bit of using systemd. All of
the set-up and tear-down gets done in the Smack
context of the system. The user session runs in a
user context and AMD can use the Smack label of
the requestor (SO_PEERSEC) to ensure that set-up
and tear-down requests are coming from the right
> - ... (non exhaustive list: please complete as needed)
I'm sure there are painful details we haven't thought
of yet. I think that by using the tools we have in the
way they're designed to work we should be able to
address any rational issue. Of course, it's the irrational
things people want the system to do that always cause
> Feel free to correct/enhance/complete my thoughts.
> Best regards,
> Stéphane Desneux
> Intel OTC - Vannes/FR
More information about the Dev