public inbox for gentoo-dev@lists.gentoo.org
 help / color / mirror / Atom feed
* [gentoo-dev] rfc: ideas for fixing OpenRC checkpath issue
@ 2018-01-10  0:07 William Hubbs
  2018-01-10  1:19 ` Michael Orlitzky
  2018-01-10 22:18 ` James Le Cuirot
  0 siblings, 2 replies; 18+ messages in thread
From: William Hubbs @ 2018-01-10  0:07 UTC (permalink / raw
  To: gentoo development; +Cc: mjo

[-- Attachment #1: Type: text/plain, Size: 470 bytes --]

All,

please take a look at the following issue.

https://github.com/openrc/openrc/issues/195

The first part of the fix is committed to master as shown on the issue;
checkpath should *never* follow symbolic links when changing ownership,
so I have moved to the lchown call instead of chown.

However, I'm not sure how to deal with the hard link issue in a way that
will not break service scripts.

If anyone has any suggestions for this, let me know.

Thanks,

William

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 195 bytes --]

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [gentoo-dev] rfc: ideas for fixing OpenRC checkpath issue
  2018-01-10  0:07 [gentoo-dev] rfc: ideas for fixing OpenRC checkpath issue William Hubbs
@ 2018-01-10  1:19 ` Michael Orlitzky
  2018-01-10 18:04   ` William Hubbs
  2018-01-10 18:17   ` Kristian Fiskerstrand
  2018-01-10 22:18 ` James Le Cuirot
  1 sibling, 2 replies; 18+ messages in thread
From: Michael Orlitzky @ 2018-01-10  1:19 UTC (permalink / raw
  To: gentoo-dev

On 01/09/2018 07:07 PM, William Hubbs wrote
> 
> However, I'm not sure how to deal with the hard link issue in a way that
> will not break service scripts.
> 

Systemd mitigates this by enabling the fs.protected_hardlinks sysctl by
default, but they have the liberty of requiring a relatively new Linux
kernel. The larger problem there is that, unless you have some kernel
protection built-in, the "Z" type in the tmpfiles.d spec is always going
to be exploitable:

  * https://github.com/OpenRC/opentmpfiles/issues/3

  * https://github.com/systemd/systemd/issues/7736

(I didn't realize at the time that the OpenRC fix still contained a race
condition.)

Ultimately, it's not safe to chown/chmod/setfacl/whatever in a directory
that is not writable only by yourself and root. There's some precedent
for this in e.g.

 https://wiki.gentoo.org/wiki/Hardened/Grsecurity_Trusted_Path_Execution

where they refuse to *execute* something that is writable by others. But
a solution like that would break existing scripts.

If it's any consolation, the tools like chown, chgrp, chmod, setfacl,
etc. are all vulnerable to the same issue themselves. GNU chown has the
"--from" flag (which still contains a race, by the way), but the other
tools don't, and are all exploitable in the same way. Again the advice
seems to be "don't do things if somebody can write to the directory
you're in."

Here's a very tedious proposal for OpenRC:

  1. Create a new helper, called e.g. "newpath", that is like checkpath
     but only creates things, and doesn't modify them.

  2. Have newpath throw a warning if it's used in a directory that is
     writable by someone other than root and the OpenRC user. This will
     prevent people from creating /foo/bar after /foo has already been
     created with owner "foo:foo". In other words, service script
     writers will be encouraged to do things in a safe order. Since
     we're starting over, this might even be made an error.

  3. Deprecate checkpath

  4. Wait a million years for people to switch from checkpath to newpath

  5. Get rid of checkpath

I'm not even sure that this solves the problem completely, but it's the
only idea I've got left.


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [gentoo-dev] rfc: ideas for fixing OpenRC checkpath issue
  2018-01-10  1:19 ` Michael Orlitzky
@ 2018-01-10 18:04   ` William Hubbs
  2018-01-10 20:25     ` Michael Orlitzky
  2018-01-10 18:17   ` Kristian Fiskerstrand
  1 sibling, 1 reply; 18+ messages in thread
From: William Hubbs @ 2018-01-10 18:04 UTC (permalink / raw
  To: gentoo-dev; +Cc: mjo

[-- Attachment #1: Type: text/plain, Size: 1676 bytes --]

On Tue, Jan 09, 2018 at 08:19:24PM -0500, Michael Orlitzky wrote:

*snip*

> Ultimately, it's not safe to chown/chmod/setfacl/whatever in a directory
> that is not writable only by yourself and root.

Let me try to phrase this another way.

If the directory we are in is not owned by us or root and is group or
world writable, checkpath should not change the ownership or permissions
of the file passed to it.

> Here's a very tedious proposal for OpenRC:
> 
>   1. Create a new helper, called e.g. "newpath", that is like checkpath
>      but only creates things, and doesn't modify them.
> 
>   2. Have newpath throw a warning if it's used in a directory that is
>      writable by someone other than root and the OpenRC user. This will
>      prevent people from creating /foo/bar after /foo has already been
>      created with owner "foo:foo". In other words, service script
>      writers will be encouraged to do things in a safe order. Since
>      we're starting over, this might even be made an error.
> 
>   3. Deprecate checkpath
> 
>   4. Wait a million years for people to switch from checkpath to newpath
> 
>   5. Get rid of checkpath
> 
> I'm not even sure that this solves the problem completely, but it's the
> only idea I've got left.

I'm not really a fan of creating a new helper unless I have to; I would
rather modify checkpath's behaviour.

The first stage of that modification would be to release a version that
outputs error messages, then convert the error messages to hard failures
in a later release.

Is this reasonable? If we go this route, what should checkpath start
complaining about?

William


[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 195 bytes --]

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [gentoo-dev] rfc: ideas for fixing OpenRC checkpath issue
  2018-01-10  1:19 ` Michael Orlitzky
  2018-01-10 18:04   ` William Hubbs
@ 2018-01-10 18:17   ` Kristian Fiskerstrand
  2018-01-12 16:33     ` Michael Orlitzky
  1 sibling, 1 reply; 18+ messages in thread
From: Kristian Fiskerstrand @ 2018-01-10 18:17 UTC (permalink / raw
  To: gentoo-dev, Michael Orlitzky


[-- Attachment #1.1: Type: text/plain, Size: 761 bytes --]

On 01/10/2018 02:19 AM, Michael Orlitzky wrote:
> On 01/09/2018 07:07 PM, William Hubbs wrote
>>
>> However, I'm not sure how to deal with the hard link issue in a way that
>> will not break service scripts.
>>
> 
> Systemd mitigates this by enabling the fs.protected_hardlinks sysctl by
> default, but they have the liberty of requiring a relatively new Linux

so does gentoo-sources since discussion in
https://bugs.gentoo.org/540006#c19
> 
> (I didn't realize at the time that the OpenRC fix still contained a race
> condition.)

This was mentioned already in https://bugs.gentoo.org/540006#c15
-- 
Kristian Fiskerstrand
OpenPGP keyblock reachable at hkp://pool.sks-keyservers.net
fpr:94CB AFDD 3034 5109 5618 35AA 0B7F 8B60 E3ED FAE3


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [gentoo-dev] rfc: ideas for fixing OpenRC checkpath issue
  2018-01-10 18:04   ` William Hubbs
@ 2018-01-10 20:25     ` Michael Orlitzky
  2018-01-10 21:54       ` William Hubbs
  0 siblings, 1 reply; 18+ messages in thread
From: Michael Orlitzky @ 2018-01-10 20:25 UTC (permalink / raw
  To: gentoo-dev

On 01/10/2018 01:04 PM, William Hubbs wrote:
> On Tue, Jan 09, 2018 at 08:19:24PM -0500, Michael Orlitzky wrote:
> 
>> Ultimately, it's not safe to chown/chmod/setfacl/whatever in a directory
>> that is not writable only by yourself and root.
> 
> Let me try to phrase this another way.
> 
> If the directory we are in is not owned by us or root and is group or
> world writable, checkpath should not change the ownership or permissions
> of the file passed to it.

There are also POSIX ACLs, NFSv4 ACLs, and god-knows-what-else to worry
about, but the above is a good start.


>> Here's a very tedious proposal for OpenRC: ...
>>
>>   2. Have newpath throw a warning if it's used in a directory that is
>>      writable by someone other than root and the OpenRC user. This will
>>      prevent people from creating /foo/bar after /foo has already been
>>      created with owner "foo:foo". In other words, service script
>>      writers will be encouraged to do things in a safe order. Since
>>      we're starting over, this might even be made an error.
> 
> I'm not really a fan of creating a new helper unless I have to; I would
> rather modify checkpath's behaviour.
> 
> The first stage of that modification would be to release a version that
> outputs error messages, then convert the error messages to hard failures
> in a later release.
> 
> Is this reasonable? If we go this route, what should checkpath start
> complaining about?

/*
 Disclaimer: I'm not even sure that this difficult proposal will solve
 the problem. Moreover there may be legitimate things going on in some
 init scripts that I haven't accounted for.
*/

The downside to keeping the name "checkpath" is that it makes it
difficult to identify unfixed scripts. If we change the name, then "grep
-rl checkpath" points them out for you; but if checkpath is modified,
you have to install the package and attempt to start/stop/save/reload it
and look for warnings.

Aside from that, it sounds workable. I guess it should warn when either,

  1 checkpath is used to modify an existing path and actually changes it

  2 checkpath is used to create a path whose parent is not writable only
    by root and the OpenRC user (i.e. the heuristic you mentioned above)

My rationale for those is as follows:

  1 Modifying existing paths in an automated fashion will never be safe
    due to the hardlink issue. If start_pre() creates both /foo
    and /foo/bar with owner "foo", then you can do that safely the first
    time around (when they're created), but the second time involves
    calling chown/chmod inside /foo which is writable by the "foo" user.

    If the service is restarted, /foo/bar might still exist, at which
    point we have to figure out what to do with it (assuming we don't
    blindly fix its permissions). I guess checkpath should check the
    existing permissions/ownership, and compare them to the desired
    ones? It's not an error if everything is the same, but if the init
    script wants something other than what's there, we should refuse to
    change things.

  2 Suppose again that we're creating both /foo and /foo/bar with owner
    "foo". If we run,

      checkpath --owner foo --directory /foo
      checkpath --owner foo --file      /foo/bar

    then there's still an opportunity for the "foo" user to trick you in
    the short window where /foo exists but /foo/bar does not. Instead,
    we'd like to nudge the service script writer to do it some other
    way. Keeping in mind that  we won't be able to modify the owner of
    /foo after /foo/bar is created (from item #1), this is the best that
    I can come up with:

      checkpath --owner foo --directory /foo
      su foo --command 'checkpath --file /foo/bar'

    That's safe because the "foo" user can only trick himself.

    The behavior of "su" isn't POSIX, but it's standard enough. If the
    construction above is common, maybe it makes sense to have checkpath
    drop privileges? So instead of,

      su foo --command 'checkpath --file /foo/bar'

    you could do,

      checkpath --as foo --file /foo/bar

    That would work because /foo is owned by "foo", and therefore
    writable by only the OpenRC user (now "foo") and root.


This is all quite half-baked, so if anyone thinks that I've overlooked
something obvious, you're probably not wrong.


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [gentoo-dev] rfc: ideas for fixing OpenRC checkpath issue
  2018-01-10 20:25     ` Michael Orlitzky
@ 2018-01-10 21:54       ` William Hubbs
  2018-01-13 20:48         ` Michael Orlitzky
  0 siblings, 1 reply; 18+ messages in thread
From: William Hubbs @ 2018-01-10 21:54 UTC (permalink / raw
  To: gentoo-dev; +Cc: mjo

[-- Attachment #1: Type: text/plain, Size: 2499 bytes --]

On Wed, Jan 10, 2018 at 03:25:55PM -0500, Michael Orlitzky wrote:
> On 01/10/2018 01:04 PM, William Hubbs wrote:
> > On Tue, Jan 09, 2018 at 08:19:24PM -0500, Michael Orlitzky wrote:
> > 
> >> Ultimately, it's not safe to chown/chmod/setfacl/whatever in a directory
> >> that is not writable only by yourself and root.
> > 
> > Let me try to phrase this another way.
> > 
> > If the directory we are in is not owned by us or root and is group or
> > world writable, checkpath should not change the ownership or permissions
> > of the file passed to it.
> 
> There are also POSIX ACLs, NFSv4 ACLs, and god-knows-what-else to worry
> about, but the above is a good start.
> 
> 
> >> Here's a very tedious proposal for OpenRC: ...
> >>
> >>   2. Have newpath throw a warning if it's used in a directory that is
> >>      writable by someone other than root and the OpenRC user. This will
> >>      prevent people from creating /foo/bar after /foo has already been
> >>      created with owner "foo:foo". In other words, service script
> >>      writers will be encouraged to do things in a safe order. Since
> >>      we're starting over, this might even be made an error.
> > 
> > I'm not really a fan of creating a new helper unless I have to; I would
> > rather modify checkpath's behaviour.
> > 
> > The first stage of that modification would be to release a version that
> > outputs error messages, then convert the error messages to hard failures
> > in a later release.
> > 
> > Is this reasonable? If we go this route, what should checkpath start
> > complaining about?
> 
> /*
>  Disclaimer: I'm not even sure that this difficult proposal will solve
>  the problem. Moreover there may be legitimate things going on in some
>  init scripts that I haven't accounted for.
> */
> 
> The downside to keeping the name "checkpath" is that it makes it
> difficult to identify unfixed scripts. If we change the name, then "grep
> -rl checkpath" points them out for you; but if checkpath is modified,
> you have to install the package and attempt to start/stop/save/reload it
> and look for warnings.

Good point, this may be a good reason to make a new helper and deprecate
checkpath. What I would do is make checkpath throw an error but keep
running,. It would have a message, something like:

"Checkpath is deprecated, please use newpath instead."

What are we saying newpath should do differently than checkpath if I
go this route?

William

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 195 bytes --]

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [gentoo-dev] rfc: ideas for fixing OpenRC checkpath issue
  2018-01-10  0:07 [gentoo-dev] rfc: ideas for fixing OpenRC checkpath issue William Hubbs
  2018-01-10  1:19 ` Michael Orlitzky
@ 2018-01-10 22:18 ` James Le Cuirot
  2018-01-10 23:31   ` Michael Orlitzky
  1 sibling, 1 reply; 18+ messages in thread
From: James Le Cuirot @ 2018-01-10 22:18 UTC (permalink / raw
  To: gentoo-dev

[-- Attachment #1: Type: text/plain, Size: 1069 bytes --]

On Tue, 9 Jan 2018 18:07:41 -0600
William Hubbs <williamh@gentoo.org> wrote:

> All,
> 
> please take a look at the following issue.
> 
> https://github.com/openrc/openrc/issues/195
> 
> The first part of the fix is committed to master as shown on the issue;
> checkpath should *never* follow symbolic links when changing ownership,
> so I have moved to the lchown call instead of chown.
> 
> However, I'm not sure how to deal with the hard link issue in a way that
> will not break service scripts.
> 
> If anyone has any suggestions for this, let me know.

I faced the hard link problem in another package (bug still restricted)
recently. I'm about to push the fix out but I just want check what I've
done is okay. The init script used to call chown/chmod -R, which is
obviously bad. I've compromised by only calling these on the
directories themselves (ignoring symlinks). I believe this is safe
because it's not possible to create hard linked directories these days?
Would you agree?

-- 
James Le Cuirot (chewi)
Gentoo Linux Developer

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 981 bytes --]

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [gentoo-dev] rfc: ideas for fixing OpenRC checkpath issue
  2018-01-10 22:18 ` James Le Cuirot
@ 2018-01-10 23:31   ` Michael Orlitzky
  0 siblings, 0 replies; 18+ messages in thread
From: Michael Orlitzky @ 2018-01-10 23:31 UTC (permalink / raw
  To: gentoo-dev

On 01/10/2018 05:18 PM, James Le Cuirot wrote:
> 
> The init script used to call chown/chmod -R, which is
> obviously bad. I've compromised by only calling these on the
> directories themselves (ignoring symlinks). I believe this is safe
> because it's not possible to create hard linked directories these days?
> Would you agree?

Are you still using chown and chmod? If so, you should switch to
checkpath -- chown and chmod don't even try to avoid hard links. I would
be surprised to see a "chown" or "chmod" in an init script that can't be
replaced by something better.

The race condition that we're talking about here is trying to squeeze
the last 1% of security out of checkpath; it's already much safer than
chown/chmod.

For example, if your script is calling chown and chmod on two
directories /foo and /foo/bar, then whoever owns /foo can kill /foo/bar
entirely and replace it with a hard link to /etc/passwd. When the
service restarts, chown and chmod won't care that you think /foo/bar
should be a directory instead.


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [gentoo-dev] rfc: ideas for fixing OpenRC checkpath issue
  2018-01-10 18:17   ` Kristian Fiskerstrand
@ 2018-01-12 16:33     ` Michael Orlitzky
  0 siblings, 0 replies; 18+ messages in thread
From: Michael Orlitzky @ 2018-01-12 16:33 UTC (permalink / raw
  To: gentoo-dev

On 01/10/2018 01:17 PM, Kristian Fiskerstrand wrote:
>>
>> (I didn't realize at the time that the OpenRC fix still contained a race
>> condition.)
> 
> This was mentioned already in https://bugs.gentoo.org/540006#c15
> 

So it is =)

I took the RESOLVED FIXED for granted when I reported the tmpfiles.d
issues. At least for symlinks, there was an easy way to avoid the race,
so something useful came out of my unwillingness to read.


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [gentoo-dev] rfc: ideas for fixing OpenRC checkpath issue
  2018-01-10 21:54       ` William Hubbs
@ 2018-01-13 20:48         ` Michael Orlitzky
  2018-01-17 15:21           ` William Hubbs
  0 siblings, 1 reply; 18+ messages in thread
From: Michael Orlitzky @ 2018-01-13 20:48 UTC (permalink / raw
  To: gentoo-dev

On 01/10/2018 04:54 PM, William Hubbs wrote:
> 
> What are we saying newpath should do differently than checkpath if I
> go this route?

I think this covers everything that we've talked about:

 1. It should refuse to modify existing paths.

    1.a. If newpath is called on an existing path, and if the requested
         owner/permissions agree with the existing set, then do nothing.
         This is expected when services restart without a reboot.

    1.b. If newpath is called on an existing path, and if the desired
         permissions differ from the existing set, then do nothing and
         log a warning.


 2. It should have a flag (say, --as=<user>[:group]) to make it run as
    an unprivileged user. Basically a portable "su -c".


 3. It should die if it's used in a directory that is writable by
    anyone other than itself or root. (If it's feasible, we might want
    to check the parent directories all the way up to the root; if I can
    write to "b", then I can write to "e" in /a/b/c/d/e.)

    Since newpath can't modify existing paths, the aforementioned "--as"
    flag will be needed to avoid this error.


And just to put it out there, this will probably make a lot of people
mad. It discourages you from doing things like setting FOO_USER=foo in
the conf.d file, because you can't "fix" the permissions on things like
/var/log/foo.log if the value of $FOO_USER ever changes. That was
inherently unsafe anyway, but I'll eat my shorts if nobody complains.

(User variables, or RC_SVCNAME, should still work fine work multiple
instances.)


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [gentoo-dev] rfc: ideas for fixing OpenRC checkpath issue
  2018-01-13 20:48         ` Michael Orlitzky
@ 2018-01-17 15:21           ` William Hubbs
  2018-01-17 15:41             ` Michael Orlitzky
  0 siblings, 1 reply; 18+ messages in thread
From: William Hubbs @ 2018-01-17 15:21 UTC (permalink / raw
  To: gentoo-dev; +Cc: mjo

[-- Attachment #1: Type: text/plain, Size: 2196 bytes --]

On Sat, Jan 13, 2018 at 03:48:10PM -0500, Michael Orlitzky wrote:
> On 01/10/2018 04:54 PM, William Hubbs wrote:
> > 
> > What are we saying newpath should do differently than checkpath if I
> > go this route?
> 
> I think this covers everything that we've talked about:
> 
>  1. It should refuse to modify existing paths.
> 
>     1.a. If newpath is called on an existing path, and if the requested
>          owner/permissions agree with the existing set, then do nothing.
>          This is expected when services restart without a reboot.
> 
>     1.b. If newpath is called on an existing path, and if the desired
>          permissions differ from the existing set, then do nothing and
>          log a warning.
 
 For both A and B above I think you mean owner/group/permissions right?

>  2. It should have a flag (say, --as=<user>[:group]) to make it run as
>     an unprivileged user. Basically a portable "su -c".

I'm not following why I need this.

>  3. It should die if it's used in a directory that is writable by
>     anyone other than itself or root. (If it's feasible, we might want
>     to check the parent directories all the way up to the root; if I can
>     write to "b", then I can write to "e" in /a/b/c/d/e.)
 
 Checkpath doesn't handle multiple layers of directories currently; you
 can't do "checkpath -d /run/a/b" without doing "checkpath -d /run/a"
 first, so I don't see a way to check parents.

>     Since newpath can't modify existing paths, the aforementioned "--as"
>     flag will be needed to avoid this error.

Which error are you referring to? I don't follow you here. I don't see
how newpath not modifying existing paths is related to this.

William


> And just to put it out there, this will probably make a lot of people
> mad. It discourages you from doing things like setting FOO_USER=foo in
> the conf.d file, because you can't "fix" the permissions on things like
> /var/log/foo.log if the value of $FOO_USER ever changes. That was
> inherently unsafe anyway, but I'll eat my shorts if nobody complains.
> 
> (User variables, or RC_SVCNAME, should still work fine work multiple
> instances.)
> 

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 195 bytes --]

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [gentoo-dev] rfc: ideas for fixing OpenRC checkpath issue
  2018-01-17 15:21           ` William Hubbs
@ 2018-01-17 15:41             ` Michael Orlitzky
  2018-01-17 17:14               ` William Hubbs
  0 siblings, 1 reply; 18+ messages in thread
From: Michael Orlitzky @ 2018-01-17 15:41 UTC (permalink / raw
  To: gentoo-dev

On 01/17/2018 10:21 AM, William Hubbs wrote:
>  
>  For both A and B above I think you mean owner/group/permissions right?

Yep.


>>  2. It should have a flag (say, --as=<user>[:group]) to make it run as
>>     an unprivileged user. Basically a portable "su -c".
> 
> I'm not following why I need this.
> 
>>  3. It should die if it's used in a directory that is writable by
>>     anyone other than itself or root. (If it's feasible, we might want
>>     to check the parent directories all the way up to the root; if I can
>>     write to "b", then I can write to "e" in /a/b/c/d/e.)
> 
>>     Since newpath can't modify existing paths, the aforementioned "--as"
>>     flag will be needed to avoid this error.
> 
> Which error are you referring to? I don't follow you here. I don't see
> how newpath not modifying existing paths is related to this.
> 


If I want to create /run/foo and /run/foo/bar, both owned by the "foo"
user, how would I do it using newpath?

1. I could create /run/foo with owner "foo", and then create
   /run/foo/bar with owner "foo". That can be done without modifying
   existing permissions, but it's not safe, because you wind up working
   as root in the directory /run/foo which is owned by the non-root
   "foo" user. If newpath disallows that unsafe operation, this approach
   is out.

2. I could create /run/foo as root:root, and then create /run/foo/bar as
   "foo". That much is safe, but then what do I do about /run/foo? It
   already exists, so if newpath will refuse to modify existing paths,
   then this approach is out too.

That leaves...

3. I can create /run/foo with owner "foo", and then setuid to the foo
   user. Now, *as the foo user* I can create /run/foo/bar, which will be
   owned by "foo". There's no risk in doing so, because the "foo" user
   can only trick himself. Moreover, the directory is writable only by
   root and the OpenRC user (currently: foo) at that point, so the extra
   safety precautions don't get in the way.


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [gentoo-dev] rfc: ideas for fixing OpenRC checkpath issue
  2018-01-17 15:41             ` Michael Orlitzky
@ 2018-01-17 17:14               ` William Hubbs
  2018-01-19  0:19                 ` Michael Orlitzky
  0 siblings, 1 reply; 18+ messages in thread
From: William Hubbs @ 2018-01-17 17:14 UTC (permalink / raw
  To: gentoo-dev; +Cc: mjo

[-- Attachment #1: Type: text/plain, Size: 2108 bytes --]

On Wed, Jan 17, 2018 at 10:41:21AM -0500, Michael Orlitzky wrote:
> If I want to create /run/foo and /run/foo/bar, both owned by the "foo"
> user, how would I do it using newpath?
> 
> 1. I could create /run/foo with owner "foo", and then create
>    /run/foo/bar with owner "foo". That can be done without modifying
>    existing permissions, but it's not safe, because you wind up working
>    as root in the directory /run/foo which is owned by the non-root
>    "foo" user. If newpath disallows that unsafe operation, this approach
>    is out.
> 
> 2. I could create /run/foo as root:root, and then create /run/foo/bar as
>    "foo". That much is safe, but then what do I do about /run/foo? It
>    already exists, so if newpath will refuse to modify existing paths,
>    then this approach is out too.
> 
> That leaves...
> 
> 3. I can create /run/foo with owner "foo", and then setuid to the foo
>    user. Now, *as the foo user* I can create /run/foo/bar, which will be
>    owned by "foo". There's no risk in doing so, because the "foo" user
>    can only trick himself. Moreover, the directory is writable only by
>    root and the OpenRC user (currently: foo) at that point, so the extra
>    safety precautions don't get in the way.

Everything I'm saying here assumes that /run/foo and /run/foo/bar do not
exist. If they do, both approaches 1 and 3 will do nothing other than
warn if the permissions or ownership has changed.

In both approaches 1 and 3, the first step will be to create the
directory /run/foo then optionally adjust permissions on it. At that
point newpath will exit.

When the second invocation of newpath starts, we know /run/foo/bar
does not exist, and creating /run/foo/bar will fail if /run/foo doesn't
exist.

Since that's true, I don't see what the difference is
between approaches 1 and 3 or what makes approach 1 so unsafe. Call me
dense if you must, lol, I'm just not getting it. At this point we know
that /run/foo is owned by foo, and I've never heard that root working in
a directory it doesn't own isn't safe.

William

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 195 bytes --]

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [gentoo-dev] rfc: ideas for fixing OpenRC checkpath issue
  2018-01-17 17:14               ` William Hubbs
@ 2018-01-19  0:19                 ` Michael Orlitzky
  2018-01-20  0:16                   ` William Hubbs
  0 siblings, 1 reply; 18+ messages in thread
From: Michael Orlitzky @ 2018-01-19  0:19 UTC (permalink / raw
  To: gentoo-dev

On 01/17/2018 12:14 PM, William Hubbs wrote:
>>
>> 1. I could create /run/foo with owner "foo", and then create
>>    /run/foo/bar with owner "foo". That can be done without modifying
>>    existing permissions, but it's not safe, because you wind up working
>>    as root in the directory /run/foo which is owned by the non-root
>>    "foo" user. If newpath disallows that unsafe operation, this approach
>>    is out.
>>
>> ...
>>
>> 3. I can create /run/foo with owner "foo", and then setuid to the foo
>>    user. Now, *as the foo user* I can create /run/foo/bar, which will be
>>    owned by "foo". There's no risk in doing so, because the "foo" user
>>    can only trick himself. Moreover, the directory is writable only by
>>    root and the OpenRC user (currently: foo) at that point, so the extra
>>    safety precautions don't get in the way.
> 
> 
> In both approaches 1 and 3, the first step will be to create the
> directory /run/foo then optionally adjust permissions on it. At that
> point newpath will exit.
> 
> When the second invocation of newpath starts, we know /run/foo/bar
> does not exist, and creating /run/foo/bar will fail if /run/foo doesn't
> exist.
> 
> Since that's true, I don't see what the difference is
> between approaches 1 and 3 or what makes approach 1 so unsafe. Call me
> dense if you must, lol, I'm just not getting it. At this point we know
> that /run/foo is owned by foo, and I've never heard that root working in
> a directory it doesn't own isn't safe.

Not at all. I'm working this out as I go, so better to speak up if
something looks fishy.

There are a few risks that I see with the first approach...


Risk #1: From what I can tell, the current implementation of checkpath
first creates the path, and then adjusts the ownership and permissions
on it. After /run/foo/bar has been created but before the permissions
and ownership are changed, the "foo" user can replace "bar" with a hard
link (because he owns /run/foo). The lchown/chmod will operate on the
target of that link, and if he's fast enough, then the "foo" user can
use that to take over root's files. (Limited to /run in this example,
but that's beside the point.)

Maybe that can be avoided. Is there a portable way to atomically create
a file/directory with its ownership and permissions already set? Or is
it possible to operate on the descriptor that you get back when creating
the path?


Risk #2: Instead consider a four-component path /run/foo/bar/baz. If you
start creating those directories with owner "foo", then when you get to
creating "baz", it's possible that "bar" has been replaced by a symlink
somewhere else.

Certain tricks exist to avoid that, but I'm not an expert on them and I
don't know how portable or secure they really are. For example, you
might get the descriptor of "bar" and then use openat(dirfd,...) instead
of open(...) to create "baz".


If both of those can be solved portably, then all you have to worry
about is everything I haven't thought of =)


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [gentoo-dev] rfc: ideas for fixing OpenRC checkpath issue
  2018-01-19  0:19                 ` Michael Orlitzky
@ 2018-01-20  0:16                   ` William Hubbs
  2018-01-20  0:53                     ` Michael Orlitzky
  0 siblings, 1 reply; 18+ messages in thread
From: William Hubbs @ 2018-01-20  0:16 UTC (permalink / raw
  To: gentoo-dev; +Cc: mjo

[-- Attachment #1: Type: text/plain, Size: 3261 bytes --]

On Thu, Jan 18, 2018 at 07:19:59PM -0500, Michael Orlitzky wrote:
> Not at all. I'm working this out as I go, so better to speak up if
> something looks fishy.
> 
> There are a few risks that I see with the first approach...
> 
> 
> Risk #1: From what I can tell, the current implementation of checkpath
> first creates the path, and then adjusts the ownership and permissions
> on it. After /run/foo/bar has been created but before the permissions
> and ownership are changed, the "foo" user can replace "bar" with a hard
> link (because he owns /run/foo). The lchown/chmod will operate on the
> target of that link, and if he's fast enough, then the "foo" user can
> use that to take over root's files. (Limited to /run in this example,
> but that's beside the point.)
> 
> Maybe that can be avoided. Is there a portable way to atomically create
> a file/directory with its ownership and permissions already set? Or is
> it possible to operate on the descriptor that you get back when creating
> the path?

Permissions are set as part of the mkdir/open/mkfifo call, so they are
set immediately when the file is created. but ownership is adjusted
separately by calling chown/fchown/lchown.

At a high level, checkpath looks like this:

1. Creating and setting permissions.
a. If the file doesn't exist, set the permissions when it is created.
b. If the file does exist, only fix the permissions if necessary.
c. At this point, the file's permissions are correct.
2. setting ownership
a. always set the ownership if the file's ownership doesn't match the
specified ownership.

It looks like we can't use your --as suggestion if we want to be
able to create paths in /var/lib and /var/spool that are owned by
non-privileged users because of the permissions on those paths. It is
possible that service scripts are doing this.

Is it worth changing the algorithm to do this instead:

0. test for existance by opening a read-only file descriptor to this
file.
1. Creating the file/directory/fifo.
a. If it doesn't exist, create it -- note that I'm not setting
permissions with the create call.
b. Open a read-only file descriptor that attaches to the newly created
file.
2. Setting Permissions.
a. Fix the permissions of the file if necessary.
3. setting ownership
a. Set the ownership if it doesn't match the specified ownership.

> Risk #2: Instead consider a four-component path /run/foo/bar/baz. If you
> start creating those directories with owner "foo", then when you get to
> creating "baz", it's possible that "bar" has been replaced by a symlink
> somewhere else.
 
 It is possible, sure, but the question I would ask is, could this also
 be a legit situation where a user would want /run/foo/bar to be a
 symlink to some other location? If it is, there's no way to tell the
 difference.

> Certain tricks exist to avoid that, but I'm not an expert on them and I
> don't know how portable or secure they really are. For example, you
> might get the descriptor of "bar" and then use openat(dirfd,...) instead
> of open(...) to create "baz".
> 
> If both of those can be solved portably, then all you have to worry
> about is everything I haven't thought of =)

Thoughts?

William


[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 195 bytes --]

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [gentoo-dev] rfc: ideas for fixing OpenRC checkpath issue
  2018-01-20  0:16                   ` William Hubbs
@ 2018-01-20  0:53                     ` Michael Orlitzky
  2018-01-20  1:14                       ` William Hubbs
  0 siblings, 1 reply; 18+ messages in thread
From: Michael Orlitzky @ 2018-01-20  0:53 UTC (permalink / raw
  To: gentoo-dev

On 01/19/2018 07:16 PM, William Hubbs wrote:
> 
> It looks like we can't use your --as suggestion if we want to be
> able to create paths in /var/lib and /var/spool that are owned by
> non-privileged users because of the permissions on those paths. It is
> possible that service scripts are doing this.
> 

Why not? Since /var/lib is root:root and mode 755, we can create
/var/lib/foo while running --as=root (the default). Then afterwards,
anything beneath /var/lib/foo would need to be created "--as" the owner
of that directory.

/var/lib or /var/spool should be no different than /run in that regard.

(Although, the ebuild should be responsible for /var/lib and /var/spool)


> Is it worth changing the algorithm to do this instead:
> 
> 0. test for existance by opening a read-only file descriptor to this
> file.
> 1. Creating the file/directory/fifo.
> a. If it doesn't exist, create it -- note that I'm not setting
> permissions with the create call.
> b. Open a read-only file descriptor that attaches to the newly created
> file.
> 2. Setting Permissions.
> a. Fix the permissions of the file if necessary.
> 3. setting ownership
> a. Set the ownership if it doesn't match the specified ownership.

Is this for checkpath? Steps (a) and (b) would need to happen at the
same time. Is there a way to determine if a file descriptor is for a
hard link? There are likely some small ways that we could still improve
checkpath, but the main issue I'm trying to solve by jumping through all
these hoops is the hard link race condition.


>> Risk #2: Instead consider a four-component path /run/foo/bar/baz. If you
>> start creating those directories with owner "foo", then when you get to
>> creating "baz", it's possible that "bar" has been replaced by a symlink
>> somewhere else.
>  
>  It is possible, sure, but the question I would ask is, could this also
>  be a legit situation where a user would want /run/foo/bar to be a
>  symlink to some other location? If it is, there's no way to tell the
>  difference.

The init script author can use the real path instead of the one
involving the symlink if he needs to. So maybe he wants /run/foo/bar to
be a symlink to /herp/derp, but then instead of doing

  newpath /run/foo/bar/baz

he could do

  newpath /herp/derp/baz

and then there are no symlinks involved.


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [gentoo-dev] rfc: ideas for fixing OpenRC checkpath issue
  2018-01-20  0:53                     ` Michael Orlitzky
@ 2018-01-20  1:14                       ` William Hubbs
  2018-01-20  1:20                         ` Michael Orlitzky
  0 siblings, 1 reply; 18+ messages in thread
From: William Hubbs @ 2018-01-20  1:14 UTC (permalink / raw
  To: gentoo-dev; +Cc: mjo

[-- Attachment #1: Type: text/plain, Size: 3190 bytes --]

On Fri, Jan 19, 2018 at 07:53:06PM -0500, Michael Orlitzky wrote:
> On 01/19/2018 07:16 PM, William Hubbs wrote:
> > 
> > It looks like we can't use your --as suggestion if we want to be
> > able to create paths in /var/lib and /var/spool that are owned by
> > non-privileged users because of the permissions on those paths. It is
> > possible that service scripts are doing this.
> > 
> 
> Why not? Since /var/lib is root:root and mode 755, we can create
> /var/lib/foo while running --as=root (the default). Then afterwards,
> anything beneath /var/lib/foo would need to be created "--as" the owner
> of that directory.

That would create an extra level of indirection for some things though,
what if /var/lib/foo needs to be owned by foo? I have /var/lib/dhcp
which is owned by dhcp:dhcp. You can't creat that with --as=dhcp.

> 
> /var/lib or /var/spool should be no different than /run in that regard.
> 
> (Although, the ebuild should be responsible for /var/lib and /var/spool)
> 
> 
> > Is it worth changing the algorithm to do this instead:
> > 
> > 0. test for existance by opening a read-only file descriptor to this
> > file.
> > 1. Creating the file/directory/fifo.
> > a. If it doesn't exist, create it -- note that I'm not setting
> > permissions with the create call.
> > b. Open a read-only file descriptor that attaches to the newly created
> > file.
> > 2. Setting Permissions.
> > a. Fix the permissions of the file if necessary.
> > 3. setting ownership
> > a. Set the ownership if it doesn't match the specified ownership.
> 
> Is this for checkpath? Steps (a) and (b) would need to happen at the
> same time. Is there a way to determine if a file descriptor is for a
> hard link? There are likely some small ways that we could still improve
> checkpath, but the main issue I'm trying to solve by jumping through all
> these hoops is the hard link race condition.

You mean steps 1 (a) and (b)? They would happen in the sequence shown.
The only call that gives you a file descriptor is open() which is not
used to create a directory or a fifo.

The link status is available via fstat() or stat().
An example of checking it is in line 146 of checkpath.c. We refuse to
chmod a file that has more than one hard link to it.

> 
> 
> >> Risk #2: Instead consider a four-component path /run/foo/bar/baz. If you
> >> start creating those directories with owner "foo", then when you get to
> >> creating "baz", it's possible that "bar" has been replaced by a symlink
> >> somewhere else.
> >  
> >  It is possible, sure, but the question I would ask is, could this also
> >  be a legit situation where a user would want /run/foo/bar to be a
> >  symlink to some other location? If it is, there's no way to tell the
> >  difference.
> 
> The init script author can use the real path instead of the one
> involving the symlink if he needs to. So maybe he wants /run/foo/bar to
> be a symlink to /herp/derp, but then instead of doing
> 
>   newpath /run/foo/bar/baz
> 
> he could do
> 
>   newpath /herp/derp/baz
> 
> and then there are no symlinks involved.

Let me think about this... :-)

William

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 195 bytes --]

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [gentoo-dev] rfc: ideas for fixing OpenRC checkpath issue
  2018-01-20  1:14                       ` William Hubbs
@ 2018-01-20  1:20                         ` Michael Orlitzky
  0 siblings, 0 replies; 18+ messages in thread
From: Michael Orlitzky @ 2018-01-20  1:20 UTC (permalink / raw
  To: gentoo-dev

On 01/19/2018 08:14 PM, William Hubbs wrote:
>>
>> Why not? Since /var/lib is root:root and mode 755, we can create
>> /var/lib/foo while running --as=root (the default). Then afterwards,
>> anything beneath /var/lib/foo would need to be created "--as" the owner
>> of that directory.
> 
> That would create an extra level of indirection for some things though,
> what if /var/lib/foo needs to be owned by foo? I have /var/lib/dhcp
> which is owned by dhcp:dhcp. You can't creat that with --as=dhcp.
> 

The same way you do it now:

  newpath --directory /var/lib/dhcp --owner dhcp:dhcp

There's no new obstacle, because /var/lib is writable only by root and
the current OpenRC user (also root, in this case).

Now if you need /var/lib/dhcp/something-else to be owned by dhcp:dhcp,
*then* you would do it --as=dhcp.


^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2018-01-20  1:21 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-01-10  0:07 [gentoo-dev] rfc: ideas for fixing OpenRC checkpath issue William Hubbs
2018-01-10  1:19 ` Michael Orlitzky
2018-01-10 18:04   ` William Hubbs
2018-01-10 20:25     ` Michael Orlitzky
2018-01-10 21:54       ` William Hubbs
2018-01-13 20:48         ` Michael Orlitzky
2018-01-17 15:21           ` William Hubbs
2018-01-17 15:41             ` Michael Orlitzky
2018-01-17 17:14               ` William Hubbs
2018-01-19  0:19                 ` Michael Orlitzky
2018-01-20  0:16                   ` William Hubbs
2018-01-20  0:53                     ` Michael Orlitzky
2018-01-20  1:14                       ` William Hubbs
2018-01-20  1:20                         ` Michael Orlitzky
2018-01-10 18:17   ` Kristian Fiskerstrand
2018-01-12 16:33     ` Michael Orlitzky
2018-01-10 22:18 ` James Le Cuirot
2018-01-10 23:31   ` Michael Orlitzky

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox