New issue
Advanced search Search tips
Note: Color blocks (like or ) mean that a user may not be available. Tooltip shows the reason.
Starred by 4 users
Status: Fixed
Owner:
Email to this user bounced
Closed: Jul 2014
Cc:



Sign in to add a comment
launchd heap overflow in log_forward
Project Member Reported by ianbeer@google.com, Apr 3 2014 Back to list
The log_forward MIG method is used for per-user launchd processes to send log messages to the root launchd (pid 1 running as root.)

job.defs:

routine
log_forward(
        j     : job_t;
        inval   : pointer_t
);


The log_forward implementation checks that the sender was a per-user launchd process before calling launchd_log_forward:

core.c:

kern_return_t
job_mig_log_forward(job_t j, vm_offset_t inval, mach_msg_type_number_t invalCnt)
{
  ...
  if (!job_assumes(j, j->per_user)) {
    return BOOTSTRAP_NOT_PRIVILEGED;
  }

  return launchd_log_forward(ldc->euid, ldc->egid, inval, invalCnt);
  ...


This means that this vulnerability can only be exploited by a per-user launchd process. This still represents a privilege escalation 
however as per-user launchds processes run with the user's uid. Exploitation is therefore predicated on being able to inject code into a process
running as the same user.

The vulnerability is in the code which deserializes the array of log messages (inval points to the controlled buffer:)

log.c:

launchd_log_forward(uid_t forward_uid, gid_t forward_gid, vm_offset_t inval, mach_msg_type_number_t invalCnt)
{
  struct logmsg_s *lm, *lm_walk;
  mach_msg_type_number_t data_left = invalCnt;
  ...
  for (lm_walk = (struct logmsg_s *)inval; (data_left > 0) && (lm_walk->obj_sz <= data_left); lm_walk = ((void *)lm_walk + lm_walk->obj_sz)) {
    ...
    if (lm_walk->obj_sz == 0) {
      ...
      break;
    }

    if (!(lm = malloc(lm_walk->obj_sz))) {         <-- (a)
      ...
      break;
    }

    memcpy(lm, lm_walk, lm_walk->obj_sz);
    lm->sender_uid = forward_uid;                  <-- (b)
    lm->sender_gid = forward_gid;

    lm->from_name += (size_t)lm;
    lm->about_name += (size_t)lm;
    lm->msg += (size_t)lm;
    lm->session_name += (size_t)lm;
  ...


There is no check on the obj_sz field at (a). By passing in a crafted data structure with an obj_sz field smaller than sizeof(struct logmsg_s)
lm will point to an undersized allocation and the assignments at (b) will point outside the allocated memory.
 
Project Member Comment 1 by ianbeer@google.com, Apr 4 2014
Labels: Deadline-90 Reported-2014-Apr-04 PublicOn-2014-Jul-04
Project Member Comment 2 by ianbeer@google.com, Apr 4 2014
Apple follow up id: 605056557
Project Member Comment 3 by ianbeer@google.com, Apr 4 2014
Labels: Id-605056557
Project Member Comment 4 by ianbeer@google.com, May 12 2014
Cc: fjserna@google.com
Project Member Comment 5 by ianbeer@google.com, May 23 2014
Cc: lee...@google.com
Project Member Comment 6 by ianbeer@google.com, Jul 3 2014
Labels: -PublicOn-2014-Jul-04 CVE-2014-1357
Status: Fixed
Advisory: http://support.apple.com/kb/HT6296
Comment 7 by cevans@google.com, Jul 31 2014
Labels: -Restrict-View-Commit
Sign in to add a comment