From 1b405df8baa78dedceda6da24510b9597aad726d Mon Sep 17 00:00:00 2001 From: des Date: Tue, 18 Oct 2011 07:28:58 +0000 Subject: 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. --- sys/kern/kern_ktrace.c | 4 +++- sys/kern/sys_capability.c | 10 ++++++++-- sys/kern/vfs_lookup.c | 18 ++++++++++++++++-- 3 files changed, 27 insertions(+), 5 deletions(-) (limited to 'sys/kern') diff --git a/sys/kern/kern_ktrace.c b/sys/kern/kern_ktrace.c index bf99971..3bb529f 100644 --- a/sys/kern/kern_ktrace.c +++ b/sys/kern/kern_ktrace.c @@ -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); diff --git a/sys/kern/sys_capability.c b/sys/kern/sys_capability.c index b22cfb2..f1fb1b1 100644 --- a/sys/kern/sys_capability.c +++ b/sys/kern/sys_capability.c @@ -218,7 +218,7 @@ cap_check(struct capability *c, cap_rights_t rights) 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 file *fp, cap_rights_t rights, */ 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); + } } /* diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c index a145017..e2aad7c 100644 --- a/sys/kern/vfs_lookup.c +++ b/sys/kern/vfs_lookup.c @@ -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; } -- cgit v1.1