Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Undefine _FORTIFY_SOURCE only on what's needed #2344

Merged
merged 1 commit into from
Aug 19, 2024

Conversation

dotnwat
Copy link
Contributor

@dotnwat dotnwat commented Jul 10, 2024

Seastar cmake build contains

target_compile_options (seastar
  PUBLIC
    -U_FORTIFY_SOURCE)

Which disables FORTIFY_SOURCE on all Seastar targets and is inherited by anything depending on Seastar.

This PR undefines this only on src/core/thread.cc which is apparently the only thing that needs it, and avoids leaking this out to dependents.

By undefining this as a public compile definition, it leaks into
everything that depends on Seastar, but appears to only be needed by
thread.cc which uses longjmp.

Signed-off-by: Noah Watkins <noahwatkins@gmail.com>
CMakeLists.txt Outdated
Comment on lines 508 to 511
set(FORTIFY_BUILD_TYPES "Release;RelWithDebInfo;Dev")
if(CMAKE_BUILD_TYPE IN_LIST FORTIFY_BUILD_TYPES)
add_definitions(-D_FORTIFY_SOURCE=2)
endif()
Copy link
Contributor Author

@dotnwat dotnwat Jul 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is added in a separate commit that we can drop.

It's only real purpose here is to demonstrate that the tests pass with _FORTIFY_SOURCE=2 while being undefined only on src/core/thread.cc.

Copy link
Contributor

@tchaikov tchaikov Jul 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this works if we use a single-configuration generator. but it does not work if we use a multi-config generator to generate the rules. if we use

cmake -G "Ninja Multi-Config" 

to generate build.ninja, we cannot get the "current" build mode via CMAKE_BUILD_TYPE anymore. as this variable is determined at the configure time. but with multi-config generator, one can pick which configuration at build time, like:

cmake --build build --config Dev --target seastar

so, i'd suggest use the generator expression, which is expanded to different value specific to each build configuration, so we could use something like:

set(Seastar_RELEASE_BUILD_TYPES "Release;RelWithDebInfo")
target_compile_definitions (seastar
  PRIVATE
    $<$<IN_LIST:$<CONFIG>,${Seastar_RELEASE_BUILD_TYPES}>:-U_FORTIFY_SOURCE)

set(Seastar_FORTIFY_BUILD_TYPES "Debug;Sanitize;Dev")
target_compile_definitions (seastar
  PRIVATE
    $<$<IN_LIST:$<CONFIG>,${Seastar_FORTIFY_BUILD_TYPES}>:-U_FORTIFY_SOURCE;-D_FORTIFY_SOURCE=2)

in which,

  1. use PRIVATE so we don't force the parent project's to use the same fortification level as seastar does
  2. instead of using add_definitions() use target_compile_definitions(), more specific this way
  3. use the generator expression as explained above.
  4. disable fortification when building release build to restore the behavior of release builds, as suggested in my review of the previous commit.
  5. enable fortification when building debug builds to detect the potential security issues.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tchaikov i'm not suggesting that we leave this here, it is merely for testing. do you want fortify sources enabled?

Copy link
Contributor

@tchaikov tchaikov Jul 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dotnwat okay. i am inclined to agree with you that we should leave it to the user of library to decide what fortification level they want to use or even disable it. so let's drop the 2nd commit.

do you want fortify sources enabled?

if you are asking in the context of this specific PR. i think we don't have to be opinioned here. if, in general, the proposed change reflects what i have in my mind. i'd like to include it in the cmake-based projects i am working on.

@xemul xemul requested a review from tchaikov July 10, 2024 05:22
# We disable _FORTIFY_SOURCE because it generates false positives with longjmp() (src/core/thread.cc)
#

target_compile_options (seastar
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To educate myself.
Before the patch FORTIFY_SOURCE was off for the whole seastar. Now it's off for thread.cc only, is that correct?
If so, do we expect any performance penalties once it's enabled for most of the seastar?

Copy link
Contributor

@tchaikov tchaikov Jul 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To educate myself. Before the patch FORTIFY_SOURCE was off for the whole seastar.

yes, it's undefined for seastar, and also for the projects which use seastar via its .pc file and those which use seastar via its CMake config files.

Now it's off for thread.cc only, is that correct?

correct.

If so, do we expect any performance penalties once it's enabled for most of the seastar?

i think so. as the fortified version of glibc function do perform extra checks. i think, the next question would be "how much?". as an application can always override the level of the fortification level at the compile time using something like -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=3. so the answer might depend on what the compile options are used.

if the overhead is not negligible, or we don't have a benchmark to justify the change, i think the safe move is probably to

  1. keep this -U_FORTIFY_SOURCE private and apply it only to src/core/thread.cc as in this commit
  2. add this option back globally in Seastar as a private option when compiling in release builds.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry, i haven't read the 2nd commit. so it has been implemented. thanks!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2nd commit does this

+set(FORTIFY_BUILD_TYPES "Release;RelWithDebInfo;Dev")
+if(CMAKE_BUILD_TYPE IN_LIST FORTIFY_BUILD_TYPES)
+  add_definitions(-D_FORTIFY_SOURCE=2)
+endif()
+

I see the final result as -- set FORTIFY_SOURCE=2 for Release build. Is level 2 considered to be "no penalty"?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no, i don't think so. it incurs less penalty than level 3. to be on the safe side, i think we should undefine this macro for Release and RelWithDebInfo. as to Dev, we can enable level 2 or even level 3.

Copy link
Contributor Author

@dotnwat dotnwat Jul 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If so, do we expect any performance penalties once it's enabled for most of the seastar?

Just to clarify, I think to some extent this is the choice of the user of Seastar or even the build system (e.g. Bazel turns this on by default. I didn't observe CMake doing so), and doesn't necessarily need to be Seastar making this decision. I only added the second commit which turns on FORTIFY_SOURCES as a demonstration, that when turned on across the code base except for thread.cc, that things still work. Having FORTIFY_SOURCES enabled by Seastar is a decision for Seastar dev.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree Seastar should leave it to the application and not change defaults.

Can we just add #undef (plus comment explaining why) to the source file?

@tchaikov
Copy link
Contributor

@dotnwat hi Noah, do you plan to continue working on this PR? i still think _FORTIFY_SOURCE is a nice feature to identify runtime issues. and the first commit would suffice. seastar applications can opt out of this feature if desired.

@dotnwat
Copy link
Contributor Author

dotnwat commented Aug 13, 2024

@tchaikov yes, thanks for the ping. I can push an update tomorrow. But please feel free to cherry-pick the first commit if you want.

@dotnwat
Copy link
Contributor Author

dotnwat commented Aug 15, 2024

@dotnwat hi Noah, do you plan to continue working on this PR? i still think _FORTIFY_SOURCE is a nice feature to identify runtime issues. and the first commit would suffice. seastar applications can opt out of this feature if desired.

@tchaikov I dropped the second commit.

@tchaikov
Copy link
Contributor

thank you Noah!

Copy link
Contributor

@tchaikov tchaikov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@tchaikov
Copy link
Contributor

@scylladb/seastar-maint hello maintainers, could you help review / merge this change?

@avikivity avikivity merged commit 1526684 into scylladb:master Aug 19, 2024
14 checks passed
dotnwat added a commit to dotnwat/redpanda that referenced this pull request Sep 11, 2024
It causes problems with longjmp

    *** longjmp causes uninitialized stack frame ***: terminated
    Aborting on shard 0.
    Backtrace:

which was taken care of in the cmake build, but needs to be fixed in our
bazel build. reference: scylladb/seastar#2344

Signed-off-by: Noah Watkins <noahwatkins@gmail.com>
WillemKauf pushed a commit to WillemKauf/redpanda that referenced this pull request Sep 12, 2024
It causes problems with longjmp

    *** longjmp causes uninitialized stack frame ***: terminated
    Aborting on shard 0.
    Backtrace:

which was taken care of in the cmake build, but needs to be fixed in our
bazel build. reference: scylladb/seastar#2344

Signed-off-by: Noah Watkins <noahwatkins@gmail.com>
rockwotj pushed a commit to rockwotj/seastar that referenced this pull request Oct 28, 2024
It causes problems with longjmp

    *** longjmp causes uninitialized stack frame ***: terminated
    Aborting on shard 0.
    Backtrace:

which was taken care of in the cmake build, but needs to be fixed in our
bazel build. reference: scylladb#2344
rockwotj pushed a commit to rockwotj/seastar that referenced this pull request Oct 28, 2024
It causes problems with longjmp

    *** longjmp causes uninitialized stack frame ***: terminated
    Aborting on shard 0.
    Backtrace:

which was taken care of in the cmake build, but needs to be fixed in our
bazel build. reference: scylladb#2344
rockwotj pushed a commit to rockwotj/seastar that referenced this pull request Oct 28, 2024
It causes problems with longjmp

    *** longjmp causes uninitialized stack frame ***: terminated
    Aborting on shard 0.
    Backtrace:

which was taken care of in the cmake build, but needs to be fixed in our
bazel build. reference: scylladb#2344
nyh pushed a commit that referenced this pull request Oct 28, 2024
It causes problems with longjmp

    *** longjmp causes uninitialized stack frame ***: terminated
    Aborting on shard 0.
    Backtrace:

which was taken care of in the cmake build, but needs to be fixed in our
bazel build. reference: #2344

Closes #2522
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.

4 participants