Blame SOURCES/GSSAPI-0.28-Fix-a-crash-in-gss_release_oid-when-destructing-out_.patch

305dfb
From 159042c71bbdd5909f792208dcdffffb1674ecfe Mon Sep 17 00:00:00 2001
305dfb
From: =?UTF-8?q?Petr=20P=C3=ADsa=C5=99?= <ppisar@redhat.com>
305dfb
Date: Thu, 19 Aug 2021 16:07:06 +0200
305dfb
Subject: [PATCH] Fix a crash in gss_release_oid() when destructing out_mech
305dfb
 returned by gss_accept_sec_context()
305dfb
MIME-Version: 1.0
305dfb
Content-Type: text/plain; charset=UTF-8
305dfb
Content-Transfer-Encoding: 8bit
305dfb
305dfb
If Perl GSSAPI was built against MIT krb5, an example gss-server.pl
305dfb
script crashed like this:
305dfb
305dfb
    Program terminated with signal SIGSEGV, Segmentation fault.
305dfb
    #0  0x00007f27f3d48b23 in __GI___libc_free (mem=<optimized out>)
305dfb
        at malloc.c:3131
305dfb
    3131	  ar_ptr = arena_for_chunk (p);
305dfb
    (gdb) bt
305dfb
    #0  0x00007f27f3d48b23 in __GI___libc_free (mem=<optimized out>)
305dfb
        at malloc.c:3131
305dfb
    #1  0x00007f27f2fe17c6 in generic_gss_release_oid (
305dfb
        minor_status=minor_status@entry=0x7fffc750333c,
305dfb
        oid=oid@entry=0x7fffc7503340) at oid_ops.c:102
305dfb
    #2  0x00007f27f2fee6df in gss_release_oid (
305dfb
        minor_status=minor_status@entry=0x7fffc750333c,
305dfb
        oid=oid@entry=0x7fffc7503340) at g_initialize.c:202
305dfb
    #3  0x00007f27f322f5cf in XS_GSSAPI__OID_DESTROY (my_perl=<optimized out>,
305dfb
        cv=0x564037c87130) at ./xs/OID.xs:24
305dfb
    #4  0x00007f27f4f58149 in Perl_pp_entersub (my_perl=0x5640378d42a0)
305dfb
        at pp_hot.c:4227
305dfb
305dfb
The cause is that gss_accept_sec_context() returns a pointer to
305dfb
a static storage in out_mech argument. When GSSAPI passed out_mech to
305dfb
a desctructor, the invoked gss_release_oid() crashed when freeing the
305dfb
memory.
305dfb
305dfb
Accoding to RFC 2744, the static storage is correct. Hence the flaw is
305dfb
on Perl GSSAPI side. This patch fixes it by copying the out_mech OID
305dfb
object on a heap which is then correctly processed by
305dfb
gss_release_oid().
305dfb
305dfb
CPAN RT#121873.
305dfb
305dfb
Signed-off-by: Petr Písař <ppisar@redhat.com>
305dfb
---
305dfb
 xs/Context.xs | 18 ++++++++++++++++++
305dfb
 1 file changed, 18 insertions(+)
305dfb
305dfb
diff --git a/xs/Context.xs b/xs/Context.xs
305dfb
index d176f08..4549595 100644
305dfb
--- a/xs/Context.xs
305dfb
+++ b/xs/Context.xs
305dfb
@@ -80,6 +80,24 @@ accept(context, acc_cred, in_token, binding, out_name, out_mech, out_token, out_
305dfb
 				       &in_token, binding, out_name, out_mech,
305dfb
 				       &out_token, out_flags, out_time,
305dfb
 				       delegated_cred);
305dfb
+#if !defined(HEIMDAL)
305dfb
+	if (out_mech && *out_mech) {
305dfb
+		/* RFC 2744 documents that the returned *out_mech is a pointer
305dfb
+		 * to static data. To prevent from freeing them when destructing
305dfb
+		 * out_mech, we change *out_mech into a pointer to a heap-allocated
305dfb
+		 * buffer with the same content. Otherwise, MITKRB5-provided
305dfb
+		 * gss_release_oid() deallocator which cannot recognize this static
305dfb
+		 * storage would crash. We use malloc() because gss_release_oid() used
305dfb
+		 * free(). */
305dfb
+		GSSAPI__OID copy = malloc(sizeof(*copy));
305dfb
+		if (!copy) croak("Not enough memory for copying out_mech!");
305dfb
+		copy->elements = malloc((*out_mech)->length);
305dfb
+		if (!copy->elements) croak("Not enough memory for copying out_mech!");
305dfb
+		memcpy(copy->elements, (*out_mech)->elements, (*out_mech)->length);
305dfb
+		copy->length = (*out_mech)->length;
305dfb
+		*out_mech = copy;
305dfb
+    }
305dfb
+#endif
305dfb
     OUTPUT:
305dfb
 	RETVAL
305dfb
 	context
305dfb
-- 
305dfb
2.31.1
305dfb