Skip to content

Commit

Permalink
xnu-3248.50.21
Browse files Browse the repository at this point in the history
  • Loading branch information
Darwin authored and das committed Jun 4, 2017
1 parent 147abd9 commit 0ed26c3
Show file tree
Hide file tree
Showing 33 changed files with 384 additions and 407 deletions.
84 changes: 69 additions & 15 deletions bsd/dev/dtrace/dtrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,8 @@ int dtrace_destructive_disallow = 0;
dtrace_optval_t dtrace_nonroot_maxsize = (16 * 1024 * 1024);
size_t dtrace_difo_maxsize = (256 * 1024);
dtrace_optval_t dtrace_dof_maxsize = (384 * 1024);
size_t dtrace_global_maxsize = (16 * 1024);
dtrace_optval_t dtrace_statvar_maxsize = (16 * 1024);
dtrace_optval_t dtrace_statvar_maxsize_max = (16 * 10 * 1024);
size_t dtrace_actions_max = (16 * 1024);
size_t dtrace_retain_max = 1024;
dtrace_optval_t dtrace_helper_actions_max = 32;
Expand Down Expand Up @@ -718,7 +719,7 @@ SYSCTL_PROC(_kern_dtrace, OID_AUTO, dof_maxsize,
sysctl_dtrace_dof_maxsize, "Q", "dtrace dof maxsize");

static int
sysctl_dtrace_global_maxsize SYSCTL_HANDLER_ARGS
sysctl_dtrace_statvar_maxsize SYSCTL_HANDLER_ARGS
{
#pragma unused(oidp, arg2, req)
int changed, error;
Expand All @@ -730,9 +731,11 @@ sysctl_dtrace_global_maxsize SYSCTL_HANDLER_ARGS

if (value <= 0)
return (ERANGE);
if (value > dtrace_statvar_maxsize_max)
return (ERANGE);

lck_mtx_lock(&dtrace_lock);
dtrace_global_maxsize = value;
dtrace_statvar_maxsize = value;
lck_mtx_unlock(&dtrace_lock);

return (0);
Expand All @@ -741,14 +744,14 @@ sysctl_dtrace_global_maxsize SYSCTL_HANDLER_ARGS
/*
* kern.dtrace.global_maxsize
*
* Set the global variable max size in bytes, check the definition of
* dtrace_global_maxsize to get the default value. Attempting to set a null or
* negative size will result in a failure.
* Set the variable max size in bytes, check the definition of
* dtrace_statvar_maxsize to get the default value. Attempting to set a null,
* too high or negative size will result in a failure.
*/
SYSCTL_PROC(_kern_dtrace, OID_AUTO, global_maxsize,
CTLTYPE_QUAD | CTLFLAG_RW | CTLFLAG_LOCKED,
&dtrace_global_maxsize, 0,
sysctl_dtrace_global_maxsize, "Q", "dtrace global maxsize");
&dtrace_statvar_maxsize, 0,
sysctl_dtrace_statvar_maxsize, "Q", "dtrace statvar maxsize");

static int
sysctl_dtrace_provide_private_probes SYSCTL_HANDLER_ARGS
Expand Down Expand Up @@ -882,12 +885,33 @@ dtrace_canstore_statvar(uint64_t addr, size_t sz,
{
int i;

size_t maxglobalsize, maxlocalsize;

maxglobalsize = dtrace_statvar_maxsize;
maxlocalsize = (maxglobalsize + sizeof (uint64_t)) * NCPU;

if (nsvars == 0)
return (0);

for (i = 0; i < nsvars; i++) {
dtrace_statvar_t *svar = svars[i];
uint8_t scope;
size_t size;

if (svar == NULL || svar->dtsv_size == 0)
if (svar == NULL || (size = svar->dtsv_size) == 0)
continue;

scope = svar->dtsv_var.dtdv_scope;

/**
* We verify that our size is valid in the spirit of providing
* defense in depth: we want to prevent attackers from using
* DTrace to escalate an orthogonal kernel heap corruption bug
* into the ability to store to arbitrary locations in memory.
*/
VERIFY((scope == DIFV_SCOPE_GLOBAL && size < maxglobalsize) ||
(scope == DIFV_SCOPE_LOCAL && size < maxlocalsize));

if (DTRACE_INRANGE(addr, sz, svar->dtsv_data, svar->dtsv_size))
return (1);
}
Expand Down Expand Up @@ -3698,7 +3722,8 @@ dtrace_dif_subr(uint_t subr, uint_t rd, uint64_t *regs,

if (!dtrace_destructive_disallow &&
dtrace_priv_proc_control(state) &&
!dtrace_istoxic(kaddr, size)) {
!dtrace_istoxic(kaddr, size) &&
dtrace_canload(kaddr, size, mstate, vstate)) {
DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
dtrace_copyout(kaddr, uaddr, size, flags);
DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
Expand All @@ -3713,7 +3738,8 @@ dtrace_dif_subr(uint_t subr, uint_t rd, uint64_t *regs,

if (!dtrace_destructive_disallow &&
dtrace_priv_proc_control(state) &&
!dtrace_istoxic(kaddr, size)) {
!dtrace_istoxic(kaddr, size) &&
dtrace_strcanload(kaddr, size, mstate, vstate)) {
DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
dtrace_copyoutstr(kaddr, uaddr, size, flags);
DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
Expand Down Expand Up @@ -5340,6 +5366,10 @@ dtrace_dif_emulate(dtrace_difo_t *difo, dtrace_mstate_t *mstate,
regs[r2] ? regs[r2] :
dtrace_strsize_default) + 1;
} else {
if (regs[r2] > LONG_MAX) {
*flags |= CPU_DTRACE_ILLOP;
break;
}
tupregs[ttop].dttk_size = regs[r2];
}

Expand Down Expand Up @@ -8799,9 +8829,10 @@ dtrace_difo_validate(dtrace_difo_t *dp, dtrace_vstate_t *vstate, uint_t nregs,
break;
}

if (v->dtdv_scope == DIFV_SCOPE_GLOBAL &&
vt->dtdt_size > dtrace_global_maxsize) {
err += efunc(i, "oversized by-ref global\n");
if ((v->dtdv_scope == DIFV_SCOPE_GLOBAL ||
v->dtdv_scope == DIFV_SCOPE_LOCAL) &&
vt->dtdt_size > dtrace_statvar_maxsize) {
err += efunc(i, "oversized by-ref static\n");
break;
}
}
Expand Down Expand Up @@ -9137,6 +9168,9 @@ dtrace_difo_chunksize(dtrace_difo_t *dp, dtrace_vstate_t *vstate)
if (srd == 0)
return;

if (sval > LONG_MAX)
return;

tupregs[ttop++].dttk_size = sval;
}

Expand Down Expand Up @@ -9198,6 +9232,19 @@ dtrace_difo_chunksize(dtrace_difo_t *dp, dtrace_vstate_t *vstate)
*/
size = P2ROUNDUP(size, sizeof (uint64_t));

/*
* Before setting the chunk size, check that we're not going
* to set it to a negative value...
*/
if (size > LONG_MAX)
return;

/*
* ...and make certain that we didn't badly overflow.
*/
if (size < ksize || size < sizeof (dtrace_dynvar_t))
return;

if (size > vstate->dtvs_dynvars.dtds_chunksize)
vstate->dtvs_dynvars.dtds_chunksize = size;
}
Expand Down Expand Up @@ -12542,6 +12589,8 @@ dtrace_dstate_init(dtrace_dstate_t *dstate, size_t size)
if ((dstate->dtds_chunksize = chunksize) == 0)
dstate->dtds_chunksize = DTRACE_DYNVAR_CHUNKSIZE;

VERIFY(dstate->dtds_chunksize < (LONG_MAX - sizeof (dtrace_dynhash_t)));

if (size < (min_size = dstate->dtds_chunksize + sizeof (dtrace_dynhash_t)))
size = min_size;

Expand Down Expand Up @@ -12582,6 +12631,9 @@ dtrace_dstate_init(dtrace_dstate_t *dstate, size_t size)
((uintptr_t)base + hashsize * sizeof (dtrace_dynhash_t));
limit = (uintptr_t)base + size;

VERIFY((uintptr_t)start < limit);
VERIFY((uintptr_t)start >= (uintptr_t)base);

maxper = (limit - (uintptr_t)start) / (int)NCPU;
maxper = (maxper / dstate->dtds_chunksize) * dstate->dtds_chunksize;

Expand All @@ -12603,7 +12655,7 @@ dtrace_dstate_init(dtrace_dstate_t *dstate, size_t size)
start = (dtrace_dynvar_t *)limit;
}

ASSERT(limit <= (uintptr_t)base + size);
VERIFY(limit <= (uintptr_t)base + size);

for (;;) {
next = (dtrace_dynvar_t *)((uintptr_t)dvar +
Expand All @@ -12612,6 +12664,8 @@ dtrace_dstate_init(dtrace_dstate_t *dstate, size_t size)
if ((uintptr_t)next + dstate->dtds_chunksize >= limit)
break;

VERIFY((uintptr_t)dvar >= (uintptr_t)base &&
(uintptr_t)dvar <= (uintptr_t)base + size);
dvar->dtdv_next = next;
dvar = next;
}
Expand Down
23 changes: 19 additions & 4 deletions bsd/hfs/hfs_catalog.c
Original file line number Diff line number Diff line change
Expand Up @@ -3057,6 +3057,7 @@ cat_getentriesattr(struct hfsmount *hfsmp, directoryhint_t *dirhint, struct cat_
}

#define SMALL_DIRENTRY_SIZE (int)(sizeof(struct dirent) - (MAXNAMLEN + 1) + 8)
#define MAX_LINKINFO_ENTRIES 3000

/*
* Callback to pack directory entries.
Expand Down Expand Up @@ -3523,12 +3524,13 @@ cat_getdirentries(struct hfsmount *hfsmp, u_int32_t entrycnt, directoryhint_t *d
struct packdirentry_state state;
void * buffer;
int bufsize;

int maxlinks;
int result;
int index;
int have_key;
int extended;

extended = flags & VNODE_READDIR_EXTENDED;

if (extended && (hfsmp->hfs_flags & HFS_STANDARD)) {
Expand All @@ -3537,10 +3539,23 @@ cat_getdirentries(struct hfsmount *hfsmp, u_int32_t entrycnt, directoryhint_t *d
fcb = hfsmp->hfs_catalog_cp->c_datafork;

/*
* Get a buffer for link info array, btree iterator and a direntry:
* Get a buffer for link info array, btree iterator and a direntry.
*
* We impose an cap of 3000 link entries when trying to compute
* the total number of hardlink entries that we'll allow in the
* linkinfo array.
*
* Note that in the case where there are very few hardlinks,
* this does not restrict or prevent us from vending out as many entries
* as we can to the uio_resid, because the getdirentries callback
* uiomoves the directory entries to the uio itself and does not use
* this MALLOC'd array. It also limits itself to maxlinks of hardlinks.
*/
maxlinks = MIN(entrycnt, (u_int32_t)(uio_resid(uio) / SMALL_DIRENTRY_SIZE));
bufsize = MAXPATHLEN + (maxlinks * sizeof(linkinfo_t)) + sizeof(*iterator);

/* Now compute the maximum link array size */
maxlinks = MIN (entrycnt, MAX_LINKINFO_ENTRIES);

bufsize = MAXPATHLEN + (maxlinks * sizeof(linkinfo_t)) + sizeof(*iterator);
if (extended) {
bufsize += 2*sizeof(struct direntry);
}
Expand Down
2 changes: 1 addition & 1 deletion bsd/hfs/hfs_vfsutils.c
Original file line number Diff line number Diff line change
Expand Up @@ -3844,7 +3844,7 @@ hfs_generate_document_id(struct hfsmount *hfsmp, uint32_t *docid)
struct FndrExtendedDirInfo *extinfo = (struct FndrExtendedDirInfo *)((void *)((char *)&cp->c_attr.ca_finderinfo + 16));

int lockflags;
if (hfs_start_transaction(hfsmp) != 0) {
if ((error = hfs_start_transaction(hfsmp)) != 0) {
return error;
}
lockflags = hfs_systemfile_lock(hfsmp, SFL_CATALOG, HFS_EXCLUSIVE_LOCK);
Expand Down
2 changes: 2 additions & 0 deletions bsd/kern/kern_exit.c
Original file line number Diff line number Diff line change
Expand Up @@ -1372,13 +1372,15 @@ reap_child_locked(proc_t parent, proc_t child, int deadparent, int reparentedtoi
#if CONFIG_FINE_LOCK_GROUPS
lck_mtx_destroy(&child->p_mlock, proc_mlock_grp);
lck_mtx_destroy(&child->p_fdmlock, proc_fdmlock_grp);
lck_mtx_destroy(&child->p_ucred_mlock, proc_ucred_mlock_grp);
#if CONFIG_DTRACE
lck_mtx_destroy(&child->p_dtrace_sprlock, proc_lck_grp);
#endif
lck_spin_destroy(&child->p_slock, proc_slock_grp);
#else /* CONFIG_FINE_LOCK_GROUPS */
lck_mtx_destroy(&child->p_mlock, proc_lck_grp);
lck_mtx_destroy(&child->p_fdmlock, proc_lck_grp);
lck_mtx_destroy(&child->p_ucred_mlock, proc_lck_grp);
#if CONFIG_DTRACE
lck_mtx_destroy(&child->p_dtrace_sprlock, proc_lck_grp);
#endif
Expand Down
31 changes: 31 additions & 0 deletions bsd/kern/kern_fork.c
Original file line number Diff line number Diff line change
Expand Up @@ -1047,6 +1047,15 @@ cloneproc(task_t parent_task, coalition_t *parent_coalitions, proc_t parent_proc
void
forkproc_free(proc_t p)
{
#if CONFIG_PERSONAS
persona_proc_drop(p);
#endif /* CONFIG_PERSONAS */

#if PSYNCH
pth_proc_hashdelete(p);
#endif /* PSYNCH */

workqueue_destroy_lock(p);

/* We held signal and a transition locks; drop them */
proc_signalend(p, 0);
Expand Down Expand Up @@ -1091,12 +1100,34 @@ forkproc_free(proc_t p)
/* Update the audit session proc count */
AUDIT_SESSION_PROCEXIT(p);

#if CONFIG_FINE_LOCK_GROUPS
lck_mtx_destroy(&p->p_mlock, proc_mlock_grp);
lck_mtx_destroy(&p->p_fdmlock, proc_fdmlock_grp);
lck_mtx_destroy(&p->p_ucred_mlock, proc_ucred_mlock_grp);
#if CONFIG_DTRACE
lck_mtx_destroy(&p->p_dtrace_sprlock, proc_lck_grp);
#endif
lck_spin_destroy(&p->p_slock, proc_slock_grp);
#else /* CONFIG_FINE_LOCK_GROUPS */
lck_mtx_destroy(&p->p_mlock, proc_lck_grp);
lck_mtx_destroy(&p->p_fdmlock, proc_lck_grp);
lck_mtx_destroy(&p->p_ucred_mlock, proc_lck_grp);
#if CONFIG_DTRACE
lck_mtx_destroy(&p->p_dtrace_sprlock, proc_lck_grp);
#endif
lck_spin_destroy(&p->p_slock, proc_lck_grp);
#endif /* CONFIG_FINE_LOCK_GROUPS */

/* Release the credential reference */
kauth_cred_unref(&p->p_ucred);

proc_list_lock();
/* Decrement the count of processes in the system */
nprocs--;

/* Take it out of process hash */
LIST_REMOVE(p, p_hash);

proc_list_unlock();

thread_call_free(p->p_rcall);
Expand Down
5 changes: 5 additions & 0 deletions bsd/kern/sys_generic.c
Original file line number Diff line number Diff line change
Expand Up @@ -3163,6 +3163,9 @@ ledger(struct proc *p, struct ledger_args *args, __unused int32_t *retval)
else if (args->cmd == LEDGER_LIMIT)
error = copyin(args->arg2, (char *)&lla, sizeof (lla));
#endif
else if ((args->cmd < 0) || (args->cmd > LEDGER_MAX_CMD))
return (EINVAL);

if (error)
return (error);
if (len < 0)
Expand Down Expand Up @@ -3239,6 +3242,8 @@ ledger(struct proc *p, struct ledger_args *args, __unused int32_t *retval)
}

default:
panic("ledger syscall logic error -- command type %d", args->cmd);
proc_rele(proc);
rval = EINVAL;
}

Expand Down
4 changes: 4 additions & 0 deletions bsd/net/route.h
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ struct route {
* gateway rather than the ultimate destination.
*/

#define NRTT_HIST 10
/*
* Kernel routing entry structure.
*/
Expand Down Expand Up @@ -205,6 +206,9 @@ struct rtentry {
uint64_t rt_expire; /* expiration time in uptime seconds */
uint64_t base_calendartime; /* calendar time upon entry creation */
uint64_t base_uptime; /* uptime upon entry creation */
u_int32_t rtt_hist[NRTT_HIST]; /* RTT history sample by TCP connections */
u_int32_t rtt_expire_ts; /* RTT history expire timestamp */
u_int8_t rtt_index; /* Index into RTT history */
};

/*
Expand Down
Loading

0 comments on commit 0ed26c3

Please sign in to comment.