From owner-svn-src-all@FreeBSD.ORG Tue Oct 18 07:28:59 2011 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 361CC1065673; Tue, 18 Oct 2011 07:28:59 +0000 (UTC) (envelope-from des@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 2469D8FC17; Tue, 18 Oct 2011 07:28:59 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id p9I7SxOO061660; Tue, 18 Oct 2011 07:28:59 GMT (envelope-from des@svn.freebsd.org) Received: (from des@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id p9I7SwSn061654; Tue, 18 Oct 2011 07:28:58 GMT (envelope-from des@svn.freebsd.org) Message-Id: <201110180728.p9I7SwSn061654@svn.freebsd.org> From: Dag-Erling Smorgrav Date: Tue, 18 Oct 2011 07:28:58 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r226495 - in head: sys/kern sys/sys usr.bin/kdump X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 18 Oct 2011 07:28:59 -0000 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__)