TE
TechEcho
Home24h TopNewestBestAskShowJobs
GitHubTwitter
Home

TechEcho

A tech news platform built with Next.js, providing global tech news and discussions.

GitHubTwitter

Home

HomeNewestBestAskShowJobs

Resources

HackerNews APIOriginal HackerNewsNext.js

© 2025 TechEcho. All rights reserved.

Consistently Making Wrong Decisions Whilst Writing Recreational C

215 pointsby luu9 months ago

11 comments

nneonneo9 months ago
This is cute! It’s worth pointing out that strace ships a similar feature (-e fault) which works for any syscall, even if the binary is statically linked. It works using ptrace, which is lower level than LD_PRELOAD. Although -e fault doesn’t support probabilistic failure, it does provide a flexible way to target specific invocations of a syscall. For example, to fail every second fork() call: -e fault=fork,errno=ENOMEM,when=1+2.
评论 #41348367 未加载
dmlorenzetti9 months ago
It seems like it would be a lot easier to just have students call, e.g., `ta_fork()` rather than `fork()`, and then provide an implementing file to be linked with their program. Then `ta_fork()` allows the TA to trigger errors, either probabilistically or deterministically (say, by setting environment variables).<p>This approach would also give students insight into testing strategies like mocking, plus it would work on more operating systems.<p>[Edit: Not to disparage this project. It seems like it would have lots of uses, and it was probably a lot of fun to develop.]
评论 #41346839 未加载
评论 #41343474 未加载
woodruffw9 months ago
Nice writeup! One limitation to this approach is that the fault injections happen at the dynamic linkage to libc layer, meaning that an enterprising student who either statically links their binary or invokes syscalls directly will circumvent the interposed functions. But in a teaching setting I could imagine this isn’t a practical concern :-)<p>(I built a similar tool[1] a few years ago, but at the syscall layer to ensure that statically linked binaries could also have faults injected into them reliably. My colleagues used it to find a handful of bugs on prominent Go codebases.)<p>[1]: <a href="https:&#x2F;&#x2F;blog.trailofbits.com&#x2F;2019&#x2F;01&#x2F;17&#x2F;how-to-write-a-rootkit-without-really-trying&#x2F;" rel="nofollow">https:&#x2F;&#x2F;blog.trailofbits.com&#x2F;2019&#x2F;01&#x2F;17&#x2F;how-to-write-a-rootk...</a>
jcalvinowens9 months ago
You can use pthread_once() to simplify the initialization part: <a href="https:&#x2F;&#x2F;man.archlinux.org&#x2F;man&#x2F;pthread_once.3.en" rel="nofollow">https:&#x2F;&#x2F;man.archlinux.org&#x2F;man&#x2F;pthread_once.3.en</a><p>I don&#x27;t understand the desire not to link to pthread, it&#x27;s about as ubiquitous as a library can be.<p>I doubt it&#x27;s really a problem in this application... but naive userspace spinlocks are absolutely horrendous, see NOTES here: <a href="https:&#x2F;&#x2F;man.archlinux.org&#x2F;man&#x2F;pthread_spin_init.3.en" rel="nofollow">https:&#x2F;&#x2F;man.archlinux.org&#x2F;man&#x2F;pthread_spin_init.3.en</a><p><pre><code> User-space spin locks [...] are, by definition, prone to priority inversion and unbounded spin times. A programmer using spin locks must be exceptionally careful not only in the code, but also in terms of system configuration, thread placement, and priority assignment.</code></pre>
ashvardanian9 months ago
Very cool! I&#x27;ve started a similar project around `LD_PRELOAD` a few months ago to profile the time different programs spend on LibC calls. Provoking failures was the next step :)<p>Logging nicely was also an issue. I decided to avoid linking to any other symbols and implemented it with inline Assembly for x86&#x2F;64 and aarch64: <a href="https:&#x2F;&#x2F;github.com&#x2F;ashvardanian&#x2F;LibSee&#x2F;blob&#x2F;fdae92e71c449c9196a7d3b7d547bdbd6417e481&#x2F;libsee.c#L425-L542">https:&#x2F;&#x2F;github.com&#x2F;ashvardanian&#x2F;LibSee&#x2F;blob&#x2F;fdae92e71c449c91...</a>
fuhsnn9 months ago
Perl, at build time, get errno numbers of the system in a similar way[0]: preprocess errno.h with `$CC -E` and recursively scan all files in # markers for macro defines.<p>The configure script even checks the existence of several system headers this way, so if your C compiler don&#x27;t support # markers in -E output, you get missing includes everywhere.<p>[0] <a href="https:&#x2F;&#x2F;github.com&#x2F;Perl&#x2F;perl5&#x2F;blob&#x2F;blead&#x2F;ext&#x2F;Errno&#x2F;Errno_pm.PL">https:&#x2F;&#x2F;github.com&#x2F;Perl&#x2F;perl5&#x2F;blob&#x2F;blead&#x2F;ext&#x2F;Errno&#x2F;Errno_pm....</a>
jrpelkonen9 months ago
Great article. Although I’ve been a Linux user since the time when stack of Slackware floppies was the prevailing installation media, I just recently learned that libc.so is also an executable.
评论 #41344287 未加载
评论 #41357044 未加载
评论 #41343267 未加载
rapidlua9 months ago
It was fun to read, but it would’ve probably been easier to rely on seccomp filters instead.
petters9 months ago
&gt; and parsing it out of the man pages is not something I’d like to imagine doing reliably. So I must satisfy myself by manually writing these facts down. And this turns out to be the bottleneck of the entire operation.<p>You can probably use an LLM for this.
评论 #41345637 未加载
supriyo-biswas9 months ago
From what I understand, it&#x27;d had been far easier to use a seccomp filter instead. Would have worked with statically linked binaries too.
Joker_vD9 months ago
&gt; (cannot dynamically load position-independent executable)<p>...why though? I mean, it&#x27;s position-independent, just load and relocate it wherever? Or does &quot;PIE&quot; mean something different in Linux from what it does in Windows?
评论 #41345163 未加载