summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordes <des@FreeBSD.org>2011-10-11 20:37:10 +0000
committerdes <des@FreeBSD.org>2011-10-11 20:37:10 +0000
commit9b8d9b3ed18d6b0c6f881baf309e3935335bc7b1 (patch)
treee9843d4ebf0bc386f58afa84935ecf276f03447c
parent42aa10a9a139809533ee7832f9cdecc8bead877d (diff)
downloadFreeBSD-src-9b8d9b3ed18d6b0c6f881baf309e3935335bc7b1.zip
FreeBSD-src-9b8d9b3ed18d6b0c6f881baf309e3935335bc7b1.tar.gz
Add a new trace point, KTRFAC_CAPFAIL, which traces capability check
failures. It is included in the default set for ktrace(1) and kdump(1).
-rw-r--r--lib/libc/sys/ktrace.27
-rw-r--r--sys/kern/kern_ktrace.c21
-rw-r--r--sys/kern/sys_capability.c10
-rw-r--r--sys/sys/ktrace.h11
-rw-r--r--usr.bin/kdump/kdump.c49
-rw-r--r--usr.bin/ktrace/ktrace.16
-rw-r--r--usr.bin/ktrace/ktrace.h2
-rw-r--r--usr.bin/ktrace/subr.c7
8 files changed, 98 insertions, 15 deletions
diff --git a/lib/libc/sys/ktrace.2 b/lib/libc/sys/ktrace.2
index 08d960d..8ab4a33 100644
--- a/lib/libc/sys/ktrace.2
+++ b/lib/libc/sys/ktrace.2
@@ -28,7 +28,7 @@
.\" @(#)ktrace.2 8.1 (Berkeley) 6/4/93
.\" $FreeBSD$
.\"
-.Dd October 9, 2011
+.Dd October 10, 2011
.Dt KTRACE 2
.Os
.Sh NAME
@@ -67,9 +67,9 @@ The
argument specifies the requested ktrace operation.
The defined operations are:
.Bl -column KTRFLAG_DESCENDXXX -offset indent
-.It "KTROP_SET Enable trace points specified in"
+.It "KTROP_SET Enable trace points specified in"
.Fa trpoints .
-.It "KTROP_CLEAR Disable trace points specified in
+.It "KTROP_CLEAR Disable trace points specified in"
.Fa trpoints .
.It "KTROP_CLEARFILE Stop all tracing."
.It "KTRFLAG_DESCEND The tracing change should apply to the"
@@ -93,6 +93,7 @@ generate much output).
.It "KTRFAC_SYSCTL Trace sysctls."
.It "KTRFAC_PROCCTOR Trace process construction."
.It "KTRFAC_PROCDTOR Trace process destruction."
+.It "KTRFAC_CAPFAIL Trace capability failures."
.It "KTRFAC_INHERIT Inherit tracing to future children."
.El
.Pp
diff --git a/sys/kern/kern_ktrace.c b/sys/kern/kern_ktrace.c
index 0f1ad91..bf99971 100644
--- a/sys/kern/kern_ktrace.c
+++ b/sys/kern/kern_ktrace.c
@@ -95,6 +95,7 @@ struct ktr_request {
void *ktr_buffer;
union {
struct ktr_proc_ctor ktr_proc_ctor;
+ struct ktr_cap_fail ktr_cap_fail;
struct ktr_syscall ktr_syscall;
struct ktr_sysret ktr_sysret;
struct ktr_genio ktr_genio;
@@ -117,6 +118,7 @@ static int data_lengths[] = {
0, /* KTR_SYSCTL */
sizeof(struct ktr_proc_ctor), /* KTR_PROCCTOR */
0, /* KTR_PROCDTOR */
+ sizeof(struct ktr_cap_fail), /* KTR_CAPFAIL */
};
static STAILQ_HEAD(, ktr_request) ktr_free;
@@ -768,6 +770,25 @@ ktrstruct(name, data, datalen)
req->ktr_header.ktr_len = buflen;
ktr_submitrequest(curthread, req);
}
+
+void
+ktrcapfail(needed, held)
+ cap_rights_t needed;
+ cap_rights_t held;
+{
+ struct thread *td = curthread;
+ struct ktr_request *req;
+ struct ktr_cap_fail *kcf;
+
+ req = ktr_getrequest(KTR_CAPFAIL);
+ if (req == NULL)
+ return;
+ kcf = &req->ktr_data.ktr_cap_fail;
+ kcf->cap_needed = needed;
+ kcf->cap_held = held;
+ ktr_enqueuerequest(td, req);
+ ktrace_exit(td);
+}
#endif /* KTRACE */
/* Interface and common routines */
diff --git a/sys/kern/sys_capability.c b/sys/kern/sys_capability.c
index 2318b12..b22cfb2 100644
--- a/sys/kern/sys_capability.c
+++ b/sys/kern/sys_capability.c
@@ -52,6 +52,7 @@
*/
#include "opt_capsicum.h"
+#include "opt_ktrace.h"
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
@@ -68,6 +69,8 @@ __FBSDID("$FreeBSD$");
#include <sys/sysctl.h>
#include <sys/systm.h>
#include <sys/ucred.h>
+#include <sys/uio.h>
+#include <sys/ktrace.h>
#include <security/audit/audit.h>
@@ -212,8 +215,13 @@ static int
cap_check(struct capability *c, cap_rights_t rights)
{
- if ((c->cap_rights | rights) != c->cap_rights)
+ if ((c->cap_rights | rights) != c->cap_rights) {
+#ifdef KTRACE
+ if (KTRPOINT(curthread, KTR_CAPFAIL))
+ ktrcapfail(rights, c->cap_rights);
+#endif
return (ENOTCAPABLE);
+ }
return (0);
}
diff --git a/sys/sys/ktrace.h b/sys/sys/ktrace.h
index edd5c02..592db6f 100644
--- a/sys/sys/ktrace.h
+++ b/sys/sys/ktrace.h
@@ -178,6 +178,15 @@ struct ktr_proc_ctor {
#define KTR_PROCDTOR 11
/*
+ * KTR_CAPFAIL - trace capability check failures
+ */
+#define KTR_CAPFAIL 12
+struct ktr_cap_fail {
+ cap_rights_t cap_needed;
+ cap_rights_t cap_held;
+};
+
+/*
* KTR_DROP - If this bit is set in ktr_type, then at least one event
* between the previous record and this record was dropped.
*/
@@ -198,6 +207,7 @@ struct ktr_proc_ctor {
#define KTRFAC_SYSCTL (1<<KTR_SYSCTL)
#define KTRFAC_PROCCTOR (1<<KTR_PROCCTOR)
#define KTRFAC_PROCDTOR (1<<KTR_PROCDTOR)
+#define KTRFAC_CAPFAIL (1<<KTR_CAPFAIL)
/*
* trace flags (also in p_traceflags)
@@ -220,6 +230,7 @@ void ktrprocexit(struct thread *);
void ktrprocfork(struct proc *, struct proc *);
void ktruserret(struct thread *);
void ktrstruct(const char *, void *, size_t);
+void ktrcapfail(cap_rights_t, cap_rights_t);
#define ktrsockaddr(s) \
ktrstruct("sockaddr", (s), ((struct sockaddr *)(s))->sa_len)
#define ktrstat(s) \
diff --git a/usr.bin/kdump/kdump.c b/usr.bin/kdump/kdump.c
index 7e1c08d..8f2f4db 100644
--- a/usr.bin/kdump/kdump.c
+++ b/usr.bin/kdump/kdump.c
@@ -99,6 +99,7 @@ void ktruser(int, unsigned char *);
void ktrsockaddr(struct sockaddr *);
void ktrstat(struct stat *);
void ktrstruct(char *, size_t);
+void ktrcapfail(struct ktr_cap_fail *);
void usage(void);
void ioctlname(unsigned long, int);
@@ -301,6 +302,8 @@ main(int argc, char *argv[])
case KTR_STRUCT:
ktrstruct(m, ktrlen);
break;
+ case KTR_CAPFAIL:
+ ktrcapfail((struct ktr_cap_fail *)m);
default:
printf("\n");
break;
@@ -440,6 +443,9 @@ dumpheader(struct ktr_header *kth)
/* FALLTHROUGH */
case KTR_PROCDTOR:
return;
+ case KTR_CAPFAIL:
+ type = "CAP ";
+ break;
default:
sprintf(unknown, "UNKNOWN(%d)", kth->ktr_type);
type = unknown;
@@ -488,6 +494,7 @@ ktrsyscall(struct ktr_syscall *ktr, u_int flags)
{
int narg = ktr->ktr_narg;
register_t *ip;
+ intmax_t arg;
if ((flags != 0 && ((flags & SV_ABI_MASK) != SV_ABI_FREEBSD)) ||
(ktr->ktr_code >= nsyscalls || ktr->ktr_code < 0))
@@ -978,12 +985,33 @@ ktrsyscall(struct ktr_syscall *ktr, u_int flags)
ip++;
narg--;
break;
- case SYS_cap_new:
- print_number(ip, narg, c);
- putchar(',');
- capname(*ip);
- ip++;
- narg--;
+ case SYS_cap_new:
+ print_number(ip, narg, c);
+ putchar(',');
+ arg = *ip;
+ ip++;
+ narg--;
+ /*
+ * Hack: the second argument is a
+ * cap_rights_t, which 64 bits wide, so on
+ * 32-bit systems, it is split between two
+ * registers.
+ *
+ * Since sizeof() is not evaluated by the
+ * preprocessor, we can't use an #ifdef,
+ * but the compiler will probably optimize
+ * the code out anyway.
+ */
+ if (sizeof(cap_rights_t) > sizeof(register_t)) {
+#if _BYTE_ORDER == _LITTLE_ENDIAN
+ arg = ((intmax_t)*ip << 32) + arg;
+#else
+ arg = (arg << 32) + *ip;
+#endif
+ ip++;
+ narg--;
+ }
+ capname(arg);
break;
}
}
@@ -1554,6 +1582,15 @@ invalid:
printf("invalid record\n");
}
+void
+ktrcapfail(struct ktr_cap_fail *ktr)
+{
+ printf("needed ");
+ capname((intmax_t)ktr->cap_needed);
+ printf(" held ");
+ capname((intmax_t)ktr->cap_held);
+}
+
#if defined(__amd64__) || defined(__i386__)
void
linux_ktrsyscall(struct ktr_syscall *ktr)
diff --git a/usr.bin/ktrace/ktrace.1 b/usr.bin/ktrace/ktrace.1
index 9cff05b..86f23ef 100644
--- a/usr.bin/ktrace/ktrace.1
+++ b/usr.bin/ktrace/ktrace.1
@@ -28,7 +28,7 @@
.\" @(#)ktrace.1 8.1 (Berkeley) 6/6/93
.\" $FreeBSD$
.\"
-.Dd February 23, 2008
+.Dd October 10, 2011
.Dt KTRACE 1
.Os
.Sh NAME
@@ -113,6 +113,8 @@ trace
.Tn I/O
.It Cm n
trace namei translations
+.It Cm p
+trace capability check failures
.It Cm s
trace signal processing
.It Cm t
@@ -127,7 +129,7 @@ trace
requests
.It Cm +
trace the default set of trace points -
-.Cm c , i , n , s , t , u , y
+.Cm c , i , n , p , s , t , u , y
.El
.It Ar command
Execute
diff --git a/usr.bin/ktrace/ktrace.h b/usr.bin/ktrace/ktrace.h
index 5e38d68..e4e4dbf 100644
--- a/usr.bin/ktrace/ktrace.h
+++ b/usr.bin/ktrace/ktrace.h
@@ -32,7 +32,7 @@
#define DEF_POINTS (KTRFAC_SYSCALL | KTRFAC_SYSRET | KTRFAC_NAMEI | \
KTRFAC_GENIO | KTRFAC_PSIG | KTRFAC_USER | \
- KTRFAC_STRUCT | KTRFAC_SYSCTL)
+ KTRFAC_STRUCT | KTRFAC_SYSCTL | KTRFAC_CAPFAIL)
#define PROC_ABI_POINTS (KTRFAC_PROCCTOR | KTRFAC_PROCDTOR)
diff --git a/usr.bin/ktrace/subr.c b/usr.bin/ktrace/subr.c
index 30b6b4d..5051de8 100644
--- a/usr.bin/ktrace/subr.c
+++ b/usr.bin/ktrace/subr.c
@@ -61,11 +61,14 @@ getpoints(char *s)
case 'c':
facs |= KTRFAC_SYSCALL | KTRFAC_SYSRET;
break;
+ case 'i':
+ facs |= KTRFAC_GENIO;
+ break;
case 'n':
facs |= KTRFAC_NAMEI;
break;
- case 'i':
- facs |= KTRFAC_GENIO;
+ case 'p':
+ facs |= KTRFAC_CAPFAIL;
break;
case 's':
facs |= KTRFAC_PSIG;
OpenPOWER on IntegriCloud