From b0ee912984fe1cebdb765a9626bcb49659cd44c9 Mon Sep 17 00:00:00 2001
From: Mark Johnston <markj@FreeBSD.org>
Date: Tue, 10 Mar 2015 21:08:58 +0000
Subject: CTF containers use the ctf_dtoldid field as a threshold type index
 which indicates the range of type indices which have been committed to the
 container by ctf_update(). However, the top bit of the dtd_type field is not
 part of the type index; rather, it is a flag used to indicate that the
 corresponding CTF container is a parent. This is why the maximum CTF type
 index is 2^15 - 1 rather than 2^16 - 1. Therefore, this flag must be masked
 off (using the CTF_TYPE_TO_INDEX macro) when comparing a type index with the
 ctf_dtoldid field of a container.

This bug was causing libctf to erroneously free committed type definitions
in ctf_discard(). libdtrace holds some references to such types, resulting
in a use-after-free.

MFC after:	2 weeks
Sponsored by:	EMC / Isilon Storage Division
---
 cddl/contrib/opensolaris/common/ctf/ctf_create.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'cddl/contrib/opensolaris/common/ctf')

diff --git a/cddl/contrib/opensolaris/common/ctf/ctf_create.c b/cddl/contrib/opensolaris/common/ctf/ctf_create.c
index 41e81e50fd08..679ed18798a7 100644
--- a/cddl/contrib/opensolaris/common/ctf/ctf_create.c
+++ b/cddl/contrib/opensolaris/common/ctf/ctf_create.c
@@ -584,7 +584,7 @@ ctf_discard(ctf_file_t *fp)
 
 	for (dtd = ctf_list_prev(&fp->ctf_dtdefs); dtd != NULL; dtd = ntd) {
 		ntd = ctf_list_prev(dtd);
-		if (dtd->dtd_type <= fp->ctf_dtoldid)
+		if (CTF_TYPE_TO_INDEX(dtd->dtd_type) <= fp->ctf_dtoldid)
 			continue; /* skip types that have been committed */
 
 		ctf_dtd_delete(fp, dtd);
@@ -1328,7 +1328,7 @@ ctf_add_type(ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type)
 	 */
 	if (dst_type == CTF_ERR && name[0] != '\0') {
 		for (dtd = ctf_list_prev(&dst_fp->ctf_dtdefs); dtd != NULL &&
-		    dtd->dtd_type > dst_fp->ctf_dtoldid;
+		    CTF_TYPE_TO_INDEX(dtd->dtd_type) > dst_fp->ctf_dtoldid;
 		    dtd = ctf_list_prev(dtd)) {
 			if (CTF_INFO_KIND(dtd->dtd_data.ctt_info) == kind &&
 			    dtd->dtd_name != NULL &&
-- 
cgit v1.2.3