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

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