hurd: Fix static-PIE startup

hurd initialization stages use RUN_HOOK to run various initialization
functions.  That is however using absolute addresses which need to be
relocated, which is done later by csu.  We can however easily make the
linker compute relative addresses which thus don't need a relocation.
The new SET_RELHOOK and RUN_RELHOOK macros implement this.
This commit is contained in:
Samuel Thibault 2021-12-28 10:27:06 +01:00
parent 2ce0481d26
commit ae49f218da
14 changed files with 140 additions and 40 deletions

View File

@ -36,7 +36,7 @@ DEFINE_HOOK (_hurd_fd_subinit, (void));
/* Initialize the file descriptor table at startup. */ /* Initialize the file descriptor table at startup. */
static void static void attribute_used_retain
init_dtable (void) init_dtable (void)
{ {
int i; int i;
@ -91,12 +91,10 @@ init_dtable (void)
/* Run things that want to run after the file descriptor table /* Run things that want to run after the file descriptor table
is initialized. */ is initialized. */
RUN_HOOK (_hurd_fd_subinit, ()); RUN_RELHOOK (_hurd_fd_subinit, ());
(void) &init_dtable; /* Avoid "defined but not used" warning. */
} }
text_set_element (_hurd_subinit, init_dtable); SET_RELHOOK (_hurd_subinit, init_dtable);
/* XXX when the linker supports it, the following functions should all be /* XXX when the linker supports it, the following functions should all be
elsewhere and just have text_set_elements here. */ elsewhere and just have text_set_elements here. */

View File

@ -17,6 +17,7 @@
#include <hurd.h> #include <hurd.h>
#include <hurd/id.h> #include <hurd/id.h>
#include "set-hooks.h"
struct hurd_id_data _hurd_id; struct hurd_id_data _hurd_id;
@ -74,7 +75,7 @@ _hurd_check_ids (void)
return 0; return 0;
} }
static void static void attribute_used_retain
init_id (void) init_id (void)
{ {
__mutex_init (&_hurd_id.lock); __mutex_init (&_hurd_id.lock);
@ -84,7 +85,5 @@ init_id (void)
_hurd_id.gen.nuids = _hurd_id.aux.nuids = 0; _hurd_id.gen.nuids = _hurd_id.aux.nuids = 0;
_hurd_id.gen.gids = _hurd_id.aux.gids = NULL; _hurd_id.gen.gids = _hurd_id.aux.gids = NULL;
_hurd_id.gen.ngids = _hurd_id.aux.ngids = 0; _hurd_id.gen.ngids = _hurd_id.aux.ngids = 0;
(void) &init_id; /* Avoid "defined but not used" warning. */
} }
text_set_element (_hurd_preinit_hook, init_id); SET_RELHOOK (_hurd_preinit_hook, init_id);

View File

@ -108,7 +108,7 @@ _hurd_init (int flags, char **argv,
/* Call other things which want to do some initialization. These are not /* Call other things which want to do some initialization. These are not
on the __libc_subinit hook because things there like to be able to on the __libc_subinit hook because things there like to be able to
assume the availability of the POSIX.1 services we provide. */ assume the availability of the POSIX.1 services we provide. */
RUN_HOOK (_hurd_subinit, ()); RUN_RELHOOK (_hurd_subinit, ());
} }
libc_hidden_def (_hurd_init) libc_hidden_def (_hurd_init)
@ -190,7 +190,7 @@ _hurd_new_proc_init (char **argv,
/* Call other things which want to do some initialization. These are not /* Call other things which want to do some initialization. These are not
on the _hurd_subinit hook because things there assume that things done on the _hurd_subinit hook because things there assume that things done
here, like _hurd_pid, are already initialized. */ here, like _hurd_pid, are already initialized. */
RUN_HOOK (_hurd_proc_subinit, ()); RUN_RELHOOK (_hurd_proc_subinit, ());
/* XXX This code should probably be removed entirely at some point. This /* XXX This code should probably be removed entirely at some point. This
conditional should make it reasonably usable with old gdb's for a conditional should make it reasonably usable with old gdb's for a
@ -242,7 +242,7 @@ _hurd_setproc (process_t procserver)
/* Call these functions again so they can fetch the /* Call these functions again so they can fetch the
new information from the new proc server. */ new information from the new proc server. */
RUN_HOOK (_hurd_proc_subinit, ()); RUN_RELHOOK (_hurd_proc_subinit, ());
if (_hurd_pgrp != oldpgrp) if (_hurd_pgrp != oldpgrp)
{ {

View File

@ -1,5 +1,6 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "set-hooks.h"
#include "hurdmalloc.h" /* XXX see that file */ #include "hurdmalloc.h" /* XXX see that file */
@ -148,7 +149,7 @@ static struct free_list malloc_free_list[NBUCKETS];
It preserves the values of data variables like malloc_free_list, but It preserves the values of data variables like malloc_free_list, but
does not save the vm_allocate'd space allocated by this malloc. */ does not save the vm_allocate'd space allocated by this malloc. */
static void static void attribute_used_retain
malloc_init (void) malloc_init (void)
{ {
int i; int i;
@ -160,11 +161,6 @@ malloc_init (void)
malloc_free_list[i].in_use = 0; malloc_free_list[i].in_use = 0;
#endif #endif
} }
/* This not only suppresses a `defined but not used' warning,
but it is ABSOLUTELY NECESSARY to avoid the hyperclever
compiler from "optimizing out" the entire function! */
(void) &malloc_init;
} }
static void static void
@ -445,4 +441,4 @@ _hurd_malloc_fork_child(void)
} }
text_set_element (_hurd_preinit_hook, malloc_init); SET_RELHOOK (_hurd_preinit_hook, malloc_init);

View File

@ -17,11 +17,12 @@
#include <hurd.h> #include <hurd.h>
#include <lowlevellock.h> #include <lowlevellock.h>
#include "set-hooks.h"
pid_t _hurd_pid, _hurd_ppid, _hurd_pgrp; pid_t _hurd_pid, _hurd_ppid, _hurd_pgrp;
int _hurd_orphaned; int _hurd_orphaned;
static void static void attribute_used_retain
init_pids (void) init_pids (void)
{ {
__USEPORT (PROC, __USEPORT (PROC,
@ -29,11 +30,9 @@ init_pids (void)
__proc_getpids (port, &_hurd_pid, &_hurd_ppid, &_hurd_orphaned); __proc_getpids (port, &_hurd_pid, &_hurd_ppid, &_hurd_orphaned);
__proc_getpgrp (port, _hurd_pid, &_hurd_pgrp); __proc_getpgrp (port, _hurd_pid, &_hurd_pgrp);
})); }));
(void) &init_pids; /* Avoid "defined but not used" warning. */
} }
text_set_element (_hurd_proc_subinit, init_pids); SET_RELHOOK (_hurd_proc_subinit, init_pids);
#include <hurd/msg_server.h> #include <hurd/msg_server.h>
#include "set-hooks.h" #include "set-hooks.h"

View File

@ -19,6 +19,7 @@
#include <hurd.h> #include <hurd.h>
#include <lock-intern.h> #include <lock-intern.h>
#include <hurd/resource.h> #include <hurd/resource.h>
#include "set-hooks.h"
/* This must be given an initializer, or the a.out linking rules will /* This must be given an initializer, or the a.out linking rules will
not include the entire file when this symbol is referenced. */ not include the entire file when this symbol is referenced. */
@ -29,7 +30,7 @@ struct rlimit _hurd_rlimits[RLIM_NLIMITS] = { { 0, }, };
mutex_init is still required below just in case of unexec. */ mutex_init is still required below just in case of unexec. */
struct mutex _hurd_rlimit_lock = { SPIN_LOCK_INITIALIZER, }; struct mutex _hurd_rlimit_lock = { SPIN_LOCK_INITIALIZER, };
static void static void attribute_used_retain
init_rlimit (void) init_rlimit (void)
{ {
int i; int i;
@ -52,7 +53,5 @@ init_rlimit (void)
} }
#undef I #undef I
} }
(void) &init_rlimit;
} }
text_set_element (_hurd_preinit_hook, init_rlimit); SET_RELHOOK (_hurd_preinit_hook, init_rlimit);

View File

@ -25,6 +25,7 @@
#include <_itoa.h> #include <_itoa.h>
#include <lock-intern.h> /* For `struct mutex'. */ #include <lock-intern.h> /* For `struct mutex'. */
#include "hurdmalloc.h" /* XXX */ #include "hurdmalloc.h" /* XXX */
#include "set-hooks.h"
static struct mutex lock; static struct mutex lock;
@ -109,7 +110,7 @@ retry:
return server; return server;
} }
static void static void attribute_used_retain
init (void) init (void)
{ {
int i; int i;
@ -118,7 +119,5 @@ init (void)
for (i = 0; i < max_domain; ++i) for (i = 0; i < max_domain; ++i)
servers[i] = MACH_PORT_NULL; servers[i] = MACH_PORT_NULL;
(void) &init; /* Avoid "defined but not used" warning. */
} }
text_set_element (_hurd_preinit_hook, init); SET_RELHOOK (_hurd_preinit_hook, init);

View File

@ -24,6 +24,8 @@
#include <sys/cdefs.h> #include <sys/cdefs.h>
#include <libc-symbols.h> #include <libc-symbols.h>
#include "set-hooks-arch.h"
#ifdef symbol_set_define #ifdef symbol_set_define
/* Define a hook variable called NAME. Functions put on this hook take /* Define a hook variable called NAME. Functions put on this hook take
arguments described by PROTO. Use `text_set_element (NAME, FUNCTION)' arguments described by PROTO. Use `text_set_element (NAME, FUNCTION)'
@ -55,6 +57,25 @@ do { \
DEFINE_HOOK (name, proto); \ DEFINE_HOOK (name, proto); \
extern void runner proto; void runner proto { RUN_HOOK (name, args); } extern void runner proto; void runner proto { RUN_HOOK (name, args); }
# ifdef SET_RELHOOK
/* This is similar to RUN_RELHOOK, but the hooks were registered with
* SET_RELHOOK so that a relative offset was computed by the linker
* rather than an absolute address by the dynamic linker. */
# define RUN_RELHOOK(NAME, ARGS) \
do { \
void *const *ptr; \
for (ptr = (void *const *) symbol_set_first_element (NAME); \
! symbol_set_end_p (NAME, ptr); ++ptr) { \
__##NAME##_hook_function_t *f = \
(void*) ((uintptr_t) ptr + (ptrdiff_t) *ptr); \
(*f) ARGS; \
} \
} while (0)
# else
# define SET_RELHOOK(NAME, HOOK) text_set_element (NAME, HOOK)
# define RUN_RELHOOK(NAME, ARGS) RUN_HOOK(NAME, ARGS)
# endif
#else #else
/* The system does not provide necessary support for this. */ /* The system does not provide necessary support for this. */
@ -66,6 +87,10 @@ extern void runner proto; void runner proto { RUN_HOOK (name, args); }
# define DEFINE_HOOK_RUNNER(name, runner, proto, args) # define DEFINE_HOOK_RUNNER(name, runner, proto, args)
# define SET_RELHOOK(NAME, HOOK)
# define RUN_RELHOOK(NAME, ARGS)
#endif #endif
#endif /* set-hooks.h */ #endif /* set-hooks.h */

View File

@ -0,0 +1,31 @@
/* Machine-dependent macros for using symbol sets for running lists of
functions. Generic/stub version.
Copyright (C) 2021 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
<https://www.gnu.org/licenses/>. */
#ifndef _SET_HOOKS_ARCH_H
#define _SET_HOOKS_ARCH_H
/* Define SET_RELHOOK to a variant of text_set_element that records a relative
offset rather than an absolute address. See sysdeps/i386/set-hooks-arch.h
for an example.
#define SET_RELHOOK(NAME, HOOK) ...
*/
#endif /* set_hooks_arch.h */

View File

@ -0,0 +1,28 @@
/* Machine-dependent macros for using symbol sets for running lists of
functions. i386 version.
Copyright (C) 2021 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
<https://www.gnu.org/licenses/>. */
#ifndef _SET_HOOKS_ARCH_H
#define _SET_HOOKS_ARCH_H
#define SET_RELHOOK(NAME, HOOK) \
asm(".section " #NAME",\"aR\"\n" \
".long "#HOOK" - .\n" \
".section .text");
#endif /* set_hooks_arch.h */

View File

@ -21,6 +21,8 @@
#include <lock-intern.h> /* For `struct mutex'. */ #include <lock-intern.h> /* For `struct mutex'. */
#include <vm_param.h> #include <vm_param.h>
#include "set-hooks.h"
/* Initial maximum size of the data segment (this is arbitrary). */ /* Initial maximum size of the data segment (this is arbitrary). */
#define DATA_SIZE (128 * 1024 * 1024) #define DATA_SIZE (128 * 1024 * 1024)
@ -130,7 +132,7 @@ _hurd_set_brk (vm_address_t addr)
return 0; return 0;
} }
static void static void attribute_used_retain
init_brk (void) init_brk (void)
{ {
vm_address_t pagend; vm_address_t pagend;
@ -160,7 +162,5 @@ init_brk (void)
/* Couldn't allocate the memory. The break will be very short. */ /* Couldn't allocate the memory. The break will be very short. */
_hurd_data_end = pagend; _hurd_data_end = pagend;
} }
(void) &init_brk; /* Avoid ``defined but not used'' warning. */
} }
text_set_element (_hurd_preinit_hook, init_brk); SET_RELHOOK (_hurd_preinit_hook, init_brk);

View File

@ -79,7 +79,7 @@ check_standard_fds (void)
check_one_fd (STDERR_FILENO, O_RDWR); check_one_fd (STDERR_FILENO, O_RDWR);
} }
static void static void attribute_used_retain
init_standard_fds (void) init_standard_fds (void)
{ {
/* Now that we have FDs, make sure that, if this is a SUID program, /* Now that we have FDs, make sure that, if this is a SUID program,
@ -87,10 +87,8 @@ init_standard_fds (void)
ourselves. If that's not possible we stop the program. */ ourselves. If that's not possible we stop the program. */
if (__builtin_expect (__libc_enable_secure, 0)) if (__builtin_expect (__libc_enable_secure, 0))
check_standard_fds (); check_standard_fds ();
(void) &init_standard_fds; /* Avoid "defined but not used" warning. */
} }
text_set_element (_hurd_fd_subinit, init_standard_fds); SET_RELHOOK (_hurd_fd_subinit, init_standard_fds);
#ifndef SHARED #ifndef SHARED

View File

@ -242,7 +242,7 @@ first_init (void)
/* Initialize data structures so we can do RPCs. */ /* Initialize data structures so we can do RPCs. */
__mach_init (); __mach_init ();
RUN_HOOK (_hurd_preinit_hook, ()); RUN_RELHOOK (_hurd_preinit_hook, ());
} }
#ifdef SHARED #ifdef SHARED

View File

@ -0,0 +1,28 @@
/* Machine-dependent macros for using symbol sets for running lists of
functions. x86-64 version.
Copyright (C) 2021 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
<https://www.gnu.org/licenses/>. */
#ifndef _SET_HOOKS_ARCH_H
#define _SET_HOOKS_ARCH_H
#define SET_RELHOOK(NAME, HOOK) \
asm(".section " #NAME",\"aR\"\n" \
".quad "#HOOK" - .\n" \
".section .text");
#endif /* set_hooks_arch.h */