hurd: Fix O_NOFOLLOW

The error code documented by POSIX for opening a symlink with O_NOFOLLOW
is ELOOP.

Also, if the translator does not expose symlink as a symlink translator but
as a S_IFLNK file, O_NOFOLLOW needs to return ELOOP too.

	* hurd/lookup-retry.c (__hurd_file_name_lookup_retry): Return ELOOP
	when opening a symlink with O_NOFOLLOW.
This commit is contained in:
Samuel Thibault 2018-03-18 19:39:29 +01:00
parent 55325314bf
commit 489999cc9c
2 changed files with 22 additions and 16 deletions

View File

@ -62,6 +62,8 @@
2018-03-18 Samuel Thibault <samuel.thibault@ens-lyon.org> 2018-03-18 Samuel Thibault <samuel.thibault@ens-lyon.org>
* sysdeps/mach/hurd/cthreads.c: Include <cthreads.h>. * sysdeps/mach/hurd/cthreads.c: Include <cthreads.h>.
* hurd/lookup-retry.c (__hurd_file_name_lookup_retry): Return ELOOP
when opening a symlink with O_NOFOLLOW.
2018-03-17 Samuel Thibault <samuel.thibault@ens-lyon.org> 2018-03-17 Samuel Thibault <samuel.thibault@ens-lyon.org>

View File

@ -127,7 +127,7 @@ __hurd_file_name_lookup_retry (error_t (*use_init_port)
{ {
/* In Linux, O_NOFOLLOW means to reject symlinks. If we /* In Linux, O_NOFOLLOW means to reject symlinks. If we
did an O_NOLINK lookup above and io_stat here to check did an O_NOLINK lookup above and io_stat here to check
for S_IFLNK, a translator like firmlink could easily for S_IFLNK only, a translator like firmlink could easily
spoof this check by not showing S_IFLNK, but in fact spoof this check by not showing S_IFLNK, but in fact
redirecting the lookup to some other name redirecting the lookup to some other name
(i.e. opening the very same holes a symlink would). (i.e. opening the very same holes a symlink would).
@ -145,23 +145,27 @@ __hurd_file_name_lookup_retry (error_t (*use_init_port)
one exception to our general translator-based rule. */ one exception to our general translator-based rule. */
struct stat64 st; struct stat64 st;
err = __io_stat (*result, &st); err = __io_stat (*result, &st);
if (!err if (!err)
&& (st.st_mode & (S_IPTRANS|S_IATRANS)))
{ {
if (st.st_uid != 0) if (S_ISLNK (st.st_mode))
err = ENOENT; err = ELOOP;
else if (st.st_mode & S_IPTRANS) else if (st.st_mode & (S_IPTRANS|S_IATRANS))
{ {
char buf[1024]; if (st.st_uid != 0)
char *trans = buf; err = ELOOP;
size_t translen = sizeof buf; else if (st.st_mode & S_IPTRANS)
err = __file_get_translator (*result, {
&trans, &translen); char buf[1024];
if (!err char *trans = buf;
&& translen > sizeof _HURD_SYMLINK size_t translen = sizeof buf;
&& !memcmp (trans, err = __file_get_translator (*result,
_HURD_SYMLINK, sizeof _HURD_SYMLINK)) &trans, &translen);
err = ENOENT; if (!err
&& translen > sizeof _HURD_SYMLINK
&& !memcmp (trans,
_HURD_SYMLINK, sizeof _HURD_SYMLINK))
err = ELOOP;
}
} }
} }
} }