New internal function __access_noerrno

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.

Checked on x86_64.

	* hurd/hurd.h (__hurd_fail_noerrno): New function.
	* include/unistd.h [IS_IN (rtld) || !defined SHARED]: Declare
	__access_noerrno.
	* io/access.c (__access_noerrno): New function.
	* sysdeps/mach/hurd/access.c (hurd_fail_seterrno): New function.
	(hurd_fail_seterrno): Likewise.
	(access_common): Likewise.
	(__access_noerrno): Likewise.
	* sysdeps/nacl/access.c (__access_noerrno): Likewise.
	* sysdeps/unix/sysv/linux/access.c (__access_noerrno): Likewise.
	* sysdeps/nacl/nacl-interfaces.h (NACL_CALL_NOERRNO): New
	macro.
This commit is contained in:
Adhemerval Zanella 2016-11-10 09:28:00 -02:00
parent 530862a63e
commit afcf3cd8eb
8 changed files with 114 additions and 6 deletions

View File

@ -1,3 +1,18 @@
2016-11-16 Adhemerval Zanella <adhemerval.zanella@linaro.org>
* hurd/hurd.h (__hurd_fail_noerrno): New function.
* include/unistd.h [IS_IN (rtld) || !defined SHARED]: Declare
__access_noerrno.
* io/access.c (__access_noerrno): New function.
* sysdeps/mach/hurd/access.c (hurd_fail_seterrno): New function.
(hurd_fail_seterrno): Likewise.
(access_common): Likewise.
(__access_noerrno): Likewise.
* sysdeps/nacl/access.c (__access_noerrno): Likewise.
* sysdeps/unix/sysv/linux/access.c (__access_noerrno): Likewise.
* sysdeps/nacl/nacl-interfaces.h (NACL_CALL_NOERRNO): New
macro.
2016-11-16 Joseph Myers <joseph@codesourcery.com>
* sysdeps/unix/sysv/linux/sh/sh4/register-dump.h (register_dump):

View File

@ -75,6 +75,35 @@ __hurd_fail (error_t err)
errno = err;
return -1;
}
_HURD_H_EXTERN_INLINE int
__hurd_fail_noerrno (error_t err)
{
switch (err)
{
case EMACH_SEND_INVALID_DEST:
case EMIG_SERVER_DIED:
/* The server has disappeared! */
err = EIEIO;
break;
case KERN_NO_SPACE:
err = ENOMEM;
break;
case KERN_INVALID_ARGUMENT:
err = EINVAL;
break;
case 0:
return 0;
default:
break;
}
return -1;
}
/* Basic ports and info, initialized by startup. */

View File

@ -181,6 +181,12 @@ extern int __getlogin_r_loginuid (char *name, size_t namesize)
# include <dl-unistd.h>
# 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

View File

@ -19,6 +19,13 @@
#include <stddef.h>
#include <unistd.h>
/* Test for access to FILE without setting errno. */
int
__access_noerrno (const char *file, int type)
{
return -1;
}
/* Test for access to FILE. */
int
__access (const char *file, int type)

View File

@ -22,9 +22,20 @@
#include <hurd/lookup.h>
#include <fcntl.h>
/* Test for access to FILE by our real user and group IDs. */
int
__access (const char *file, int type)
static int
hurd_fail_seterrno (error_t err)
{
return __hurd_fail (err);
}
static int
hurd_fail_noerrno (error_t err)
{
return __hurd_fail_noerrno (err);
}
static int
access_common (const char *file, int type, int (*errfunc) (error_t))
{
error_t err;
file_t rcrdir, rcwdir, io;
@ -120,13 +131,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 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 __hurd_fail (err);
return errfunc (err);
flags = 0;
if (type & R_OK)
@ -138,9 +149,23 @@ __access (const char *file, int type)
if (flags & ~allowed)
/* We are not allowed all the requested types of access. */
return __hurd_fail (EACCES);
return errfunc (EACESS);
return 0;
}
/* Test for access to FILE by our real user and group IDs without setting
errno. */
int
__access_noerrno (const char *file, int type)
{
return access_common (file, type, hurd_fail_noerrno);
}
/* 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);
}
weak_alias (__access, access)

View File

@ -19,6 +19,13 @@
#include <unistd.h>
#include <nacl-interfaces.h>
/* Test for access to FILE without setting errno. */
int
__access_noerrno (const char *file, int type)
{
return NACL_CALL_NOERRNO (__nacl_irt_dev_filename.access (file, type), 0);
}
/* Test for access to FILE. */
int
__access (const char *file, int type)

View File

@ -113,4 +113,8 @@ __nacl_fail (int err)
#define NACL_CALL(err, val) \
({ int _err = (err); _err ? __nacl_fail (_err) : (val); })
/* Same as NACL_CALL but without setting errno. */
#define NACL_CALL_NOERRNO(err, val) \
({ int _err = (err); _err ? _err : (val); })
#endif /* nacl-interfaces.h */

View File

@ -20,6 +20,21 @@
#include <unistd.h>
#include <sysdep-cancel.h>
int
__access_noerrno (const char *file, int type)
{
int res;
INTERNAL_SYSCALL_DECL (err);
#ifdef __NR_access
res = INTERNAL_SYSCALL_CALL (access, err, file, type);
#else
res = INTERNAL_SYSCALL_CALL (faccessat, err, AT_FDCWD, file, type);
#endif
if (INTERNAL_SYSCALL_ERROR_P (res, err))
return INTERNAL_SYSCALL_ERRNO (res, err);
return 0;
}
int
__access (const char *file, int type)
{