[DTrace-devel] [PATCH v3 13/19] alloca: support null pointers
Nick Alcock
nick.alcock at oracle.com
Tue Mar 29 13:37:08 UTC 2022
On 28 Mar 2022, Kris Van Hees verbalised:
> We already have validation of memory access for other cases because those
> require the use of bpf_probe_read() which employs the address validation that
> the kernel provides already. No need to do it ourselves. We can just ensure
> that we report BADADDR for failed bpf_probe_read( calls.
So... I just checked. Nearly all our bpf_probe_read calls are in the
string stuff, which is a) in raw asm (and thus hard enough to maintain
as it is, and IIRC a nightmare to write) and b) usually does not verify
any such thing and just assumes bpf_probe_read will never fail or
returns wrong results without faulting if it does. As far as I can
tell, we never raise any faults in bpf/*.S at all, and the code in dt_cg
that calls it never faults in response to erroneous return values either
(unsurprisingly: mostly it can't distinguish fault returns from
non-faulting valid error-return-value returns: the dt_cg calling code
would be the wrong place to raise these faults).
basename.S: returns <= 1 (including negative) return '.'
dirname.S: ditto
index.S: has error-checking of a sort, but all errors yield -1, so no
BADADDR is ever raised even if you pass in complete garbage and
bpf_probe_read fails
rindex.S: ditto
strchr.S: ditto
substr.S: errors silently return the empty string (!)
strcmp.S: almost no error-checking. Most reads from strings are
assumed never to fail: in the one case there is error-checking
we just return 0 on error, because a null pointer is obviously
equal to everything
strjoin.S: errors yield a silent return with no error
lltostr.S: no error-checking.
strlen.c: no error-checking, but at least it's returning -1 on error; of
course, that's not a BADADDR fault
strchr.S: ditto.
strtok.S: delimiter table copy not error-checked. Initial temp copy of
string not error-checked. Everything else is error-checked,
but by then it is of course too late. On error we just return
0 anyway. No fault raised.
get_bvar is fine (though this only uses it in the implementation of
DIF_VAR_PPID, which had better not fail :) )
In conclusion: our error checking of copies lies somewhere between
nonexistent and worse than that (in that errors lead to outright wrong
results).
In conclusion: we should *definitely* not remove the extra checks yet.
Given that our rate of spontanoeusly writing accurate error checks in
response to bpf_probe_read* calls appears to be near-zero, I suspect we
should never remove them at all and should probably think about adding
more. At least dt_cg_check_notnull is a single centralized place to add
the damn things.
Alternatively, I could add error checking to all of this and remove the
extra near-nullptr checking when I do that (since we *do* need error
checking there, no matter what). That should be a separate commit
though. How we ensure that future new code properly checks these things
for errors, when we never managed it before, I have no idea.
More information about the DTrace-devel
mailing list