Re: [PATCH] Bindings to *at functions & allowing more functions to operate on ports

2021-05-05 Thread Maxime Devos
rob piko schreef op di 04-05-2021 om 18:58 [-0400]:
> Hello Maxime,
> 
> > * Use O_NOFOLLOW to *not* follow the symbolic link.
> >  Patch for adding O_NOFOLLOW to guile:
> 
> According to the man pages for the O_NOFOLLOW:
> 
> > If the trailing component (i.e., basename) of pathname is
> >   a symbolic link, then the open fails, with the error
> >   ELOOP.  Symbolic links in earlier components of the
> >   pathname will still be followed.
> 
> Sounds like O_NOFOLLOW would not fix the issue if the symlink is found in 
> other parts of the pathname outside of the basename?
Indeed! To avoid *all* symlinks, and not only a symlink in the trailing 
component,
you would need to call 'open' with O_NOFOLLOW in a loop.

Something like:
  (let* ((dir (open "/symlinks/acceptable-here" O_RDONLY))
 ;; Symlinks are not followed here.
 (dir* (openat dir "dir" (logior O_RDONLY O_NOFOLLOW)))
 (file (openat dir* "file" (logior O_RDONLY O_NOFOLLOW
(close dir)
(close dir*)
file)

It has been a while since I wrote the patch though, maybe the argument
order is a little different.

Greetings,
Maxime.


signature.asc
Description: This is a digitally signed message part


Re: [PATCH] Bindings to *at functions & allowing more functions to operate on ports

2021-05-04 Thread rob piko
Hello Maxime,

> * Use O_NOFOLLOW to *not* follow the symbolic link.
>  Patch for adding O_NOFOLLOW to guile:

According to the man pages for the O_NOFOLLOW:

If the trailing component (i.e., basename) of *pathname* is
>   a symbolic link, then the open fails, with the error
>   *ELOOP*.  Symbolic links in earlier components of the
>   pathname will still be followed.
>
>
Sounds like O_NOFOLLOW would not fix the issue if the symlink is found in
other parts of the pathname outside of the basename?

Regards,
Kostyantyn Kovalskyy


On Sun, Mar 28, 2021 at 7:18 AM  wrote:

> On Sat, Mar 27, 2021 at 10:19:20PM +0100, Maxime Devos wrote:
> > Hi,
> >
> > [CC'ing some Guile and Guix maintainers because this is
> > important for the security of Guix System.]
>
> [snipped CC, since my answer is just a thankyou]
>
> > I want to explain why these patches (and the O_FLAGS (*)
> > patch) should be included in Guile [...]
>
> *THANK YOU*
>
> This from someone striving to make Guile the "default tool for
> around the house".
>
> Cheers
>  - t
>


Re: [PATCH] Bindings to *at functions & allowing more functions to operate on ports

2021-03-27 Thread Maxime Devos
Hi,

[CC'ing some Guile and Guix maintainers because this is
important for the security of Guix System.]

I want to explain why these patches (and the O_FLAGS (*)
patch) should be included in Guile.  Functions like "openat"
are important to avoid TOCTTOU (time-of-check to time-of-use)
vulnerabilities involving symbolic links.

For example, suppose we have a web server implemented in
Guile.  Suppose the address is https://web.gnu.  It allows
a local user U (and some others) to define their own web
pages to host at http://web.gnu/~U, by writing files to
/home/U/www.  As there are multiple users, the server has
to run as root.

Now suppose U is the malicious kind of user.  Then $U
could create a symlink at /home/U/www/maliciousity pointing
to /home/other-user/.gnupg/private-keys-v1.d/FINGERPRINT.key.

Now U could download other-user's gpg key, for example
with "wget http://web.gnu/~U/maliciousity;.  Oops!

How can this vulnerability be avoided?

* Use O_NOFOLLOW to *not* follow the symbolic link.
  Patch for adding O_NOFOLLOW to guile:
  .

And why do we need openat?  Well, suppose the web server
is not read-only, and supports (say) WebDAV or FTP for
modifying files remotely (I mean U can remotely modify
http://web.gnu/~U).  Then U could create a symlink
at /home/U/www/maliciousity pointing to /home/other-user.
Now U can peek into other-user's home directory and overwrite
files.  Oops!

How can the web server avoid this?

* First open "/home/U" as usual, resulting in a port $1.
  Then use (openat $1 "maliciousity" O_NOFOLLOW), resulting
  in a port $2.  Use (stat $2) to see if $2 is a directory
  or a regular file **and** to see if $2 is owned by $2!
  If necessary, recurse, etc.  Display a directory listing
  or display the file, etc.

How does this matter for Guix?

Guix has a TOCTTOU race:
.
It has been partially fixed:
.
However, a complete fix requires bindings to "openat".

I found another similar issue in Guix lately (not yet disclosed publicly).
While I think the conditions for this other potential security issue
to be exploitable don't ever happen in practice, I would still like
to fix this issue, and to be able to prevent similar issues from appearing
in the future.

Greetings,
Maxime.


signature.asc
Description: This is a digitally signed message part