From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mout.web.de (mout.web.de [212.227.17.11]) by sourceware.org (Postfix) with ESMTPS id 52FFD385840D for ; Sat, 4 Sep 2021 19:00:57 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 52FFD385840D X-UI-Sender-Class: c548c8c5-30a9-4db5-a2e7-cb6cb037b8f9 Received: from reader ([185.220.101.9]) by smtp.web.de (mrweb103 [213.165.67.124]) with ESMTPSA (Nemesis) id 0MTy9d-1mV5Kp3dir-00Qnhq for ; Sat, 04 Sep 2021 21:00:55 +0200 Received: by reader (Postfix, from userid 1000) id 3CD2E21DD; Sat, 4 Sep 2021 21:00:45 +0200 (CEST) Date: Sat, 4 Sep 2021 21:00:45 +0200 From: Dennis Filder To: libc-help@sourceware.org Subject: LD_PRELOAD wrappers for system calls and stdio Message-ID: MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline X-Provags-ID: V03:K1:GW5hS4ANLCXSLP9N09ICk21N9lhV519dVuieLF95PpvMC4zcF3i ZOlXkVND0sJxIfOkLWVU4iYkPTSSR9/ZUpLtKYvB0bg/k6Nm/08bTybIZD62KmrLf3lxqND TPA8a5wC50tNgCHvkjcehF45wfmmy5H4B60t0latPaZ17KigbuAb1Q7pycaZlV4mddacrwQ 8q6IQl4svFQY0SEwjcjIA== X-UI-Out-Filterresults: notjunk:1;V03:K0:bPe5gPM19OE=:1lCAoXYvbhUJ91mSsbGGUx 0Og7zuz88VMVfbgRzhd82NHJDQBFj2YFitj7Iv4AQXRTrzKOdM9txa68fs9vo3oza9S9EJD77 eBfetAiy0Qc55ZDYFaNFnv4/iFNGQqE+mkweyFqEhPcHvJX06POCU7ARIg7SqcFP/P/b+uxU7 bIuusr+A/UpfZs5BpxIQzdxKHYgpFmj/geCZnjTcUNAbWxyg9a2pB9EdYk06WFUynabe4pHq3 4qV1dhldOPdGjBNe2H5c57nZC6yXUQrWCE0onPJnDmnhKdq+xWO0N751zcbufJCIrzFLUgjom Ghtxsc6o30XJ8jbvVXCvy7oRR0B5meesDyDFBOSLfN1xiQM9HU0tMe+/lsZYEgVPCDkXdlorZ ldzEqWkK/QaorU9+3n6TveCsN/qDUfyq4X6vzgrAWlBYnhJ9AfNlFdZWRGggK35UctJigMA5h m/NtVPNoucKr4LbAv67HrCh6qiRZ13mReaW0iCXzx4JW/ZRTD5Yu4MRhcvL7iMI2ArkA2iKp/ qrTOfHHeSQJzsoRBuwffcjUllX6zEya6xCAnUHc2Ph6oQ83rNLVOuFNRecRJtxj7nfD/5usng 2K4ogXKSMKblbTp4FQHKDjP3pHzvEJCZ5yA7yBa9l/lzytqRJ1vS42JUPrpE/ANPXmSy2xEIi NkhzXNj4k6OpwnTKzCpKjzF2s5H3VM08eWgwgeW+8dMysVwqgnIsSZA/ZH8k91iza0pGTBQeP KePL1kN/7E3LC+iKJHUzTXlQGVNn9z+v5f5OyfHtTzMZ4wOMcKfzOds1GMy4mPVLJ6oUH+w3B 9bG9IWJjgvAeyPUkr1k0cE/WSbRwTVZ7imQ9aSrSfdfzeqSMOthbkxPKuB4lQskBPokVRSiK2 L95+LiQBZho3fnWl+5AsITOjqOf1zSPoGA4lbQwH9YBzdAIxsojH/oyqcSovyTeuq69kUE2mo OB5uJyWM1nrp2lDnsWi6iFRelE1vil5HYITOMkTSiPoldds7gv8wQ5UaCzc4sVdtYHVoS7Ss/ HR3ezMI+mP+u2Q0dyIyjeUALSarOVFrxnvD0GXTsNLOL99y63Hdfm3ZQna2m3dpR6dJBqFqZG CPPCNxXV5cavdhMikL+BOTvWuWYHBbTokE7qIFS1zlrPgoYDsvhd7tBcw== X-Spam-Status: No, score=-3028.0 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, RCVD_IN_ABUSEAT, RCVD_IN_BL_SPAMCOP_NET, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=no autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: libc-help@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-help mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 04 Sep 2021 19:01:00 -0000 Hi, I'm trying to write an LD_PRELOAD hack for the purpose of tracing/logging. The goal was to get a time-stamped copy of everything that is ever read/written over a selected set of file descriptors and log it to another file descriptor. A second goal was achieving a high degree of portability. My naive hope was that I could implement this by wrapping just a handful of system call wrappers and be done with it. Imagine my surprise when in the process of coding that up (under Linux) I came to notice that not all stdio functions use write() internally to actually write data to a file descriptor. Some, e.g. fwrite(), do something esoteric which involves book-keeping with a FILE object and also an apparently in-lined invocation of syscall(SYS_write, ...). If my understanding is correct then this means that it is literally impossible to attain my goal by wrapping only the system call wrappers which would leave me (and thus basically everyone in a similar position) with these options: a) also wrap essentially /every/ stdio function that is not guaranteed to only call already wrapped functions, b) use the Linux Auditing System instead, or c) use ptrace() instead and reimplement 3/4 of ltrace/strace. Neither prospect has me rejoicing as they involve either a ton of work and/or sacrificing portability. What am I supposed to do? I'm currently examining what it would take for option a), but I'm running into a steady stream of roadblocks. A major one I'm stuck at are the variadic functions (printf and friends). One way out seems to be to use GCC's __builtin_apply and calculate its size argument using a function that would have to be similar to glibc's parse_printf_format, but which would only return the number of bytes the arguments occupy on the stack (Would it be too much to ask to provide such a function as part of glibc?). But I don't know if register-involving calling conventions will harmonize with that approach. Will they? Also what makes me reluctant to explore this further is the fear that I will eventually have to implement not just wrappers, but full-on replacements. And I'd probably have to do the same for libstdc++, too. Thanks in advance for any help/clarification. P.S.: Solutions that involve installing a specially built version of glibc (e.g. with INLINE_SYSCALL undefined) are less than ideal because this project is not for personal, but public use, and having a custom-built libc as a dependency is thus effectively a showstopper. But maybe it would be possible to transplant a subset of routines from such a libc into my library. But how would I even do that? Close study of build logs tells me one of stdio-common/stamp.o and libc_pic.{a,os,os.clean} probably contains what I want, but I'm not sure what will break if I just copy that over.