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,11 +145,14 @@ __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 (S_ISLNK (st.st_mode))
err = ELOOP;
else if (st.st_mode & (S_IPTRANS|S_IATRANS))
{ {
if (st.st_uid != 0) if (st.st_uid != 0)
err = ENOENT; err = ELOOP;
else if (st.st_mode & S_IPTRANS) else if (st.st_mode & S_IPTRANS)
{ {
char buf[1024]; char buf[1024];
@ -161,7 +164,8 @@ __hurd_file_name_lookup_retry (error_t (*use_init_port)
&& translen > sizeof _HURD_SYMLINK && translen > sizeof _HURD_SYMLINK
&& !memcmp (trans, && !memcmp (trans,
_HURD_SYMLINK, sizeof _HURD_SYMLINK)) _HURD_SYMLINK, sizeof _HURD_SYMLINK))
err = ENOENT; err = ELOOP;
}
} }
} }
} }