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
_______________________________________________
Dev mailing list
[email protected]
https://lists.tizen.org/listinfo/dev

Reply via email to