diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -354,7 +354,11 @@ exec_args_get_begin_envv(args) - args->begin_argv); AUDIT_ARG_ENVV(exec_args_get_begin_envv(args), args->envc, args->endp - exec_args_get_begin_envv(args)); - +#ifdef KTRACE + if (KTRPOINT(td, KTR_EXECVE_ARGS)) { + ktrexecveargs(args); + } +#endif /* Must have at least one argument. */ if (args->argc == 0) { exec_free_args(args); diff --git a/sys/kern/kern_ktrace.c b/sys/kern/kern_ktrace.c --- a/sys/kern/kern_ktrace.c +++ b/sys/kern/kern_ktrace.c @@ -58,6 +58,7 @@ #include #include #include +#include #include @@ -104,6 +105,7 @@ struct ktr_fault ktr_fault; struct ktr_faultend ktr_faultend; struct ktr_struct_array ktr_struct_array; + struct ktr_execve_args ktr_execve_args; } ktr_data; STAILQ_ENTRY(ktr_request) ktr_list; }; @@ -124,6 +126,7 @@ [KTR_FAULT] = sizeof(struct ktr_fault), [KTR_FAULTEND] = sizeof(struct ktr_faultend), [KTR_STRUCT_ARRAY] = sizeof(struct ktr_struct_array), + [KTR_EXECVE_ARGS] = sizeof(struct ktr_execve_args), }; static STAILQ_HEAD(, ktr_request) ktr_free; @@ -559,6 +562,27 @@ ktr_submitrequest(curthread, req); } +void +ktrexecveargs(struct image_args *args) +{ + struct ktr_request *req; + struct ktr_execve_args *ktp; + char *buf; + + buf = malloc(args->endp - args->begin_argv, M_KTRACE, M_WAITOK); + bcopy(args->begin_argv, buf, args->endp - args->begin_argv); + req = ktr_getrequest(KTR_EXECVE_ARGS); + if (req == NULL) { + free(buf, M_KTRACE); + return; + } + ktp = &req->ktr_data.ktr_execve_args; + ktp->envv_offset = exec_args_get_begin_envv(args) - args->begin_argv; + req->ktr_header.ktr_len = args->endp - args->begin_argv; + req->ktr_buffer = buf; + ktr_submitrequest(curthread, req); +} + void ktrsysret(int code, int error, register_t retval) { diff --git a/sys/sys/ktrace.h b/sys/sys/ktrace.h --- a/sys/sys/ktrace.h +++ b/sys/sys/ktrace.h @@ -263,6 +263,11 @@ */ }; +#define KTR_EXECVE_ARGS 16 +struct ktr_execve_args { + size_t envv_offset; +}; + /* * KTR_DROP - If this bit is set in ktr_type, then at least one event * between the previous record and this record was dropped. @@ -295,6 +300,7 @@ #define KTRFAC_FAULT (1<ktr_type); type = unknown; @@ -1646,6 +1653,35 @@ printf("\"%.*s\"\n", len, cp); } +void +ktrexecveargs(struct ktr_execve_args *ktr, int len) +{ + size_t datalen = len - sizeof (struct ktr_execve_args); + char *dp = (char *)ktr + sizeof (struct ktr_execve_args); + size_t i; + + i = 0; + printf("ARGV: "); + while (i < ktr->envv_offset) { + printf("\"%s\"", dp + i); + i += strlen(dp + i) + 1; + if (i != ktr->envv_offset) { + printf(", "); + } + } + printf(" "); + i = ktr->envv_offset; + printf("ENVV: "); + while (i < datalen) { + printf("\"%s\"", dp + i); + i += strlen(dp + i) + 1; + if (i != datalen) { + printf(", "); + } + } + printf("\n"); +} + void hexdump(char *p, int len, int screenwidth) { diff --git a/usr.bin/ktrace/ktrace.h b/usr.bin/ktrace/ktrace.h --- a/usr.bin/ktrace/ktrace.h +++ b/usr.bin/ktrace/ktrace.h @@ -31,7 +31,8 @@ #define DEF_POINTS (KTRFAC_SYSCALL | KTRFAC_SYSRET | KTRFAC_NAMEI | \ KTRFAC_GENIO | KTRFAC_PSIG | KTRFAC_USER | \ - KTRFAC_STRUCT | KTRFAC_SYSCTL | KTRFAC_STRUCT_ARRAY) + KTRFAC_STRUCT | KTRFAC_SYSCTL | KTRFAC_STRUCT_ARRAY | \ + KTRFAC_EXECVE_ARGS) #define PROC_ABI_POINTS (KTRFAC_PROCCTOR | KTRFAC_PROCDTOR) diff --git a/usr.bin/ktrace/ktrace.1 b/usr.bin/ktrace/ktrace.1 --- a/usr.bin/ktrace/ktrace.1 +++ b/usr.bin/ktrace/ktrace.1 @@ -142,6 +142,10 @@ trace .Xr sysctl 3 requests +.It Cm e +trace +.Xr execve 2 +requests .It Cm + trace the default set of trace points - .Cm c , i , n , s , t , u , y diff --git a/usr.bin/ktrace/subr.c b/usr.bin/ktrace/subr.c --- a/usr.bin/ktrace/subr.c +++ b/usr.bin/ktrace/subr.c @@ -81,6 +81,9 @@ case 'y': facs |= KTRFAC_SYSCTL; break; + case 'e': + facs |= KTRFAC_EXECVE_ARGS; + break; case '+': facs |= DEF_POINTS; break;