forked from pool/glibc
Andreas Schwab
746e16d2b9
- Update to glibc 2.17.90 85891acadf1b: * CVE-2013-2207 Incorrectly granting access to another user's pseudo-terminal has been fixed by disabling the use of pt_chown (Bugzilla #15755). Distributions can re-enable building and using pt_chown via the new configure option `--enable-pt_chown'. Enabling the use of pt_chown carries with it considerable security risks and should only be used if the distribution understands and accepts the risks. * CVE-2013-0242 Buffer overrun in regexp matcher has been fixed (Bugzilla #15078). * CVE-2013-1914 Stack overflow in getaddrinfo with many results has been fixed (Bugzilla #15330). * Add support for calling C++11 thread_local object destructors on thread and program exit. This needs compiler support for offloading C++11 destructor calls to glibc. * Improved worst case performance of libm functions with double inputs and output. * Support for priority inherited mutexes in pthread condition variables on non-x86 architectures. * Optimized string functions for AArch64. Implemented by Marcus Shawcroft. * Optimized string functions for ARM. Implemented by Will Newton and Richard Henderson. * Added a benchmark framework to track performance of functions in glibc. * New <math.h> macro named issignaling to check for a signaling NaN (sNaN). It is based on draft TS 18661 and currently enabled as a GNU extension. * On Linux, the clock function now uses the clock_gettime system call for improved precision, rather than old times system call. * Added new API functions pthread_getattr_default_np and pthread_setattr_default_np to get and set the default pthread attributes of a process. * Added support for TSX lock elision for pthread mutexes on i386 and x86-64. OBS-URL: https://build.opensuse.org/request/show/186119 OBS-URL: https://build.opensuse.org/package/show/Base:System/glibc?expand=0&rev=304
337 lines
8.5 KiB
C
337 lines
8.5 KiB
C
/* skeleton based on version from Fedora Core 3 */
|
|
|
|
#define _GNU_SOURCE
|
|
|
|
#include <sys/types.h>
|
|
#include <sys/wait.h>
|
|
#include <stdio.h>
|
|
#include <errno.h>
|
|
#include <unistd.h>
|
|
#include <sys/time.h>
|
|
#include <dirent.h>
|
|
#include <stddef.h>
|
|
#include <fcntl.h>
|
|
#include <string.h>
|
|
#include <sys/stat.h>
|
|
#include <elf.h>
|
|
|
|
#define verbose_exec(failcode, path...) \
|
|
do \
|
|
{ \
|
|
char *const arr[] = { path, NULL }; \
|
|
vexec (failcode, arr); \
|
|
} while (0)
|
|
|
|
__attribute__((noinline)) void vexec (int failcode, char *const path[]);
|
|
__attribute__((noinline)) void says (const char *str);
|
|
__attribute__((noinline)) void sayn (long num);
|
|
__attribute__((noinline)) void message (char *const path[]);
|
|
__attribute__((noinline)) int check_elf (const char *name);
|
|
|
|
int
|
|
main (void)
|
|
{
|
|
char initpath[256];
|
|
struct stat root, init_root;
|
|
|
|
/* First, get rid of platform-optimized libraries. We remove any we have
|
|
ever built, since otherwise we might end up using some old leftover
|
|
libraries when new ones aren't installed in their place anymore. */
|
|
#ifdef REMOVE_TLS_DIRS
|
|
const char *library[] = {"libc.so.6", "libc.so.6.1", "libm.so.6",
|
|
"libm.so.6.1", "librt.so.1", "librtkaio.so.1",
|
|
"libpthread.so.0", "libthread_db.so.1"};
|
|
const char *remove_dir[] = {
|
|
#ifdef __i386__
|
|
"/lib/i686/",
|
|
#endif
|
|
#ifdef __powerpc64__
|
|
#ifdef REMOVE_PPC_OPTIMIZE_POWER4
|
|
"/lib64/power4/",
|
|
"/lib64/ppc970/",
|
|
#endif
|
|
#ifdef REMOVE_PPC_OPTIMIZE_POWER5
|
|
"/lib64/power5/",
|
|
"/lib64/power5+/",
|
|
#endif
|
|
#ifdef REMOVE_PPC_OPTIMIZE_POWER6
|
|
"/lib64/power6/",
|
|
"/lib64/power6x/",
|
|
#endif
|
|
#ifdef REMOVE_PPC_OPTIMIZE_POWER7
|
|
"/lib64/power7/",
|
|
#endif
|
|
#ifdef REMOVE_PPC_OPTIMIZE_CELL
|
|
"/lib64/ppc-cell-be/",
|
|
#endif
|
|
#endif /* __powerpc64__ */
|
|
#ifdef __powerpc__
|
|
#ifdef REMOVE_PPC_OPTIMIZE_POWER4
|
|
"/lib/power4/",
|
|
"/lib/ppc970/",
|
|
#endif
|
|
#ifdef REMOVE_PPC_OPTIMIZE_POWER5
|
|
"/lib/power5/",
|
|
"/lib/power5+/",
|
|
#endif
|
|
#ifdef REMOVE_PPC_OPTIMIZE_POWER6
|
|
"/lib/power6/",
|
|
"/lib/power6x/",
|
|
#endif
|
|
#ifdef REMOVE_PPC_OPTIMIZE_POWER7
|
|
"/lib/power7/",
|
|
#endif
|
|
#ifdef REMOVE_PPC_OPTIMIZE_CELL
|
|
"/lib/ppc-cell-be/",
|
|
#endif
|
|
#endif /* __powerpc__ */
|
|
LIBDIR"/tls/" };
|
|
int i, j;
|
|
|
|
for (i = 0; i < sizeof (remove_dir) / sizeof (remove_dir[0]); ++i)
|
|
for (j = 0; j < sizeof (library) / sizeof (library[0]); j++)
|
|
{
|
|
char buf[strlen (remove_dir[i]) + strlen (library[j]) + 1];
|
|
char readlink_buf[(strlen (remove_dir[i]) + strlen (library[j])) * 2 + 30];
|
|
ssize_t len;
|
|
char *cp;
|
|
|
|
cp = stpcpy (buf, remove_dir[i]);
|
|
strcpy (cp, library[j]);
|
|
/* This file could be a symlink to library-%{version}.so, so check
|
|
this and don't remove only the link, but also the library itself. */
|
|
cp = stpcpy (readlink_buf, remove_dir[i]);
|
|
if ((len = readlink (buf, cp, (sizeof (readlink_buf)
|
|
- (cp - readlink_buf) - 1))) > 0)
|
|
{
|
|
cp[len] = '\0';
|
|
if (cp[0] != '/') cp = readlink_buf;
|
|
unlink (cp);
|
|
}
|
|
unlink (buf);
|
|
}
|
|
#endif
|
|
|
|
/* If installing bi-arch glibc, rpm sometimes doesn't unpack all files
|
|
before running one of the lib's %post scriptlet. /sbin/ldconfig will
|
|
then be run by the other arch's %post. */
|
|
if (access ("/sbin/ldconfig", X_OK) == 0)
|
|
verbose_exec (110, "/sbin/ldconfig", "/sbin/ldconfig", "-X");
|
|
|
|
if (utimes (GCONV_MODULES_DIR "/gconv-modules.cache", NULL) == 0)
|
|
{
|
|
#ifndef ICONVCONFIG
|
|
#define ICONVCONFIG "/usr/sbin/iconvconfig"
|
|
#endif
|
|
verbose_exec (113, ICONVCONFIG, "/usr/sbin/iconvconfig",
|
|
"-o", GCONV_MODULES_DIR"/gconv-modules.cache",
|
|
"--nostdlib", GCONV_MODULES_DIR);
|
|
}
|
|
|
|
/* Check if telinit is available and the init fifo as well. */
|
|
if (access ("/sbin/telinit", X_OK) || access ("/dev/initctl", F_OK))
|
|
_exit (0);
|
|
/* Check if we are not inside of some chroot, because we'd just
|
|
timeout and leave /etc/initrunlvl. */
|
|
if (readlink ("/proc/1/exe", initpath, 256) <= 0 ||
|
|
readlink ("/proc/1/root", initpath, 256) <= 0 ||
|
|
access ("/.buildenv", F_OK) == 0 || /* XEN build */
|
|
stat ("/proc/1/root", &init_root) < 0 ||
|
|
stat ("/", &root) < 0 ||
|
|
init_root.st_dev != root.st_dev || init_root.st_ino != root.st_ino)
|
|
_exit (0);
|
|
|
|
if (check_elf ("/proc/1/exe"))
|
|
verbose_exec (116, "/sbin/telinit", "/sbin/telinit", "u");
|
|
|
|
#if 0
|
|
/* Check if we can safely condrestart sshd. */
|
|
if (access ("/sbin/service", X_OK) == 0
|
|
&& access ("/usr/sbin/sshd", X_OK) == 0
|
|
&& access ("/bin/bash", X_OK) == 0)
|
|
{
|
|
if (check_elf ("/usr/sbin/sshd"))
|
|
verbose_exec (121, "/sbin/service", "/sbin/service", "sshd", "condrestart");
|
|
}
|
|
#endif
|
|
|
|
_exit(0);
|
|
}
|
|
|
|
void
|
|
vexec (int failcode, char *const path[])
|
|
{
|
|
pid_t pid;
|
|
int status, save_errno;
|
|
|
|
pid = vfork ();
|
|
if (pid == 0)
|
|
{
|
|
execv (path[0], path + 1);
|
|
save_errno = errno;
|
|
message (path);
|
|
says (" exec failed with errno ");
|
|
sayn (save_errno);
|
|
says ("\n");
|
|
_exit (failcode);
|
|
}
|
|
else if (pid < 0)
|
|
{
|
|
save_errno = errno;
|
|
message (path);
|
|
says (" fork failed with errno ");
|
|
sayn (save_errno);
|
|
says ("\n");
|
|
_exit (failcode + 1);
|
|
}
|
|
if (waitpid (0, &status, 0) != pid || !WIFEXITED (status))
|
|
{
|
|
message (path);
|
|
says (" child terminated abnormally\n");
|
|
_exit (failcode + 2);
|
|
}
|
|
if (WEXITSTATUS (status))
|
|
{
|
|
message (path);
|
|
says (" child exited with exit code ");
|
|
sayn (WEXITSTATUS (status));
|
|
says ("\n");
|
|
_exit (WEXITSTATUS (status));
|
|
}
|
|
}
|
|
|
|
void
|
|
says (const char *str)
|
|
{
|
|
write (1, str, strlen (str));
|
|
}
|
|
|
|
void
|
|
sayn (long num)
|
|
{
|
|
char string[sizeof (long) * 3 + 1];
|
|
char *p = string + sizeof (string) - 1;
|
|
|
|
*p = '\0';
|
|
if (num == 0)
|
|
*--p = '0';
|
|
else
|
|
while (num)
|
|
{
|
|
*--p = '0' + num % 10;
|
|
num = num / 10;
|
|
}
|
|
|
|
says (p);
|
|
}
|
|
|
|
void
|
|
message (char *const path[])
|
|
{
|
|
says ("/usr/sbin/glibc_post_upgrade: While trying to execute ");
|
|
says (path[0]);
|
|
}
|
|
|
|
int
|
|
check_elf (const char *name)
|
|
{
|
|
/* Play safe, if we can't open or read, assume it might be
|
|
ELF for the current arch. */
|
|
int ret = 1;
|
|
int fd = open (name, O_RDONLY);
|
|
if (fd >= 0)
|
|
{
|
|
Elf32_Ehdr ehdr;
|
|
if (read (fd, &ehdr, offsetof (Elf32_Ehdr, e_version))
|
|
== offsetof (Elf32_Ehdr, e_version))
|
|
{
|
|
ret = 0;
|
|
if (ehdr.e_ident[EI_CLASS]
|
|
== (sizeof (long) == 8 ? ELFCLASS64 : ELFCLASS32))
|
|
{
|
|
#if defined __i386__
|
|
ret = ehdr.e_machine == EM_386;
|
|
#elif defined __x86_64__
|
|
ret = ehdr.e_machine == EM_X86_64;
|
|
#elif defined __ia64__
|
|
ret = ehdr.e_machine == EM_IA_64;
|
|
#elif defined __powerpc64__
|
|
ret = ehdr.e_machine == EM_PPC64;
|
|
#elif defined __powerpc__
|
|
ret = ehdr.e_machine == EM_PPC;
|
|
#elif defined __s390__ || defined __s390x__
|
|
ret = ehdr.e_machine == EM_S390;
|
|
#elif defined __x86_64__
|
|
ret = ehdr.e_machine == EM_X86_64;
|
|
#elif defined __sparc__
|
|
if (sizeof (long) == 8)
|
|
ret = ehdr.e_machine == EM_SPARCV9;
|
|
else
|
|
ret = (ehdr.e_machine == EM_SPARC
|
|
|| ehdr.e_machine == EM_SPARC32PLUS);
|
|
#else
|
|
ret = 1;
|
|
#endif
|
|
}
|
|
}
|
|
close (fd);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
#ifdef SMALL_BINARY
|
|
|
|
int __libc_multiple_threads __attribute__((nocommon));
|
|
int __libc_enable_asynccancel (void) { return 0; }
|
|
void __libc_disable_asynccancel (int x) { }
|
|
void __libc_csu_init (void) { }
|
|
void __libc_csu_fini (void) { }
|
|
pid_t __fork (void) { return -1; }
|
|
char thr_buf[65536];
|
|
|
|
#ifndef __powerpc__
|
|
int
|
|
__libc_start_main (int (*main) (void), int argc, char **argv,
|
|
void (*init) (void), void (*fini) (void),
|
|
void (*rtld_fini) (void), void * stack_end)
|
|
#else
|
|
struct startup_info
|
|
{
|
|
void *sda_base;
|
|
int (*main) (int, char **, char **, void *);
|
|
int (*init) (int, char **, char **, void *);
|
|
void (*fini) (void);
|
|
};
|
|
|
|
int
|
|
__libc_start_main (int argc, char **ubp_av, char **ubp_ev,
|
|
void *auxvec, void (*rtld_fini) (void),
|
|
struct startup_info *stinfo,
|
|
char **stack_on_entry)
|
|
#endif
|
|
{
|
|
#if defined __ia64__ || defined __powerpc64__
|
|
register void *r13 __asm ("r13") = thr_buf + 32768;
|
|
__asm ("" : : "r" (r13));
|
|
#elif defined __sparc__
|
|
register void *g6 __asm ("g6") = thr_buf + 32768;
|
|
# ifdef __arch64__
|
|
__thread_self = thr_buf + 32768;
|
|
# else
|
|
register void *__thread_self __asm ("g7") = thr_buf + 32768;
|
|
# endif
|
|
__asm ("" : : "r" (g6), "r" (__thread_self));
|
|
#elif defined __s390__ && !defined __s390x__
|
|
__asm ("sar %%a0,%0" : : "d" (thr_buf + 32768));
|
|
#elif defined __s390x__
|
|
__asm ("sar %%a1,%0; srlg 0,%0,32; sar %%a0,0" : : "d" (thr_buf + 32768) : "0");
|
|
#elif defined __powerpc__ && !defined __powerpc64__
|
|
register void *r2 __asm ("r2") = thr_buf + 32768;
|
|
__asm ("" : : "r" (r2));
|
|
#endif
|
|
main();
|
|
return 0;
|
|
}
|
|
|
|
#endif
|