fix null pointer dereferences found by malloc-error-check cocci - #15560
fix null pointer dereferences found by malloc-error-check cocci#15560kenifor wants to merge 8 commits into
Conversation
The identifier regex used PCRE-style '(A|B)' syntax, but Coccinelle uses OCaml Str where '|' and '()' are literal characters. The @malloced rule never matched any SC*alloc call, making the entire script a no-op. Replace all five identifier =~ patterns with the correct OCaml Str alternation syntax 'A\|B'.
When Redis output is configured in stream/xadd mode with a positive stream-maxlen, SCConfLogOpenRedis() allocates redis_setup.stream_format and immediately passes it to snprintf(). If SCCalloc() fails, snprintf() receives a NULL destination pointer and the process can crash during Redis output initialization. Handle this unrecoverable setup failure with FatalError(), matching the surrounding Redis initialization error handling. Ticket: 8588
SCStrdup result was stored and immediately used without checking for NULL, which would cause a NULL dereference if allocation fails.
The original pointer was overwritten with the SCRealloc result before checking for NULL, causing a memory leak if reallocation fails. Check the temporary pointer first before assigning.
Two SCStrdup calls that set ref->key had no NULL check. On allocation failure the pointer would be used immediately, causing a NULL dereference.
PacketAlertCreate is called from PacketInit on the packet allocation path. Crashing the process on allocation failure is inappropriate here; the caller should be able to drop the packet gracefully. Make PacketInit return bool and propagate the NULL result from PacketAlertCreate up through PacketGetFromAlloc, which already returns NULL to signal allocation failure to its callers. Update the four UNITTESTS-only helpers in defrag.c accordingly.
If SCCalloc fails, decoded is NULL and the subsequent SCBase64Decode call would dereference it. Return early on allocation failure.
Two fixes: - Remove extra parentheses in existing NULL check: (*ext) -> *ext, which was causing the cocci script to miss the check as a false negative. - Simplify SCHSConfigInit to return SCCalloc() directly; the caller in detect-engine.c already checks the return value for NULL.
catenacyber
left a comment
There was a problem hiding this comment.
Thanks for the work, I think it needs a dedicated ticket for the qa/cocci fix
CI : ✅
Git ID set : looks fine for me
CLA : did you sign it ?
Doc update : not needed
Redmine ticket : I think we should have one for the cocci/QA fix, and rather a distinct one from https://redmine.openinfosecfoundation.org/issues/8588 which can include the other fixes...
Rustfmt : no rust
Tests : this is nice
Dependencies added: none
Code : good
Commits segmentation : ok cool
Commit messages : ok, I find them too long/verbose
Do you know if this was always broken ? or broken by a coccinelle update ?
| maxlen integer formatted as a string */ | ||
| log_ctx->redis_setup.stream_format = SCCalloc(100, sizeof(char)); | ||
| if (unlikely(log_ctx->redis_setup.stream_format == NULL)) { | ||
| FatalError("Unable to allocate redis stream format"); |
There was a problem hiding this comment.
Yes, I think it as a relevant to a fatal error as the ones just below it.
| DEBUG_VALIDATE_BUG_ON(pa_array == NULL); | ||
|
|
||
| return pa_array; | ||
| return SCCalloc(packet_alert_max, sizeof(PacketAlert)); |
There was a problem hiding this comment.
The commit message should not mention FatalError which is not the case in main right now
| if (!PacketInit(p)) { | ||
| SCFree(p); | ||
| return NULL; | ||
| } |
There was a problem hiding this comment.
I don't know what we prefer, if this approach or the one in the next function (line 1228), but we should be consistent.
jufajardini
left a comment
There was a problem hiding this comment.
Thanks for your work! I've pointed some inconsistencies I think should be addressed, since we'll have another iteration.
| if (IPV6_GET_RAW_VER(ip6p) != 6) | ||
| goto error; | ||
| if (IPV6_GET_RAW_NH(ip6p) != 44) | ||
| goto error; | ||
| if (IPV6_GET_RAW_PLEN(ip6p) != sizeof(IPV6FragHdr) + content_len) | ||
| goto error; | ||
|
|
There was a problem hiding this comment.
Same here, I think: some tests are using FAIL_IF, some are not...
|
NOTE: This PR may contain new authors. |
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #15560 +/- ##
==========================================
- Coverage 82.86% 82.85% -0.01%
==========================================
Files 999 999
Lines 272627 272641 +14
==========================================
- Hits 225904 225891 -13
- Misses 46723 46750 +27
Flags with carried forward coverage won't be shown. Click here to find out more. 🚀 New features to boost your workflow:
|
Addressed in #15584: added Ticket: 8641 for the cocci fix, corrected the decode commit message, and clarified the defrag.c helpers (different styles reflect different return types: Re: "was this always broken?" — yes, from the beginning. The |
|
Merged by #15584 |
Supersedes #15552. Updated
util/mpm-hscommit: instead ofFatalError,SCHSConfigInitnow returnsSCCalloc()directly — the caller indetect-engine.calready checks the return value for NULL.