Upstream-Status: Backport

Concatenated fix of PowerPC time related system calls in eglibc 2.18 taken
from upstream glibc. Eglibc 2.17 does not have this issue and the patches are
already part of 2.19.
This compilation includes the following committs:


PowerPC: Fix vDSO missing ODP entries

author	Adhemerval Zanella <azanella@linux.vnet.ibm.com>
	Thu, 7 Nov 2013 11:34:22 +0000 (05:34 -0600)

This patch fixes the vDSO symbol used directed in IFUNC resolver where
they do not have an associated ODP entry leading to undefined behavior
in some cases. It adds an artificial OPD static entry to such cases
and set its TOC to non 0 to avoid triggering lazy resolutions.


Update copyright notices with scripts/update-copyrights

author	Allan McRae <allan@archlinux.org>
	Wed, 1 Jan 2014 11:03:15 +0000 (21:03 +1000)

((Only for files otherwise touched by this patch))


PowerPC: Fix ftime gettimeofday internal call returning bogus data

author	Adhemerval Zanella <azanella@linux.vnet.ibm.com>
	Thu, 16 Jan 2014 12:53:18 +0000 (06:53 -0600)

This patches fixes BZ#16430 by setting a different symbol for internal
GLIBC calls that points to ifunc resolvers. For PPC32, if the symbol
is defined as hidden (which is the case for gettimeofday and time) the
compiler will create local branches (symbol@local) and linker will not
create PLT calls (required for IFUNC). This will leads to internal symbol
calling the IFUNC resolver instead of the resolved symbol.
For PPC64 this behavior does not occur because a call to a function in
another translation unit might use a different toc pointer thus requiring
a PLT call.


PowerPC: Fix gettimeofday ifunc selection

author	Adhemerval Zanella <azanella@linux.vnet.ibm.com>
	Mon, 20 Jan 2014 18:29:51 +0000 (12:29 -0600)

The IFUNC selector for gettimeofday runs before _libc_vdso_platform_setup where
__vdso_gettimeofday is set. The selector then sets __gettimeofday (the internal
version used within GLIBC) to use the system call version instead of the vDSO one.
This patch changes the check if vDSO is available to get its value directly
instead of rely on __vdso_gettimeofday.

This patch changes it by getting the vDSO value directly.

It fixes BZ#16431.


---
diff -pruN libc.orig/sysdeps/unix/sysv/linux/powerpc/bits/libc-vdso.h libc/sysdeps/unix/sysv/linux/powerpc/bits/libc-vdso.h
--- libc.orig/sysdeps/unix/sysv/linux/powerpc/bits/libc-vdso.h
+++ libc/sysdeps/unix/sysv/linux/powerpc/bits/libc-vdso.h
@@ -1,5 +1,5 @@
 /* Resolve function pointers to VDSO functions.
-   Copyright (C) 2005-2013 Free Software Foundation, Inc.
+   Copyright (C) 2005-2014 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
@@ -34,12 +34,32 @@ extern void *__vdso_getcpu;
 
 extern void *__vdso_time;
 
-/* This macro is needed for PPC64 to return a skeleton OPD entry of a vDSO
-   symbol.  This works because _dl_vdso_vsym always return the function
-   address, and no vDSO symbols use the TOC or chain pointers from the OPD
-   so we can allow them to be garbage.  */
 #if defined(__PPC64__) || defined(__powerpc64__)
-#define VDSO_IFUNC_RET(value)  ((void *) &(value))
+/* The correct solution is for _dl_vdso_vsym to return the address of the OPD
+   for the kernel VDSO function.  That address would then be stored in the
+   __vdso_* variables and returned as the result of the IFUNC resolver function.
+   Yet, the kernel does not contain any OPD entries for the VDSO functions
+   (incomplete implementation).  However, PLT relocations for IFUNCs still expect
+   the address of an OPD to be returned from the IFUNC resolver function (since
+   PLT entries on PPC64 are just copies of OPDs).  The solution for now is to
+   create an artificial static OPD for each VDSO function returned by a resolver
+   function.  The TOC value is set to a non-zero value to avoid triggering lazy
+   symbol resolution via .glink0/.plt0 for a zero TOC (requires thread-safe PLT
+   sequences) when the dynamic linker isn't prepared for it e.g. RTLD_NOW.  None
+   of the kernel VDSO routines use the TOC or AUX values so any non-zero value
+   will work.  Note that function pointer comparisons will not use this artificial
+   static OPD since those are resolved via ADDR64 relocations and will point at
+   the non-IFUNC default OPD for the symbol.  Lastly, because the IFUNC relocations
+   are processed immediately at startup the resolver functions and this code need
+   not be thread-safe, but if the caller writes to a PLT slot it must do so in a
+   thread-safe manner with all the required barriers.  */
+#define VDSO_IFUNC_RET(value)                            \
+  ({                                                     \
+    static Elf64_FuncDesc vdso_opd = { .fd_toc = ~0x0 }; \
+    vdso_opd.fd_func = (Elf64_Addr)value;                \
+    &vdso_opd;                                           \
+  })
+
 #else
 #define VDSO_IFUNC_RET(value)  ((void *) (value))
 #endif
diff -pruN libc.orig/sysdeps/unix/sysv/linux/powerpc/gettimeofday.c libc/sysdeps/unix/sysv/linux/powerpc/gettimeofday.c
--- libc.orig/sysdeps/unix/sysv/linux/powerpc/gettimeofday.c
+++ libc/sysdeps/unix/sysv/linux/powerpc/gettimeofday.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2005-2013 Free Software Foundation, Inc.
+/* Copyright (C) 2005-2014 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
@@ -22,6 +22,7 @@
 
 # include <dl-vdso.h>
 # include <bits/libc-vdso.h>
+# include <dl-machine.h>
 
 void *gettimeofday_ifunc (void) __asm__ ("__gettimeofday");
 
@@ -34,17 +35,36 @@ __gettimeofday_syscall (struct timeval *
 void *
 gettimeofday_ifunc (void)
 {
+  PREPARE_VERSION (linux2615, "LINUX_2.6.15", 123718565);
+
   /* If the vDSO is not available we fall back syscall.  */
-  return (__vdso_gettimeofday ? VDSO_IFUNC_RET (__vdso_gettimeofday)
-	  : __gettimeofday_syscall);
+  void *vdso_gettimeofday = _dl_vdso_vsym ("__kernel_gettimeofday", &linux2615);
+  return (vdso_gettimeofday ? VDSO_IFUNC_RET (vdso_gettimeofday)
+         : (void*)__gettimeofday_syscall);
 }
 asm (".type __gettimeofday, %gnu_indirect_function");
 
 /* This is doing "libc_hidden_def (__gettimeofday)" but the compiler won't
    let us do it in C because it doesn't know we're defining __gettimeofday
    here in this file.  */
-asm (".globl __GI___gettimeofday\n"
-     "__GI___gettimeofday = __gettimeofday");
+asm (".globl __GI___gettimeofday");
+
+/* __GI___gettimeofday is defined as hidden and for ppc32 it enables the
+   compiler make a local call (symbol@local) for internal GLIBC usage. It
+   means the PLT won't be used and the ifunc resolver will be called directly.
+   For ppc64 a call to a function in another translation unit might use a
+   different toc pointer thus disallowing direct branchess and making internal
+   ifuncs calls safe.  */
+#ifdef __powerpc64__
+asm ("__GI___gettimeofday = __gettimeofday");
+#else
+int
+__gettimeofday_vsyscall (struct timeval *tv, struct timezone *tz)
+{
+  return INLINE_VSYSCALL (gettimeofday, 2, tv, tz);
+}
+asm ("__GI___gettimeofday = __gettimeofday_vsyscall");
+#endif
 
 #else
 
diff -pruN libc.orig/sysdeps/unix/sysv/linux/powerpc/time.c libc/sysdeps/unix/sysv/linux/powerpc/time.c
--- libc.orig/sysdeps/unix/sysv/linux/powerpc/time.c
+++ libc/sysdeps/unix/sysv/linux/powerpc/time.c
@@ -1,5 +1,5 @@
 /* time system call for Linux/PowerPC.
-   Copyright (C) 2013 Free Software Foundation, Inc.
+   Copyright (C) 2013-2014 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
@@ -20,7 +20,9 @@
 
 # include <time.h>
 # include <sysdep.h>
+# include <dl-vdso.h>
 # include <bits/libc-vdso.h>
+# include <dl-machine.h>
 
 void *time_ifunc (void) asm ("time");
 
@@ -43,17 +45,36 @@ time_syscall (time_t *t)
 void *
 time_ifunc (void)
 {
+  PREPARE_VERSION (linux2615, "LINUX_2.6.15", 123718565);
+
   /* If the vDSO is not available we fall back to the syscall.  */
-  return (__vdso_time ? VDSO_IFUNC_RET (__vdso_time)
-	  : time_syscall);
+  void *vdso_time = _dl_vdso_vsym ("__kernel_time", &linux2615);
+  return (vdso_time ? VDSO_IFUNC_RET (vdso_time)
+         : (void*)time_syscall);
 }
 asm (".type time, %gnu_indirect_function");
 
 /* This is doing "libc_hidden_def (time)" but the compiler won't
  * let us do it in C because it doesn't know we're defining time
  * here in this file.  */
-asm (".globl __GI_time\n"
-     "__GI_time = time");
+asm (".globl __GI_time");
+
+/* __GI_time is defined as hidden and for ppc32 it enables the
+   compiler make a local call (symbol@local) for internal GLIBC usage. It
+   means the PLT won't be used and the ifunc resolver will be called directly.
+   For ppc64 a call to a function in another translation unit might use a
+   different toc pointer thus disallowing direct branchess and making internal
+   ifuncs calls safe.  */
+#ifdef __powerpc64__
+asm ("__GI_time = time");
+#else
+time_t
+__time_vsyscall (time_t *t)
+{
+  return INLINE_VSYSCALL (time, 1, t);
+}
+asm ("__GI_time = __time_vsyscall");
+#endif
 
 #else
 
