From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 85934 invoked by alias); 24 Oct 2016 14:43:18 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Received: (qmail 85719 invoked by uid 89); 24 Oct 2016 14:43:16 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.1 required=5.0 tests=BAYES_00,RCVD_IN_DNSWL_NONE,SPF_NEUTRAL autolearn=no version=3.3.2 spammy=avoids, mach, 1389, Lesser X-HELO: homiemail-a45.g.dreamhost.com From: Siddhesh Poyarekar To: libc-alpha@sourceware.org Subject: [PATCH 2/6] New internal function __access_noerrno Date: Mon, 24 Oct 2016 14:43:00 -0000 Message-Id: <1477320168-23397-3-git-send-email-siddhesh@sourceware.org> In-Reply-To: <1477320168-23397-1-git-send-email-siddhesh@sourceware.org> References: <1477320168-23397-1-git-send-email-siddhesh@sourceware.org> X-SW-Source: 2016-10/txt/msg00383.txt.bz2 Implement an internal version of __access called __access_noerrno that avoids setting errno. This is useful to check accessibility of files very early on in process startup i.e. before TLS setup. This allows tunables to replace MALLOC_CHECK_ safely (i.e. check existence of /etc/suid-debug to enable/disable MALLOC_CHECK) and at the same time initialize very early so that it can override IFUNCs. * include/unistd.h [IS_IN (rtld) || !defined SHARED]: Declare __access_noerrno. * io/Makefile (routines): Add access_noerrno. * io/access.c (__ACCESS)[!__ACCESS]: Define as __access. (__access): Rename to __ACCESS. [!NOERRNO]: Retain default __access logic. * io/access_noerrno.c: New file. * sysdeps/mach/hurd/access.c (__ACCESS)[!__ACCESS]: Define as __access. (__HURD_FAIL): New macro. (__access): Rename to __ACCESS. Use __HURD_FAIL instead of __hurd_fail. [!NOERRNO]: Set weak alias to access. * sysdeps/nacl/access.c (__ACCESS)[!__ACCESS]: Define as __access. (DO_NACL_CALL): New macro. (__access): Rename to __ACCESS. Use DO_NACL_CALL instead of NACL_CALL. [!NOERRNO]: Set weak alias to access. * sysdeps/nacl/nacl-interfaces.h (NACL_CALL_NOERRNO): New macro. * sysdeps/unix/access_noerrno.c: New file. * sysdeps/unix/sysv/linux/generic/access.c: Include sysdep.h. (__ACCESS)[!__ACCESS]: Define as __access. (__access): Rename to __ACCESS. [NOERRNO]: Call faccessat syscall without setting errno. --- include/unistd.h | 6 +++++ io/Makefile | 1 + io/access.c | 10 ++++++++- io/access_noerrno.c | 21 ++++++++++++++++++ sysdeps/mach/hurd/access.c | 20 +++++++++++++---- sysdeps/nacl/access.c | 16 ++++++++++++-- sysdeps/nacl/nacl-interfaces.h | 4 ++++ sysdeps/unix/access_noerrno.c | 38 ++++++++++++++++++++++++++++++++ sysdeps/unix/sysv/linux/generic/access.c | 19 +++++++++++++++- 9 files changed, 127 insertions(+), 8 deletions(-) create mode 100644 io/access_noerrno.c create mode 100644 sysdeps/unix/access_noerrno.c diff --git a/include/unistd.h b/include/unistd.h index d2802b2..6144f41 100644 --- a/include/unistd.h +++ b/include/unistd.h @@ -181,6 +181,12 @@ extern int __getlogin_r_loginuid (char *name, size_t namesize) # include # endif +# if IS_IN (rtld) || !defined SHARED +/* __access variant that does not set errno. Used in very early initialization + code in libc.a and ld.so. */ +extern __typeof (__access) __access_noerrno attribute_hidden; +# endif + __END_DECLS # endif diff --git a/io/Makefile b/io/Makefile index e5493b3..1ebb0d0 100644 --- a/io/Makefile +++ b/io/Makefile @@ -40,6 +40,7 @@ routines := \ mkdir mkdirat \ open open_2 open64 open64_2 openat openat_2 openat64 openat64_2 \ read write lseek lseek64 access euidaccess faccessat \ + access_noerrno \ fcntl flock lockf lockf64 \ close dup dup2 dup3 pipe pipe2 \ creat creat64 \ diff --git a/io/access.c b/io/access.c index 4534704..80cfa98 100644 --- a/io/access.c +++ b/io/access.c @@ -19,10 +19,15 @@ #include #include +#ifndef __ACCESS +# define __ACCESS __access +#endif + /* Test for access to FILE. */ int -__access (const char *file, int type) +__ACCESS (const char *file, int type) { +#ifndef NOERRNO if (file == NULL || (type & ~(R_OK|W_OK|X_OK|F_OK)) != 0) { __set_errno (EINVAL); @@ -30,8 +35,11 @@ __access (const char *file, int type) } __set_errno (ENOSYS); +#endif return -1; } +#ifndef NOERRNO stub_warning (access) weak_alias (__access, access) +#endif diff --git a/io/access_noerrno.c b/io/access_noerrno.c new file mode 100644 index 0000000..4bd531f --- /dev/null +++ b/io/access_noerrno.c @@ -0,0 +1,21 @@ +/* Test for access to a file but do not set errno on error. + Copyright (C) 2016 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#define NOERRNO 1 +#define __ACCESS __access_noerrno +#include diff --git a/sysdeps/mach/hurd/access.c b/sysdeps/mach/hurd/access.c index c308340..189fefe 100644 --- a/sysdeps/mach/hurd/access.c +++ b/sysdeps/mach/hurd/access.c @@ -22,9 +22,19 @@ #include #include +#ifndef __ACCESS +# define __ACCESS __access +#endif + +#ifndef NOERRNO +# define __HURD_FAIL(e) __hurd_fail (e) +#else +# define __HURD_FAIL(e) (e) +#endif + /* Test for access to FILE by our real user and group IDs. */ int -__access (const char *file, int type) +__ACCESS (const char *file, int type) { error_t err; file_t rcrdir, rcwdir, io; @@ -120,13 +130,13 @@ __access (const char *file, int type) if (rcwdir != MACH_PORT_NULL) __mach_port_deallocate (__mach_task_self (), rcwdir); if (err) - return __hurd_fail (err); + return __HURD_FAIL (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 __hurd_fail (err); + return __HURD_FAIL (err); flags = 0; if (type & R_OK) @@ -138,9 +148,11 @@ __access (const char *file, int type) if (flags & ~allowed) /* We are not allowed all the requested types of access. */ - return __hurd_fail (EACCES); + return __HURD_FAIL (EACCES); return 0; } +#ifndef NOERRNO weak_alias (__access, access) +#endif diff --git a/sysdeps/nacl/access.c b/sysdeps/nacl/access.c index 95a0fb7..b7339e7 100644 --- a/sysdeps/nacl/access.c +++ b/sysdeps/nacl/access.c @@ -19,10 +19,22 @@ #include #include +#ifndef __ACCESS +# define __ACCESS __access +#endif + +#ifndef NOERRNO +# define DO_NACL_CALL NACL_CALL +#else +# define DO_NACL_CALL NACL_CALL_NOERRNO +#endif + /* Test for access to FILE. */ int -__access (const char *file, int type) +__ACCESS (const char *file, int type) { - return NACL_CALL (__nacl_irt_dev_filename.access (file, type), 0); + return DO_NACL_CALL (__nacl_irt_dev_filename.access (file, type), 0); } +#ifndef NOERRNO weak_alias (__access, access) +#endif diff --git a/sysdeps/nacl/nacl-interfaces.h b/sysdeps/nacl/nacl-interfaces.h index b7b45bb..fd8d580 100644 --- a/sysdeps/nacl/nacl-interfaces.h +++ b/sysdeps/nacl/nacl-interfaces.h @@ -113,4 +113,8 @@ __nacl_fail (int err) #define NACL_CALL(err, val) \ ({ int _err = (err); _err ? __nacl_fail (_err) : (val); }) +/* Don't set errno. */ +#define NACL_CALL_NOERRNO(err, val) \ + ({ int _err = (err); _err ? _err : (val); }) + #endif /* nacl-interfaces.h */ diff --git a/sysdeps/unix/access_noerrno.c b/sysdeps/unix/access_noerrno.c new file mode 100644 index 0000000..1ff90a2 --- /dev/null +++ b/sysdeps/unix/access_noerrno.c @@ -0,0 +1,38 @@ +/* Test for access to a file but do not set errno on error. + Copyright (C) 2016 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf , 2011. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + . */ + +#include +#include +#include +#include +#include +#include + +/* Test for access to FILE. */ +int +__access_noerrno (const char *file, int type) +{ + INTERNAL_SYSCALL_DECL (err); + int res; + res = INTERNAL_SYSCALL (access, err, 2, file, type); + if (INTERNAL_SYSCALL_ERROR_P (res, err)) + return INTERNAL_SYSCALL_ERRNO (res, err); + else + return 0; +} diff --git a/sysdeps/unix/sysv/linux/generic/access.c b/sysdeps/unix/sysv/linux/generic/access.c index 586aa93..5bafc06 100644 --- a/sysdeps/unix/sysv/linux/generic/access.c +++ b/sysdeps/unix/sysv/linux/generic/access.c @@ -21,11 +21,28 @@ #include #include #include +#include + +#ifndef __ACCESS +# define __ACCESS __access +#endif /* Test for access to FILE. */ int -__access (const char *file, int type) +__ACCESS (const char *file, int type) { +#ifndef NOERRNO return INLINE_SYSCALL (faccessat, 3, AT_FDCWD, file, type); +#else + INTERNAL_SYSCALL_DECL (err); + int res; + res = INTERNAL_SYSCALL (faccessat, err, 3, AT_FDCWD, file, type); + if (INTERNAL_SYSCALL_ERROR_P (res, err)) + return INTERNAL_SYSCALL_ERRNO (res, err); + else + return 0; +#endif } +#ifndef NOERRNO weak_alias (__access, access) +#endif -- 2.7.4