Skip to content

Conversation

@brooksdavis
Copy link
Member

During today's compartmentalization meeting I realized one could write a macro that replace calls to fprintf that take stderr as an argument with a call to another function where stderr is used implicitly. This optimization occurs even at -O0 with all the compilers I tested. In this PR I add __stderr_printf as well as wide char and locale aware variants and add a macro.

I've currently put the fprintf macro behind a defined(__SQUASH_FPRINTF_STDERR) so we can experiment with doing this selectively. That being said, with two trivial patches I've not included, it is possible to build world and boot the resulting system with the macro universally defined.

This closes the symmetry gap between printf and fprintf(stderr,...).

It is a common pattern in image libraries to have output to stderr
be the only IO in otherwise compute-only code.  With CHERI
compartmentalization using __stedrr_printf(...) vs fprintf(stderr,
...) is the difference between being able to write to stderr vs a
gadget that can write to any open file descriptor (given the ability
to corrupt __stderrp).
When __SQUASH_FPRINTF_STDERR is defined, replace fprintf(stderr, ...)
with __stderr_printf(...).

If __stderr_printf (or the like) were standard, a compiler could do this
and it would be much tidier.  As it is, this works quite well (even at
-O0 across all compilers I tested) and because we're defining a
function-like macro you can still take a function pointer to fprintf().
@brooksdavis brooksdavis changed the base branch from main to dev May 20, 2025 23:27
@jrtc27
Copy link
Member

jrtc27 commented May 20, 2025

Hm. I need to think about this. I don't love the use of strings, and I don't love that this is relying on optimisations for something that I'm very surprised is done even at -O0.

@brooksdavis
Copy link
Member Author

Hm. I need to think about this. I don't love the use of strings, and I don't love that this is relying on optimisations for something that I'm very surprised is done even at -O0.

I was surprised to find that it's such a universally applied optimization, but it seems to be (I checked back to gcc 4.0 in compiler explorer). I do tend to think the transformation ultimately belongs in the compiler if at all rather than in a system wide macro.

@brooksdavis
Copy link
Member Author

There's probably a case to be made for using __builtin_choose_expr instead of the if statement. That will fail if it's somehow non-const. It does look like extremely old clang versions don't make __builtin_strcmp const, but they aren't especially relevant. That does suggest you couldn't do this universally without some guards unless you did it in the compiler.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants