Skip to content

tests: move GSS-API dynamic stub into debug-mode libcurl #17752

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 75 commits into from

Conversation

vszakats
Copy link
Member

@vszakats vszakats commented Jun 26, 2025

Replace the libstubgss.so-based overload solution with one built into
libcurl at compile-time.

The previous, LD_PRELOAD-based, solution was non-portable, allowlisted
for Linux, BSD and Solaris. It also required non-debug builds, which
turned out to be an accidental condition:
7d342c7. It also required a curl tool
built against a shared libcurl. Detecting this condition wasn't always
accurate, e.g. with certain cmake configurations.

The overload solution also didn't work on macOS, though it theoretically
should have:

Experiments on making the overload solution work in more envs:

The replacement solution is overloading the necessary GSS-API functions
for test 2056 and 2057 at compile time. It requires a debug-enabled curl
build (due to its insecure nature).

This makes these tests run on all platforms. Including most GSS jobs in
CI, that are running tests. (the exception is old-linux, non-debug jobs,
where it felt overkill to enable debug for this.)

The refactored GSS stub code needs to overload less than before because
it's free to use the official GSS API. (This didn't work with
the overload solution on Alpine for example). It can also use libcurl
functions, allowing to replace snprintf() with msnprintf().

OS/400 is also overloading GSS API functions. I haven't tested how this
works after this PR. In theory it should, because this PR doesn't rely
on preprocessor overrides.

Note that for future GSS tests, it may be necessary to stub these GSS
API functions: gss_inquire_context(), gss_unwrap(), gss_wrap().
They are on codepaths not (yet) touched by tests.

Also:

  • stub-gss: check for token buffer overrun.
  • stub-gss: replace size macros with sizeof().
  • GHA: enable debug for some jobs with GSS.
  • GHA/linux: ignore results for 2056 and 2057 in the valgrind job.
    They leak the same way as seen with 2077 and 2078.
    Ref: 7020ba7 tests: re-enable 1510, unignore 2027 2051 in GHA/macos, document heimdal memleak #17462
    Ref: 1467597 cmake: fix pkg-config-based detection in FindGSS.cmake #14430
  • GHA/linux: fix to ignore gss_import_name() leaks in valgrind builds.
    only.
  • lib/vauth/krb5_gssapi: reduce variable scope.
  • lib/vauth/spnego_gssapi: reduce variable scope.
  • tests/libtest: drop code and build logic dealing with libstubgss.
  • runtests:
    • drop ld_preload feature.
    • drop special handling of LD_PRELOAD env in tests.
    • drop logic dealing with shared curl tool detection.
    • drop LD_PRELOAD envs from tests.

Follow-up to 56d949d #1687


w/o ws https://github.com/curl/curl/pull/17752/files?w=1

  • replace opt-in CPPFLAGS with opt-out, or just tie it to DEBUGBUILD?
    Yes. The stub code only kicks in if env CURL_STUB_GSS_CREDS is filled.
    With curl tests this happens in test 2056, 2057. If they cause a problem,
    they can be disabled or ignored via TFLAGS. This seem sufficient as an
    escape hatch.
  • fix memleaks reported by valgrind:
    https://github.com/curl/curl/actions/runs/15931031764/job/44940047401?pr=17752#step:39:6488
    → Instead of fixing, append the newly tested tests to the existing ignore list.
    (I was staring at lib/vauth/spnego_sspi.c again, but can't spot the leaks.)
  • make the stub opt-in, add a curlinfo feature and run tests when built-in. Opt-in in CI.
  • Make it require debug-enabled build or not? [NO]
  • Do this, or not do this? [→ TRY DIFFERENTLY, see below]
  • That said the stub solution is not the most portable. I wonder if there
    is a platform-agnostic way to do this. Perhaps by moving to unit-tests and
    remapping these APIs to the test stubs at libcurlu compile-time? Like
    done already for two similar (but smaller) stub libs. Or make them
    DEBUGBUILD dependent, an keep tests as-is (except for !DebugDebug).
    Ref: 56d949d
    This needs using macros to call the overridden APIs from curl.

@vszakats vszakats marked this pull request as draft June 26, 2025 09:49
@github-actions github-actions bot added the tests label Jun 26, 2025
@bagder
Copy link
Member

bagder commented Jun 26, 2025

Perhaps by moving to unit-tests and remapping these APIs to the test stubs at libcurlu compile-time?

If we make them rely on debug-builds, we could do the stubbed behavior conditional on an environment variable in classic style which they would avoid relying on ld_preload.

@testclutch

This comment was marked as resolved.

@vszakats

This comment was marked as resolved.

@vszakats vszakats changed the title tests: move stubgss library to data tests: move gss stub into lib Jun 26, 2025
@vszakats vszakats changed the title tests: move gss stub into lib tests: move gss stub into debug-mode libcurl Jun 26, 2025
@vszakats
Copy link
Member Author

vszakats commented Jun 26, 2025

Right, so the stub also stubs the gss_name_t APIs and replaces
the complex struct with a raw string pointer!

@vszakats vszakats force-pushed the t-stubgss-to-data branch from 4e1cb03 to 5862f57 Compare June 27, 2025 08:21
@vszakats vszakats force-pushed the t-stubgss-to-data branch 2 times, most recently from c98b48d to 6d0ce4e Compare June 27, 2025 16:21
@vszakats
Copy link
Member Author

vszakats commented Jun 27, 2025

There were a couple of issues. Once fixed, the in-lib stubs work
(almost) as expected:

  • must also overload gss_delete_sec_context(), as discovered
    via tests: stop limiting ld_preload feature to non-debug builds #17759, by reducing the standalone stub.

  • just in case replace snprintf() with memcpy()s and use the length
    returned by gss_display_name(), to avoid issue when the returned
    string buffer isn't null-terminated.
    edit: → replaced with msnprintf().

  • last but not least I again been caught off-guard by memdebug override,
    which was causing the allocator faults. Must use vanilla, non-overriden
    alloc/free in the stub code to play ball with gss internals.

The in-lib stub code is smaller, since we don't have to reimplement
as much as with the standalone stub, because we can safely use libgss
native public API. Only internals need to be reimplemented.

Speaking of, I'll add a macro to disable this in case gss internals
change and break debug-enabled builds.

But, there are memleaks reported by valgrind, which need to be fixed
before continuing. (This may not be related to the stub. It's the first
time these tests are run under valgrind in CI.)

valgrind
=== Start of file valgrind2056
 ==13493== 32 bytes in 1 blocks are possibly lost in loss record 39 of 93
 ==13493==    at 0x4846828: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
 ==13493==    by 0x5D85D11: heim_dict_set_value (in /usr/lib/x86_64-linux-gnu/libheimbase.so.1.0.0)
 ==13493==    by 0x54453D3: ??? (in /usr/lib/x86_64-linux-gnu/libkrb5.so.26.0.0)
 ==13493==    by 0x4A56ED2: __pthread_once_slow (pthread_once.c:116)
 ==13493==    by 0x5D8657D: heim_base_once_f (in /usr/lib/x86_64-linux-gnu/libheimbase.so.1.0.0)
 ==13493==    by 0x54075B5: krb5_init_context (in /usr/lib/x86_64-linux-gnu/libkrb5.so.26.0.0)
 ==13493==    by 0x4F9FA8F: ??? (in /usr/lib/x86_64-linux-gnu/libgssapi.so.3.0.0)
 ==13493==    by 0x4F9EF05: ??? (in /usr/lib/x86_64-linux-gnu/libgssapi.so.3.0.0)
 ==13493==    by 0x4FA9D87: gss_import_name (in /usr/lib/x86_64-linux-gnu/libgssapi.so.3.0.0)
 ==13493==    by 0x493C56E: Curl_auth_decode_spnego_message (in /home/runner/work/curl/curl/bld/lib/libcurl.so.4.8.0)
 ==13493==    by 0x48D722F: Curl_input_negotiate (in /home/runner/work/curl/curl/bld/lib/libcurl.so.4.8.0)
 ==13493==    by 0x48D745A: Curl_output_negotiate (in /home/runner/work/curl/curl/bld/lib/libcurl.so.4.8.0)
 ==13493==    by 0x48BCB74: output_auth_headers (in /home/runner/work/curl/curl/bld/lib/libcurl.so.4.8.0)
 ==13493==    by 0x48BD064: Curl_http_output_auth (in /home/runner/work/curl/curl/bld/lib/libcurl.so.4.8.0)
 ==13493==    by 0x48C160B: Curl_http (in /home/runner/work/curl/curl/bld/lib/libcurl.so.4.8.0)
 ==13493==    by 0x48EE699: multi_do (in /home/runner/work/curl/curl/bld/lib/libcurl.so.4.8.0)
 ==13493== 
 ==13493== 69 bytes in 1 blocks are possibly lost in loss record 48 of 93
 ==13493==    at 0x484D953: calloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
 ==13493==    by 0x5D864DD: ??? (in /usr/lib/x86_64-linux-gnu/libheimbase.so.1.0.0)
 ==13493==    by 0x5D88F70: heim_string_create_with_bytes (in /usr/lib/x86_64-linux-gnu/libheimbase.so.1.0.0)
 ==13493==    by 0x544505E: ??? (in /usr/lib/x86_64-linux-gnu/libkrb5.so.26.0.0)
 ==13493==    by 0x4A56ED2: __pthread_once_slow (pthread_once.c:116)
 ==13493==    by 0x5D8657D: heim_base_once_f (in /usr/lib/x86_64-linux-gnu/libheimbase.so.1.0.0)
 ==13493==    by 0x54075B5: krb5_init_context (in /usr/lib/x86_64-linux-gnu/libkrb5.so.26.0.0)
 ==13493==    by 0x4F9FA8F: ??? (in /usr/lib/x86_64-linux-gnu/libgssapi.so.3.0.0)
 ==13493==    by 0x4F9EF05: ??? (in /usr/lib/x86_64-linux-gnu/libgssapi.so.3.0.0)
 ==13493==    by 0x4FA9D87: gss_import_name (in /usr/lib/x86_64-linux-gnu/libgssapi.so.3.0.0)
 ==13493==    by 0x493C56E: Curl_auth_decode_spnego_message (in /home/runner/work/curl/curl/bld/lib/libcurl.so.4.8.0)
 ==13493==    by 0x48D722F: Curl_input_negotiate (in /home/runner/work/curl/curl/bld/lib/libcurl.so.4.8.0)
 ==13493==    by 0x48D745A: Curl_output_negotiate (in /home/runner/work/curl/curl/bld/lib/libcurl.so.4.8.0)
 ==13493==    by 0x48BCB74: output_auth_headers (in /home/runner/work/curl/curl/bld/lib/libcurl.so.4.8.0)
 ==13493==    by 0x48BD064: Curl_http_output_auth (in /home/runner/work/curl/curl/bld/lib/libcurl.so.4.8.0)
 ==13493==    by 0x48C160B: Curl_http (in /home/runner/work/curl/curl/bld/lib/libcurl.so.4.8.0)
 ==13493== 
 ==13493== 80 bytes in 1 blocks are possibly lost in loss record 51 of 93
 ==13493==    at 0x484D953: calloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
 ==13493==    by 0x5D864DD: ??? (in /usr/lib/x86_64-linux-gnu/libheimbase.so.1.0.0)
 ==13493==    by 0x5D85AEE: heim_dict_create (in /usr/lib/x86_64-linux-gnu/libheimbase.so.1.0.0)
 ==13493==    by 0x5445371: ??? (in /usr/lib/x86_64-linux-gnu/libkrb5.so.26.0.0)
 ==13493==    by 0x4A56ED2: __pthread_once_slow (pthread_once.c:116)
 ==13493==    by 0x5D8657D: heim_base_once_f (in /usr/lib/x86_64-linux-gnu/libheimbase.so.1.0.0)
 ==13493==    by 0x54075B5: krb5_init_context (in /usr/lib/x86_64-linux-gnu/libkrb5.so.26.0.0)
 ==13493==    by 0x4F9FA8F: ??? (in /usr/lib/x86_64-linux-gnu/libgssapi.so.3.0.0)
 ==13493==    by 0x4F9EF05: ??? (in /usr/lib/x86_64-linux-gnu/libgssapi.so.3.0.0)
 ==13493==    by 0x4FA9D87: gss_import_name (in /usr/lib/x86_64-linux-gnu/libgssapi.so.3.0.0)
 ==13493==    by 0x493C56E: Curl_auth_decode_spnego_message (in /home/runner/work/curl/curl/bld/lib/libcurl.so.4.8.0)
 ==13493==    by 0x48D722F: Curl_input_negotiate (in /home/runner/work/curl/curl/bld/lib/libcurl.so.4.8.0)
 ==13493==    by 0x48D745A: Curl_output_negotiate (in /home/runner/work/curl/curl/bld/lib/libcurl.so.4.8.0)
 ==13493==    by 0x48BCB74: output_auth_headers (in /home/runner/work/curl/curl/bld/lib/libcurl.so.4.8.0)
 ==13493==    by 0x48BD064: Curl_http_output_auth (in /home/runner/work/curl/curl/bld/lib/libcurl.so.4.8.0)
 ==13493==    by 0x48C160B: Curl_http (in /home/runner/work/curl/curl/bld/lib/libcurl.so.4.8.0)
 ==13493== 
 ==13493== 80 bytes in 1 blocks are possibly lost in loss record 52 of 93
 ==13493==    at 0x484D953: calloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
 ==13493==    by 0x5D864DD: ??? (in /usr/lib/x86_64-linux-gnu/libheimbase.so.1.0.0)
 ==13493==    by 0x5D85AEE: heim_dict_create (in /usr/lib/x86_64-linux-gnu/libheimbase.so.1.0.0)
 ==13493==    by 0x54453B7: ??? (in /usr/lib/x86_64-linux-gnu/libkrb5.so.26.0.0)
 ==13493==    by 0x4A56ED2: __pthread_once_slow (pthread_once.c:116)
 ==13493==    by 0x5D8657D: heim_base_once_f (in /usr/lib/x86_64-linux-gnu/libheimbase.so.1.0.0)
 ==13493==    by 0x54075B5: krb5_init_context (in /usr/lib/x86_64-linux-gnu/libkrb5.so.26.0.0)
 ==13493==    by 0x4F9FA8F: ??? (in /usr/lib/x86_64-linux-gnu/libgssapi.so.3.0.0)
 ==13493==    by 0x4F9EF05: ??? (in /usr/lib/x86_64-linux-gnu/libgssapi.so.3.0.0)
 ==13493==    by 0x4FA9D87: gss_import_name (in /usr/lib/x86_64-linux-gnu/libgssapi.so.3.0.0)
 ==13493==    by 0x493C56E: Curl_auth_decode_spnego_message (in /home/runner/work/curl/curl/bld/lib/libcurl.so.4.8.0)
 ==13493==    by 0x48D722F: Curl_input_negotiate (in /home/runner/work/curl/curl/bld/lib/libcurl.so.4.8.0)
 ==13493==    by 0x48D745A: Curl_output_negotiate (in /home/runner/work/curl/curl/bld/lib/libcurl.so.4.8.0)
 ==13493==    by 0x48BCB74: output_auth_headers (in /home/runner/work/curl/curl/bld/lib/libcurl.so.4.8.0)
 ==13493==    by 0x48BD064: Curl_http_output_auth (in /home/runner/work/curl/curl/bld/lib/libcurl.so.4.8.0)
 ==13493==    by 0x48C160B: Curl_http (in /home/runner/work/curl/curl/bld/lib/libcurl.so.4.8.0)
 ==13493== 
 ==13493== 88 bytes in 1 blocks are possibly lost in loss record 53 of 93
 ==13493==    at 0x484D953: calloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
 ==13493==    by 0x5D85B5A: heim_dict_create (in /usr/lib/x86_64-linux-gnu/libheimbase.so.1.0.0)
 ==13493==    by 0x5445371: ??? (in /usr/lib/x86_64-linux-gnu/libkrb5.so.26.0.0)
 ==13493==    by 0x4A56ED2: __pthread_once_slow (pthread_once.c:116)
 ==13493==    by 0x5D8657D: heim_base_once_f (in /usr/lib/x86_64-linux-gnu/libheimbase.so.1.0.0)
 ==13493==    by 0x54075B5: krb5_init_context (in /usr/lib/x86_64-linux-gnu/libkrb5.so.26.0.0)
 ==13493==    by 0x4F9FA8F: ??? (in /usr/lib/x86_64-linux-gnu/libgssapi.so.3.0.0)
 ==13493==    by 0x4F9EF05: ??? (in /usr/lib/x86_64-linux-gnu/libgssapi.so.3.0.0)
 ==13493==    by 0x4FA9D87: gss_import_name (in /usr/lib/x86_64-linux-gnu/libgssapi.so.3.0.0)
 ==13493==    by 0x493C56E: Curl_auth_decode_spnego_message (in /home/runner/work/curl/curl/bld/lib/libcurl.so.4.8.0)
 ==13493==    by 0x48D722F: Curl_input_negotiate (in /home/runner/work/curl/curl/bld/lib/libcurl.so.4.8.0)
 ==13493==    by 0x48D745A: Curl_output_negotiate (in /home/runner/work/curl/curl/bld/lib/libcurl.so.4.8.0)
 ==13493==    by 0x48BCB74: output_auth_headers (in /home/runner/work/curl/curl/bld/lib/libcurl.so.4.8.0)
 ==13493==    by 0x48BD064: Curl_http_output_auth (in /home/runner/work/curl/curl/bld/lib/libcurl.so.4.8.0)
 ==13493==    by 0x48C160B: Curl_http (in /home/runner/work/curl/curl/bld/lib/libcurl.so.4.8.0)
 ==13493==    by 0x48EE699: multi_do (in /home/runner/work/curl/curl/bld/lib/libcurl.so.4.8.0)
 ==13493== 
 ==13493== 88 bytes in 1 blocks are possibly lost in loss record 54 of 93
 ==13493==    at 0x484D953: calloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
 ==13493==    by 0x5D85B5A: heim_dict_create (in /usr/lib/x86_64-linux-gnu/libheimbase.so.1.0.0)
 ==13493==    by 0x54453B7: ??? (in /usr/lib/x86_64-linux-gnu/libkrb5.so.26.0.0)
 ==13493==    by 0x4A56ED2: __pthread_once_slow (pthread_once.c:116)
 ==13493==    by 0x5D8657D: heim_base_once_f (in /usr/lib/x86_64-linux-gnu/libheimbase.so.1.0.0)
 ==13493==    by 0x54075B5: krb5_init_context (in /usr/lib/x86_64-linux-gnu/libkrb5.so.26.0.0)
 ==13493==    by 0x4F9FA8F: ??? (in /usr/lib/x86_64-linux-gnu/libgssapi.so.3.0.0)
 ==13493==    by 0x4F9EF05: ??? (in /usr/lib/x86_64-linux-gnu/libgssapi.so.3.0.0)
 ==13493==    by 0x4FA9D87: gss_import_name (in /usr/lib/x86_64-linux-gnu/libgssapi.so.3.0.0)
 ==13493==    by 0x493C56E: Curl_auth_decode_spnego_message (in /home/runner/work/curl/curl/bld/lib/libcurl.so.4.8.0)
 ==13493==    by 0x48D722F: Curl_input_negotiate (in /home/runner/work/curl/curl/bld/lib/libcurl.so.4.8.0)
 ==13493==    by 0x48D745A: Curl_output_negotiate (in /home/runner/work/curl/curl/bld/lib/libcurl.so.4.8.0)
 ==13493==    by 0x48BCB74: output_auth_headers (in /home/runner/work/curl/curl/bld/lib/libcurl.so.4.8.0)
 ==13493==    by 0x48BD064: Curl_http_output_auth (in /home/runner/work/curl/curl/bld/lib/libcurl.so.4.8.0)
 ==13493==    by 0x48C160B: Curl_http (in /home/runner/work/curl/curl/bld/lib/libcurl.so.4.8.0)
 ==13493==    by 0x48EE699: multi_do (in /home/runner/work/curl/curl/bld/lib/libcurl.so.4.8.0)
 ==13493== 
=== End of file valgrind2056

https://github.com/curl/curl/actions/runs/15931031764/job/44940047401?pr=17752#step:39:6487

@vszakats vszakats force-pushed the t-stubgss-to-data branch from 6d0ce4e to 3e5e6b5 Compare June 27, 2025 17:36
@vszakats
Copy link
Member Author

vszakats commented Jun 27, 2025

The valgrind issues seem pre-existing: In CI, test 2077 and 2078
are already added to the ignore-list for a different job. Looks like
the same applies to the newly enabled GSS tests, but they were
not hit in CI before this patch.

Ref: 7020ba7 #17462
Ref: 1467597 #14430

@github-actions github-actions bot added cmdline tool CI Continuous Integration labels Jun 27, 2025
@vszakats vszakats marked this pull request as ready for review June 27, 2025 19:46
vszakats added 24 commits June 30, 2025 19:08
Also enable debug mode in a few CI jobs to enable stub-gss.
Drop stub-gss from old-linux to avoid enabling debug mode
(no strong reason, but doesn't seem to be worth messing with it).
Detection wasn't accurate for cmake builds at least. It was checking
if a shared libcurl was built, but that's just an indirect signal to
detect if the curl tool was built against that, or a static libcurl.
In cmake, there is a separate user option to decide about this.
@vszakats vszakats force-pushed the t-stubgss-to-data branch from 9b1c3fa to c7fb9d5 Compare June 30, 2025 17:08
@vszakats vszakats changed the title tests: move gss stub into debug-mode libcurl tests: move GSS-API stub into debug-mode libcurl Jun 30, 2025
@vszakats vszakats changed the title tests: move GSS-API stub into debug-mode libcurl tests: move GSS-API dynamic stub into debug-mode libcurl Jun 30, 2025
@vszakats vszakats closed this in 7384083 Jun 30, 2025
@vszakats vszakats deleted the t-stubgss-to-data branch June 30, 2025 22:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CI Continuous Integration cmdline tool tests
Development

Successfully merging this pull request may close these issues.

3 participants