[tip:x86/urgent] x86: gettimeofday() vDSO: fix segfault when tv == NULL

From: tip-bot for John Wright
Date: Thu Apr 30 2009 - 06:40:26 EST


Commit-ID: 2f65dd475c6a8a997145ea83cc3d2d5e6dc55af1
Gitweb: http://git.kernel.org/tip/2f65dd475c6a8a997145ea83cc3d2d5e6dc55af1
Author: John Wright <john.wright@xxxxxx>
AuthorDate: Wed, 29 Apr 2009 14:32:01 -0600
Committer: Ingo Molnar <mingo@xxxxxxx>
CommitDate: Thu, 30 Apr 2009 12:31:45 +0200

x86: gettimeofday() vDSO: fix segfault when tv == NULL

According to the gettimeofday(2) manual:

If either tv or tz is NULL, the corresponding structure is not
set or returned.

Since it is legal to give NULL as the tv argument, the code should make
sure tv is not NULL before trying to dereference it.

This issue manifests itself on x86_64 when vdso=0 is not on the kernel
command-line and libc uses the vDSO for gettimeofday() (e.g. glibc >=
2.7). A simple reproducer:

#include <stdio.h>
#include <sys/time.h>

int main(void)
{
struct timezone tz;

gettimeofday(NULL, &tz);

return 0;
}

See http://bugs.debian.org/466491 for more details.

[ Impact: fix gettimeofday(NULL, &tz) segfault ]

Signed-off-by: John Wright <john.wright@xxxxxx>
Cc: Andi Kleen <ak@xxxxxxx>
Cc: John Wright <john.wright@xxxxxx>
LKML-Reference: <1241037121-14805-1-git-send-email-john.wright@xxxxxx>
Signed-off-by: Ingo Molnar <mingo@xxxxxxx>


---
arch/x86/vdso/vclock_gettime.c | 12 +++++++-----
1 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/arch/x86/vdso/vclock_gettime.c b/arch/x86/vdso/vclock_gettime.c
index d9d3582..6a40b78 100644
--- a/arch/x86/vdso/vclock_gettime.c
+++ b/arch/x86/vdso/vclock_gettime.c
@@ -104,11 +104,13 @@ notrace int __vdso_gettimeofday(struct timeval *tv, struct timezone *tz)
{
long ret;
if (likely(gtod->sysctl_enabled && gtod->clock.vread)) {
- BUILD_BUG_ON(offsetof(struct timeval, tv_usec) !=
- offsetof(struct timespec, tv_nsec) ||
- sizeof(*tv) != sizeof(struct timespec));
- do_realtime((struct timespec *)tv);
- tv->tv_usec /= 1000;
+ if (likely(tv != NULL)) {
+ BUILD_BUG_ON(offsetof(struct timeval, tv_usec) !=
+ offsetof(struct timespec, tv_nsec) ||
+ sizeof(*tv) != sizeof(struct timespec));
+ do_realtime((struct timespec *)tv);
+ tv->tv_usec /= 1000;
+ }
if (unlikely(tz != NULL)) {
/* Avoid memcpy. Some old compilers fail to inline it */
tz->tz_minuteswest = gtod->sys_tz.tz_minuteswest;
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/