فهرست منبع

fix dangling pointers in x32 syscall timespec fixup code

the lifetime of compound literals is the block in which they appear.
the temporary struct __timespec_kernel objects created as compound
literals no longer existed at the time their addresses were passed to
the kernel.
Rich Felker 10 سال پیش
والد
کامیت
4f69594689
2فایلهای تغییر یافته به همراه23 افزوده شده و 10 حذف شده
  1. 7 3
      arch/x32/src/syscall_cp_fixup.c
  2. 16 7
      arch/x32/syscall_arch.h

+ 7 - 3
arch/x32/src/syscall_cp_fixup.c

@@ -9,14 +9,18 @@ long __syscall_cp_internal(volatile void*, long long, long long, long long, long
 struct __timespec { long long tv_sec; long tv_nsec; };
 struct __timespec_kernel { long long tv_sec; long long tv_nsec; };
 #define __tsc(X) ((struct __timespec*)(unsigned long)(X))
-#define __fixup(X) do { if(X) X = (unsigned long) (&(struct __timespec_kernel) \
-                   { .tv_sec = __tsc(X)->tv_sec, .tv_nsec = __tsc(X)->tv_nsec}); } while(0)
+#define __fixup(X) do { if(X) { \
+	ts->tv_sec = __tsc(X)->tv_sec; \
+	ts->tv_nsec = __tsc(X)->tv_nsec; \
+	(X) = (unsigned long)ts; } } while(0)
 
 #ifdef SHARED
 __attribute__((__visibility__("hidden")))
 #endif
 long __syscall_cp_asm (volatile void * foo, long long n, long long a1, long long a2, long long a3,
-	                     long long a4, long long a5, long long a6) {
+	                     long long a4, long long a5, long long a6)
+{
+	struct __timespec_kernel ts[1];
 	switch (n) {
 	case SYS_mq_timedsend: case SYS_mq_timedreceive: case SYS_pselect6:
 		__fixup(a5);

+ 16 - 7
arch/x32/syscall_arch.h

@@ -6,8 +6,10 @@ typedef long long syscall_arg_t;
 struct __timespec { long long tv_sec; long tv_nsec; };
 struct __timespec_kernel { long long tv_sec; long long tv_nsec; };
 #define __tsc(X) ((struct __timespec*)(unsigned long)(X))
-#define __fixup(X) do { if(X) X = (unsigned long) (&(struct __timespec_kernel) \
-                   { .tv_sec = __tsc(X)->tv_sec, .tv_nsec = __tsc(X)->tv_nsec}); } while(0)
+#define __fixup(X) do { if(X) { \
+	ts->tv_sec = __tsc(X)->tv_sec; \
+	ts->tv_nsec = __tsc(X)->tv_nsec; \
+	(X) = (unsigned long)ts; } } while(0)
 #define __fixup_case_2 \
 	case SYS_nanosleep: \
 		__fixup(a1); break; \
@@ -17,10 +19,13 @@ struct __timespec_kernel { long long tv_sec; long long tv_nsec; };
 	case SYS_clock_nanosleep: case SYS_rt_sigtimedwait: case SYS_ppoll: \
 		__fixup(a3); break; \
 	case SYS_utimensat: \
-		if(a3) a3 = (unsigned long) ((struct __timespec_kernel[2]) { \
-		[0] = {.tv_sec = __tsc(a3)[0].tv_sec, .tv_nsec = __tsc(a3)[0].tv_nsec}, \
-		[1] = {.tv_sec = __tsc(a3)[1].tv_sec, .tv_nsec = __tsc(a3)[1].tv_nsec}, \
-		}); break;
+		if(a3) { \
+			ts[0].tv_sec = __tsc(a3)[0].tv_sec; \
+			ts[0].tv_nsec = __tsc(a3)[0].tv_nsec; \
+			ts[1].tv_sec = __tsc(a3)[1].tv_sec; \
+			ts[1].tv_nsec = __tsc(a3)[1].tv_nsec; \
+			a3 = (unsigned long)ts; \
+		} break;
 #define __fixup_case_4 \
 	case SYS_futex: \
 		if((a2 & (~128 /* FUTEX_PRIVATE_FLAG */)) == 0 /* FUTEX_WAIT */) __fixup(a4); break;
@@ -45,7 +50,7 @@ static __inline long __syscall1(long long n, long long a1)
 static __inline long __syscall2(long long n, long long a1, long long a2)
 {
 	unsigned long ret;
-	struct __timespec *ts2 = 0;
+	struct __timespec_kernel ts[1];
 	switch (n) {
 		__fixup_case_2;
 	}
@@ -57,6 +62,7 @@ static __inline long __syscall2(long long n, long long a1, long long a2)
 static __inline long __syscall3(long long n, long long a1, long long a2, long long a3)
 {
 	unsigned long ret;
+	struct __timespec_kernel ts[2];
 	switch (n) {
 		__fixup_case_2;
 		__fixup_case_3;
@@ -71,6 +77,7 @@ static __inline long __syscall4(long long n, long long a1, long long a2, long lo
 {
 	unsigned long ret;
 	register long long a4 __asm__("r10") = a4_;
+	struct __timespec_kernel ts[2];
 	switch (n) {
 		__fixup_case_2;
 		__fixup_case_3;
@@ -87,6 +94,7 @@ static __inline long __syscall5(long long n, long long a1, long long a2, long lo
 	unsigned long ret;
 	register long long a4 __asm__("r10") = a4_;
 	register long long a5 __asm__("r8") = a5_;
+	struct __timespec_kernel ts[2];
 	switch (n) {
 		__fixup_case_2;
 		__fixup_case_3;
@@ -105,6 +113,7 @@ static __inline long __syscall6(long long n, long long a1, long long a2, long lo
 	register long long a4 __asm__("r10") = a4_;
 	register long long a5 __asm__("r8") = a5_;
 	register long long a6 __asm__("r9") = a6_;
+	struct __timespec_kernel ts[2];
 	switch (n) {
 		__fixup_case_2;
 		__fixup_case_3;