There's a null pointer dereference on kernel/auditsc.c as follows: (1) go around the loop that starts at line 281 once, follow a path till you get to line 434. This line tests for "if (ctx)", which implies that null is a legal value for that variable. (2) go around the loop again, this time selecting the "case AUDIT_PERM" at line 460. (3) then the function call on line 461 passes a null pointer, "ctx," into procedure "audit_match_perm." However this procedure dereferences "ctx" unconditionally at its very first statement "unsigned n = ctx->major".
An identical error occurs in case we don't go around the loop again, ie., in case we do step (1) above and instead of step (2) we exit from the loop. In such case, the error occurs at line 469.
Reply-To: akpm@linux-foundation.org On Sat, 15 Dec 2007 13:29:07 -0800 (PST) bugme-daemon@bugzilla.kernel.org wrote: > http://bugzilla.kernel.org/show_bug.cgi?id=9576 > > Summary: Dereferencing a null pointer on kernel/auditsc.c at line > 461 > Product: Process Management > Version: 2.5 > KernelVersion: 2.6.23 > Platform: All > OS/Version: Linux > Tree: Mainline > Status: NEW > Severity: normal > Priority: P1 > Component: Other > AssignedTo: process_other@kernel-bugs.osdl.org > ReportedBy: marciobuss@gmail.com > > > There's a null pointer dereference on kernel/auditsc.c as follows: > > (1) go around the loop that starts at line 281 once, follow a path > till you get to line 434. This line tests for "if (ctx)", which > implies that null is a legal value for that variable. > > (2) go around the loop again, this time selecting the > "case AUDIT_PERM" at line 460. > > (3) then the function call on line 461 passes a null pointer, > "ctx," into procedure "audit_match_perm." However this > procedure dereferences "ctx" unconditionally at its very > first statement "unsigned n = ctx->major". > >
This situation arises because audit_filter_rules() is used to check both syscall and task rules, which have fairly different characteristics. When it's doing syscall rules it's called on syscall entry and exit where you can assume ctx is good because it has already been checked further up the call stack. When it's doing task rules it's called for a new task that doesn't have a ctx yet. That is why the checks are there. We don't actually see a null ptr dereference in real life for some obscure reasons. AUDIT_PERM - the auditctl configuration tool doesn't let you specify perms in a rule without also specifying a watch. A watch field will always fail to match at task create time (the name parameter is NULL). I imagine auditctl always orders the rule so AUDIT_WATCH comes before AUDIT_PERM, so we get the 0 result first time through the loop and jump out early. AUDIT_FILTERKEY - auditctl doesn't let you specify a filterkey in a rule unless you also specify either a syscall or a watch. A syscall isn't allowed in a task rule and a watch won't match at task create time (same as above). AUDIT_SUBJ_* - you can make a rule that will match on task create with one of these fields. Then without checking ctx we will assign it to audit_buffer->ctx. However, we are safe because audit_buffer->ctx is never actually used as far as I can tell. The kernel interface doesn't make the restrictions that the auditctl tool makes. If you wrote your own configuration tool, you could produce a null ptr dereference pretty easily. I agree with you that this code should be cleaned up, or at the very least commented.
This was corrected in 2.6.27-rc2 by Zhang Xiliang in commit 1a61c88defcd611bd148d6c960b498e1b8bbbe00.