From patchwork Wed Jan 10 01:05:31 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Samuel Thibault X-Patchwork-Id: 857861 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=sourceware.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=libc-alpha-return-88989-incoming=patchwork.ozlabs.org@sourceware.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; secure) header.d=sourceware.org header.i=@sourceware.org header.b="AVC+3zo4"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3zGW665xbxz9s7v for ; Wed, 10 Jan 2018 12:05:50 +1100 (AEDT) DomainKey-Signature: a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:from:to:cc:subject:date:message-id; q=dns; s= default; b=EXgknWxeJB81XyIPPO+HmcbaLGxmgN0OXp2xfFVjVT81HQ97UzcfE sAKzrRiXCjUwsGXp7u+3jalJZjn7nwY/euZ/PNoJ6/MJw4tAsDaWqUJXNVPDHJIW tuZak2vg62AGwCS6H+CHGW3r+MXb85EjXo3DzOxdR774Abc91/qTB8= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:from:to:cc:subject:date:message-id; s=default; bh=bOsfd17z6S6/rpDCa8p/IMKBnNw=; b=AVC+3zo4Y95Y0SoHTyLfUxu4EZec i4ynpBWaDfd9/ZLVL3EPjdZYgvv+GeQsdWWs4ALOV+ZFzYj+SxoIh47PZGTcgPCE HotVohm9fUZP18kfhuB1zRB8ns7o/WRzbY4nZTkPFL+WDL2pthx5iAEhLvtLYq5f 3b9mo7ZmLUVe07c= Received: (qmail 56534 invoked by alias); 10 Jan 2018 01:05:43 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 56498 invoked by uid 89); 10 Jan 2018 01:05:41 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-26.1 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_SHORT, SPF_HELO_PASS, SPF_NEUTRAL, URIBL_RED autolearn=ham version=3.3.2 spammy=GID, gid, *at, authenticated X-HELO: hera.aquilenet.fr From: Samuel Thibault To: libc-alpha@sourceware.org Cc: Samuel Thibault Subject: [hurd,commited] hurd: Implement faccessat without AT_EACCESS flag Date: Wed, 10 Jan 2018 02:05:31 +0100 Message-Id: <20180110010531.30187-1-samuel.thibault@ens-lyon.org> * hurd/hurd/fd.h: Include (__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. --- ChangeLog | 22 +++++ hurd/hurd/fd.h | 21 +++++ hurd/lookup-at.c | 13 +-- include/unistd.h | 3 + sysdeps/mach/hurd/access.c | 141 +------------------------------- sysdeps/mach/hurd/euidaccess.c | 31 +------ sysdeps/mach/hurd/faccessat.c | 181 +++++++++++++++++++++++++++++++++++++---- 7 files changed, 218 insertions(+), 194 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8b752efd64..b1da834f8e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,25 @@ +2018-01-10 Samuel Thibault + + * hurd/hurd/fd.h: Include + (__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 [BZ #22691] diff --git a/hurd/hurd/fd.h b/hurd/hurd/fd.h index 7fd2297779..809a73f5dd 100644 --- a/hurd/hurd/fd.h +++ b/hurd/hurd/fd.h @@ -26,6 +26,7 @@ #include #include #include +#include /* Structure representing a file descriptor. */ @@ -254,6 +255,26 @@ extern int _hurd_select (int nfds, struct pollfd *pollfds, const struct timespec *timeout, 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. AT_FLAGS may only contain AT_SYMLINK_FOLLOW or AT_SYMLINK_NOFOLLOW, which will remove and add O_NOLINK from FLAGS respectively. diff --git a/hurd/lookup-at.c b/hurd/lookup-at.c index abf9047e57..deddc2264c 100644 --- a/hurd/lookup-at.c +++ b/hurd/lookup-at.c @@ -29,16 +29,9 @@ __file_name_lookup_at (int fd, int at_flags, error_t err; file_t result; - if ((at_flags & AT_SYMLINK_FOLLOW) && (at_flags & AT_SYMLINK_NOFOLLOW)) - return (__hurd_fail (EINVAL), 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); + err = __hurd_at_flags (&at_flags, &flags); + if (err) + return (__hurd_fail (err), MACH_PORT_NULL); if (fd == AT_FDCWD || file_name[0] == '/') return __file_name_lookup (file_name, flags, mode); diff --git a/include/unistd.h b/include/unistd.h index f884fdae99..0f91b8babc 100644 --- a/include/unistd.h +++ b/include/unistd.h @@ -25,6 +25,9 @@ libc_hidden_proto (readlinkat) /* Now define the internal interfaces. */ extern int __access (const char *__name, int __type) attribute_hidden; 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) attribute_hidden; extern __off_t __lseek (int __fd, __off_t __offset, int __whence); diff --git a/sysdeps/mach/hurd/access.c b/sysdeps/mach/hurd/access.c index 9195bd61ff..31fd5bea56 100644 --- a/sysdeps/mach/hurd/access.c +++ b/sysdeps/mach/hurd/access.c @@ -15,145 +15,10 @@ License along with the GNU C Library; if not, see . */ +#include #include -#include -#include -#include -#include #include -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 errno. This may be unsafe to run during initialization of tunables 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 __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. */ int __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) diff --git a/sysdeps/mach/hurd/euidaccess.c b/sysdeps/mach/hurd/euidaccess.c index 613872a207..2c7ce1f2b6 100644 --- a/sysdeps/mach/hurd/euidaccess.c +++ b/sysdeps/mach/hurd/euidaccess.c @@ -16,42 +16,13 @@ License along with the GNU C Library; if not, see . */ -#include -#include #include #include -#include int __euidaccess (const char *file, int type) { - error_t err; - 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; + return __faccessat (AT_FDCWD, file, type, AT_EACCESS); } weak_alias (__euidaccess, euidaccess) weak_alias (__euidaccess, eaccess) diff --git a/sysdeps/mach/hurd/faccessat.c b/sysdeps/mach/hurd/faccessat.c index 260060639f..d9bceaada7 100644 --- a/sysdeps/mach/hurd/faccessat.c +++ b/sysdeps/mach/hurd/faccessat.c @@ -23,31 +23,167 @@ #include #include #include +#include +#include +#include -int -faccessat (int fd, const char *file, int type, int flag) +static int +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; - file_t port; - int allowed, flags; + file_t rcrdir, rcwdir, io; + int flags, allowed; - if ((flag & AT_EACCESS) == 0) + if ((at_flags & AT_EACCESS) == AT_EACCESS) { - if (fd == AT_FDCWD || file[0] == '/') - return __access (file, type); - __set_errno (ENOTSUP); /* XXX later */ - return -1; + /* Use effective permissions. */ + io = __file_name_lookup_at (fd, at_flags &~ AT_EACCESS, file, 0, 0); + if (io == MACH_PORT_NULL) + 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; - port = __file_name_lookup_at (fd, flag &~ AT_EACCESS, file, 0, 0); - if (port == MACH_PORT_NULL) - return -1; + 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); + } /* 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); + err = __file_check_access (io, &allowed); + __mach_port_deallocate (__mach_task_self (), io); if (err) - return __hurd_fail (err); + return errfunc (err); flags = 0; if (type & R_OK) @@ -59,7 +195,20 @@ faccessat (int fd, const char *file, int type, int flag) if (flags & ~allowed) /* We are not allowed all the requested types of access. */ - return __hurd_fail (EACCES); + return errfunc (EACCES); 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)