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 corruption due to unchecked strcpy in init_session MIG ipc
Project Member Reported by ianbeer@google.com, Apr 4 2014 Back to list
MIG ipc routine:

routine
init_session(
				j			: job_t;
				session		: name_t;
				asport		: mach_port_t
);

Implementation:

core.c:

kern_return_t
job_mig_init_session(job_t j, name_t session_type, mach_port_t asport)
{
...
	if (j->mgr->session_initialized) {
		job_log(j, LOG_ERR, "Tried to initialize an already setup session!");
		kr = BOOTSTRAP_NOT_PRIVILEGED;              <-- even if the session is already initialized there's no early return here, it will still hit the strcpy
	}
...

	jobmgr_log(j->mgr, LOG_DEBUG, "Initializing as %s", session_type);
	strcpy(j->mgr->name_init, session_type);           <-- unchecked strcpy



The buffer which is being copied into is allocated here:

jobmgr_t 
jobmgr_new(jobmgr_t jm, mach_port_t requestorport, mach_port_t transfer_port, bool sflag, const char *name, bool skip_init, mach_port_t asport)
{
	job_t bootstrapper = NULL;
	jobmgr_t jmr;
...
	jmr = calloc(1, sizeof(struct jobmgr_s) + (name ? (strlen(name) + 1) : NAME_MAX + 1)); <-- here



jobmgr_t is typedef'd as a pointer to a struct jobmgr_s, which has a zero-sized array at the end:

struct jobmgr_s {
... 
	union {
		const char name[0];
		char name_init[0];
	};
};


It's possible to force the allocation of a new jobmgr_t with a partially controlled name field using the subset MIG ipc - this will allocate only enough space for this string in the jobmgr_s struct:

kern_return_t
job_mig_subset(job_t j, mach_port_t requestorport, mach_port_t *subsetportp)
{
	int bsdepth = 0;
	jobmgr_t jmr;
...
	jmr = j->mgr;
...
	char name[NAME_MAX];
	snprintf(name, sizeof(name), "%s[%i].subset.%i", j->anonymous ? j->prog : j->label, j->p, MACH_PORT_INDEX(requestorport));

	if (!job_assumes(j, (jmr = jobmgr_new(j->mgr, requestorport, MACH_PORT_NULL, false, name, true, j->asport)) != NULL)) {


This subset bootstrap port can then be passed to init_session with a longer session_type.
 
Project Member Comment 1 by ianbeer@google.com, Apr 4 2014
Labels: Deadline-90 Reported-2014-Apr-04 PublicOn-2014-Jul-04 Id-605057125
Apple follow up id: 605057125
Project Member Comment 2 by ianbeer@google.com, May 12 2014
Cc: fjserna@google.com
Project Member Comment 3 by ianbeer@google.com, May 23 2014
Cc: lee...@google.com
Project Member Comment 4 by ianbeer@google.com, Jul 3 2014
Labels: -PublicOn-2014-Jul-04 CVE-2014-1356
Apple advisory: http://support.apple.com/kb/HT6296
Project Member Comment 5 by ianbeer@google.com, Jul 3 2014
Status: Fixed
Comment 6 by cevans@google.com, Jul 31 2014
Labels: -Restrict-View-Commit
Sign in to add a comment