BZ#331380 Syscall param timer_create(evp) points to uninitialised byte(s)

Only check struct sigevent actually used by the kernel. If SIGEV_THREAD_ID
is set check sigev_notify_thread_id, otherwise don't.

git-svn-id: svn://svn.valgrind.org/valgrind/trunk@13835 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/NEWS b/NEWS
index b3fc82d..f1aa78c 100644
--- a/NEWS
+++ b/NEWS
@@ -60,6 +60,7 @@
 331257  Fix type of jump buffer in test none/tests/faultstatus
 331305  configure uses bash specific syntax
 331337  s390x WARNING: unhandled syscall: 326 (dup3)
+331380  Syscall param timer_create(evp) points to uninitialised byte(s)
 n-i-bz  Fix KVM_CREATE_IRQCHIP ioctl handling
 
 Release 3.9.0 (31 October 2013)
diff --git a/coregrind/m_syswrap/syswrap-linux.c b/coregrind/m_syswrap/syswrap-linux.c
index 9dadd84..1a7fa6b 100644
--- a/coregrind/m_syswrap/syswrap-linux.c
+++ b/coregrind/m_syswrap/syswrap-linux.c
@@ -2175,8 +2175,18 @@
    PRE_REG_READ3(long, "timer_create",
                  vki_clockid_t, clockid, struct sigevent *, evp,
                  vki_timer_t *, timerid);
-   if (ARG2 != 0)
-      PRE_MEM_READ( "timer_create(evp)", ARG2, sizeof(struct vki_sigevent) );
+   if (ARG2 != 0) {
+      struct vki_sigevent *evp = (struct vki_sigevent *) ARG2;
+      PRE_MEM_READ( "timer_create(evp.sigev_value)", (Addr)&evp->sigev_value,
+                    sizeof(vki_sigval_t) );
+      PRE_MEM_READ( "timer_create(evp.sigev_signo)", (Addr)&evp->sigev_signo,
+                    sizeof(int) );
+      PRE_MEM_READ( "timer_create(evp.sigev_notify)", (Addr)&evp->sigev_notify,
+                    sizeof(int) );
+      if ((evp->sigev_notify & VKI_SIGEV_THREAD_ID) != 0)
+         PRE_MEM_READ( "timer_create(evp.sigev_notify_thread_id)",
+                       (Addr)&evp->vki_sigev_notify_thread_id, sizeof(int) );
+   }
    PRE_MEM_WRITE( "timer_create(timerid)", ARG3, sizeof(vki_timer_t) );
 }
 POST(sys_timer_create)
diff --git a/include/vki/vki-linux.h b/include/vki/vki-linux.h
index 14bb8bf..a3c4b3c 100644
--- a/include/vki/vki-linux.h
+++ b/include/vki/vki-linux.h
@@ -544,6 +544,9 @@
 #define VKI_SIGEV_PAD_SIZE	((VKI_SIGEV_MAX_SIZE - VKI___ARCH_SIGEV_PREAMBLE_SIZE) \
 		/ sizeof(int))
 
+/* This is the flag the kernel handles, userspace/glibc handles SEGEV_THEAD. */
+#define VKI_SIGEV_THREAD_ID	4
+
 typedef struct vki_sigevent {
 	vki_sigval_t sigev_value;
 	int sigev_signo;
@@ -559,6 +562,8 @@
 	} _sigev_un;
 } vki_sigevent_t;
 
+#define vki_sigev_notify_thread_id	_sigev_un._tid
+
 //----------------------------------------------------------------------
 // From elsewhere...
 //----------------------------------------------------------------------