summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2009-03-11 21:48:36 +0000
committerjhb <jhb@FreeBSD.org>2009-03-11 21:48:36 +0000
commit2548f05c6c8be3fe53f4191e634699bb4fa4c56b (patch)
tree48083c4fab749cb8da99377a83f7d470672d4c2c
parentde74558fd8fae07358ec61b9001d0a7590bb9d22 (diff)
downloadFreeBSD-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.c40
-rw-r--r--sys/kern/kern_sysctl.c11
-rw-r--r--sys/sys/ktrace.h9
-rw-r--r--usr.bin/kdump/kdump.11
-rw-r--r--usr.bin/kdump/kdump.c4
-rw-r--r--usr.bin/ktrace/ktrace.14
-rw-r--r--usr.bin/ktrace/ktrace.h3
-rw-r--r--usr.bin/ktrace/subr.c3
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;
OpenPOWER on IntegriCloud