version 1.128.4.2, 2007/12/27 00:45:59 |
version 1.128.4.3, 2008/02/18 21:06:45 |
|
|
ktefree(struct ktrace_entry *kte) |
ktefree(struct ktrace_entry *kte) |
{ |
{ |
|
|
KERNEL_LOCK(1, curlwp); /* XXXSMP */ |
|
if (kte->kte_buf != kte->kte_space) |
if (kte->kte_buf != kte->kte_space) |
kmem_free(kte->kte_buf, kte->kte_bufsz); |
kmem_free(kte->kte_buf, kte->kte_bufsz); |
pool_put(&kte_pool, kte); |
pool_put(&kte_pool, kte); |
KERNEL_UNLOCK_ONE(curlwp); /* XXXSMP */ |
|
} |
} |
|
|
/* |
/* |
Line 500 ktealloc(struct ktrace_entry **ktep, voi |
|
Line 498 ktealloc(struct ktrace_entry **ktep, voi |
|
if (ktrenter(l)) |
if (ktrenter(l)) |
return EAGAIN; |
return EAGAIN; |
|
|
KERNEL_LOCK(1, l); /* XXXSMP */ |
|
kte = pool_get(&kte_pool, PR_WAITOK); |
kte = pool_get(&kte_pool, PR_WAITOK); |
if (sz > sizeof(kte->kte_space)) { |
if (sz > sizeof(kte->kte_space)) { |
if ((buf = kmem_alloc(sz, KM_SLEEP)) == NULL) { |
if ((buf = kmem_alloc(sz, KM_SLEEP)) == NULL) { |
pool_put(&kte_pool, kte); |
pool_put(&kte_pool, kte); |
KERNEL_UNLOCK_ONE(l); /* XXXSMP */ |
|
ktrexit(l); |
ktrexit(l); |
return ENOMEM; |
return ENOMEM; |
} |
} |
} else |
} else |
buf = kte->kte_space; |
buf = kte->kte_space; |
KERNEL_UNLOCK_ONE(l); /* XXXSMP */ |
|
|
|
kte->kte_bufsz = sz; |
kte->kte_bufsz = sz; |
kte->kte_buf = buf; |
kte->kte_buf = buf; |
Line 544 ktealloc(struct ktrace_entry **ktep, voi |
|
Line 539 ktealloc(struct ktrace_entry **ktep, voi |
|
} |
} |
|
|
void |
void |
ktr_syscall(register_t code, register_t realcode, |
ktr_syscall(register_t code, const register_t args[], int narg) |
const struct sysent *callp, const register_t args[]) |
|
{ |
{ |
lwp_t *l = curlwp; |
lwp_t *l = curlwp; |
struct proc *p = l->l_proc; |
struct proc *p = l->l_proc; |
struct ktrace_entry *kte; |
struct ktrace_entry *kte; |
struct ktr_syscall *ktp; |
struct ktr_syscall *ktp; |
register_t *argp; |
register_t *argp; |
int argsize; |
|
size_t len; |
size_t len; |
u_int i; |
u_int i; |
|
|
if (!KTRPOINT(p, KTR_SYSCALL)) |
if (!KTRPOINT(p, KTR_SYSCALL)) |
return; |
return; |
|
|
if (callp == NULL) |
len = sizeof(struct ktr_syscall) + narg * sizeof argp[0]; |
callp = p->p_emul->e_sysent; |
|
|
|
argsize = callp[code].sy_argsize; |
|
#ifdef _LP64 |
|
if (p->p_flag & PK_32) |
|
argsize = argsize << 1; |
|
#endif |
|
len = sizeof(struct ktr_syscall) + argsize; |
|
|
|
if (ktealloc(&kte, (void *)&ktp, l, KTR_SYSCALL, len)) |
if (ktealloc(&kte, (void *)&ktp, l, KTR_SYSCALL, len)) |
return; |
return; |
|
|
ktp->ktr_code = realcode; |
ktp->ktr_code = code; |
ktp->ktr_argsize = argsize; |
ktp->ktr_argsize = narg * sizeof argp[0]; |
argp = (register_t *)(ktp + 1); |
argp = (register_t *)(ktp + 1); |
for (i = 0; i < (argsize / sizeof(*argp)); i++) |
for (i = 0; i < narg; i++) |
*argp++ = args[i]; |
*argp++ = args[i]; |
|
|
ktraddentry(l, kte, KTA_WAITOK); |
ktraddentry(l, kte, KTA_WAITOK); |
Line 1034 ktrace_common(lwp_t *curl, int ops, int |
|
Line 1019 ktrace_common(lwp_t *curl, int ops, int |
|
|
|
curp = curl->l_proc; |
curp = curl->l_proc; |
descend = ops & KTRFLAG_DESCEND; |
descend = ops & KTRFLAG_DESCEND; |
facs = facs & ~((unsigned) KTRFAC_ROOT); |
facs = facs & ~((unsigned) KTRFAC_PERSISTENT); |
|
|
(void)ktrenter(curl); |
(void)ktrenter(curl); |
|
|
Line 1059 ktrace_common(lwp_t *curl, int ops, int |
|
Line 1044 ktrace_common(lwp_t *curl, int ops, int |
|
if (ktd == NULL) { |
if (ktd == NULL) { |
ktd = kmem_alloc(sizeof(*ktd), KM_SLEEP); |
ktd = kmem_alloc(sizeof(*ktd), KM_SLEEP); |
TAILQ_INIT(&ktd->ktd_queue); |
TAILQ_INIT(&ktd->ktd_queue); |
callout_init(&ktd->ktd_wakch, 0); |
callout_init(&ktd->ktd_wakch, CALLOUT_MPSAFE); |
cv_init(&ktd->ktd_cv, "ktrwait"); |
cv_init(&ktd->ktd_cv, "ktrwait"); |
cv_init(&ktd->ktd_sync_cv, "ktrsync"); |
cv_init(&ktd->ktd_sync_cv, "ktrsync"); |
ktd->ktd_flags = 0; |
ktd->ktd_flags = 0; |
Line 1081 ktrace_common(lwp_t *curl, int ops, int |
|
Line 1066 ktrace_common(lwp_t *curl, int ops, int |
|
if (fp->f_type == DTYPE_PIPE) |
if (fp->f_type == DTYPE_PIPE) |
ktd->ktd_flags |= KTDF_INTERACTIVE; |
ktd->ktd_flags |= KTDF_INTERACTIVE; |
|
|
error = kthread_create(PRI_NONE, 0, NULL, |
error = kthread_create(PRI_NONE, KTHREAD_MPSAFE, NULL, |
ktrace_thread, ktd, &ktd->ktd_lwp, "ktrace"); |
ktrace_thread, ktd, &ktd->ktd_lwp, "ktrace"); |
if (error != 0) { |
if (error != 0) { |
kmem_free(ktd, sizeof(*ktd)); |
kmem_free(ktd, sizeof(*ktd)); |
goto done; |
goto done; |
} |
} |
|
|
mutex_enter(&fp->f_lock); |
FILE_LOCK(fp); |
fp->f_count++; |
fp->f_count++; |
mutex_exit(&fp->f_lock); |
FILE_UNLOCK(fp); |
ktd->ktd_fp = fp; |
ktd->ktd_fp = fp; |
|
|
mutex_enter(&ktrace_lock); |
mutex_enter(&ktrace_lock); |
Line 1311 ktrops(lwp_t *curl, struct proc *p, int |
|
Line 1296 ktrops(lwp_t *curl, struct proc *p, int |
|
ktradref(p); |
ktradref(p); |
} |
} |
p->p_traceflag |= facs; |
p->p_traceflag |= facs; |
if (kauth_authorize_generic(curl->l_cred, |
if (kauth_authorize_process(curl->l_cred, KAUTH_PROCESS_KTRACE, |
KAUTH_GENERIC_ISSUSER, NULL) == 0) |
p, KAUTH_ARG(KAUTH_REQ_PROCESS_KTRACE_PERSISTENT), NULL, |
p->p_traceflag |= KTRFAC_ROOT; |
NULL) == 0) |
|
p->p_traceflag |= KTRFAC_PERSISTENT; |
} else { |
} else { |
/* KTROP_CLEAR */ |
/* KTROP_CLEAR */ |
if (((p->p_traceflag &= ~facs) & KTRFAC_MASK) == 0) { |
if (((p->p_traceflag &= ~facs) & KTRFAC_MASK) == 0) { |
|
|
auio.uio_iovcnt < sizeof(aiov) / sizeof(aiov[0]) - 1); |
auio.uio_iovcnt < sizeof(aiov) / sizeof(aiov[0]) - 1); |
|
|
again: |
again: |
mutex_enter(&fp->f_lock); |
FILE_LOCK(fp); |
FILE_USE(fp); |
FILE_USE(fp); |
error = (*fp->f_ops->fo_write)(fp, &fp->f_offset, &auio, |
error = (*fp->f_ops->fo_write)(fp, &fp->f_offset, &auio, |
fp->f_cred, FOF_UPDATE_OFFSET); |
fp->f_cred, FOF_UPDATE_OFFSET); |
Line 1494 ktrace_thread(void *arg) |
|
Line 1480 ktrace_thread(void *arg) |
|
TAILQ_REMOVE(&ktdq, ktd, ktd_list); |
TAILQ_REMOVE(&ktdq, ktd, ktd_list); |
mutex_exit(&ktrace_lock); |
mutex_exit(&ktrace_lock); |
|
|
mutex_enter(&fp->f_lock); |
FILE_LOCK(fp); |
FILE_USE(fp); |
FILE_USE(fp); |
|
|
/* |
/* |
Line 1515 ktrace_thread(void *arg) |
|
Line 1501 ktrace_thread(void *arg) |
|
/* |
/* |
* Return true if caller has permission to set the ktracing state |
* Return true if caller has permission to set the ktracing state |
* of target. Essentially, the target can't possess any |
* of target. Essentially, the target can't possess any |
* more permissions than the caller. KTRFAC_ROOT signifies that |
* more permissions than the caller. KTRFAC_PERSISTENT signifies that |
* root previously set the tracing status on the target process, and |
* the tracing will persist on sugid processes during exec; it is only |
* so, only root may further change it. |
* settable by a process with appropriate credentials. |
* |
* |
* TODO: check groups. use caller effective gid. |
* TODO: check groups. use caller effective gid. |
*/ |
*/ |
Line 1527 ktrcanset(lwp_t *calll, struct proc *tar |
|
Line 1513 ktrcanset(lwp_t *calll, struct proc *tar |
|
KASSERT(mutex_owned(&targetp->p_mutex)); |
KASSERT(mutex_owned(&targetp->p_mutex)); |
KASSERT(mutex_owned(&ktrace_lock)); |
KASSERT(mutex_owned(&ktrace_lock)); |
|
|
if (kauth_authorize_process(calll->l_cred, KAUTH_PROCESS_CANKTRACE, |
if (kauth_authorize_process(calll->l_cred, KAUTH_PROCESS_KTRACE, |
targetp, NULL, NULL, NULL) == 0) |
targetp, NULL, NULL, NULL) == 0) |
return (1); |
return (1); |
|
|