Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 18 Oct 2011 07:28:58 +0000 (UTC)
From:      Dag-Erling Smorgrav <des@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r226495 - in head: sys/kern sys/sys usr.bin/kdump
Message-ID:  <201110180728.p9I7SwSn061654@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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__)



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201110180728.p9I7SwSn061654>