Skip to content

Conversation

@vszakats
Copy link
Member

@vszakats vszakats commented Oct 10, 2025

Before this patch, this code used to call gss_release_buffer() on
objects with buffers allocated via curl's allocator.
gss_release_buffer() calls system (or Win32) free on these buffers,
which may mismatch with curl's allocator. To fix it, align these calls
with the pattern used in vauth modules, by replacing
gss_release_buffer() with curl free to release the buffers.

Use Curl_safefree() to set the freed pointer to NULL, as
gss_release_buffer() did.

Also: use object length var when allocating.

Reported-by: Joshua Rogers

@vszakats vszakats marked this pull request as draft October 10, 2025 23:55
@vszakats vszakats changed the title gss: use CRT malloc to alloc buffers handed to GSS-API socks_gssapi: use CRT malloc to alloc buffers handed to GSS-API Oct 10, 2025
@vszakats vszakats changed the title socks_gssapi: use CRT malloc to alloc buffers handed to GSS-API socks_gssapi: use system malloc for buffers handed to GSS-API Oct 10, 2025
@vszakats vszakats marked this pull request as ready for review October 11, 2025 00:55
@vszakats vszakats changed the title socks_gssapi: use system malloc for buffers handed to GSS-API socks_gssapi: use system malloc for buffers handed to GSS Oct 11, 2025
@vszakats vszakats changed the title socks_gssapi: use system malloc for buffers handed to GSS socks_gssapi: use system malloc for buffers released via gss_release_buffer() Oct 11, 2025
@vszakats vszakats changed the title socks_gssapi: use system malloc for buffers released via gss_release_buffer() socks_gssapi: use system malloc for buffers passed to gss_release_buffer() Oct 11, 2025
@jay
Copy link
Member

jay commented Oct 11, 2025

This commit needs an explanation why it is necessary

@vszakats
Copy link
Member Author

@jay Added a commit message.

@jay
Copy link
Member

jay commented Oct 11, 2025

Renaming malloc as curlx_malloc requires more mental processing when skimming the code. You see malloc and you know instantly what it is. malloc and, in the rare case, (malloc) are easier to understand

@bagder
Copy link
Member

bagder commented Oct 11, 2025

This GSS API uses system free() to free these buffers

Is this documented/suggested behavior? It seems like a brittle operation to malloc in one library and have another free the memory. It would feel more appropriate if the GSS library itself had some way to do that malloc?

@vszakats
Copy link
Member Author

One issue is that it isn't actually malloc. As this bug shows. One other is that it requires fragile PP tricks, and order-dependent includes.

@bagder
Copy link
Member

bagder commented Oct 11, 2025

One issue is that it isn't actually malloc.

That's my point. libcurl handles its memory the way it wants, and another library should not free its memory. And vice versa.

Maybe we should add a gss_malloc() macro ourselves if GSS doesn't have one, that makes it clear what the malloc is for.

@vszakats
Copy link
Member Author

vszakats commented Oct 11, 2025

No, it doesn't seem like the documented way after a quick glance at https://manpages.debian.org/stretch/gss-man/gss_release_buffer.3.en.html. Haven't dug into why it's done that way. I'm thinking to close this without merge.

edit: but, there are 2 (and 3 not long ago) GSS implementations, and this was the man page of just one of them.

@jay
Copy link
Member

jay commented Oct 11, 2025

Yeah it says for that function that "The storage must have been allocated by a GSS-API routine." But I don't see a similar gss_malloc etc in their API. There's one piece of code that already does the (malloc) trick:

curl/lib/curl_gssapi.c

Lines 216 to 223 in 11b9912

/* To avoid memdebug macro replacement, wrap the name in parentheses to call
the original version. It is freed via the GSS API gss_release_buffer(). */
token = (malloc)(length);
if(!token) {
free(ctx);
*min = STUB_GSS_NO_MEMORY;
return GSS_S_FAILURE;
}

@vszakats
Copy link
Member Author

That's in the local debug stub/wrapper, so not exactly the same situation, but I met this tricky API there first. There is also the "import" variant. (I'm on a phone, not able to check anything ATM)

@bagder
Copy link
Member

bagder commented Oct 13, 2025

BTW, this mixup is also reported by Joshua:

F-110: Application-allocated gss_recv_token.value freed via gss_release_buffer (heap corruption/DoS)

  • Evidence: lib/socks_gssapi.c. gss_recv_token.value is allocated with malloc but freed with gss_release_buffer.
  • Rationale: This is the same lifetime violation as the previous finding but for inbound tokens, and it can corrupt the heap or crash.

@vszakats
Copy link
Member Author

vszakats commented Oct 13, 2025

Got it from there, yes. It's also F-109.

As for F-111, it looked okay. But might use a second look.

@vszakats
Copy link
Member Author

vszakats commented Oct 14, 2025

In krb5_gssapi.c, .value is also allocated with the curl allocator,
but it's also freed via curl's free, instead of calling gss_release_buffer().

Both pass the buffers as inputs to gss_import_name() (which then
creates a GSS "name", without reusing (as far as I clould trace the code)
the passed input for the returned output. Its output then needs to be released
with gss_release_name().

gss_release_buffer() internally either uses free() or the native Win32
API on Windows (only with MIT Kerberos), so I need to give this another go
to apply the pattern used in krb5_gssapi.c and avoid using gss_release_buffer()
for cases where the buffer was allocated by curl. (This API seems to be designed
to free buffers allocated and returned by a GSS API.)

@vszakats vszakats force-pushed the gssmem branch 2 times, most recently from 3f6647a to cabb9b1 Compare October 14, 2025 15:39
@vszakats vszakats changed the title socks_gssapi: use system malloc for buffers passed to gss_release_buffer() socks_gssapi: replace gss_release_buffer() with free() for objects owned by curl Oct 14, 2025
@vszakats vszakats changed the title socks_gssapi: replace gss_release_buffer() with free() for objects owned by curl socks_gssapi: replace gss_release_buffer() with free() for buffers owned by curl Oct 14, 2025
@vszakats vszakats changed the title socks_gssapi: replace gss_release_buffer() with free() for buffers owned by curl socks_gssapi: replace gss_release_buffer() with free() for buffers owned by libcurl Oct 14, 2025
@vszakats
Copy link
Member Author

I reworked this to replace the buffer release wth curl free to match
the curl allocators. (instead of using GSS's release buffer API.)

This makes this code similar to other GSS code in the repo, and also
works with MIT Kerberos Windows, which doesn't use the system
malloc/free anyway.

Reviews are welcome!

@jay
Copy link
Member

jay commented Oct 19, 2025

I reworked this to replace the buffer release wth curl free

Looks ok to me as long as those gss buffer objects are not used after free

@vszakats
Copy link
Member Author

vszakats commented Oct 19, 2025

I reworked this to replace the buffer release wth curl free

Looks ok to me as long as those gss buffer objects are not used after free

Indeed, though this patch doesn't change the placement of free
calls, nor does it add or remove any, it will now actually free those buffers.
Which may bring pre-existing issues to the surface, if there was one.

@vszakats
Copy link
Member Author

I replaced free() with Curl_safefree() to set the freed pointer to NULL.
To avoid a dangling pointer, and to bring it closer to the replaced API which
also did this.

@vszakats vszakats changed the title socks_gssapi: replace gss_release_buffer() with free() for buffers owned by libcurl socks_gssapi: replace gss_release_buffer() with curl free for buffers owned by libcurl Oct 19, 2025
@vszakats vszakats closed this in e781899 Oct 20, 2025
@vszakats vszakats deleted the gssmem branch October 20, 2025 12:24
vszakats added a commit to vszakats/curl that referenced this pull request Oct 20, 2025
To mimic this behavior of the previously used `gss_release_buffer()`.

Follow-up to e781899 curl#19018
vszakats added a commit that referenced this pull request Oct 25, 2025
To mimic this behavior of the previously used `gss_release_buffer()`.

Some or all of these zero assignments may be redundant.

Follow-up to e781899 #19018

Closes #19167
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Development

Successfully merging this pull request may close these issues.

3 participants