Looking for alternative to RESTRICT=userpriv

classic Classic list List threaded Threaded
17 messages Options
Reply | Threaded
Open this post in threaded view
|

Looking for alternative to RESTRICT=userpriv

Michał Górny-5
Hello, developers.

I've been doing some research wrt use of RESTRICT=userpriv [1] lately
and found out that most of the affected packages use it solely to gain
access to files or devices that are restricted to specific groups. I've
specifically noted three cases:

1) ebuilds using CUDA that needed to access /dev/nvidia* (restricted to
video group),

2) game ebuilds that needed to access game executables (restricted to
games group but hopefully subject to change),

3) qmail-related ebuilds that needed to access restricted files (no
details yet).

I believe that most (if not all) of uses of RESTRICT=userpriv are
overkill. It implies elevating privileges for the whole build process
while what's really needed is an access to a particular file or device,
or a capability of some kind for a single command execution.

I would therefore like to ask the Community for ideas on how
RESTRICT=userpriv could be effectively replaced by something safer.


I can enumerate the following possibilities:

a) explicitly requesting user to alter group membership for the build
user. This is already done in some of the CUDA ebuilds.

Advantages:

- limits elevated privileges to a particular group access,

- works now.

Disadvantages:

- requires manual intervention (we even can't properly name the user
  since there's no PMS function/variable to obtain it),

- increases privileges for all ebuilds rather than the one needing it.
  Developers using it will not get proper failures for ebuilds not
  having the check,

- doesn't cover other uses of FEATURES=userpriv.


b) SUPPLEMENTARY_GROUPS support [2]. The idea is to use setgroups() to
transparently enable group membership for the build process.

Advantages:

- transparent, relatively simple.

Disadvantages:

- quite ugly name ;),

- doesn't cover other uses of FEATURES=userpriv.


c) 'esudo' helper [3]. This is a more generic form of (2), with support
for other potential privilege changes.

Advantages:

- allows to raise privileges precisely for one command,

- flexible -- may alter EUID, EGID, groups, capabilities.

Disadvantages:

- hard to implement -- especially if we want to make it capable of
  running bash functions.


What do you think? Do you have other ideas?


[1]:https://bugs.gentoo.org/show_bug.cgi?id=516568
[2]:https://bugs.gentoo.org/show_bug.cgi?id=516614
[3]:https://bugs.gentoo.org/show_bug.cgi?id=516616

--
Best regards,
Michał Górny

signature.asc (968 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Looking for alternative to RESTRICT=userpriv

Ulrich Mueller-2
>>>>> On Tue, 8 Jul 2014, Michał Górny wrote:

> a) explicitly requesting user to alter group membership for the
> build user. This is already done in some of the CUDA ebuilds.

> [...]

This doesn't work out of the box for users, therefore it is not really
a solution.

> b) SUPPLEMENTARY_GROUPS support [2]. The idea is to use setgroups()
> to transparently enable group membership for the build process.

> Advantages:

> - transparent, relatively simple.

> Disadvantages:

> - quite ugly name ;),

Certainly this can be changed. :)

> - doesn't cover other uses of FEATURES=userpriv.

Which ones? Are there examples for such uses in the Portage tree?

> c) 'esudo' helper [3]. This is a more generic form of (2), with
> support for other potential privilege changes.

> [...]

> Disadvantages:

> - hard to implement -- especially if we want to make it capable of
>   running bash functions.

Any idea how to implement it? Does it imply adding app-admin/sudo to
the system set?

> What do you think? Do you have other ideas?

Looking at the bugs that you have filed, it looks like most ebuilds
using userpriv restriction could be fixed, without any additional
support added to the package manager.

How many ebuilds will be left, after doing these fixes? Is it really
worth the effort then?

Ulrich

attachment0 (501 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Looking for alternative to RESTRICT=userpriv

Joshua Kinard-2
In reply to this post by Michał Górny-5
On 07/08/2014 09:25, Michał Górny wrote:
>
> 3) qmail-related ebuilds that needed to access restricted files (no
> details yet).

I believe this relates to /var access.  qmail is noted in our security
guide[1] for its desire to want to install itself into /var/qmail[2],
including binaries, libs, etc.

1. http://www.gentoo.org/doc/en/security/security-handbook.xml?part=1&chap=4
2. http://cr.yp.to/qmail/var-qmail.html

--
Joshua Kinard
Gentoo/MIPS
[hidden email]
4096R/D25D95E3 2011-03-28

"The past tempts us, the present confuses us, the future frightens us.  And
our lives slip away, moment by moment, lost in that vast, terrible in-between."

--Emperor Turhan, Centauri Republic

Reply | Threaded
Open this post in threaded view
|

Re: Looking for alternative to RESTRICT=userpriv

Michał Górny-5
In reply to this post by Ulrich Mueller-2
Dnia 2014-07-08, o godz. 16:17:02
Ulrich Mueller <[hidden email]> napisał(a):

> >>>>> On Tue, 8 Jul 2014, Michał Górny wrote:
>
> > b) SUPPLEMENTARY_GROUPS support [2]. The idea is to use setgroups()
> > to transparently enable group membership for the build process.
>
> > Advantages:
>
> > - transparent, relatively simple.
>
> > Disadvantages:
>
> > - quite ugly name ;),
>
> Certainly this can be changed. :)
>
> > - doesn't cover other uses of FEATURES=userpriv.
>
> Which ones? Are there examples for such uses in the Portage tree?
I meant RESTRICT=userpriv, of course :).

So far most of the 'why are you blocking userpriv?' bugs lie with no
answer but there's already the case of fatsort which tests loop-mount
a VFAT filesystem and use it to run tests. This effectively makes it
require CAP_SYSADMIN.

Of course, we could discuss that the test is very wrong to do that,
that it fails when there's no VFAT support in kernel etc. I'd love to
see upstream switching to some userspace FAT manipulation tools
(mtools, for example) but it's not my call.

> > c) 'esudo' helper [3]. This is a more generic form of (2), with
> > support for other potential privilege changes.
>
> > [...]
>
> > Disadvantages:
>
> > - hard to implement -- especially if we want to make it capable of
> >   running bash functions.
>
> Any idea how to implement it? Does it imply adding app-admin/sudo to
> the system set?
I don't think we'd use the reference 'sudo' impl. Rather some
in-portage helper, possibly setuid. Or portage's IPC but that would
imply running the command in an isolated environment (possibly
beneficial).

> > What do you think? Do you have other ideas?
>
> Looking at the bugs that you have filed, it looks like most ebuilds
> using userpriv restriction could be fixed, without any additional
> support added to the package manager.
>
> How many ebuilds will be left, after doing these fixes? Is it really
> worth the effort then?

What kind of fixes do you mean? Killing the games group? Adding ACLs
for portage user?

Please also remember that the bugs don't cover all cases. For example,
many CUDA/nvidia cases use solution alike (1) at the moment.

--
Best regards,
Michał Górny

signature.asc (968 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Looking for alternative to RESTRICT=userpriv

Zac Medico-2
On 07/09/2014 07:17 AM, Michał Górny wrote:

>>> c) 'esudo' helper [3]. This is a more generic form of (2), with
>>> support for other potential privilege changes.
>>
>>> [...]
>>
>>> Disadvantages:
>>
>>> - hard to implement -- especially if we want to make it capable of
>>>   running bash functions.
>>
>> Any idea how to implement it? Does it imply adding app-admin/sudo to
>> the system set?
>
> I don't think we'd use the reference 'sudo' impl. Rather some
> in-portage helper, possibly setuid. Or portage's IPC but that would
> imply running the command in an isolated environment (possibly
> beneficial).

The environment doesn't necessarily have to be isolated, since we could
extend the existing environment saving/loading support to be used for by
esudo. The steps to implement the shared environment could be as follows:

1) When esudo is called, it saves the current (unprivileged) bash
environment to a file.

2) esudo uses IPC to request that a process with elevated privileges be
launched to run a specific command using the saved environment, and that
the environment of the elevated process be saved to a file after the
command completes.
3) Before esudo returns, it loads the environment that was saved by the
elevated process before it exited.

Of course, we could also use pipes as a substitute for saving the
environments to temporary files.
--
Thanks,
Zac

Reply | Threaded
Open this post in threaded view
|

Re: Re: Looking for alternative to RESTRICT=userpriv

Steven J. Long
On Wed, Sep 24, 2014 at 09:51:31PM -0700, Zac Medico wrote:
> On 07/09/2014 07:17 AM, Michał Górny wrote:
> >>> c) 'esudo' helper [3]. This is a more generic form of (2), with
> >>> support for other potential privilege changes.
> >>
..

> > I don't think we'd use the reference 'sudo' impl. Rather some
> > in-portage helper, possibly setuid. Or portage's IPC but that would
> > imply running the command in an isolated environment (possibly
> > beneficial).
>
> The environment doesn't necessarily have to be isolated, since we could
> extend the existing environment saving/loading support to be used for by
> esudo. The steps to implement the shared environment could be as follows:
>
> 1) When esudo is called, it saves the current (unprivileged) bash
> environment to a file.
>
> 2) esudo uses IPC to request that a process with elevated privileges be
> launched to run a specific command using the saved environment, and that
> the environment of the elevated process be saved to a file after the
> command completes.

I don't think it's going to be quite that easy to get the output env,
certainly not from some random command; tbh I don't even see the need
for it, unless I'm missing something. From the "elevated process" after
it waits on the child, but not from the child unless you control the
code.

> 3) Before esudo returns, it loads the environment that was saved by the
> elevated process before it exited.

What's the use-case for this part? I could see it with a function, but
then you just run that as part of the ebuild. For running a specific
command to access a device with privilege, or to add a user etc, I
don't really see the point. (so why bother with the implementation
complexity.)

Other than that, I agree esudo is the best approach, and gives us
much better granularity over privilege escalation, as discussed in
the bug.

Part of me thinks though, that it'd be much cleaner to give the
portage user access to sudo. Isn't that effectively the purpose
of the "suid helper"? In which case we get all the options for
env etc, of sudo, and the admin gets to configure it along with
the normal wheel setup.

Just a thought.
Regards,
igli
--
#friendly-coders -- We're friendly, but we're not /that/ friendly ;-)

Reply | Threaded
Open this post in threaded view
|

Re: Re: Looking for alternative to RESTRICT=userpriv

Zac Medico-2
On 09/28/2014 09:23 PM, Steven J. Long wrote:

> On Wed, Sep 24, 2014 at 09:51:31PM -0700, Zac Medico wrote:
>> On 07/09/2014 07:17 AM, Michał Górny wrote:
>>>>> c) 'esudo' helper [3]. This is a more generic form of (2), with
>>>>> support for other potential privilege changes.
>>>>
> ..
>>> I don't think we'd use the reference 'sudo' impl. Rather some
>>> in-portage helper, possibly setuid. Or portage's IPC but that would
>>> imply running the command in an isolated environment (possibly
>>> beneficial).
>>
>> The environment doesn't necessarily have to be isolated, since we could
>> extend the existing environment saving/loading support to be used for by
>> esudo. The steps to implement the shared environment could be as follows:
>>
>> 1) When esudo is called, it saves the current (unprivileged) bash
>> environment to a file.
>>
>> 2) esudo uses IPC to request that a process with elevated privileges be
>> launched to run a specific command using the saved environment, and that
>> the environment of the elevated process be saved to a file after the
>> command completes.
>
> I don't think it's going to be quite that easy to get the output env,
> certainly not from some random command; tbh I don't even see the need
> for it, unless I'm missing something. From the "elevated process" after
> it waits on the child, but not from the child unless you control the
> code.

We control the shell code that launches the requested command, so we can
save the environment after the requested command completes (using a
modified version of our existing environment persistence code).

>> 3) Before esudo returns, it loads the environment that was saved by the
>> elevated process before it exited.
>
> What's the use-case for this part? I could see it with a function, but
> then you just run that as part of the ebuild. For running a specific
> command to access a device with privilege, or to add a user etc, I
> don't really see the point. (so why bother with the implementation
> complexity.)

Well, maybe it's not very useful. I just thought I'd mention it in case
anyone found it useful for some reason.

> Other than that, I agree esudo is the best approach, and gives us
> much better granularity over privilege escalation, as discussed in
> the bug.

Yeah, me too.

> Part of me thinks though, that it'd be much cleaner to give the
> portage user access to sudo. Isn't that effectively the purpose
> of the "suid helper"? In which case we get all the options for
> env etc, of sudo, and the admin gets to configure it along with
> the normal wheel setup.

Depending on our goals, using sudo may or may not have advantages. It.
really depends on whether or not we want esudo to interact with the
local sudo configuration. If we want it to be independent of the local
sudo configuration, then it makes sense for the package manager to use
it's own privilege escalation mechanism.
--
Thanks,
Zac

Reply | Threaded
Open this post in threaded view
|

Re: Re: Re: Looking for alternative to RESTRICT=userpriv

Steven J. Long
On Mon, Sep 29, 2014, Zac Medico wrote:

> On 09/28/2014, Steven J. Long wrote:
> > On Wed, Sep 24, 2014, Zac Medico wrote:
> >> The environment doesn't necessarily have to be isolated, since we could
> >> extend the existing environment saving/loading support to be used for by
> >> esudo. The steps to implement the shared environment could be as follows:
> >>
> >> 1) When esudo is called, it saves the current (unprivileged) bash
> >> environment to a file.
> >>
> >> 2) esudo uses IPC to request that a process with elevated privileges be
> >> launched to run a specific command using the saved environment, and that
> >> the environment of the elevated process be saved to a file after the
> >> command completes.
> >
> > I don't think it's going to be quite that easy to get the output env,
> > certainly not from some random command; tbh I don't even see the need
> > for it, unless I'm missing something. From the "elevated process" after
> > it waits on the child, but not from the child unless you control the
> > code.
>
> We control the shell code that launches the requested command, so we can
> save the environment after the requested command completes (using a
> modified version of our existing environment persistence code).

Yeah but think it through; the "elevated process" inherits its environment
from us (current state, as normal). It runs a child process: nothing in the
env of that child is going to affect our env, by definition. The command
completes, and we save back the same env we started with.

Sure, the child inherits its env from us, but we don't need to do anything
to make that happen: it's standard. In fact we take efforts to clean the
env in some situations for that reason.

I just can't see it working, apart from perhaps where a command outputs
settings which should be run through eval. In which case, eval them
in ebuild space after the command has output whatever under esudo. To
be flexible, you're going to want to save them anyway for later use,
which again implies that happening in the ebuild/eclass.

> > Other than that, I agree esudo is the best approach, and gives us
> > much better granularity over privilege escalation, as discussed in
> > the bug.
>
> Yeah, me too.

Cool, glad we're on same page.

> > Part of me thinks though, that it'd be much cleaner to give the
> > portage user access to sudo. Isn't that effectively the purpose
> > of the "suid helper"? In which case we get all the options for
> > env etc, of sudo, and the admin gets to configure it along with
> > the normal wheel setup.
>
> Depending on our goals, using sudo may or may not have advantages. It.
> really depends on whether or not we want esudo to interact with the
> local sudo configuration. If we want it to be independent of the local
> sudo configuration, then it makes sense for the package manager to use
> it's own privilege escalation mechanism.

IDK; "independent of the local sudo configuration" /sounds/ good, but
what we are talking about is the configuration for *one* user, that to
run the package manager at the heart of our distro. Speaking as a uadmin
(a Gentoo user who's a defacto admin, not what I think of as an "admin",
which would be a net-admin) I'd much rather configure that in the same
place I configure everything else.

It's not like I don't see the portage user in /etc/passwd et al, or it's
little-known. We set perms for it on /var/tmp/portage so that userpriv
can work, at least we did last time I set that up. /usr/portage is
set like that too, here. So we already have to deal with the user part
of userpriv, as admins.

On the implementation side, it makes a lot of sense: we delegate the
worry to a package used cross-distro for this specific purpose. In fact
this conversation has made me understand ubuntu a bit more, where I
always used to smile at the overuse of sudo. I certainly wouldn't
want the implementation headache of maintaining a secure clone.

AFAICT functional wrapping can be used for the capability side, but
I'd be interested to read otherwise, ie the ins and outs of why not.

Regards,
igli
--
#friendly-coders -- We're friendly, but we're not /that/ friendly ;-)

Reply | Threaded
Open this post in threaded view
|

Re: Re: Re: Looking for alternative to RESTRICT=userpriv

Zac Medico-2
On 09/29/2014 04:31 PM, Steven J. Long wrote:

> On Mon, Sep 29, 2014, Zac Medico wrote:
>> On 09/28/2014, Steven J. Long wrote:
>>> On Wed, Sep 24, 2014, Zac Medico wrote:
>>>> The environment doesn't necessarily have to be isolated, since we could
>>>> extend the existing environment saving/loading support to be used for by
>>>> esudo. The steps to implement the shared environment could be as follows:
>>>>
>>>> 1) When esudo is called, it saves the current (unprivileged) bash
>>>> environment to a file.
>>>>
>>>> 2) esudo uses IPC to request that a process with elevated privileges be
>>>> launched to run a specific command using the saved environment, and that
>>>> the environment of the elevated process be saved to a file after the
>>>> command completes.
>>>
>>> I don't think it's going to be quite that easy to get the output env,
>>> certainly not from some random command; tbh I don't even see the need
>>> for it, unless I'm missing something. From the "elevated process" after
>>> it waits on the child, but not from the child unless you control the
>>> code.
>>
>> We control the shell code that launches the requested command, so we can
>> save the environment after the requested command completes (using a
>> modified version of our existing environment persistence code).
>
> Yeah but think it through; the "elevated process" inherits its environment
> from us (current state, as normal). It runs a child process: nothing in the
> env of that child is going to affect our env, by definition. The command
> completes, and we save back the same env we started with.
>
> Sure, the child inherits its env from us, but we don't need to do anything
> to make that happen: it's standard. In fact we take efforts to clean the
> env in some situations for that reason.
>
> I just can't see it working, apart from perhaps where a command outputs
> settings which should be run through eval. In which case, eval them
> in ebuild space after the command has output whatever under esudo. To
> be flexible, you're going to want to save them anyway for later use,
> which again implies that happening in the ebuild/eclass.

You're thinking in terms of a SUID helper like sudo. The implementation
that I've been suggesting does not involve a SUID helper. Instead, IPC
would be used to request that the privileged parent process launch a new
privileged process on behalf of esudo. In this context, unless the esudo
implementation provides explicit support for environment inheritance,
the new privileged process will not inherit any environment from the
environment where esudo was called.

>>> Other than that, I agree esudo is the best approach, and gives us
>>> much better granularity over privilege escalation, as discussed in
>>> the bug.
>>
>> Yeah, me too.
>
> Cool, glad we're on same page.
>
>>> Part of me thinks though, that it'd be much cleaner to give the
>>> portage user access to sudo. Isn't that effectively the purpose
>>> of the "suid helper"? In which case we get all the options for
>>> env etc, of sudo, and the admin gets to configure it along with
>>> the normal wheel setup.
>>
>> Depending on our goals, using sudo may or may not have advantages. It.
>> really depends on whether or not we want esudo to interact with the
>> local sudo configuration. If we want it to be independent of the local
>> sudo configuration, then it makes sense for the package manager to use
>> it's own privilege escalation mechanism.
>
> IDK; "independent of the local sudo configuration" /sounds/ good, but
> what we are talking about is the configuration for *one* user, that to
> run the package manager at the heart of our distro. Speaking as a uadmin
> (a Gentoo user who's a defacto admin, not what I think of as an "admin",
> which would be a net-admin) I'd much rather configure that in the same
> place I configure everything else.
>
> It's not like I don't see the portage user in /etc/passwd et al, or it's
> little-known. We set perms for it on /var/tmp/portage so that userpriv
> can work, at least we did last time I set that up. /usr/portage is
> set like that too, here. So we already have to deal with the user part
> of userpriv, as admins.
>
> On the implementation side, it makes a lot of sense: we delegate the
> worry to a package used cross-distro for this specific purpose. In fact
> this conversation has made me understand ubuntu a bit more, where I
> always used to smile at the overuse of sudo. I certainly wouldn't
> want the implementation headache of maintaining a secure clone.

The IPC implementation that I've suggested does not involve an SUID
helper, so it is much more secure. Security would rely on the permission
bits of the named pipes that are used to implement IPC.

> AFAICT functional wrapping can be used for the capability side, but
> I'd be interested to read otherwise, ie the ins and outs of why not.
>
> Regards,
> igli
>


--
Thanks,
Zac

Reply | Threaded
Open this post in threaded view
|

Re: Looking for alternative to RESTRICT=userpriv

Steven J. Long
On Tue, Sep 30, 2014 at 07:52:02AM -0700, Zac Medico wrote:

> On 09/29/2014 04:31 PM, Steven J. Long wrote:
> > On Mon, Sep 29, 2014, Zac Medico wrote:
> >> On 09/28/2014, Steven J. Long wrote:
> >>> On Wed, Sep 24, 2014, Zac Medico wrote:
> >>>> 1) When esudo is called, it saves the current (unprivileged) bash
> >>>> environment to a file.
> >>>>
> >>>> 2) esudo uses IPC to request that a process with elevated privileges be
> >>>> launched to run a specific command using the saved environment, and that
> >>>> the environment of the elevated process be saved to a file after the
> >>>> command completes.
> >>>
> >>> I don't think it's going to be quite that easy to get the output env,
> >>> certainly not from some random command; tbh I don't even see the need
> >>> for it, unless I'm missing something. From the "elevated process" after
> >>> it waits on the child, but not from the child unless you control the
> >>> code.
> >>
> >> We control the shell code that launches the requested command, so we can
> >> save the environment after the requested command completes (using a
> >> modified version of our existing environment persistence code).
> >
> > Yeah but think it through; the "elevated process" inherits its environment
> > from us (current state, as normal). It runs a child process: nothing in the
> > env of that child is going to affect our env, by definition. The command
> > completes, and we save back the same env we started with.
> >
> > Sure, the child inherits its env from us, but we don't need to do anything
> > to make that happen: it's standard. In fact we take efforts to clean the
> > env in some situations for that reason.
> >
> > I just can't see it working, apart from perhaps where a command outputs
> > settings which should be run through eval. In which case, eval them
> > in ebuild space after the command has output whatever under esudo. To
> > be flexible, you're going to want to save them anyway for later use,
> > which again implies that happening in the ebuild/eclass.
>
> You're thinking in terms of a SUID helper like sudo. The implementation
> that I've been suggesting does not involve a SUID helper.

No, I'm thinking in terms of "a process with elevated privileges" running
"a specific command"; whether that first process is started by us or not,
is irrelevant to whether it can get the environment from a child process
we have no control over, after it "completes".

Sure it can save its own, but since it's a generic "run any command" helper,
it can't do much more than give us back what we gave it, unless you're
talking about echoing back settings, in the manner of gpg et al, which
by definition is not about the saved env. That's why we have to use that
format in the first place; because the env setting must be done by the
process which wants to use it (have it inherited for child processes),
for the same reason: a child process can never affect the parent env.

> Instead, IPC
> would be used to request that the privileged parent process launch a new
> privileged process on behalf of esudo. In this context, unless the esudo
> implementation provides explicit support for environment inheritance,
> the new privileged process will not inherit any environment from the
> environment where esudo was called.

Well, assuming that were the implementation, that explains why you'd want
to save the env off, so that the privileged helper can access it. It still
sounds like more work in the long run in terms of what's happening, but
regardless: it doesn't get you the resultant env from the child command.

But like I said, that's of dubious utility in any case. I think we should
just forget about it.

> > So we already have to deal with the user part of userpriv, as admins.
> >
> > On the implementation side, it makes a lot of sense: we delegate the
> > worry to a package used cross-distro for this specific purpose. In fact
> > this conversation has made me understand ubuntu a bit more, where I
> > always used to smile at the overuse of sudo. I certainly wouldn't
> > want the implementation headache of maintaining a secure clone.
>
> The IPC implementation that I've suggested does not involve an SUID
> helper, so it is much more secure. Security would rely on the permission
> bits of the named pipes that are used to implement IPC.

I see, so presumably there's a fifo pair, that only the portage user can
access (likely at dir level too), one read-only? On the other end of which
you have a waiting process, ie a daemon, in the classic sense, with root
privilege, so it can run any command as any user, with any set of caps
required. If you're using IPC to request a process with privilege be
launched, something's got to be listening to the other end.

I don't see how that's "more secure", but then I don't really care how you
implement it, either ;) It's certainly less deps, I guess.

It still just sounds like a reimpl of sudo, by an indirect method (root
userland daemon, as opposed to kernel suid) leading to a lot more going
on at runtime (env saving to file, reloading in a new child process
from the privileged daemon, before we can start the actual command.)

And as above, it cannot get us the env after randomcmd completes, but
that's orthogonal, since nothing can, and programs aren't written
to output to their env, since the parent can't access it.

I assume you have code in mind for this already, perhaps from another
project? If so, and it's a reasonable maintenance burden, ie not
much needs to change once it's up and running correctly, then fair
enough. Though from what I've seen even Linux-specific projects just
exec the command, after setting privileges, namespace etc as
appropriate, from a suid helper.

Are you sure you don't want to borrow someone else's code for a suid
helper instead? Not sure what a daemon buys you, apart from extra
maintenance overhead (listener, loading env, as well as what a suid
helper would do, and a protocol for communication, which no doubt is
going to change over time) plus an attack vector for someone who can
crack portage or python at any future point, or just get portage uid
via some other vector; for a relatively infrequent operation.

Regards,
igli
--
#friendly-coders -- We're friendly, but we're not /that/ friendly ;-)

Reply | Threaded
Open this post in threaded view
|

Re: Looking for alternative to RESTRICT=userpriv

Peter Stuge-4
Steven J. Long wrote:
> On Tue, Sep 30, 2014 at 07:52:02AM -0700, Zac Medico wrote:
> > The IPC implementation that I've suggested does not involve an SUID
> > helper, so it is much more secure. Security would rely on the permission
> > bits of the named pipes that are used to implement IPC.
..
> I don't see how that's "more secure"

It's a lot more secure to have a single well-defined privileged trust
anchor (the privileged process) with a well-defined protocol, than to
have built-in privilege escalation which allows arbitrary actions.


> Not sure what a daemon buys you

Not requiring built-in privilege escalation.


//Peter

Reply | Threaded
Open this post in threaded view
|

Re: Re: Looking for alternative to RESTRICT=userpriv

Steven J. Long
On Fri, Oct 03, 2014 at 05:01:20AM +0200, Peter Stuge wrote:

> Steven J. Long wrote:
> > On Tue, Sep 30, 2014 at 07:52:02AM -0700, Zac Medico wrote:
> > > The IPC implementation that I've suggested does not involve an SUID
> > > helper, so it is much more secure. Security would rely on the permission
> > > bits of the named pipes that are used to implement IPC.
> ..
> > I don't see how that's "more secure"
>
> It's a lot more secure to have a single well-defined privileged trust
> anchor (the privileged process) with a well-defined protocol, than to
> have built-in privilege escalation which allows arbitrary actions.

You appear to have missed the point of what it does. All you'd be doing
is providing the exact same ability, in a much more convoluted manner.
Since after all the whole point is to run arbitrary commands that affect
the root system.

As stated, now you have to implement the listener, which has to load the
env, and a protocol for communication, which no doubt is going to change
over time. On top of the usual work, ie what a suid helper would have to
do in any case.

And you've just provided a nice juicy vector for someone who can crack
portage or python at any future point, or just get portage uid via ANY
other vector, to use your "well-defined protocol" (you hope) to execute
arbitrary actions, since that is *precisely* the point of it.

The security you mention is nothing but a pipe-dream; reliant on user
permission over the fifo and containing dir which is _exactly_ the same
kernel mechanism you can apply to an suid helper, *without* all the
moving parts and the hopeful intentions (because it "sounds good") leave
alone yaf daemon running to subvert the usual security mechanism.

Any method you can think of to provide verification of what's happening,
is just more complexity that can and will be gamed; and crackers only
have to get lucky once, in millions of automated attempts. Why give them
a target in the first place; you're just encouraging noise and waste of
bandwidth + cycles.

And as stated, it doesn't get you the env from the command in any case,
so I don't see the point at all. All it does is add maintenance headache
and a false sense of security.

It's more secure to have a smaller, tighter "trust anchor" that does as
little as possible and can be audited, as opposed to _hoping_ that our
latest python download, is so large there's nothing obviously wrong.

Sure the suid helper is a target too: get portage uid and run that.
What's the difference when you have a daemon? None. Both rely on the
kernel to enforce access permission. (which is why agent accounts can
never login, and are not in any of the groups we add ourselves to.)
So if it's the same access permission..

It's just much easier thereafter to attack a daemon, where the people
whose code you're attacking have many more things to worry about, which
tends to change over time, than a small focussed program, which can
then have more checks built-in (assuming you go for a custom impl as
opposed to existing mechanisms that are proven.) The same ones you'd
end up adding to the daemon, only without having to worry about
maintaining a protocol, the daemon and the client as well.

As a result you can cut to the chase, and focus on what matters.
Though personally I'd rather rely on the admin as well as the
developer, to keep an eye on their own system.

sudo just happens to have it all taken care of for us, and be a much
better focus for many distros to ensure security, and tie into PAM,
rather than everyone go off and try it in the script-language dejour.
As well as integrate cleanly with everything else. It's even easy for
the admin to switch it off in case of concern, in the same place they
deal with other security problems, and indeed restrict times and
so much more; things we'd end up getting bugs about adding, and so
the cycle of featuritis and reimplementation of the wheel goes.

There's much more control, and we get it for zero effort. It's also
transparent to the admin, as opposed to a bespoke implementation they
know nothing about. (which is why people collaborate cross-platform.)

But like I said, I don't particularly care how it's implemented so long
as it's not a method which sounds nice but has nothing else to recommend
it, and opens gaping holes on closer analysis. Using a suid helper means
you can delegate the work to someone who's focussed on it, and it can
remain *small*. sudo has a lot going for it, that means we have much
less to worry about.

By all means show me where I'm wrong; but answer the substantive points,
please. In summary you'd be providing the same ability, and the exact
same access control, with a much crappier method, convoluted and much
more fragile, apparently because it sounds nice. gack.

Regards
steveL

Next it'll be javascript with a fast-moving engine.. lul.
--
#friendly-coders -- We're friendly, but we're not /that/ friendly ;-)

Reply | Threaded
Open this post in threaded view
|

Re: Re: Looking for alternative to RESTRICT=userpriv

Peter Stuge-4
Steven J. Long wrote:
> > It's a lot more secure to have a single well-defined privileged trust
> > anchor (the privileged process) with a well-defined protocol, than to
> > have built-in privilege escalation which allows arbitrary actions.
>
> You appear to have missed the point of what it does.

I haven't.


> the whole point is to run arbitrary commands that affect the root system.

I don't think that's the case. Are you sure that it is?

With a trust root of our own it is very easy to decide what is allowed
and I imagine that we want to.

I'm sure you see the vast difference between built-in privilege
escalation for a user process and having a separate, controlled,
code path with privileges.

You claim that they are the same, but unless the protocol supports
transfering machine code for privileged execution that's plain wrong.

Maybe you tend to support such arbitrary code execution, but I don't
think that's what is being proposed here, and a lot of people have
done just fine designing and implementing protocols without such
problems in the past.

And you have a very long way of saying that you don't care. :)


//Peter

Reply | Threaded
Open this post in threaded view
|

Re: Looking for alternative to RESTRICT=userpriv

Steven J. Long
Peter Stuge wrote:
> Steven J. Long wrote:
> > > It's a lot more secure to have a single well-defined privileged trust
> > > anchor (the privileged process) with a well-defined protocol, than to
> > > have built-in privilege escalation which allows arbitrary actions.
> >
> > the whole point is to run arbitrary commands that affect the root system.
>
> I don't think that's the case. Are you sure that it is?

Ah I see, so you're saying it's limited to a small allowed set of whitelisted
actions? Sorry was under the impression it was a generic "esudo whatever"
esoteric command might be required for build-system X to communicate with
driver Y, perhaps as a specific user.

> With a trust root of our own it is very easy to decide what is allowed
> and I imagine that we want to.
>
> I'm sure you see the vast difference between built-in privilege
> escalation for a user process and having a separate, controlled,
> code path with privileges.
>
> You claim that they are the same, but unless the protocol supports
> transfering machine code for privileged execution that's plain wrong.
>
> Maybe you tend to support such arbitrary code execution, but I don't
> think that's what is being proposed here, and a lot of people have
> done just fine designing and implementing protocols without such
> problems in the past.
>
> And you have a very long way of saying that you don't care. :)

Yeah, sorry for going on.

Having thought about it, if emerge is the listener, and the ebuild or the
monitor is its child running the install phase (or similar) then it
doesn't even need named IPC. In any case the listener would only be
active when emerge is running, started by root.

If you were to go that route a Unix domain socket would be better than
a fifo, as you could then get peer credentials to verify the pid at the
time of execution, and directory access perms would still apply.

Apologies again for noise.
steveL.
--
#friendly-coders -- We're friendly, but we're not /that/ friendly ;-)

Reply | Threaded
Open this post in threaded view
|

Re: Looking for alternative to RESTRICT=userpriv

Zac Medico-2
In reply to this post by Steven J. Long
On 10/02/2014 07:32 PM, Steven J. Long wrote:

> On Tue, Sep 30, 2014 at 07:52:02AM -0700, Zac Medico wrote:
>> On 09/29/2014 04:31 PM, Steven J. Long wrote:
>>> On Mon, Sep 29, 2014, Zac Medico wrote:
>>>> On 09/28/2014, Steven J. Long wrote:
>>>>> On Wed, Sep 24, 2014, Zac Medico wrote:
>>>>>> 1) When esudo is called, it saves the current (unprivileged) bash
>>>>>> environment to a file.
>>>>>>
>>>>>> 2) esudo uses IPC to request that a process with elevated privileges be
>>>>>> launched to run a specific command using the saved environment, and that
>>>>>> the environment of the elevated process be saved to a file after the
>>>>>> command completes.
>>>>>
>>>>> I don't think it's going to be quite that easy to get the output env,
>>>>> certainly not from some random command; tbh I don't even see the need
>>>>> for it, unless I'm missing something. From the "elevated process" after
>>>>> it waits on the child, but not from the child unless you control the
>>>>> code.
>>>>
>>>> We control the shell code that launches the requested command, so we can
>>>> save the environment after the requested command completes (using a
>>>> modified version of our existing environment persistence code).
>>>
>>> Yeah but think it through; the "elevated process" inherits its environment
>>> from us (current state, as normal). It runs a child process: nothing in the
>>> env of that child is going to affect our env, by definition. The command
>>> completes, and we save back the same env we started with.
>>>
>>> Sure, the child inherits its env from us, but we don't need to do anything
>>> to make that happen: it's standard. In fact we take efforts to clean the
>>> env in some situations for that reason.
>>>
>>> I just can't see it working, apart from perhaps where a command outputs
>>> settings which should be run through eval. In which case, eval them
>>> in ebuild space after the command has output whatever under esudo. To
>>> be flexible, you're going to want to save them anyway for later use,
>>> which again implies that happening in the ebuild/eclass.
>>
>> You're thinking in terms of a SUID helper like sudo. The implementation
>> that I've been suggesting does not involve a SUID helper.
>
> No, I'm thinking in terms of "a process with elevated privileges" running
> "a specific command"; whether that first process is started by us or not,
> is irrelevant to whether it can get the environment from a child process
> we have no control over, after it "completes".

You're assuming that we have no control over the child process, which
would be true with a SUID helper like sudo (in the absence of a wrapper
script, see below) that is only designed to run a specific command and
then exit without saving the enviroment.

However, imagine a helper that is designed to run a requested shell
command and then save the environment before it exits. It could be done
with sudo if you simply required that the first argument to sudo be a
wrapper script that executes the requested command and then saves the
environment. For example, consider the following usage:

  sudo /foo/bar/wrapper.sh <requested shell command with arguments>

If the sudo command is constructed shown above, then wrapper.sh can load
an arbitrary environment, execute the requested shell command with
arguments, and then save the resulting environment afterwards.

> Sure it can save its own, but since it's a generic "run any command" helper,
> it can't do much more than give us back what we gave it, unless you're
> talking about echoing back settings, in the manner of gpg et al, which
> by definition is not about the saved env. That's why we have to use that
> format in the first place; because the env setting must be done by the
> process which wants to use it (have it inherited for child processes),
> for the same reason: a child process can never affect the parent env.

We could implement esudo so that it will insert wrapper.sh into the sudo
arguments, so that the caller doesn't have to know anything about the
wrapper.sh implementation details. For example:

  esudo <requested shell command with arguments>

So, the privilege escalation mechanism is indeed irrelevant, as long as
there's some opportunity to insert a wrapper script that runs with
escalated privileges, allowing it to load/save the environment at the
appropriate time during shell execution.

>> Instead, IPC
>> would be used to request that the privileged parent process launch a new
>> privileged process on behalf of esudo. In this context, unless the esudo
>> implementation provides explicit support for environment inheritance,
>> the new privileged process will not inherit any environment from the
>> environment where esudo was called.
>
> Well, assuming that were the implementation, that explains why you'd want
> to save the env off, so that the privileged helper can access it. It still
> sounds like more work in the long run in terms of what's happening, but
> regardless: it doesn't get you the resultant env from the child command.

Except that it is possible to save the resultant env from the child
command, using a wrapper as described above.

> But like I said, that's of dubious utility in any case. I think we should
> just forget about it.

It may have dubious utility, but it's still possible, nonetheless.

>>> So we already have to deal with the user part of userpriv, as admins.
>>>
>>> On the implementation side, it makes a lot of sense: we delegate the
>>> worry to a package used cross-distro for this specific purpose. In fact
>>> this conversation has made me understand ubuntu a bit more, where I
>>> always used to smile at the overuse of sudo. I certainly wouldn't
>>> want the implementation headache of maintaining a secure clone.
>>
>> The IPC implementation that I've suggested does not involve an SUID
>> helper, so it is much more secure. Security would rely on the permission
>> bits of the named pipes that are used to implement IPC.
>
> I see, so presumably there's a fifo pair, that only the portage user can
> access (likely at dir level too), one read-only? On the other end of which
> you have a waiting process, ie a daemon, in the classic sense, with root
> privilege, so it can run any command as any user, with any set of caps
> required. If you're using IPC to request a process with privilege be
> launched, something's got to be listening to the other end.

Yes, this is how ebuild helpers like has_version and best_version
already work. The IPC system can easily be extended to handle privilege
escalation commands.

> I don't see how that's "more secure", but then I don't really care how you
> implement it, either ;) It's certainly less deps, I guess.

Well, a named pipe that is only readable/writable by a specific user is
inherently more secure that a SUID binary that can be executed by any user.

> It still just sounds like a reimpl of sudo, by an indirect method (root
> userland daemon, as opposed to kernel suid) leading to a lot more going
> on at runtime (env saving to file, reloading in a new child process
> from the privileged daemon, before we can start the actual command.)

Well, the daemon is already there listening for commands such as
has_version and best_version. Extending it to handle privilege
escalation would be fairly easy. The overhead involved is negligible.
For things like has_version and best_version, the daemon approach is
actually much more efficient than the alternatives, since the daemon has
access to relatively long-lived database instances that would otherwise
have to be instantiated for each has_version/best_version call.

> And as above, it cannot get us the env after randomcmd completes, but
> that's orthogonal, since nothing can, and programs aren't written
> to output to their env, since the parent can't access it.

Again, a wrapper script like wrapper.sh described above would have
access to the resultant env.

> I assume you have code in mind for this already, perhaps from another
> project? If so, and it's a reasonable maintenance burden, ie not
> much needs to change once it's up and running correctly, then fair
> enough.

What I have in mind is the existing IPC system that portage already uses
to implement commands like has_version and best_version.

> Though from what I've seen even Linux-specific projects just
> exec the command, after setting privileges, namespace etc as
> appropriate, from a suid helper.

An SUID helper would certainly work. However, given the existing IPC
infrastructure, I would use IPC.

> Are you sure you don't want to borrow someone else's code for a suid
> helper instead? Not sure what a daemon buys you, apart from extra
> maintenance overhead (listener, loading env, as well as what a suid
> helper would do, and a protocol for communication, which no doubt is
> going to change over time) plus an attack vector for someone who can
> crack portage or python at any future point, or just get portage uid
> via some other vector; for a relatively infrequent operation.

The portage user/group is already a possible attack vector:

 https://bugs.gentoo.org/show_bug.cgi?id=149062

For this reason, it's very important not to grant access to this
user/group to untrusted users.
--
Thanks,
Zac

Reply | Threaded
Open this post in threaded view
|

Re: Re: Looking for alternative to RESTRICT=userpriv

Steven J. Long
On Sun, Oct 05, 2014, Zac Medico wrote:
> On 10/02/2014 07:32 PM, Steven J. Long wrote:
> > On Tue, Sep 30, 2014, Zac Medico wrote:
> >>> On Mon, Sep 29, 2014, Zac Medico wrote:
> >>>> We control the shell code that launches the requested command, so we can
> >>>> save the environment after the requested command completes (using a
> >>>> modified version of our existing environment persistence code).
> >>>
<snip>

> >> You're thinking in terms of a SUID helper like sudo. The implementation
> >> that I've been suggesting does not involve a SUID helper.
> >
> > No, I'm thinking in terms of "a process with elevated privileges" running
> > "a specific command"; whether that first process is started by us or not,
> > is irrelevant to whether it can get the environment from a child process
> > we have no control over, after it "completes".
>
> You're assuming that we have no control over the child process, which
> would be true with a SUID helper like sudo (in the absence of a wrapper
> script, see below) that is only designed to run a specific command and
> then exit without saving the enviroment.

I've already agreed you can run a shell command that you control: that's
equivalent to running a process whose code you control.

> However, imagine a helper that is designed to run a requested shell
> command and then save the environment before it exits. It could be done
> with sudo if you simply required that the first argument to sudo be a
> wrapper script that executes the requested command and then saves the
> environment. For example, consider the following usage:
>
>   sudo /foo/bar/wrapper.sh <requested shell command with arguments>

> If the sudo command is constructed shown above, then wrapper.sh can load
> an arbitrary environment, execute the requested shell command with
> arguments, and then save the resulting environment afterwards.

What command exactly? Since after any external it runs, which I thought was
the whole point of this, it can't get the resultant env. You're in the
same situation, only you're discussing a shell command as opposed to a
"privileged process".

I'm just trying to get at which env exactly you think you're getting.

> > Sure it can save its own, but since it's a generic "run any command" helper,
> > it can't do much more than give us back what we gave it, unless you're
> > talking about echoing back settings, in the manner of gpg et al, which
> > by definition is not about the saved env. That's why we have to use that
> > format in the first place; because the env setting must be done by the
> > process which wants to use it (have it inherited for child processes),
> > for the same reason: a child process can never affect the parent env.
>
> We could implement esudo so that it will insert wrapper.sh into the sudo
> arguments, so that the caller doesn't have to know anything about the
> wrapper.sh implementation details. For example:

>   esudo <requested shell command with arguments>

So that's going to call the listener with a string to eval(gack) and the
listener will then launch a bash process to evaluate the line, correct?

Given that this is ebuild context, that's likely going to be a process
that loads the env saved before the call, in order to have access to the
functions and metadata declared in the ebuild. And then evaluates the
line given (which sets off all sorts of alarm-bells).

In the typical case that's just going to be an external we could have
called anyway. In the case pertinent to this discussion, there is some
sort of env-setting going on. But not from externals, unless of the
gpg-ilk such that we can load any variable settings they give us, or
they write out to a file we can source; iow not from 99% of externals.

Presumably the shell line (I'd guess a call to a saved function in env)
is going to export settings back to the env, which will be saved by the
usual mechanism.

Is that about right?

> So, the privilege escalation mechanism is indeed irrelevant, as long as
> there's some opportunity to insert a wrapper script that runs with
> escalated privileges, allowing it to load/save the environment at the
> appropriate time during shell execution.

Yeah we just run a shell script (as a privileged user). Which can save its
own env off for sure; just not the env from some external it happens to
run, which is usually the functional aspect of a shell script. It could
run something like gpg et al which give an env return, as I described before.

> >> Instead, IPC
> >> would be used to request that the privileged parent process launch a new
> >> privileged process on behalf of esudo. In this context, unless the esudo
> >> implementation provides explicit support for environment inheritance,
> >> the new privileged process will not inherit any environment from the
> >> environment where esudo was called.
> >
> > Well, assuming that were the implementation, that explains why you'd want
> > to save the env off, so that the privileged helper can access it. It still
> > sounds like more work in the long run in terms of what's happening, but
> > regardless: it doesn't get you the resultant env from the child command.
>
> Except that it is possible to save the resultant env from the child
> command, using a wrapper as described above.

No, you haven't convinced me of that at all. It's certainly possible to save
the env from a command whose _code you control_, as I stated *upfront*. But
not from some random command you don't. Running it from shell doesn't get
round that, and if you save the resultant env, you're just doing what I
said before, in the context of a "privileged process".

If that's all you mean, then fair enough. Presumably there is some interest
in elevated shell scripts running specific commands and then exporting to
the env, as opposed to just running a specific command to access a device,
say.

> > But like I said, that's of dubious utility in any case. I think we should
> > just forget about it.
>
> It may have dubious utility, but it's still possible, nonetheless.

Nope, show me the flow of execution and convince me: you haven't yet. It
shouldn't be hard, a -> b -> c with ids that make sense, and a line
indicating foo=bar  and show how it flows back to the caller. (Each is a
separate process.) It'd take 5 minutes to work out on a bit of paper,
for you.

All you've demonstrated so far, is that it's possible to run a script.

> >> The IPC implementation that I've suggested does not involve an SUID
> >> helper, so it is much more secure. Security would rely on the permission
> >> bits of the named pipes that are used to implement IPC.
> >
> > I see, so presumably there's a fifo pair, that only the portage user can
> > access (likely at dir level too), one read-only? On the other end of which
> > you have a waiting process, ie a daemon, in the classic sense, with root
> > privilege, so it can run any command as any user, with any set of caps
> > required. If you're using IPC to request a process with privilege be
> > launched, something's got to be listening to the other end.
>
> Yes, this is how ebuild helpers like has_version and best_version
> already work. The IPC system can easily be extended to handle privilege
> escalation commands.
>
> > I don't see how that's "more secure", but then I don't really care how you
> > implement it, either ;) It's certainly less deps, I guess.
>
> Well, a named pipe that is only readable/writable by a specific user is
> inherently more secure that a SUID binary that can be executed by any user.

Who said it can be executed by any user? That would be foolish; my point
("borrow a suid helper") was you use the same file perms you're using above
for the fifo, for the executable, at least in terms of effect: only the
portage uid has access to the dir, only the portage gid can run the binary,
which is suid root.

See: _same_ access control (kernel-fs), no difference in terms of security,
*much* less effort in general terms.

That can additionally be configured by sudo, much the same as the admin can
configure any command they like via sudo, should they have it installed. But
it doesn't have to be: it's just a suid helper you install along with your
package, that has specific permissions on the directory and the executable,
which the helper checks, much like ssh checks perms on ~/.ssh.

I accept, however, that you have the below already running, and have no wish
to influence your implementation decision in-situ. Just to verify that
what you're talking about seems reasonable.

If above you mean that your named-pipe/listener is inherently more secure
than sudo, forgive me for demurring. As well argue that every daemon is
inherently more secure than sudo, simply because they're not suid.

I'd gone on the helper as I wasn't sure sudo can do caps, and it seems to
me you're going to want a bit of extra stuff like fs and network namespaces
which are simple enough in C.

> Well, the daemon is already there listening for commands such as
> has_version and best_version. Extending it to handle privilege
> escalation would be fairly easy. The overhead involved is negligible.
> For things like has_version and best_version, the daemon approach is
> actually much more efficient than the alternatives, since the daemon has
> access to relatively long-lived database instances that would otherwise
> have to be instantiated for each has_version/best_version call.

Yeah fair enough.

> > And as above, it cannot get us the env after randomcmd completes, but
> > that's orthogonal, since nothing can, and programs aren't written
> > to output to their env, since the parent can't access it.
>
> Again, a wrapper script like wrapper.sh described above would have
> access to the resultant env.

Only of _itself_, same as "code we control" in prior mails.

If that suffices, then fair enough; but it's not the mythical "run external
command as privileged user and get resultant env" that was presented
at the start of this. Since that doesn't exist, unless you get into debug
facilities, and afaic that really would be Doing It Wrong.

> What I have in mind is the existing IPC system that portage already uses
> to implement commands like has_version and best_version.

So the back-end process running the database queries is already privileged;
or would be, or is a helper?

> > Though from what I've seen even Linux-specific projects just
> > exec the command, after setting privileges, namespace etc as
> > appropriate, from a suid helper.
>
> An SUID helper would certainly work. However, given the existing IPC
> infrastructure, I would use IPC.

Yeah it's always tempting to integrate everything. It always seems to
make so much sense, the bits are right there..
 
> The portage user/group is already a possible attack vector:
>
>  https://bugs.gentoo.org/show_bug.cgi?id=149062
>
> For this reason, it's very important not to grant access to this
> user/group to untrusted users.

In which case, the suid helper seems even more appropriate to my tired
old eyes. Still, good luck with whichever way you go.

Regards
igli
--
#friendly-coders -- We're friendly, but we're not /that/ friendly ;-)

Reply | Threaded
Open this post in threaded view
|

Re: Re: Looking for alternative to RESTRICT=userpriv

Zac Medico-2
On 10/11/2014 12:06 AM, Steven J. Long wrote:

> On Sun, Oct 05, 2014, Zac Medico wrote:
>> On 10/02/2014 07:32 PM, Steven J. Long wrote:
>>> On Tue, Sep 30, 2014, Zac Medico wrote:
>>>>> On Mon, Sep 29, 2014, Zac Medico wrote:
>>>>>> We control the shell code that launches the requested command, so we can
>>>>>> save the environment after the requested command completes (using a
>>>>>> modified version of our existing environment persistence code).
>>>>>
> <snip>
>>>> You're thinking in terms of a SUID helper like sudo. The implementation
>>>> that I've been suggesting does not involve a SUID helper.
>>>
>>> No, I'm thinking in terms of "a process with elevated privileges" running
>>> "a specific command"; whether that first process is started by us or not,
>>> is irrelevant to whether it can get the environment from a child process
>>> we have no control over, after it "completes".
>>
>> You're assuming that we have no control over the child process, which
>> would be true with a SUID helper like sudo (in the absence of a wrapper
>> script, see below) that is only designed to run a specific command and
>> then exit without saving the enviroment.
>
> I've already agreed you can run a shell command that you control: that's
> equivalent to running a process whose code you control.
>
>> However, imagine a helper that is designed to run a requested shell
>> command and then save the environment before it exits. It could be done
>> with sudo if you simply required that the first argument to sudo be a
>> wrapper script that executes the requested command and then saves the
>> environment. For example, consider the following usage:
>>
>>   sudo /foo/bar/wrapper.sh <requested shell command with arguments>
>
>> If the sudo command is constructed shown above, then wrapper.sh can load
>> an arbitrary environment, execute the requested shell command with
>> arguments, and then save the resulting environment afterwards.
>
> What command exactly? Since after any external it runs, which I thought was
> the whole point of this, it can't get the resultant env. You're in the
> same situation, only you're discussing a shell command as opposed to a
> "privileged process".
>
> I'm just trying to get at which env exactly you think you're getting.

The shell env consists of shell variables and functions.

Maybe it helps if I explain it in terms of existing ebuild phases that
are already supported. For example, pkg_setup runs as root, and the
ebuild's shell enviroment is saved. This environment contains the ebuild
functions and variables as well as the functions and variables of the
eclasses it inherits. When the src_unpack phase is called, it runs as
the "portage" user, and it's able to load the environment from
pkg_setup. So, we have two phases sharing/mutating the same shell
environment, yet they run as different users with different privileges.

The pkg_setup/src_unpack environment sharing is very similar to the
environment sharing that I have suggested for esudo. You can consider
them to be practically identical, except that esudo will allow an
unprivileged phase to launch a privileged shell with a shared
environment, using basically the same mechanics that allow pkg_setup and
src_unpack to share the same environment.

>>> Sure it can save its own, but since it's a generic "run any command" helper,
>>> it can't do much more than give us back what we gave it, unless you're
>>> talking about echoing back settings, in the manner of gpg et al, which
>>> by definition is not about the saved env. That's why we have to use that
>>> format in the first place; because the env setting must be done by the
>>> process which wants to use it (have it inherited for child processes),
>>> for the same reason: a child process can never affect the parent env.
>>
>> We could implement esudo so that it will insert wrapper.sh into the sudo
>> arguments, so that the caller doesn't have to know anything about the
>> wrapper.sh implementation details. For example:
>
>>   esudo <requested shell command with arguments>
>
> So that's going to call the listener with a string to eval(gack) and the
> listener will then launch a bash process to evaluate the line, correct?
>
> Given that this is ebuild context, that's likely going to be a process
> that loads the env saved before the call, in order to have access to the
> functions and metadata declared in the ebuild. And then evaluates the
> line given (which sets off all sorts of alarm-bells).

Right.

> In the typical case that's just going to be an external we could have
> called anyway. In the case pertinent to this discussion, there is some
> sort of env-setting going on. But not from externals, unless of the
> gpg-ilk such that we can load any variable settings they give us, or
> they write out to a file we can source; iow not from 99% of externals.
>
> Presumably the shell line (I'd guess a call to a saved function in env)
> is going to export settings back to the env, which will be saved by the
> usual mechanism.
>
> Is that about right?

Right. Maybe I should have read your this part of your email before I
wrote the pkg_setup/src_unpack example above, because it seems like your
getting the idea now.

>> So, the privilege escalation mechanism is indeed irrelevant, as long as
>> there's some opportunity to insert a wrapper script that runs with
>> escalated privileges, allowing it to load/save the environment at the
>> appropriate time during shell execution.
>
> Yeah we just run a shell script (as a privileged user). Which can save its
> own env off for sure; just not the env from some external it happens to
> run, which is usually the functional aspect of a shell script. It could
> run something like gpg et al which give an env return, as I described before.
>>>> Instead, IPC
>>>> would be used to request that the privileged parent process launch a new
>>>> privileged process on behalf of esudo. In this context, unless the esudo
>>>> implementation provides explicit support for environment inheritance,
>>>> the new privileged process will not inherit any environment from the
>>>> environment where esudo was called.
>>>
>>> Well, assuming that were the implementation, that explains why you'd want
>>> to save the env off, so that the privileged helper can access it. It still
>>> sounds like more work in the long run in terms of what's happening, but
>>> regardless: it doesn't get you the resultant env from the child command.
>>
>> Except that it is possible to save the resultant env from the child
>> command, using a wrapper as described above.
>
> No, you haven't convinced me of that at all. It's certainly possible to save
> the env from a command whose _code you control_, as I stated *upfront*. But
> not from some random command you don't. Running it from shell doesn't get
> round that, and if you save the resultant env, you're just doing what I
> said before, in the context of a "privileged process".

I've been talking about the *shell* environment (sorry, thought it would
be obvious). When speaking about the writing of ebuilds and eclasses,
generally "the environment" means the "shell environment" which consists
of shell variables and functions.

> If that's all you mean, then fair enough. Presumably there is some interest
> in elevated shell scripts running specific commands and then exporting to
> the env, as opposed to just running a specific command to access a device,
> say.

Sure, there may be some interest in it. I can practically already hear
people asking "why can't we use esudo to call a shell function from the
ebuild env". The answer would be that we didn't design it that way, not
that it wasn't possible.

>>> But like I said, that's of dubious utility in any case. I think we should
>>> just forget about it.
>>
>> It may have dubious utility, but it's still possible, nonetheless.
>
> Nope, show me the flow of execution and convince me: you haven't yet. It
> shouldn't be hard, a -> b -> c with ids that make sense, and a line
> indicating foo=bar  and show how it flows back to the caller. (Each is a
> separate process.) It'd take 5 minutes to work out on a bit of paper,
> for you.
>
> All you've demonstrated so far, is that it's possible to run a script.

Does the pkg_setup/src_unpack example that I've given above clarify it
for you?

>>>> The IPC implementation that I've suggested does not involve an SUID
>>>> helper, so it is much more secure. Security would rely on the permission
>>>> bits of the named pipes that are used to implement IPC.
>>>
>>> I see, so presumably there's a fifo pair, that only the portage user can
>>> access (likely at dir level too), one read-only? On the other end of which
>>> you have a waiting process, ie a daemon, in the classic sense, with root
>>> privilege, so it can run any command as any user, with any set of caps
>>> required. If you're using IPC to request a process with privilege be
>>> launched, something's got to be listening to the other end.
>>
>> Yes, this is how ebuild helpers like has_version and best_version
>> already work. The IPC system can easily be extended to handle privilege
>> escalation commands.
>>
>>> I don't see how that's "more secure", but then I don't really care how you
>>> implement it, either ;) It's certainly less deps, I guess.
>>
>> Well, a named pipe that is only readable/writable by a specific user is
>> inherently more secure that a SUID binary that can be executed by any user.
>
> Who said it can be executed by any user? That would be foolish; my point
> ("borrow a suid helper") was you use the same file perms you're using above
> for the fifo, for the executable, at least in terms of effect: only the
> portage uid has access to the dir, only the portage gid can run the binary,
> which is suid root.

Generally sudo is installed with a+x, and I thought that you had
suggested that we use sudo. Anyway, I think we should focus this
discussion on the environment loading/saving. The privilege escalation
mechanism can be considered as an irrelevant implementation detail.

> See: _same_ access control (kernel-fs), no difference in terms of security,
> *much* less effort in general terms.
>
> That can additionally be configured by sudo, much the same as the admin can
> configure any command they like via sudo, should they have it installed. But
> it doesn't have to be: it's just a suid helper you install along with your
> package, that has specific permissions on the directory and the executable,
> which the helper checks, much like ssh checks perms on ~/.ssh.
>
> I accept, however, that you have the below already running, and have no wish
> to influence your implementation decision in-situ. Just to verify that
> what you're talking about seems reasonable.
>
> If above you mean that your named-pipe/listener is inherently more secure
> than sudo, forgive me for demurring. As well argue that every daemon is
> inherently more secure than sudo, simply because they're not suid.
>
> I'd gone on the helper as I wasn't sure sudo can do caps, and it seems to
> me you're going to want a bit of extra stuff like fs and network namespaces
> which are simple enough in C.
>
>> Well, the daemon is already there listening for commands such as
>> has_version and best_version. Extending it to handle privilege
>> escalation would be fairly easy. The overhead involved is negligible.
>> For things like has_version and best_version, the daemon approach is
>> actually much more efficient than the alternatives, since the daemon has
>> access to relatively long-lived database instances that would otherwise
>> have to be instantiated for each has_version/best_version call.
>
> Yeah fair enough.
>
>>> And as above, it cannot get us the env after randomcmd completes, but
>>> that's orthogonal, since nothing can, and programs aren't written
>>> to output to their env, since the parent can't access it.
>>
>> Again, a wrapper script like wrapper.sh described above would have
>> access to the resultant env.
>
> Only of _itself_, same as "code we control" in prior mails.
>
> If that suffices, then fair enough; but it's not the mythical "run external
> command as privileged user and get resultant env" that was presented
> at the start of this. Since that doesn't exist, unless you get into debug
> facilities, and afaic that really would be Doing It Wrong.

I'm sorry I wasn't more clear that I was speaking about the *shell*
environment. Again, I thought it would be obvious to the audience here.

>> What I have in mind is the existing IPC system that portage already uses
>> to implement commands like has_version and best_version.
>
> So the back-end process running the database queries is already privileged;
> or would be, or is a helper?
>
>>> Though from what I've seen even Linux-specific projects just
>>> exec the command, after setting privileges, namespace etc as
>>> appropriate, from a suid helper.
>>
>> An SUID helper would certainly work. However, given the existing IPC
>> infrastructure, I would use IPC.
>
> Yeah it's always tempting to integrate everything. It always seems to
> make so much sense, the bits are right there..
>  
>> The portage user/group is already a possible attack vector:
>>
>>  https://bugs.gentoo.org/show_bug.cgi?id=149062
>>
>> For this reason, it's very important not to grant access to this
>> user/group to untrusted users.
>
> In which case, the suid helper seems even more appropriate to my tired
> old eyes. Still, good luck with whichever way you go.

For the purposes of this discussion, it's best that the privilege
escalation mechanism be considered an irrelevant implementation detail.
--
Thanks,
Zac