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