diff options
author | jhb <jhb@FreeBSD.org> | 2009-03-11 21:48:36 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2009-03-11 21:48:36 +0000 |
commit | 2548f05c6c8be3fe53f4191e634699bb4fa4c56b (patch) | |
tree | 48083c4fab749cb8da99377a83f7d470672d4c2c | |
parent | de74558fd8fae07358ec61b9001d0a7590bb9d22 (diff) | |
download | FreeBSD-src-2548f05c6c8be3fe53f4191e634699bb4fa4c56b.zip FreeBSD-src-2548f05c6c8be3fe53f4191e634699bb4fa4c56b.tar.gz |
Add a new type of KTRACE record for sysctl(3) invocations. It uses the
internal sysctl_sysctl_name() handler to map the MIB array to a string
name and logs this name in the trace log. This can be useful to see
exactly which sysctls a thread is invoking.
MFC after: 1 month
-rw-r--r-- | sys/kern/kern_ktrace.c | 40 | ||||
-rw-r--r-- | sys/kern/kern_sysctl.c | 11 | ||||
-rw-r--r-- | sys/sys/ktrace.h | 9 | ||||
-rw-r--r-- | usr.bin/kdump/kdump.1 | 1 | ||||
-rw-r--r-- | usr.bin/kdump/kdump.c | 4 | ||||
-rw-r--r-- | usr.bin/ktrace/ktrace.1 | 4 | ||||
-rw-r--r-- | usr.bin/ktrace/ktrace.h | 3 | ||||
-rw-r--r-- | usr.bin/ktrace/subr.c | 3 |
8 files changed, 72 insertions, 3 deletions
diff --git a/sys/kern/kern_ktrace.c b/sys/kern/kern_ktrace.c index f4304de..6ccf2c0 100644 --- a/sys/kern/kern_ktrace.c +++ b/sys/kern/kern_ktrace.c @@ -111,6 +111,7 @@ static int data_lengths[] = { sizeof(struct ktr_csw), /* KTR_CSW */ 0, /* KTR_USER */ 0, /* KTR_STRUCT */ + 0, /* KTR_SYSCTL */ }; static STAILQ_HEAD(, ktr_request) ktr_free; @@ -319,7 +320,7 @@ ktr_enqueuerequest(struct thread *td, struct ktr_request *req) * is used both internally before committing other records, and also on * system call return. We drain all the ones we can find at the time when * drain is requested, but don't keep draining after that as those events - * may me approximately "after" the current event. + * may be approximately "after" the current event. */ static void ktr_drain(struct thread *td) @@ -481,6 +482,40 @@ ktrnamei(path) } void +ktrsysctl(name, namelen) + int *name; + u_int namelen; +{ + struct ktr_request *req; + u_int mib[CTL_MAXNAME + 2]; + char *mibname; + size_t mibnamelen; + int error; + + /* Lookup name of mib. */ + KASSERT(namelen <= CTL_MAXNAME, ("sysctl MIB too long")); + mib[0] = 0; + mib[1] = 1; + bcopy(name, mib + 2, namelen * sizeof(*name)); + mibnamelen = 128; + mibname = malloc(mibnamelen, M_KTRACE, M_WAITOK); + error = kernel_sysctl(curthread, mib, namelen + 2, mibname, &mibnamelen, + NULL, 0, &mibnamelen, 0); + if (error) { + free(mibname, M_KTRACE); + return; + } + req = ktr_getrequest(KTR_SYSCTL); + if (req == NULL) { + free(mibname, M_KTRACE); + return; + } + req->ktr_header.ktr_len = mibnamelen; + req->ktr_buffer = mibname; + ktr_submitrequest(curthread, req); +} + +void ktrgenio(fd, rw, uio, error) int fd; enum uio_rw rw; @@ -925,6 +960,9 @@ ktr_writerequest(struct thread *td, struct ktr_request *req) mtx_unlock(&ktrace_mtx); kth = &req->ktr_header; + KASSERT(((u_short)kth->ktr_type & ~KTR_DROP) < + sizeof(data_lengths) / sizeof(data_lengths[0]), + ("data_lengths array overflow")); datalen = data_lengths[(u_short)kth->ktr_type & ~KTR_DROP]; buflen = kth->ktr_len; auio.uio_iov = &aiov[0]; diff --git a/sys/kern/kern_sysctl.c b/sys/kern/kern_sysctl.c index 1d283df..d39db26 100644 --- a/sys/kern/kern_sysctl.c +++ b/sys/kern/kern_sysctl.c @@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$"); #include "opt_compat.h" +#include "opt_ktrace.h" #include "opt_mac.h" #include <sys/param.h> @@ -54,6 +55,9 @@ __FBSDID("$FreeBSD$"); #include <sys/sysproto.h> #include <sys/uio.h> #include <sys/vimage.h> +#ifdef KTRACE +#include <sys/ktrace.h> +#endif #include <security/mac/mac_framework.h> @@ -758,7 +762,7 @@ sysctl_sysctl_next(SYSCTL_HANDLER_ARGS) static SYSCTL_NODE(_sysctl, 2, next, CTLFLAG_RD, sysctl_sysctl_next, ""); static int -name2oid (char *name, int *oid, int *len, struct sysctl_oid **oidpp) +name2oid(char *name, int *oid, int *len, struct sysctl_oid **oidpp) { int i; struct sysctl_oid *oidp; @@ -1499,6 +1503,11 @@ userland_sysctl(struct thread *td, int *name, u_int namelen, void *old, req.newfunc = sysctl_new_user; req.lock = REQ_LOCKED; +#ifdef KTRACE + if (KTRPOINT(curthread, KTR_SYSCTL)) + ktrsysctl(name, namelen); +#endif + SYSCTL_XLOCK(); CURVNET_SET(TD_TO_VNET(curthread)); diff --git a/sys/sys/ktrace.h b/sys/sys/ktrace.h index cf9f977..8aedac1 100644 --- a/sys/sys/ktrace.h +++ b/sys/sys/ktrace.h @@ -158,6 +158,12 @@ struct sockaddr; struct stat; /* + * KTR_SYSCTL - name of a sysctl MIB + */ +#define KTR_SYSCTL 9 + /* record contains null-terminated MIB name */ + +/* * KTR_DROP - If this bit is set in ktr_type, then at least one event * between the previous record and this record was dropped. */ @@ -175,6 +181,8 @@ struct stat; #define KTRFAC_CSW (1<<KTR_CSW) #define KTRFAC_USER (1<<KTR_USER) #define KTRFAC_STRUCT (1<<KTR_STRUCT) +#define KTRFAC_SYSCTL (1<<KTR_SYSCTL) + /* * trace flags (also in p_traceflags) */ @@ -190,6 +198,7 @@ void ktrcsw(int, int); void ktrpsig(int, sig_t, sigset_t *, int); void ktrgenio(int, enum uio_rw, struct uio *, int); void ktrsyscall(int, int narg, register_t args[]); +void ktrsysctl(int *name, u_int namelen); void ktrsysret(int, int, register_t); void ktrprocexit(struct thread *); void ktruserret(struct thread *); diff --git a/usr.bin/kdump/kdump.1 b/usr.bin/kdump/kdump.1 index 34b5bd4..b5e313b 100644 --- a/usr.bin/kdump/kdump.1 +++ b/usr.bin/kdump/kdump.1 @@ -172,6 +172,7 @@ The possible operations are: .It Li CSW Ta context switch Ta stop/resume user/kernel .It Li USER Ta data from user process Ta the data .It Li STRU Ta various syscalls Ta structure +.It Li SCTL Ta Xr sysctl 3 requests Ta MIB name .El .Sh SEE ALSO .Xr ktrace 1 diff --git a/usr.bin/kdump/kdump.c b/usr.bin/kdump/kdump.c index 72afdc8..079d272 100644 --- a/usr.bin/kdump/kdump.c +++ b/usr.bin/kdump/kdump.c @@ -217,6 +217,7 @@ main(int argc, char *argv[]) ktrsysret((struct ktr_sysret *)m); break; case KTR_NAMEI: + case KTR_SYSCTL: ktrnamei(m, ktrlen); break; case KTR_GENIO: @@ -288,6 +289,9 @@ dumpheader(struct ktr_header *kth) case KTR_STRUCT: type = "STRU"; break; + case KTR_SYSCTL: + type = "SCTL"; + break; default: (void)sprintf(unknown, "UNKNOWN(%d)", kth->ktr_type); type = unknown; diff --git a/usr.bin/ktrace/ktrace.1 b/usr.bin/ktrace/ktrace.1 index 83c80c9..88e80a2 100644 --- a/usr.bin/ktrace/ktrace.1 +++ b/usr.bin/ktrace/ktrace.1 @@ -125,6 +125,10 @@ trace various structures userland traces .It Cm w context switches +.It Cm y +trace +.Xr sysctl 3 +requests .It Cm + trace the default set of trace points - .Cm c , n , i , s , t , u diff --git a/usr.bin/ktrace/ktrace.h b/usr.bin/ktrace/ktrace.h index 51d85ee..e8f4d0b 100644 --- a/usr.bin/ktrace/ktrace.h +++ b/usr.bin/ktrace/ktrace.h @@ -35,7 +35,8 @@ */ #define DEF_POINTS (KTRFAC_SYSCALL | KTRFAC_SYSRET | KTRFAC_NAMEI | \ - KTRFAC_GENIO | KTRFAC_PSIG | KTRFAC_USER | KTRFAC_STRUCT) + KTRFAC_GENIO | KTRFAC_PSIG | KTRFAC_USER | \ + KTRFAC_STRUCT | KTRFAC_SYSCTL) #define ALL_POINTS (DEF_POINTS | KTRFAC_CSW) diff --git a/usr.bin/ktrace/subr.c b/usr.bin/ktrace/subr.c index cfc4f3a..a9d3f64 100644 --- a/usr.bin/ktrace/subr.c +++ b/usr.bin/ktrace/subr.c @@ -83,6 +83,9 @@ getpoints(char *s) case 'w': facs |= KTRFAC_CSW; break; + case 'y': + facs |= KTRFAC_SYSCTL; + break; case '+': facs |= DEF_POINTS; break; |