On Sat, Nov 01, 2014 at 05:21:51PM -0400, Simo Sorce wrote:
On Sat, 1 Nov 2014 17:24:53 +0100
Jakub Hrozek <jhrozek(a)redhat.com> wrote:
> On Wed, Jul 23, 2014 at 03:38:13PM +0200, Jakub Hrozek wrote:
> > === Providers ===
> > The providers are dynamically loadable libraries that are loaded by
> > the `sssd_be` process. After startup, the sssd_be process dlopens
> > the provider library and dlsyms the handlers. During sssd
> > operation, the `sssd_be` process mostly unpacks requests arriving
> > on the SBUS and calls the provider-specific handlers.
> > We have two options here - either drop the privileges in the
> > provider library itself or directly in the `sssd_be` process.
> > Dropping privileges in the `sssd_be` process has the advantage of
> > modifying only one place and being sure that no matter the back
> > end, the privileges would always be dropped.
> > On the other hand, becoming user in the library itself might be
> > beneficial for scenarios where the back end requires root access for
> > initialization. Also, if some third-party proprietary module
> > absolutely requires to run as root, we shouldn't enforce the
> > privilege drop.
> > If we don't care about the third party modules, we could take an
> > approach where the provider would drop privilege as soon as it can
> > and after all the initialization was completed, the sssd_be process
> > would ensure the privileges are indeed dropped. Because there are
> > no third party back ends so far and there was no attempt to write
> > one, this is currently safe.
> After some experimentation and poking at the krb5 code, I think a
> different route is needed. We can't reasonably drop the privileges in
> the provider's setup routines themselves, because we don't know if
> another provider needs root privileges or not. For example consider a
> LDAP + Kerberos combination, the LDAP ID provider can't drop
> privileges until Kerberos provider initializes because the Kerberos
> provider might need root privileges to check exisiting ccaches for
> renewal after startup.
> We can drop privileges after the whole initialization finishes, but we
> should strive to reduce the privileged code even further.
> Michal had an idea of adding another function to the providers that
> would perform privileged init, then sssd_be would drop privs and
> proceed with the rest of the init.
> So the initialization would change from:
> id_provider = dlopen()
> id_init = dlsym(id_provider)
> auth_provider = dlopen()
> auth_init = dlsym(auth_provider)
> to something like:
> id_provider = dlopen()
> auth_provider = dlopen()
> privileged_id_init = dlsym(id_provider)
> privileged_auth_init = dlsym(auth_provider)
> The privileged init would initialize private data the provider needs
> and pass it on to the non-privileged init code.
> There are some other alternatives, like a setuid setup process or
> performing the initialization in the monitor, but I like this option
> the best because passing on complex data structures between processes
> is tricky. This way we also keep no knowledge about provider internals
> outside the provider code.
> Simo, I CC-ed you directly because I know you prefer to be aware of
> changes to the data_provider_be.c module. Do you agree with this plan?
Are we sure we will be able to meaningfully separate "privileged
initialization" from non-privileged items ?
Right now we've identified the places that need root access during
initialization because we crawled the whole SSSD codebase while making
it rootless -- they're the keytab processing after startup of IPA and AD
providers and reading the ccaches of users when initializing the
renewal. In general, the only access where we might fail unprivileged
atm is keytab access or ccache access.
I can't guarantee other problems in the future, true, but that's not a
problem limited to initialization, but we might run into a similar
problem during runtime as well.
My fear is that we complicate the init system and end up having all
initialization in privileged_*_init() anyway, and *_init() become empty
I am comfortable with keeping the whole init privileged TBH.
Right, the initialization is a small window, at least time-wise, compared to
the code that runs during regular SSSD execution. Separating the privileged
init would have two benefits from my point of view.
1) Making the surface of the code that runs as root smaller in
general. This is mostly interested in downstream groups that aim at
limiting the root code.
2) Being able to separate the code that we know is required to run
privileged and be able to unit test SSSD as a whole during make
check, using wrappers.
With 1) we can wait for some feedback from downstream. 2) is more of a
convenience -- in order for SSSD to run as a completely different user,
we need to do changes in the monitor (like stop requiring that monitor
runs as root)
In conclusion, for now maybe we can file a ticket describing the privileged
init, defer it and wait for downstream feedback as well as see how our
testing with a custom destdir goes. Revive this ticket if we see a need
and keep the backend init privileged now.