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

8329013: StackOverflowError when starting Apache Tomcat with signed jar #18534

Closed
wants to merge 2 commits into from

Conversation

coffeys
Copy link
Contributor

@coffeys coffeys commented Mar 28, 2024

Calling extra logging calls during initialization of Logger libraries can cause recursion leading to StackOverflowError
This patch adds logic to the EventHelper class to detect recursion and prevent it.


Progress

  • Change must be properly reviewed (1 review required, with at least 1 Reviewer)
  • Change must not contain extraneous whitespace
  • Commit message must refer to an issue

Issue

  • JDK-8329013: StackOverflowError when starting Apache Tomcat with signed jar (Bug - P4)

Reviewers

Reviewing

Using git

Checkout this PR locally:
$ git fetch https://git.openjdk.org/jdk.git pull/18534/head:pull/18534
$ git checkout pull/18534

Update a local copy of the PR:
$ git checkout pull/18534
$ git pull https://git.openjdk.org/jdk.git pull/18534/head

Using Skara CLI tools

Checkout this PR locally:
$ git pr checkout 18534

View PR using the GUI difftool:
$ git pr show -t 18534

Using diff file

Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/18534.diff

Webrev

Link to Webrev Comment

@bridgekeeper
Copy link

bridgekeeper bot commented Mar 28, 2024

👋 Welcome back coffeys! A progress list of the required criteria for merging this PR into master will be added to the body of your pull request. There are additional pull request commands available for use with this pull request.

@openjdk
Copy link

openjdk bot commented Mar 28, 2024

@coffeys This change now passes all automated pre-integration checks.

ℹ️ This project also has non-automated pre-integration requirements. Please see the file CONTRIBUTING.md for details.

After integration, the commit message for the final commit will be:

8329013: StackOverflowError when starting Apache Tomcat with signed jar

Reviewed-by: dfuchs, jpai

You can use pull request commands such as /summary, /contributor and /issue to adjust it as needed.

At the time when this comment was updated there had been 169 new commits pushed to the master branch:

  • dd5d7d0: 8327002: (fs) java/nio/file/Files/CopyMoveVariations.java should be able to test across file systems
  • 6ae1cf1: 8329368: Generational ZGC: Remove the unnecessary friend classes in ZAllocator
  • 7eb78e3: 8320676: Manual printer tests have no Pass/Fail buttons, instructions close set 1
  • 5ac067f: 8329289: Unify SetupJdkExecutable and SetupJdkLibrary
  • 5ae849d: 8329292: Fix missing cleanups in java.management and jdk.management
  • ed821cb: 8324807: Manual printer tests have no Pass/Fail buttons, instructions close set 2
  • 5cf457b: 8329320: Simplify awt/print/PageFormat/NullPaper.java test
  • 8b934aa: 8329358: Generational ZGC: Remove the unused method ZPointer::set_remset_bits
  • 3b582df: 8051959: Add thread and timestamp options to java.security.debug system property
  • 816638e: 8329352: Remove dead code in splashscreen_sys.c
  • ... and 159 more: https://git.openjdk.org/jdk/compare/d3f3011d56267360d65841da3550eca79cf1575b...master

As there are no conflicts, your changes will automatically be rebased on top of these commits when integrating. If you prefer to avoid this automatic rebasing, please check the documentation for the /integrate command for further details.

➡️ To integrate this PR with the above commit message to the master branch, type /integrate in a new comment.

@openjdk openjdk bot changed the title 8329013 8329013: StackOverflowError when starting Apache Tomcat with signed jar Mar 28, 2024
@openjdk openjdk bot added the rfr Pull request is ready for review label Mar 28, 2024
@openjdk
Copy link

openjdk bot commented Mar 28, 2024

@coffeys The following labels will be automatically applied to this pull request:

  • core-libs
  • security

When this pull request is ready to be reviewed, an "RFR" email will be sent to the corresponding mailing lists. If you would like to change these labels, use the /label pull request command.

@openjdk openjdk bot added security security-dev@openjdk.org core-libs core-libs-dev@openjdk.org labels Mar 28, 2024
@mlbridge
Copy link

mlbridge bot commented Mar 28, 2024

Webrevs

@jaikiran
Copy link
Member

jaikiran commented Apr 2, 2024

Hello Sean, from what I understand of this proposed fix, what we are attempting here is to prevent a re-entrant call into System.getLogger()? Is my understanding correct? The linked JBS issue has a stacktrace from Java 8 and doesn't match the current mainline code so it isn't fully clear to me what's triggering the re-entrancy and StackOverFlowError. I tried to reproduce this with the jtreg test that's part of this PR, without including your proposed fix, but that didn't reproduce the StackOverFlowError but the test seems to have uncovered some kind of deadlock in running the shutdown hook that the LogManager installs in the Runtime. I will check that issue separately.

@coffeys
Copy link
Contributor Author

coffeys commented Apr 2, 2024

Thanks for taking a look at this Jai. Without the src patch, the test should create an SOE. Have a look at the resulting jtr file[1]. jtreg complains about a timeout due to some other lock up issue. I figured that since the test shouldn't fail, then it shouldn't be an issue. Probably worth logging another issue to track that.

The EventHelper class can be called to log crypto events - if these events occur during logging initialization, then recursive calls can cause problems. This patch should fix up that area and block recursive calls (by returning false in the 2nd recursive call into same method)

[1] (pasting a better SOE stacktrace (first one was partial removal of src patch)

at java.base/jdk.internal.logger.LazyLoggers.getLogger(LazyLoggers.java:435) at java.base/java.lang.System.getLogger(System.java:1831) at java.base/jdk.internal.event.EventHelper.isLoggingSecurity(EventHelper.java:166) at RecursiveEventHelper.getProperty(RecursiveEventHelper.java:56) at java.logging/java.util.logging.LogManager.getLevelProperty(LogManager.java:2340) at java.logging/java.util.logging.LogManager$LoggerContext.addLocalLogger(LogManager.java:802) at java.logging/java.util.logging.LogManager$LoggerContext.ensureDefaultLogger(LogManager.java:752) at java.logging/java.util.logging.LogManager$LoggerContext.ensureAllDefaultLoggers(LogManager.java:716) at java.logging/java.util.logging.LogManager$LoggerContext.addLocalLogger(LogManager.java:774) at java.logging/java.util.logging.LogManager$LoggerContext.addLocalLogger(LogManager.java:758) at java.logging/java.util.logging.LogManager$SystemLoggerContext.demandLogger(LogManager.java:939) at java.logging/java.util.logging.LogManager.demandSystemLogger(LogManager.java:559) at java.logging/java.util.logging.LogManager$LoggingProviderAccess.demandLoggerFor(LogManager.java:2727) at java.logging/sun.util.logging.internal.LoggingProviderImpl.demandJULLoggerFor(LoggingProviderImpl.java:412) at java.logging/sun.util.logging.internal.LoggingProviderImpl.demandLoggerFor(LoggingProviderImpl.java:438) at java.base/jdk.internal.logger.DefaultLoggerFinder.getLogger(DefaultLoggerFinder.java:159) at java.base/jdk.internal.logger.LazyLoggers.getLoggerFromFinder(LazyLoggers.java:410) at java.base/jdk.internal.logger.LazyLoggers.getLazyLogger(LazyLoggers.java:465) at java.base/jdk.internal.logger.LazyLoggers.getLogger(LazyLoggers.java:435) at java.base/java.lang.System.getLogger(System.java:1831) at java.base/jdk.internal.event.EventHelper.isLoggingSecurity(EventHelper.java:166) STATUS:Failed.main' threw exception: java.lang.StackOverflowError
`

@jaikiran
Copy link
Member

jaikiran commented Apr 2, 2024

You are right, turns out the jtr file did have the StackOverFlowError from the test introduced in this PR - I just didn't check it given the other issue.

Now that I look at the stacktrace and the complex checks we are adding, I am starting to wonder if these re-entrancy checks should actually be added within the jdk.internal.logger implementation code/classes, instead of at these call sites. As far as I can see, the jdk.internal.event.EventHelper isn't doing anything out of the ordinary and the same issue could probably end up in some other parts during the logging initialization.

Copy link
Member

@dfuch dfuch left a comment

Choose a reason for hiding this comment

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

The code changes LGTM. Some comments on the test.

EventHelper.isLoggingSecurity();
return super.getProperty(p);
}
}
Copy link
Member

Choose a reason for hiding this comment

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

add newline?

// opening of a signed jar during System logger initialization triggered
// a recursive call (via EventHelper.isLoggingSecurity) back into
// logger API
EventHelper.isLoggingSecurity();
Copy link
Member

Choose a reason for hiding this comment

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

As an additional check you could set a static volatile boolean to true here and double check that it's been set at the end of the main method,

Copy link
Member

Choose a reason for hiding this comment

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

In fact it doesn't need to be volatile since it all happens in the main thread - but that's not a big issue.

@coffeys
Copy link
Contributor Author

coffeys commented Apr 2, 2024

@jaikiran I did look at adding logic in the Logger libraries also to correct this issue. Significant work was done in that area last year via JDK-8314263

I guess the question is what sort of Logger and LoggerFinder would you return in cases where recursion is detected ? Extra issues might arise from the System.getLogger method being public and widely used. Additional issues might stem from the fact that Logger libraries can be plugged in and returned Logger might be stored as a static variable etc.

It seemed safer to catch the issue at the EventHelper level - a library that's confined to internal JDK use.

@jaikiran
Copy link
Member

jaikiran commented Apr 2, 2024

I guess the question is what sort of Logger and LoggerFinder would you return in cases where recursion is detected ? Extra issues might arise from the System.getLogger method being public and widely used. Additional issues might stem from the fact that Logger libraries can be plugged in and returned Logger might be stored as a static variable etc.

Agreed - a lot of questions will need to be answered before attempting any change in that code. I don't have answers to any of those though :)

Given that System.getLogger() is public API and from the looks of it, any application code can trigger this issue without a JDK internal class involvement (I'm guessing if you modify the test in this PR to replace the call to EventHelper.isLoggingSecurity(); with var foo = System.getLogger("bar"); the StackOverFlowError issue will reproduce?), I think the real issue will continue to exist after this change.

Having said that, I didn't mean to stop you from doing this change in EventHelper. My question was merely an observation. Your change in the current form looks OK to me.

@openjdk openjdk bot added the ready Pull request is ready to be integrated label Apr 2, 2024
@coffeys
Copy link
Contributor Author

coffeys commented Apr 2, 2024

Thanks for the reviews. Yes - your suggestion would be another example of how recursion could occur with the System Logger Jai. I'll have a look to see if some sort of Noop Logger could be returned if recursion is detected at System Logger end.

/integrate

@openjdk
Copy link

openjdk bot commented Apr 2, 2024

Going to push as commit 925d829.
Since your change was applied there have been 169 commits pushed to the master branch:

  • dd5d7d0: 8327002: (fs) java/nio/file/Files/CopyMoveVariations.java should be able to test across file systems
  • 6ae1cf1: 8329368: Generational ZGC: Remove the unnecessary friend classes in ZAllocator
  • 7eb78e3: 8320676: Manual printer tests have no Pass/Fail buttons, instructions close set 1
  • 5ac067f: 8329289: Unify SetupJdkExecutable and SetupJdkLibrary
  • 5ae849d: 8329292: Fix missing cleanups in java.management and jdk.management
  • ed821cb: 8324807: Manual printer tests have no Pass/Fail buttons, instructions close set 2
  • 5cf457b: 8329320: Simplify awt/print/PageFormat/NullPaper.java test
  • 8b934aa: 8329358: Generational ZGC: Remove the unused method ZPointer::set_remset_bits
  • 3b582df: 8051959: Add thread and timestamp options to java.security.debug system property
  • 816638e: 8329352: Remove dead code in splashscreen_sys.c
  • ... and 159 more: https://git.openjdk.org/jdk/compare/d3f3011d56267360d65841da3550eca79cf1575b...master

Your commit was automatically rebased without conflicts.

@openjdk openjdk bot added the integrated Pull request has been integrated label Apr 2, 2024
@openjdk openjdk bot closed this Apr 2, 2024
@openjdk openjdk bot removed ready Pull request is ready to be integrated rfr Pull request is ready for review labels Apr 2, 2024
@openjdk
Copy link

openjdk bot commented Apr 2, 2024

@coffeys Pushed as commit 925d829.

💡 You may see a message that your pull request was closed with unmerged commits. This can be safely ignored.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
core-libs core-libs-dev@openjdk.org integrated Pull request has been integrated security security-dev@openjdk.org
Development

Successfully merging this pull request may close these issues.

3 participants