svn commit: r226495 - in head: sys/kern sys/sys usr.bin/kdump
Dag-Erling Smorgrav
des at FreeBSD.org
Tue Oct 18 07:28:59 UTC 2011
Author: des
Date: Tue Oct 18 07:28:58 2011
New Revision: 226495
URL: http://svn.freebsd.org/changeset/base/226495
Log:
Revisit the capability failure trace points. The initial implementation
only logged instances where an operation on a file descriptor required
capabilities which the file descriptor did not have. By adding a type enum
to struct ktr_cap_fail, we can catch other types of capability failures as
well, such as disallowed system calls or attempts to wrap a file descriptor
with more capabilities than it had to begin with.
Modified:
head/sys/kern/kern_ktrace.c
head/sys/kern/sys_capability.c
head/sys/kern/vfs_lookup.c
head/sys/sys/ktrace.h
head/usr.bin/kdump/kdump.c
Modified: head/sys/kern/kern_ktrace.c
==============================================================================
--- head/sys/kern/kern_ktrace.c Tue Oct 18 07:17:44 2011 (r226494)
+++ head/sys/kern/kern_ktrace.c Tue Oct 18 07:28:58 2011 (r226495)
@@ -772,7 +772,8 @@ ktrstruct(name, data, datalen)
}
void
-ktrcapfail(needed, held)
+ktrcapfail(type, needed, held)
+ enum ktr_cap_fail_type type;
cap_rights_t needed;
cap_rights_t held;
{
@@ -784,6 +785,7 @@ ktrcapfail(needed, held)
if (req == NULL)
return;
kcf = &req->ktr_data.ktr_cap_fail;
+ kcf->cap_type = type;
kcf->cap_needed = needed;
kcf->cap_held = held;
ktr_enqueuerequest(td, req);
Modified: head/sys/kern/sys_capability.c
==============================================================================
--- head/sys/kern/sys_capability.c Tue Oct 18 07:17:44 2011 (r226494)
+++ head/sys/kern/sys_capability.c Tue Oct 18 07:28:58 2011 (r226495)
@@ -218,7 +218,7 @@ cap_check(struct capability *c, cap_righ
if ((c->cap_rights | rights) != c->cap_rights) {
#ifdef KTRACE
if (KTRPOINT(curthread, KTR_CAPFAIL))
- ktrcapfail(rights, c->cap_rights);
+ ktrcapfail(CAPFAIL_NOTCAPABLE, rights, c->cap_rights);
#endif
return (ENOTCAPABLE);
}
@@ -314,8 +314,14 @@ kern_capwrap(struct thread *td, struct f
*/
if (fp->f_type == DTYPE_CAPABILITY) {
cp_old = fp->f_data;
- if ((cp_old->cap_rights | rights) != cp_old->cap_rights)
+ if ((cp_old->cap_rights | rights) != cp_old->cap_rights) {
+#ifdef KTRACE
+ if (KTRPOINT(curthread, KTR_CAPFAIL))
+ ktrcapfail(CAPFAIL_INCREASE,
+ rights, cp_old->cap_rights);
+#endif
return (ENOTCAPABLE);
+ }
}
/*
Modified: head/sys/kern/vfs_lookup.c
==============================================================================
--- head/sys/kern/vfs_lookup.c Tue Oct 18 07:17:44 2011 (r226494)
+++ head/sys/kern/vfs_lookup.c Tue Oct 18 07:28:58 2011 (r226495)
@@ -188,8 +188,13 @@ namei(struct nameidata *ndp)
*/
if (IN_CAPABILITY_MODE(td)) {
ndp->ni_strictrelative = 1;
- if (ndp->ni_dirfd == AT_FDCWD)
+ if (ndp->ni_dirfd == AT_FDCWD) {
+#ifdef KTRACE
+ if (KTRPOINT(td, KTR_CAPFAIL))
+ ktrcapfail(CAPFAIL_LOOKUP, 0, 0);
+#endif
error = ECAPMODE;
+ }
}
#endif
if (error) {
@@ -281,8 +286,13 @@ namei(struct nameidata *ndp)
if (*(cnp->cn_nameptr) == '/') {
vrele(dp);
VFS_UNLOCK_GIANT(vfslocked);
- if (ndp->ni_strictrelative != 0)
+ if (ndp->ni_strictrelative != 0) {
+#ifdef KTRACE
+ if (KTRPOINT(curthread, KTR_CAPFAIL))
+ ktrcapfail(CAPFAIL_LOOKUP, 0, 0);
+#endif
return (ENOTCAPABLE);
+ }
while (*(cnp->cn_nameptr) == '/') {
cnp->cn_nameptr++;
ndp->ni_pathlen--;
@@ -644,6 +654,10 @@ dirloop:
*/
if (cnp->cn_flags & ISDOTDOT) {
if (ndp->ni_strictrelative != 0) {
+#ifdef KTRACE
+ if (KTRPOINT(curthread, KTR_CAPFAIL))
+ ktrcapfail(CAPFAIL_LOOKUP, 0, 0);
+#endif
error = ENOTCAPABLE;
goto bad;
}
Modified: head/sys/sys/ktrace.h
==============================================================================
--- head/sys/sys/ktrace.h Tue Oct 18 07:17:44 2011 (r226494)
+++ head/sys/sys/ktrace.h Tue Oct 18 07:28:58 2011 (r226495)
@@ -181,7 +181,14 @@ struct ktr_proc_ctor {
* KTR_CAPFAIL - trace capability check failures
*/
#define KTR_CAPFAIL 12
+enum ktr_cap_fail_type {
+ CAPFAIL_NOTCAPABLE, /* insufficient capabilities in cap_check() */
+ CAPFAIL_INCREASE, /* attempt to increase capabilities */
+ CAPFAIL_SYSCALL, /* disallowed system call */
+ CAPFAIL_LOOKUP, /* disallowed VFS lookup */
+};
struct ktr_cap_fail {
+ enum ktr_cap_fail_type cap_type;
cap_rights_t cap_needed;
cap_rights_t cap_held;
};
@@ -230,7 +237,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);
+void ktrcapfail(enum ktr_cap_fail_type, cap_rights_t, cap_rights_t);
#define ktrsockaddr(s) \
ktrstruct("sockaddr", (s), ((struct sockaddr *)(s))->sa_len)
#define ktrstat(s) \
Modified: head/usr.bin/kdump/kdump.c
==============================================================================
--- head/usr.bin/kdump/kdump.c Tue Oct 18 07:17:44 2011 (r226494)
+++ head/usr.bin/kdump/kdump.c Tue Oct 18 07:28:58 2011 (r226495)
@@ -1592,10 +1592,36 @@ invalid:
void
ktrcapfail(struct ktr_cap_fail *ktr)
{
- printf("needed ");
- capname((intmax_t)ktr->cap_needed);
- printf(" held ");
- capname((intmax_t)ktr->cap_held);
+ switch (ktr->cap_type) {
+ case CAPFAIL_NOTCAPABLE:
+ /* operation on fd with insufficient capabilities */
+ printf("operation requires ");
+ capname((intmax_t)ktr->cap_needed);
+ printf(", process holds ");
+ capname((intmax_t)ktr->cap_held);
+ break;
+ case CAPFAIL_INCREASE:
+ /* requested more capabilities than fd already has */
+ printf("attempt to increase capabilities from ");
+ capname((intmax_t)ktr->cap_needed);
+ printf(" to ");
+ capname((intmax_t)ktr->cap_held);
+ break;
+ case CAPFAIL_SYSCALL:
+ /* called restricted syscall */
+ printf("disallowed system call");
+ break;
+ case CAPFAIL_LOOKUP:
+ /* used ".." in strict-relative mode */
+ printf("restricted VFS lookup");
+ break;
+ default:
+ printf("unknown capability failure: ");
+ capname((intmax_t)ktr->cap_needed);
+ printf(" ");
+ capname((intmax_t)ktr->cap_held);
+ break;
+ }
}
#if defined(__amd64__) || defined(__i386__)
More information about the svn-src-all
mailing list