Skip to content

out_azure_kusto: Close OAuth handles in case of failure#11438

Open
ag-ramachandran wants to merge 2 commits intofluent:masterfrom
ag-ramachandran:bugfix/OAuthErrorFixes
Open

out_azure_kusto: Close OAuth handles in case of failure#11438
ag-ramachandran wants to merge 2 commits intofluent:masterfrom
ag-ramachandran:bugfix/OAuthErrorFixes

Conversation

@ag-ramachandran
Copy link
Contributor

@ag-ramachandran ag-ramachandran commented Feb 9, 2026

Signed-off-by: ag-ramachandran [email protected]


Enter [N/A] in the box, if an item is not applicable to your change.

Testing
Before we can approve your change; please submit the following in a comment:

  • Example configuration file for the change
  • Debug log output from testing the change
  • Attached Valgrind output that shows no leaks or memory corruption was found

If this is a change to packaging of containers or native binaries then please confirm it works for all targets.

  • Run local packaging test showing all targets (including any new ones) build.
  • Set ok-package-test label to test for all targets (requires maintainer to do).

Documentation

  • Documentation required for this feature

Backporting

  • Backport to latest stable release.

Fluent Bit is licensed under Apache 2.0, by submitting this pull request I understand that this code will be released under the terms of that license.

Summary by CodeRabbit

  • Bug Fixes
    • More specific and actionable MSI/OAuth2 error messages to aid troubleshooting.
    • Enabled OAuth2 token retrieval for service-principal authentication flows.
    • Added explicit cleanup on initialization failures to prevent resource leaks.
    • Removed noisy error logging for mutex lock failures to reduce false alarms.

@coderabbitai
Copy link

coderabbitai bot commented Feb 9, 2026

📝 Walkthrough

Walkthrough

Adds explicit resource cleanup paths during Azure Kusto plugin initialization failures, tightens MSI/OAuth2 error messages, enables OAuth2 for service-principal token construction, and removes an error log on token-mutex lock failure in the plugin's C implementation.

Changes

Cohort / File(s) Summary
Azure Kusto plugin
plugins/out_azure_kusto/azure_kusto.c
Added explicit cleanup on upstream and OAuth2 init failures (destroy resources_mutex, token_mutex, blob_mutex; destroy upstream; free oauth_url; destroy config/OAuth2 contexts); enabled OAuth2 (ctx->o->cfg.enabled = FLB_TRUE) when building service-principal tokens; improved MSI/oauth2 error messages; removed an error log on token mutex lock failure; added token cleanup label to ensure mutex unlocking.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐇 I munched on mutexes through the night,

Freed the tokens, set messages right,
Cleaned the paths where errors creep,
Closed the locks before sleep,
The Kusto plugin hops in light.

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: adding OAuth handle cleanup on initialization failures in the out_azure_kusto plugin.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

No actionable comments were generated in the recent review. 🎉


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8287a33d31

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
plugins/out_azure_kusto/azure_kusto.c (3)

946-962: ⚠️ Potential issue | 🔴 Critical

Null-pointer dereference of ctx->u and double-free of ctx->oauth_url.

Two issues in this error-handling block:

  1. NULL dereference (pre-existing, adjacent to your change): ctx->u is used at lines 947–951 before the NULL check at line 952. If flb_upstream_create_url returns NULL, the access to ctx->u->base will crash. The NULL check must come first.

  2. Double-free: Line 958 calls flb_sds_destroy(ctx->oauth_url) without setting ctx->oauth_url = NULL. Then line 960 calls flb_azure_kusto_conf_destroy(ctx), which [per the snippet at azure_kusto_conf.c:858-861] also destroys ctx->oauth_url if it's non-NULL—resulting in a double-free.

Proposed fix
     ctx->u = flb_upstream_create_url(config, ctx->ingestion_endpoint, io_flags, ins->tls);
+    if (!ctx->u) {
+        flb_plg_error(ctx->ins, "upstream creation failed");
+        pthread_mutex_destroy(&ctx->resources_mutex);
+        pthread_mutex_destroy(&ctx->token_mutex);
+        pthread_mutex_destroy(&ctx->blob_mutex);
+        flb_azure_kusto_conf_destroy(ctx);
+        return -1;
+    }
     if (ctx->buffering_enabled ==  FLB_TRUE){
         flb_stream_disable_flags(&ctx->u->base, FLB_IO_ASYNC);
         ctx->u->base.net.io_timeout = ctx->io_timeout;
         ctx->has_old_buffers = azure_kusto_store_has_data(ctx);
     }
-    if (!ctx->u) {
-        flb_plg_error(ctx->ins, "upstream creation failed");
-        pthread_mutex_destroy(&ctx->resources_mutex);
-        pthread_mutex_destroy(&ctx->token_mutex);
-        pthread_mutex_destroy(&ctx->blob_mutex);
-        if (ctx->oauth_url) {
-            flb_sds_destroy(ctx->oauth_url);
-        }
-        flb_azure_kusto_conf_destroy(ctx);
-        return -1;
-    }

Note: flb_azure_kusto_conf_destroy already handles ctx->oauth_url, ctx->o, and ctx->resources cleanup, so the separate flb_sds_destroy(ctx->oauth_url) is not only a double-free but also unnecessary.


967-980: ⚠️ Potential issue | 🔴 Critical

Same double-free of ctx->oauth_url as in the upstream failure path.

Lines 971–973 free ctx->oauth_url without nulling it, then flb_azure_kusto_conf_destroy at line 978 frees it again. Either remove the manual flb_sds_destroy (since conf_destroy handles it) or null out the pointer after freeing.

Proposed fix (remove redundant free, let conf_destroy handle it)
     if (!ctx->o) {
         flb_plg_error(ctx->ins, "cannot create oauth2 context");
-        if (ctx->oauth_url) {
-            flb_sds_destroy(ctx->oauth_url);
-        }
         flb_upstream_destroy(ctx->u);
         pthread_mutex_destroy(&ctx->resources_mutex);
         pthread_mutex_destroy(&ctx->token_mutex);
         pthread_mutex_destroy(&ctx->blob_mutex);
         flb_azure_kusto_conf_destroy(ctx);
         return -1;
     }

152-158: ⚠️ Potential issue | 🟠 Major

Pre-existing: mutex leak when output allocation fails.

Line 157 returns NULL without reaching the pthread_mutex_unlock at line 163. Since this PR is specifically about closing handles and unlocking mutexes on error paths, this missed case is worth fixing too.

Proposed fix
     if (ret == 0) {
         output = flb_sds_create_size(flb_sds_len(ctx->o->token_type) +
                                      flb_sds_len(ctx->o->access_token) + 2);
         if (!output) {
             flb_plg_error(ctx->ins, "error creating token buffer");
-            return NULL;
+            pthread_mutex_unlock(&ctx->token_mutex);
+            return NULL;
         }
🤖 Fix all issues with AI agents
In `@plugins/out_azure_kusto/azure_kusto.c`:
- Around line 116-123: token_cleanup currently unlocks ctx->token_mutex and then
returns success, which both hides errors and causes a double-unlock; fix by
removing the mutex unlock from the token_cleanup block and ensuring error paths
return -1 instead of jumping to token_cleanup. Concretely: in the token_cleanup
label (symbol: token_cleanup) delete the pthread_mutex_unlock(&ctx->token_mutex)
call and change token_cleanup to return -1 for error paths (or replace all
existing error goto token_cleanup sites in get_azure_kusto_token with direct
"return -1"); leave the mutex unlock to the caller get_azure_kusto_token
(symbol: get_azure_kusto_token) and ensure successful completion still returns 0
only when ctx->o->access_token is valid.
🧹 Nitpick comments (1)
plugins/out_azure_kusto/azure_kusto.c (1)

102-105: Redundant null check: ctx->o is already dereferenced earlier in this function.

ctx->o is used at line 77 (flb_oauth2_payload_clear(ctx->o)) and lines 79–97 (flb_oauth2_payload_append(ctx->o, ...)), so if it were NULL, the function would have already crashed before reaching line 103. The guard is a no-op.

Also, minor style nit: missing space after if (if(ctx->o)if (ctx->o)).

Simplify
-    /* Enable OAuth2 for token retrieval */
-    if(ctx->o){
-        ctx->o->cfg.enabled = FLB_TRUE;  
-    }
+    /* Enable OAuth2 for token retrieval */
+    ctx->o->cfg.enabled = FLB_TRUE;

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
plugins/out_azure_kusto/azure_kusto.c (1)

941-957: ⚠️ Potential issue | 🔴 Critical

Critical: ctx->u is dereferenced before NULL check when buffering is enabled, causing crash and preventing cleanup code from executing.

When flb_upstream_create_url returns NULL and ctx->buffering_enabled == FLB_TRUE, lines 943–944 dereference ctx->u before the null check at line 947. This causes a NULL-pointer dereference crash.

Additionally, there is a double-free bug: line 953 explicitly destroys ctx->oauth_url but does not NULL it. Then line 955 calls flb_azure_kusto_conf_destroy, which will attempt to destroy the same pointer again (lines 860–862 in azure_kusto_conf.c check if (ctx->oauth_url), which is still non-NULL after the explicit destroy).

The null check must move above the buffering block, and ctx->oauth_url must be set to NULL after explicit destruction or the explicit destruction removed entirely (letting conf_destroy handle it). The same pattern appears at lines 966–973 (oauth2 creation failure).

Proposed fix for NULL-deref and double-free
     ctx->u = flb_upstream_create_url(config, ctx->ingestion_endpoint, io_flags, ins->tls);
+    if (!ctx->u) {
+        flb_plg_error(ctx->ins, "upstream creation failed");
+        pthread_mutex_destroy(&ctx->resources_mutex);
+        pthread_mutex_destroy(&ctx->token_mutex);
+        pthread_mutex_destroy(&ctx->blob_mutex);
+        if (ctx->oauth_url) {
+            flb_sds_destroy(ctx->oauth_url);
+            ctx->oauth_url = NULL;
+        }
+        flb_azure_kusto_conf_destroy(ctx);
+        return -1;
+    }
     if (ctx->buffering_enabled ==  FLB_TRUE){
         flb_stream_disable_flags(&ctx->u->base, FLB_IO_ASYNC);
         ctx->u->base.net.io_timeout = ctx->io_timeout;
         ctx->has_old_buffers = azure_kusto_store_has_data(ctx);
     }
-    if (!ctx->u) {
-        flb_plg_error(ctx->ins, "upstream creation failed");
-        pthread_mutex_destroy(&ctx->resources_mutex);
-        pthread_mutex_destroy(&ctx->token_mutex);
-        pthread_mutex_destroy(&ctx->blob_mutex);
-        if (ctx->oauth_url) {
-            flb_sds_destroy(ctx->oauth_url);
-        }
-        flb_azure_kusto_conf_destroy(ctx);
-        return -1;
-    }

Note: Add ctx->oauth_url = NULL; after the explicit destroy to prevent double-free in conf_destroy.

🤖 Fix all issues with AI agents
In `@plugins/out_azure_kusto/azure_kusto.c`:
- Around line 102-105: Remove the redundant null-check around enabling OAuth2:
instead of wrapping the assignment in an if, directly set ctx->o->cfg.enabled =
FLB_TRUE; (delete the surrounding if(ctx->o) block entirely). Ensure spacing
follows project style if you edit surrounding lines (use "if (…)" only where a
check is actually required elsewhere) and leave the assignment to
ctx->o->cfg.enabled as-is so the OAuth2 token retrieval logic sees the flag.
🧹 Nitpick comments (2)
plugins/out_azure_kusto/azure_kusto.c (2)

962-975: Cleanup on OAuth2 creation failure looks correct in structure.

The cleanup order (oauth_url → upstream → mutexes → conf_destroy) mirrors the exit path in cb_azure_kusto_exit, which is good. The same double-free concern for ctx->oauth_url raised above applies here as well — if flb_azure_kusto_conf_destroy frees oauth_url, lines 966–968 would double-free it.

A defensive fix (applicable to both error paths) is to NULL out the pointer after destroying:

if (ctx->oauth_url) {
    flb_sds_destroy(ctx->oauth_url);
    ctx->oauth_url = NULL;
}

126-128: Silent failure on mutex lock.

When pthread_mutex_lock fails, the function returns NULL with no diagnostic. The caller will log a generic "cannot retrieve oauth2 token" error, which makes it harder to identify mutex-related failures. Consider keeping at least a flb_plg_warn here.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
plugins/out_azure_kusto/azure_kusto.c (2)

146-154: ⚠️ Potential issue | 🔴 Critical

Mutex leak on allocation failure — token_mutex is never unlocked.

When flb_sds_create_size fails at line 148, the function returns NULL at line 150 while still holding ctx->token_mutex (locked at line 124). This permanently deadlocks all subsequent token operations. Given this PR's focus on closing handles on failure paths, this appears to be a missed case.

Proposed fix
     if (ret == 0) {
         output = flb_sds_create_size(flb_sds_len(ctx->o->token_type) +
                                      flb_sds_len(ctx->o->access_token) + 2);
         if (!output) {
             flb_plg_error(ctx->ins, "error creating token buffer");
+            pthread_mutex_unlock(&ctx->token_mutex);
             return NULL;
         }
         flb_sds_snprintf(&output, flb_sds_alloc(output), "%s %s", ctx->o->token_type,
                          ctx->o->access_token);
     }

894-915: ⚠️ Potential issue | 🟠 Major

Leaking ctx on buffering validation failures

The early return -1 statements at lines 899, 906, 910, and 914 don't call flb_azure_kusto_conf_destroy(ctx). Since ctx is allocated at line 884, these returns leak the configuration context. Later error paths in the same function (e.g., line 925) correctly include cleanup—these validation checks should too.

Fix for all four paths
         int ret = azure_kusto_store_init(ctx);
         if (ret == -1) {
             flb_plg_error(ctx->ins, "Failed to initialize kusto storage: %s",
                           ctx->store_dir);
+            flb_azure_kusto_conf_destroy(ctx);
             return -1;
         }
         ctx->has_old_buffers = azure_kusto_store_has_data(ctx);
 
         /* validate 'total_file_size' */
         if (ctx->file_size <= 0) {
             flb_plg_error(ctx->ins, "Failed to parse upload_file_size");
+            flb_azure_kusto_conf_destroy(ctx);
             return -1;
         }
         if (ctx->file_size < 1000000) {
             flb_plg_error(ctx->ins, "upload_file_size must be at least 1MB");
+            flb_azure_kusto_conf_destroy(ctx);
             return -1;
         }
         if (ctx->file_size > MAX_FILE_SIZE) {
             flb_plg_error(ctx->ins, "Max total_file_size must be lower than %ld bytes", MAX_FILE_SIZE);
+            flb_azure_kusto_conf_destroy(ctx);
             return -1;
         }

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant