hurd: Implement faccessat without AT_EACCESS flag

* hurd/hurd/fd.h: Include <fcntl.h>
(__hurd_at_flags): New function.
* hurd/lookup-at.c (__file_name_lookup_at): Replace flag computation
with call to __hurd_at_flags.
* include/unistd.h (__faccessat, __faccessat_noerrno): Add declaration.
* sysdeps/mach/hurd/access.c (access_common): Move implementation to
__faccessat
(hurd_fail_seterrno, hurd_fail_noerrno): Move to sysdeps/mach/hurd/faccessat.c.
(__access_noerrno): Use __faccessat_common instead of access_common.
(__access): Likewise.
* sysdeps/mach/hurd/euidaccess.c (__euidaccess): Replace implementation
with a call to __faccessat.
* sysdeps/mach/hurd/faccessat.c (faccessat): Rename into...
(__faccessat_common): ... this. Move implementation of __access into it when
AT_FLAGS does not contain AT_EACCESS. Make it call __hurd_at_flags, add
reauthenticate_cwdir_at helper to implement AT mechanism.
(__faccessat_noerrno): New function, just calls __faccessat_common.
(__faccessat): New function, just calls __faccessat_common.
(faccessat): Define weak alias.
This commit is contained in:
Samuel Thibault 2018-01-10 01:58:23 +01:00
parent 87faac5516
commit 09085ede12
7 changed files with 219 additions and 195 deletions

View File

@ -1,3 +1,25 @@
2018-01-10 Samuel Thibault <samuel.thibault@ens-lyon.org>
* hurd/hurd/fd.h: Include <fcntl.h>
(__hurd_at_flags): New function.
* hurd/lookup-at.c (__file_name_lookup_at): Replace flag computation
with call to __hurd_at_flags.
* include/unistd.h (__faccessat, __faccessat_noerrno): Add declaration.
* sysdeps/mach/hurd/access.c (access_common): Move implementation to
__faccessat
(hurd_fail_seterrno, hurd_fail_noerrno): Move to sysdeps/mach/hurd/faccessat.c.
(__access_noerrno): Use __faccessat_common instead of access_common.
(__access): Likewise.
* sysdeps/mach/hurd/euidaccess.c (__euidaccess): Replace implementation
with a call to __faccessat.
* sysdeps/mach/hurd/faccessat.c (faccessat): Rename into...
(__faccessat_common): ... this. Move implementation of __access into it when
AT_FLAGS does not contain AT_EACCESS. Make it call __hurd_at_flags, add
reauthenticate_cwdir_at helper to implement AT mechanism.
(__faccessat_noerrno): New function, just calls __faccessat_common.
(__faccessat): New function, just calls __faccessat_common.
(faccessat): Define weak alias.
2018-01-10 Joseph Myers <joseph@codesourcery.com> 2018-01-10 Joseph Myers <joseph@codesourcery.com>
[BZ #22691] [BZ #22691]

View File

@ -26,6 +26,7 @@
#include <hurd/hurd_types.h> #include <hurd/hurd_types.h>
#include <hurd/port.h> #include <hurd/port.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <fcntl.h>
/* Structure representing a file descriptor. */ /* Structure representing a file descriptor. */
@ -254,6 +255,26 @@ extern int _hurd_select (int nfds, struct pollfd *pollfds,
const struct timespec *timeout, const struct timespec *timeout,
const sigset_t *sigmask); const sigset_t *sigmask);
/* Apply AT_FLAGS on FLAGS, in preparation for calling
__hurd_file_name_lookup. */
_HURD_FD_H_EXTERN_INLINE error_t
__hurd_at_flags (int *at_flags, int *flags)
{
if ((*at_flags & AT_SYMLINK_FOLLOW) && (*at_flags & AT_SYMLINK_NOFOLLOW))
return EINVAL;
*flags |= (*at_flags & AT_SYMLINK_NOFOLLOW) ? O_NOLINK : 0;
*at_flags &= ~AT_SYMLINK_NOFOLLOW;
if (*at_flags & AT_SYMLINK_FOLLOW)
*flags &= ~O_NOLINK;
*at_flags &= ~AT_SYMLINK_FOLLOW;
if (*at_flags != 0)
return EINVAL;
return 0;
}
/* Variant of file_name_lookup used in *at function implementations. /* Variant of file_name_lookup used in *at function implementations.
AT_FLAGS may only contain AT_SYMLINK_FOLLOW or AT_SYMLINK_NOFOLLOW, AT_FLAGS may only contain AT_SYMLINK_FOLLOW or AT_SYMLINK_NOFOLLOW,
which will remove and add O_NOLINK from FLAGS respectively. which will remove and add O_NOLINK from FLAGS respectively.

View File

@ -29,16 +29,9 @@ __file_name_lookup_at (int fd, int at_flags,
error_t err; error_t err;
file_t result; file_t result;
if ((at_flags & AT_SYMLINK_FOLLOW) && (at_flags & AT_SYMLINK_NOFOLLOW)) err = __hurd_at_flags (&at_flags, &flags);
return (__hurd_fail (EINVAL), MACH_PORT_NULL); if (err)
return (__hurd_fail (err), MACH_PORT_NULL);
flags |= (at_flags & AT_SYMLINK_NOFOLLOW) ? O_NOLINK : 0;
at_flags &= ~AT_SYMLINK_NOFOLLOW;
if (at_flags & AT_SYMLINK_FOLLOW)
flags &= ~O_NOLINK;
at_flags &= ~AT_SYMLINK_FOLLOW;
if (at_flags != 0)
return (__hurd_fail (EINVAL), MACH_PORT_NULL);
if (fd == AT_FDCWD || file_name[0] == '/') if (fd == AT_FDCWD || file_name[0] == '/')
return __file_name_lookup (file_name, flags, mode); return __file_name_lookup (file_name, flags, mode);

View File

@ -25,6 +25,9 @@ libc_hidden_proto (readlinkat)
/* Now define the internal interfaces. */ /* Now define the internal interfaces. */
extern int __access (const char *__name, int __type) attribute_hidden; extern int __access (const char *__name, int __type) attribute_hidden;
extern int __euidaccess (const char *__name, int __type); extern int __euidaccess (const char *__name, int __type);
extern int __faccessat (int __fd, const char *__file, int __type, int __flag);
extern int __faccessat_noerrno (int __fd, const char *__file, int __type,
int __flag);
extern __off64_t __lseek64 (int __fd, __off64_t __offset, int __whence) extern __off64_t __lseek64 (int __fd, __off64_t __offset, int __whence)
attribute_hidden; attribute_hidden;
extern __off_t __lseek (int __fd, __off_t __offset, int __whence); extern __off_t __lseek (int __fd, __off_t __offset, int __whence);

View File

@ -15,145 +15,10 @@
License along with the GNU C Library; if not, see License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */ <http://www.gnu.org/licenses/>. */
#include <errno.h>
#include <unistd.h> #include <unistd.h>
#include <hurd.h>
#include <hurd/port.h>
#include <hurd/id.h>
#include <hurd/lookup.h>
#include <fcntl.h> #include <fcntl.h>
static int
hurd_fail_seterrno (error_t err)
{
return __hurd_fail (err);
}
static int
hurd_fail_noerrno (error_t err)
{
return -1;
}
static int
access_common (const char *file, int type, int (*errfunc) (error_t))
{
error_t err;
file_t rcrdir, rcwdir, io;
int flags, allowed;
error_t reauthenticate (int which, file_t *result)
{
/* Get a port to our root directory, authenticated with the real IDs. */
error_t err;
mach_port_t ref;
ref = __mach_reply_port ();
err = HURD_PORT_USE
(&_hurd_ports[which],
({
err = __io_reauthenticate (port, ref, MACH_MSG_TYPE_MAKE_SEND);
if (!err)
err = __auth_user_authenticate (_hurd_id.rid_auth,
ref, MACH_MSG_TYPE_MAKE_SEND,
result);
err;
}));
__mach_port_destroy (__mach_task_self (), ref);
return err;
}
error_t init_port (int which, error_t (*operate) (mach_port_t))
{
switch (which)
{
case INIT_PORT_AUTH:
return (*operate) (_hurd_id.rid_auth);
case INIT_PORT_CRDIR:
return (reauthenticate (INIT_PORT_CRDIR, &rcrdir) ?:
(*operate) (rcrdir));
case INIT_PORT_CWDIR:
return (reauthenticate (INIT_PORT_CWDIR, &rcwdir) ?:
(*operate) (rcwdir));
default:
return _hurd_ports_use (which, operate);
}
}
rcrdir = rcwdir = MACH_PORT_NULL;
HURD_CRITICAL_BEGIN;
__mutex_lock (&_hurd_id.lock);
/* Get _hurd_id up to date. */
if (err = _hurd_check_ids ())
goto lose;
if (_hurd_id.rid_auth == MACH_PORT_NULL)
{
/* Set up _hurd_id.rid_auth. This is a special auth server port
which uses the real uid and gid (the first aux uid and gid) as
the only effective uid and gid. */
if (_hurd_id.aux.nuids < 1 || _hurd_id.aux.ngids < 1)
{
/* We do not have a real UID and GID. Lose, lose, lose! */
err = EGRATUITOUS;
goto lose;
}
/* Create a new auth port using our real UID and GID (the first
auxiliary UID and GID) as the only effective IDs. */
if (err = __USEPORT (AUTH,
__auth_makeauth (port,
NULL, MACH_MSG_TYPE_COPY_SEND, 0,
_hurd_id.aux.uids, 1,
_hurd_id.aux.uids,
_hurd_id.aux.nuids,
_hurd_id.aux.gids, 1,
_hurd_id.aux.gids,
_hurd_id.aux.ngids,
&_hurd_id.rid_auth)))
goto lose;
}
if (!err)
/* Look up the file name using the modified init ports. */
err = __hurd_file_name_lookup (&init_port, &__getdport, 0,
file, 0, 0, &io);
/* We are done with _hurd_id.rid_auth now. */
lose:
__mutex_unlock (&_hurd_id.lock);
HURD_CRITICAL_END;
if (rcrdir != MACH_PORT_NULL)
__mach_port_deallocate (__mach_task_self (), rcrdir);
if (rcwdir != MACH_PORT_NULL)
__mach_port_deallocate (__mach_task_self (), rcwdir);
if (err)
return errfunc (err);
/* Find out what types of access we are allowed to this file. */
err = __file_check_access (io, &allowed);
__mach_port_deallocate (__mach_task_self (), io);
if (err)
return errfunc (err);
flags = 0;
if (type & R_OK)
flags |= O_READ;
if (type & W_OK)
flags |= O_WRITE;
if (type & X_OK)
flags |= O_EXEC;
if (flags & ~allowed)
/* We are not allowed all the requested types of access. */
return errfunc (EACCES);
return 0;
}
/* Test for access to FILE by our real user and group IDs without setting /* Test for access to FILE by our real user and group IDs without setting
errno. This may be unsafe to run during initialization of tunables errno. This may be unsafe to run during initialization of tunables
since access_common calls __hurd_file_name_lookup, which calls since access_common calls __hurd_file_name_lookup, which calls
@ -161,13 +26,13 @@ access_common (const char *file, int type, int (*errfunc) (error_t))
int int
__access_noerrno (const char *file, int type) __access_noerrno (const char *file, int type)
{ {
return access_common (file, type, hurd_fail_noerrno); return __faccessat_noerrno (AT_FDCWD, file, type, 0);
} }
/* Test for access to FILE by our real user and group IDs. */ /* Test for access to FILE by our real user and group IDs. */
int int
__access (const char *file, int type) __access (const char *file, int type)
{ {
return access_common (file, type, hurd_fail_seterrno); return __faccessat (AT_FDCWD, file, type, 0);
} }
weak_alias (__access, access) weak_alias (__access, access)

View File

@ -16,42 +16,13 @@
License along with the GNU C Library; if not, see License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */ <http://www.gnu.org/licenses/>. */
#include <errno.h>
#include <stddef.h>
#include <unistd.h> #include <unistd.h>
#include <fcntl.h> #include <fcntl.h>
#include <hurd.h>
int int
__euidaccess (const char *file, int type) __euidaccess (const char *file, int type)
{ {
error_t err; return __faccessat (AT_FDCWD, file, type, AT_EACCESS);
file_t port;
int allowed, flags;
port = __file_name_lookup (file, 0, 0);
if (port == MACH_PORT_NULL)
return -1;
/* Find out what types of access we are allowed to this file. */
err = __file_check_access (port, &allowed);
__mach_port_deallocate (__mach_task_self (), port);
if (err)
return __hurd_fail (err);
flags = 0;
if (type & R_OK)
flags |= O_READ;
if (type & W_OK)
flags |= O_WRITE;
if (type & X_OK)
flags |= O_EXEC;
if (flags & ~allowed)
/* We are not allowed all the requested types of access. */
return __hurd_fail (EACCES);
return 0;
} }
weak_alias (__euidaccess, euidaccess) weak_alias (__euidaccess, euidaccess)
weak_alias (__euidaccess, eaccess) weak_alias (__euidaccess, eaccess)

View File

@ -23,31 +23,167 @@
#include <sys/types.h> #include <sys/types.h>
#include <hurd.h> #include <hurd.h>
#include <hurd/fd.h> #include <hurd/fd.h>
#include <hurd/port.h>
#include <hurd/id.h>
#include <hurd/lookup.h>
int static int
faccessat (int fd, const char *file, int type, int flag) hurd_fail_seterrno (error_t err)
{
return __hurd_fail (err);
}
static int
hurd_fail_noerrno (error_t err)
{
return -1;
}
static int
__faccessat_common (int fd, const char *file, int type, int at_flags,
int (*errfunc) (error_t))
{ {
error_t err; error_t err;
file_t port; file_t rcrdir, rcwdir, io;
int allowed, flags; int flags, allowed;
if ((flag & AT_EACCESS) == 0) if ((at_flags & AT_EACCESS) == AT_EACCESS)
{ {
if (fd == AT_FDCWD || file[0] == '/') /* Use effective permissions. */
return __access (file, type); io = __file_name_lookup_at (fd, at_flags &~ AT_EACCESS, file, 0, 0);
__set_errno (ENOTSUP); /* XXX later */ if (io == MACH_PORT_NULL)
return -1; return -1;
}
else
{
/* We have to use real permissions instead of the
usual effective permissions. */
int hurd_flags = 0;
__hurd_at_flags (&at_flags, &hurd_flags);
error_t reauthenticate_cwdir_at (file_t *result)
{
/* Get a port to the FD directory, authenticated with the real IDs. */
error_t err;
mach_port_t ref;
ref = __mach_reply_port ();
err = HURD_DPORT_USE
(fd,
({
err = __io_reauthenticate (port, ref, MACH_MSG_TYPE_MAKE_SEND);
if (!err)
err = __auth_user_authenticate (_hurd_id.rid_auth,
ref, MACH_MSG_TYPE_MAKE_SEND,
result);
err;
}));
__mach_port_destroy (__mach_task_self (), ref);
return err;
}
error_t reauthenticate (int which, file_t *result)
{
/* Get a port to our root directory, authenticated with the real IDs. */
error_t err;
mach_port_t ref;
ref = __mach_reply_port ();
err = HURD_PORT_USE
(&_hurd_ports[which],
({
err = __io_reauthenticate (port, ref, MACH_MSG_TYPE_MAKE_SEND);
if (!err)
err = __auth_user_authenticate (_hurd_id.rid_auth,
ref, MACH_MSG_TYPE_MAKE_SEND,
result);
err;
}));
__mach_port_destroy (__mach_task_self (), ref);
return err;
}
error_t init_port (int which, error_t (*operate) (mach_port_t))
{
switch (which)
{
case INIT_PORT_AUTH:
return (*operate) (_hurd_id.rid_auth);
case INIT_PORT_CRDIR:
return (reauthenticate (INIT_PORT_CRDIR, &rcrdir) ?:
(*operate) (rcrdir));
case INIT_PORT_CWDIR:
if (fd == AT_FDCWD || file[0] == '/')
return (reauthenticate (INIT_PORT_CWDIR, &rcwdir) ?:
(*operate) (rcwdir));
else
return (reauthenticate_cwdir_at (&rcwdir) ?:
(*operate) (rcwdir));
default:
return _hurd_ports_use (which, operate);
}
}
rcrdir = rcwdir = MACH_PORT_NULL;
HURD_CRITICAL_BEGIN;
__mutex_lock (&_hurd_id.lock);
/* Get _hurd_id up to date. */
if (err = _hurd_check_ids ())
goto lose;
if (_hurd_id.rid_auth == MACH_PORT_NULL)
{
/* Set up _hurd_id.rid_auth. This is a special auth server port
which uses the real uid and gid (the first aux uid and gid) as
the only effective uid and gid. */
if (_hurd_id.aux.nuids < 1 || _hurd_id.aux.ngids < 1)
{
/* We do not have a real UID and GID. Lose, lose, lose! */
err = EGRATUITOUS;
goto lose;
}
/* Create a new auth port using our real UID and GID (the first
auxiliary UID and GID) as the only effective IDs. */
if (err = __USEPORT (AUTH,
__auth_makeauth (port,
NULL, MACH_MSG_TYPE_COPY_SEND, 0,
_hurd_id.aux.uids, 1,
_hurd_id.aux.uids,
_hurd_id.aux.nuids,
_hurd_id.aux.gids, 1,
_hurd_id.aux.gids,
_hurd_id.aux.ngids,
&_hurd_id.rid_auth)))
goto lose;
}
if (!err)
/* Look up the file name using the modified init ports. */
err = __hurd_file_name_lookup (&init_port, &__getdport, 0,
file, hurd_flags, 0, &io);
/* We are done with _hurd_id.rid_auth now. */
lose:
__mutex_unlock (&_hurd_id.lock);
HURD_CRITICAL_END;
if (rcrdir != MACH_PORT_NULL)
__mach_port_deallocate (__mach_task_self (), rcrdir);
if (rcwdir != MACH_PORT_NULL)
__mach_port_deallocate (__mach_task_self (), rcwdir);
if (err)
return errfunc (err);
} }
port = __file_name_lookup_at (fd, flag &~ AT_EACCESS, file, 0, 0);
if (port == MACH_PORT_NULL)
return -1;
/* Find out what types of access we are allowed to this file. */ /* Find out what types of access we are allowed to this file. */
err = __file_check_access (port, &allowed); err = __file_check_access (io, &allowed);
__mach_port_deallocate (__mach_task_self (), port); __mach_port_deallocate (__mach_task_self (), io);
if (err) if (err)
return __hurd_fail (err); return errfunc (err);
flags = 0; flags = 0;
if (type & R_OK) if (type & R_OK)
@ -59,7 +195,20 @@ faccessat (int fd, const char *file, int type, int flag)
if (flags & ~allowed) if (flags & ~allowed)
/* We are not allowed all the requested types of access. */ /* We are not allowed all the requested types of access. */
return __hurd_fail (EACCES); return errfunc (EACCES);
return 0; return 0;
} }
int
__faccessat_noerrno (int fd, const char *file, int type, int at_flags)
{
return __faccessat_common (fd, file, type, at_flags, hurd_fail_noerrno);
}
int
__faccessat (int fd, const char *file, int type, int at_flags)
{
return __faccessat_common (fd, file, type, at_flags, hurd_fail_seterrno);
}
weak_alias (__faccessat, faccessat)