[Dev] Tizen 3.0 proposal for fixing OSP/WRT/Core hard-coded UID issue

Stéphane Desneux stephane.desneux at eurogiciel.fr
Fri Oct 11 22:16:10 GMT 2013


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: 
https://docs.google.com/spreadsheet/ccc?key=0AjtZj4rPRmUKdE9zdG5qT2VuQ3FYNmcyc0h6eVRXTUE&usp=drive_web#gid=1). 


 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
- 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
to
# 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).


B) the launcher agent
---------------------

Actually, the primary 'launcher' is the AMD daemon (from aul package), started 
by systemd as root, with full caps (some *must* be dropped as Casey indicated). 
AMD is responsible for receiving launch requests from userland, make the 
necessary checks and pass the launch request to launchpad daemons (wrt or osp) 
to fork the app inside the user session.

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) )

On AMD side:
- 1 user = 1 environment table (in memory, probably)
- the rule for launching an app is simple: no|empty environment = no launch. 
'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. 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 perhaps 
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...

The 'AMD-agent' would be started inside the user session when needed and would 
be responsible for updating the launch environment for this user inside the AMD 
daemon:
- 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 
environment
- 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.
- 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).

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
- use SMACK (best way to secure that ?)
- ... (non exhaustive list: please complete as needed)


-----

Feel free to correct/enhance/complete my thoughts.

Best regards,
    Stéphane

-- 
Stéphane Desneux
Intel OTC - Vannes/FR


More information about the Dev mailing list