On Tue, Jun 05, 2018 at 22:04:37 +0200, Kamil Rytarowski wrote: > On 05.06.2018 20:47, Valery Ushakov wrote: > > Kamil Rytarowski <n...@gmx.com> wrote: > > > >> On 05.06.2018 18:14, Valery Ushakov wrote: > >>> Kamil Rytarowski <n...@gmx.com> wrote: > >>> > >>>> We've faced a problem with sanitizing part of the NetBSD userland, as we > >>>> need to use helper functions to make sanitization possible in some > >>>> narrow cases that aren't clear for sanitizers. > >>>> > >>>> The current problem is the usage of callback functions defined in > >>>> programs and executed from the internals of libc. > >>> [...] > >>>> Once a callback function is executed from the internals of libc, a > >>>> sanitized program does not know whether the arguments passed to it are > >>>> properly initialized. > >>> > >>> Why? What makes calling from libc special? It's probably obvious to > >>> you since you've been workign on this for a while, but most of us have > >>> no clue. > > [...] > >> In the fts_open(3) case, there is performed allocation of FTSENT > >> entries inside libc and this buffer is passed to the callback > >> function without prior notifying the user of fts_open(3) about these > >> elements (their address and size of initialized buffer). MSan does > >> not know whether the passed arguments to the arguments of the > >> callback are initialized or not. > > > > So the issue is that libc is compiled without sanitizer and > > allocations done inside libc are not known to a sanitizer? For libc > > functions that return allocated memory I guess you mark it in the > > sanitizer's interposed wrapper ("interceptor"?), but in the case of > > callbacks there is no interceptor between libc and the callback to do > > that. Is that about right? > [...] > but in general the sanitizers have no > information what happens inside libc, treating it as a blackbox. > [...] > > Interceptos mostly have rules of type PreRead/PostRead and > PreWrite/PostWrite arguments passed to functions in libc (pthread, ..). > In the MSan case during PreWrite there is a check whether arguments > passed to a function are properly initialized, and in PostRead phase > mark the buffers as initialized. > > In the fts_open(3) case there is no stage between the time of being > aware about initialzed (not just allocated) FTSENT buffers and executing > callback function that already needs this information. In this case, > there is need to help to Memory Sanitizer with explicit __msan_unpoison().
It sounds like sanitizers must use run-time generated closures or compile-time generated auxiliary functions to wrap libc callbacks. I.e. when code calls fts_open(..., compare); the sanitizer must generate code to call fts_open(..., sanitize_compare); where sanitize_compare does the pre/post checks around a call to the real compare. > There are similar cases when someone is using syscall(2) directly. > There are helper macros and functions to make usage of > syscall(2)-like API easier, e.g. for write(2): > > __sanitizer_syscall_pre_write(fd, buf, nbyte) > res = write(fd, buf, nbyte) > __sanitizer_syscall_post_write(res, fd, buf, nbyte) I'm confused, how is this write(2) example relevant to syscall(2)? -uwe