Page MenuHomeFreeBSD

D40676.diff
No OneTemporary

D40676.diff

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
@@ -923,14 +923,17 @@
}
void
-ktrcapfail(enum ktr_cap_fail_type type, const cap_rights_t *needed,
- const cap_rights_t *held)
+ktrcapfail(enum ktr_cap_violation type, const void *data)
{
struct thread *td = curthread;
struct ktr_request *req;
struct ktr_cap_fail *kcf;
+ union ktr_cap_data *kcd;
- if (__predict_false(curthread->td_pflags & TDP_INKTRACE))
+ if (__predict_false(td->td_pflags & TDP_INKTRACE))
+ return;
+ if (type != CAPFAIL_SYSCALL &&
+ (td->td_sa.callp->sy_flags & SYF_CAPENABLED) == 0)
return;
req = ktr_getrequest(KTR_CAPFAIL);
@@ -938,14 +941,32 @@
return;
kcf = &req->ktr_data.ktr_cap_fail;
kcf->cap_type = type;
- if (needed != NULL)
- kcf->cap_needed = *needed;
- else
- cap_rights_init(&kcf->cap_needed);
- if (held != NULL)
- kcf->cap_held = *held;
- else
- cap_rights_init(&kcf->cap_held);
+ kcf->cap_code = td->td_sa.code;
+ kcf->cap_svflags = td->td_proc->p_sysent->sv_flags;
+ if (data != NULL) {
+ kcd = &kcf->cap_data;
+ switch (type) {
+ case CAPFAIL_NOTCAPABLE:
+ case CAPFAIL_INCREASE:
+ kcd->cap_needed = *(const cap_rights_t *)data;
+ kcd->cap_held = *((const cap_rights_t *)data + 1);
+ break;
+ case CAPFAIL_SYSCALL:
+ case CAPFAIL_SIGNAL:
+ case CAPFAIL_PROTO:
+ kcd->cap_int = *(const int *)data;
+ break;
+ case CAPFAIL_SOCKADDR:
+ kcd->cap_sockaddr = *(const struct sockaddr *)data;
+ break;
+ case CAPFAIL_NAMEI:
+ strlcpy(kcd->cap_path, data, MAXPATHLEN);
+ break;
+ case CAPFAIL_CPUSET:
+ default:
+ break;
+ }
+ }
ktr_enqueuerequest(td, req);
ktrace_exit(td);
}
diff --git a/sys/kern/sys_capability.c b/sys/kern/sys_capability.c
--- a/sys/kern/sys_capability.c
+++ b/sys/kern/sys_capability.c
@@ -154,14 +154,13 @@
static inline int
_cap_check(const cap_rights_t *havep, const cap_rights_t *needp,
- enum ktr_cap_fail_type type)
+ enum ktr_cap_violation type)
{
+ const cap_rights_t rights[] = { *needp, *havep };
if (!cap_rights_contains(havep, needp)) {
-#ifdef KTRACE
- if (KTRPOINT(curthread, KTR_CAPFAIL))
- ktrcapfail(type, needp, havep);
-#endif
+ if (CAP_TRACING(curthread))
+ ktrcapfail(type, rights);
return (ENOTCAPABLE);
}
return (0);
@@ -180,11 +179,10 @@
int
cap_check_failed_notcapable(const cap_rights_t *havep, const cap_rights_t *needp)
{
+ const cap_rights_t rights[] = { *needp, *havep };
-#ifdef KTRACE
- if (KTRPOINT(curthread, KTR_CAPFAIL))
- ktrcapfail(CAPFAIL_NOTCAPABLE, needp, havep);
-#endif
+ if (CAP_TRACING(curthread))
+ ktrcapfail(CAPFAIL_NOTCAPABLE, rights);
return (ENOTCAPABLE);
}
diff --git a/sys/sys/capsicum.h b/sys/sys/capsicum.h
--- a/sys/sys/capsicum.h
+++ b/sys/sys/capsicum.h
@@ -44,6 +44,7 @@
#include <sys/caprights.h>
#include <sys/file.h>
#include <sys/fcntl.h>
+#include <sys/ktrace.h>
#ifndef _KERNEL
#include <stdbool.h>
@@ -419,6 +420,12 @@
#include <sys/systm.h>
+#ifdef KTRACE
+#define CAP_TRACING(td) KTRPOINT((td), KTR_CAPFAIL)
+#else
+#define CAP_TRACING(td) 0
+#endif
+
#define IN_CAPABILITY_MODE(td) (((td)->td_ucred->cr_flags & CRED_FLAG_CAPMODE) != 0)
struct filedesc;
diff --git a/sys/sys/ktrace.h b/sys/sys/ktrace.h
--- a/sys/sys/ktrace.h
+++ b/sys/sys/ktrace.h
@@ -32,8 +32,10 @@
#ifndef _SYS_KTRACE_H_
#define _SYS_KTRACE_H_
+#include <sys/param.h>
#include <sys/caprights.h>
#include <sys/signal.h>
+#include <sys/socket.h>
#include <sys/_uio.h>
/*
@@ -205,16 +207,31 @@
* KTR_CAPFAIL - trace capability check failures
*/
#define KTR_CAPFAIL 12
-enum ktr_cap_fail_type {
+enum ktr_cap_violation {
CAPFAIL_NOTCAPABLE, /* insufficient capabilities in cap_check() */
- CAPFAIL_INCREASE, /* attempt to increase capabilities */
+ CAPFAIL_INCREASE, /* attempt to increase rights on a capability */
CAPFAIL_SYSCALL, /* disallowed system call */
- CAPFAIL_LOOKUP, /* disallowed VFS lookup */
+ CAPFAIL_SIGNAL, /* sent signal to process other than self */
+ CAPFAIL_PROTO, /* disallowed protocol */
+ CAPFAIL_SOCKADDR, /* restricted address lookup */
+ CAPFAIL_NAMEI, /* restricted namei lookup */
+ CAPFAIL_CPUSET, /* restricted CPU set modification */
};
+
+union ktr_cap_data {
+ cap_rights_t cap_rights[2];
+#define cap_needed cap_rights[0]
+#define cap_held cap_rights[1]
+ int cap_int;
+ struct sockaddr cap_sockaddr;
+ char cap_path[MAXPATHLEN];
+};
+
struct ktr_cap_fail {
- enum ktr_cap_fail_type cap_type;
- cap_rights_t cap_needed;
- cap_rights_t cap_held;
+ enum ktr_cap_violation cap_type;
+ short cap_code;
+ u_int cap_svflags;
+ union ktr_cap_data cap_data;
};
/*
@@ -317,8 +334,7 @@
void ktrstruct(const char *, const void *, size_t);
void ktrstruct_error(const char *, const void *, size_t, int);
void ktrstructarray(const char *, enum uio_seg, const void *, int, size_t);
-void ktrcapfail(enum ktr_cap_fail_type, const cap_rights_t *,
- const cap_rights_t *);
+void ktrcapfail(enum ktr_cap_violation, const void *);
#define ktrcaprights(s) \
ktrstruct("caprights", (s), sizeof(cap_rights_t))
#define ktritimerval(s) \
diff --git a/usr.bin/kdump/kdump.c b/usr.bin/kdump/kdump.c
--- a/usr.bin/kdump/kdump.c
+++ b/usr.bin/kdump/kdump.c
@@ -2125,35 +2125,74 @@
void
ktrcapfail(struct ktr_cap_fail *ktr)
{
+ union ktr_cap_data *kcd = &ktr->cap_data;
+
switch (ktr->cap_type) {
case CAPFAIL_NOTCAPABLE:
/* operation on fd with insufficient capabilities */
printf("operation requires ");
- sysdecode_cap_rights(stdout, &ktr->cap_needed);
+ sysdecode_cap_rights(stdout, &kcd->cap_needed);
printf(", descriptor holds ");
- sysdecode_cap_rights(stdout, &ktr->cap_held);
+ sysdecode_cap_rights(stdout, &kcd->cap_held);
break;
case CAPFAIL_INCREASE:
/* requested more capabilities than fd already has */
printf("attempt to increase capabilities from ");
- sysdecode_cap_rights(stdout, &ktr->cap_held);
+ sysdecode_cap_rights(stdout, &kcd->cap_held);
printf(" to ");
- sysdecode_cap_rights(stdout, &ktr->cap_needed);
+ sysdecode_cap_rights(stdout, &kcd->cap_needed);
break;
case CAPFAIL_SYSCALL:
/* called restricted syscall */
- printf("disallowed system call");
+ printf("system call not allowed: ");
+ syscallname(ktr->cap_code, ktr->cap_svflags);
+ if (syscallabi(ktr->cap_svflags) == SYSDECODE_ABI_FREEBSD) {
+ switch (ktr->cap_code) {
+ case SYS_sysarch:
+ printf(", op: ");
+ print_integer_arg(sysdecode_sysarch_number,
+ kcd->cap_int);
+ break;
+ case SYS_fcntl:
+ printf(", cmd: ");
+ print_integer_arg(sysdecode_fcntl_cmd,
+ kcd->cap_int);
+ break;
+ }
+ }
break;
- case CAPFAIL_LOOKUP:
- /* absolute or AT_FDCWD path, ".." path, etc. */
- printf("restricted VFS lookup");
+ case CAPFAIL_SIGNAL:
+ /* sent signal to proc other than self */
+ syscallname(ktr->cap_code, ktr->cap_svflags);
+ printf(": signal delivery not allowed: ");
+ print_integer_arg(sysdecode_signal, kcd->cap_int);
break;
- default:
- printf("unknown capability failure: ");
- sysdecode_cap_rights(stdout, &ktr->cap_needed);
- printf(" ");
- sysdecode_cap_rights(stdout, &ktr->cap_held);
+ case CAPFAIL_PROTO:
+ /* created socket with restricted protocol */
+ syscallname(ktr->cap_code, ktr->cap_svflags);
+ printf(": protocol not allowed: ");
+ print_integer_arg(sysdecode_ipproto, kcd->cap_int);
break;
+ case CAPFAIL_SOCKADDR:
+ /* unable to look up address */
+ syscallname(ktr->cap_code, ktr->cap_svflags);
+ printf(": restricted address lookup: ");
+ ktrsockaddr(&kcd->cap_sockaddr);
+ return;
+ case CAPFAIL_NAMEI:
+ /* absolute or AT_FDCWD path, ".." path, etc. */
+ syscallname(ktr->cap_code, ktr->cap_svflags);
+ printf(": restricted VFS lookup: %s\n", kcd->cap_path);
+ return;
+ case CAPFAIL_CPUSET:
+ /* modification of an external cpuset */
+ syscallname(ktr->cap_code, ktr->cap_svflags);
+ printf(": restricted cpuset operation\n");
+ return;
+ default:
+ syscallname(ktr->cap_code, ktr->cap_svflags);
+ printf(": unknown capability failure\n");
+ return;
}
printf("\n");
}

File Metadata

Mime Type
text/plain
Expires
Sun, Apr 27, 5:55 PM (16 h, 45 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
17820489
Default Alt Text
D40676.diff (7 KB)

Event Timeline