Skip to content
This repository has been archived by the owner on Sep 2, 2022. It is now read-only.

8272058: 25 Null pointer dereference defect groups in 4 files #51

Closed
wants to merge 7 commits into from
Closed

8272058: 25 Null pointer dereference defect groups in 4 files #51

wants to merge 7 commits into from

Conversation

dcubed-ojdk
Copy link
Member

@dcubed-ojdk dcubed-ojdk commented Dec 20, 2021

A small refactoring to resolve a Parfait complaint about the return value from
MacroAssembler::target_addr_for_insn(address insn_addr, unsigned insn)
on AARCH64. The logic that supports returning nullptr as the target addr for
a particular instruction is moved from
MacroAssembler::target_addr_for_insn(address insn_addr, unsigned insn) to
MacroAssembler::target_addr_for_insn_allow_null_ret(address insn_addr, unsigned insn).
A couple of target_addr_for_insn() call sites that can tolerate a nullptr are
converted to use target_addr_for_insn_allow_null_ret().

This fix has been tested with Mach5 Tier[1-3].


Progress

  • Change must not contain extraneous whitespace
  • Commit message must refer to an issue
  • Change must be properly reviewed

Issue

  • JDK-8272058: 25 Null pointer dereference defect groups in 4 files

Reviewers

Reviewing

Using git

Checkout this PR locally:
$ git fetch https://git.openjdk.java.net/jdk18 pull/51/head:pull/51
$ git checkout pull/51

Update a local copy of the PR:
$ git checkout pull/51
$ git pull https://git.openjdk.java.net/jdk18 pull/51/head

Using Skara CLI tools

Checkout this PR locally:
$ git pr checkout 51

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

Using diff file

Download this PR as a diff file:
https://git.openjdk.java.net/jdk18/pull/51.diff

@bridgekeeper
Copy link

bridgekeeper bot commented Dec 20, 2021

👋 Welcome back dcubed! 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.

@dcubed-ojdk
Copy link
Member Author

dcubed-ojdk commented Dec 20, 2021

The Parfait complaint at the root of this issue is:

MacroAssembler::target_addr_for_insn
open/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp

286. | } else if (Instruction_aarch64::extract(insn, 31, 22) == 0b1011100101 &&
287. |            Instruction_aarch64::extract(insn, 4, 0) == 0b11111) {
288. |   return 0;  // Null pointer introduced .
289. | } else {
290. |   ShouldNotReachHere();

@openjdk
Copy link

openjdk bot commented Dec 20, 2021

@dcubed-ojdk The following label will be automatically applied to this pull request:

  • hotspot

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

@openjdk openjdk bot added the hotspot hotspot-dev@openjdk.java.net label Dec 20, 2021
@dcubed-ojdk
Copy link
Member Author

/label add hotspot-runtime

@openjdk openjdk bot added the hotspot-runtime hotspot-runtime-dev@openjdk.java.net label Dec 20, 2021
@openjdk
Copy link

openjdk bot commented Dec 20, 2021

@dcubed-ojdk
The hotspot-runtime label was successfully added.

@dcubed-ojdk
Copy link
Member Author

/label remove hotspot

@openjdk openjdk bot removed the hotspot hotspot-dev@openjdk.java.net label Dec 20, 2021
@openjdk
Copy link

openjdk bot commented Dec 20, 2021

@dcubed-ojdk
The hotspot label was successfully removed.

@dcubed-ojdk dcubed-ojdk marked this pull request as ready for review December 20, 2021 21:24
@openjdk openjdk bot added the rfr Pull request is ready for review label Dec 20, 2021
@mlbridge
Copy link

mlbridge bot commented Dec 20, 2021

Webrevs

@dholmes-ora
Copy link
Member

Hi Dan,

In terms of the refactoring and addressing the warning this seems reasonable. But in terms of semantics this claims that all the remaining callsites for target_addr_for_insn can never pass an insn that can lead to a NULL address. I can't verify that claim. This needs some Aarch64 experts to chime in - perhaps @theRealAph?

Thanks,
David

@dcubed-ojdk
Copy link
Member Author

@dholmes-ora - Thanks for taking a look. I did take the time to look at all the
remaining call sites for target_addr_for_insn and, in some cases, their callers
and I didn't see anything where it made sense to run into an insn that could
lead to a nullptr address. Of course, that's just code inspection on my part
so I also created guarantee() traps at all the call-sites and ran those bits
thru Mach5 Tier[1-8] testing without hitting any of the traps. As you pointed
out in the bug report, that kind of testing isn't proof either, but it helps me
believe that I didn't miss anything too obvious.

Having @theRealAph chime in here would be wonderful!

@dcubed-ojdk
Copy link
Member Author

@gerard-ziemski - When you have a chance, could you take a look at this one?

Copy link

@gerard-ziemski gerard-ziemski left a comment

Choose a reason for hiding this comment

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

I don't understand the underlying code, but from a big picture point of view, splitting the call into "null not allowed" and "null allowed" makes sense. If the testing came back fine, then that's the best we can do, without asking someone who wrote this code to chime in.

Just one question: why do we need the "null allowed" version here?

void NativeMovRegMem::verify() {
#ifdef ASSERT
address dest = MacroAssembler::target_addr_for_insn_allow_null_ret(instruction_address());
#endif
}

@dcubed-ojdk
Copy link
Member Author

@gerard-ziemski - Thanks for the review.

According to "git blame", the original author is:

9c458de hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp (Andrew Haley 2015-01-20 11:34:17 -0800 211) address MacroAssembler::target_addr_for_insn(address insn_addr, unsigned insn) {

which I believe is why @dholmes-ora pinged @theRealAph on this PR...

As for this function:

void NativeMovRegMem::verify() {
#ifdef ASSERT
  address dest = MacroAssembler::target_addr_for_insn_allow_null_ret(instruction_address());
#endif
}

I did not see any harm in converting to target_addr_for_insn_allow_null_ret.
The baseline code worked just fine before I refactored it so I'm giving
the function equivalence. In other words, if NativeMovRegMem::verify()
was previous called with an instruction_address() value that leads to
a nullptr, then baseline verify() would work without error. I wanted the
new verify() to also work the same.

@gerard-ziemski
Copy link

@gerard-ziemski - Thanks for the review.

According to "git blame", the original author is:

9c458de hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp (Andrew Haley 2015-01-20 11:34:17 -0800 211) address MacroAssembler::target_addr_for_insn(address insn_addr, unsigned insn) {

which I believe is why @dholmes-ora pinged @theRealAph on this PR...

As for this function:

void NativeMovRegMem::verify() {
#ifdef ASSERT
  address dest = MacroAssembler::target_addr_for_insn_allow_null_ret(instruction_address());
#endif
}

I did not see any harm in converting to target_addr_for_insn_allow_null_ret. The baseline code worked just fine before I refactored it so I'm giving the function equivalence. In other words, if NativeMovRegMem::verify() was previous called with an instruction_address() value that leads to a nullptr, then baseline verify() would work without error. I wanted the new verify() to also work the same.

As long as parfait doesn't complain here - I didn't see where we checked for NULL explicitly in this case. I assume that parfait skips the ASSERT parts?

@dcubed-ojdk
Copy link
Member Author

As long as parfait doesn't complain here - I didn't see where we checked for NULL
explicitly in this case. I assume that parfait skips the ASSERT parts?

Parfait does not complain anymore. The key about this call is that we don't de-reference
the return value from target_addr_for_insn_allow_null_ret. So we allow nullptr to be
returned, but we don't use it.

@dholmes-ora
Copy link
Member

Perhaps Boris Ulasevich boris.ulasevich@bell-sw.com could review?

@mlbridge
Copy link

mlbridge bot commented Dec 24, 2021

Mailing list message from David Holmes on hotspot-runtime-dev:

Adding Boris Ulasevich <boris.ulasevich at bell-sw.com> to cc list :)

On 24/12/2021 12:42 pm, David Holmes wrote:

} else {
ShouldNotReachHere();
}
return address(((uint64_t)insn_addr + (offset << 2)));
}

address MacroAssembler::target_addr_for_insn_allow_null_ret(address insn_addr, unsigned insn) {
if (Instruction_aarch64::extract(insn, 31, 22) == 0b1011100101 &&

Choose a reason for hiding this comment

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

Consider replacing raw constants check with NativeInstruction::is_ldrw_to_zr function call which performs the same check.

Copy link
Member Author

Choose a reason for hiding this comment

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

Good catch. There are actually two uses of the raw constants in
macroAssembler_aarch64.cpp and I've cleaned up both.

Copy link
Contributor

Choose a reason for hiding this comment

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

This was a nice refactoring.

Choose a reason for hiding this comment

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

Good. Thank you!

Choose a reason for hiding this comment

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

Good.

@@ -283,15 +283,20 @@ address MacroAssembler::target_addr_for_insn(address insn_addr, unsigned insn) {
return address(uint64_t(Instruction_aarch64::extract(insns[0], 20, 5))
+ (uint64_t(Instruction_aarch64::extract(insns[1], 20, 5)) << 16)
+ (uint64_t(Instruction_aarch64::extract(insns[2], 20, 5)) << 32));
} else if (Instruction_aarch64::extract(insn, 31, 22) == 0b1011100101 &&

Choose a reason for hiding this comment

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

It must be a check for safePoint poll: ldrw zr, polling_page. Technically, the target address for this instruction is zero and the function is correct. I am not sure Parfait is right in his complaints. After all, does this code ever works? That is, if you remove it, will the SholdNotReachHere below fire?

Copy link
Member Author

Choose a reason for hiding this comment

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

I don't think the safepoint poll is coming thru this code path. I ran this fix
through Mach5 Tier[1-6] and did not see any failures caused by hitting
a ShouldNotReachHere() call. It's hard to imagine that Tier[1-6] testing
wouldn't exercise the safepoint polling code paths.

I've also verified that the Parfait tool no longer issues the complaints.

I will poke around and see if I can determine what the safepoint polling
is doing.

Copy link
Member Author

Choose a reason for hiding this comment

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

@bulasevich - I've made another pass through the code and checked the
calls to MacroAssembler::target_addr_for_insn() and I don't see any of
those calls in areas related to safepoint polling. From the other POV, I
took a look at the aarch64 safepoint polling code and I don't see a way
into MacroAssembler::target_addr_for_insn() .

It is entirely possible that I'm missing something here and would appreciate
it if you could sanity check my conclusions here.

Copy link

@ghost ghost Jan 18, 2022

Choose a reason for hiding this comment

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

I believe this code is dead, in both MacroAssembler::pd_patch_instruction() and MacroAssembler::target_addr_for_insn(), since the poll read is PIC, we are not patching and should not need to acquire any target to update.

The associated fix_relocation_after_move() will not invoke any of the above on the poll read since the maybe_cpool_ref() condition is used:

void poll_Relocation::fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest) {
  if (NativeInstruction::maybe_cpool_ref(addr())) {
    address old_addr = old_addr_for(addr(), src, dest);
    MacroAssembler::pd_patch_instruction(addr(), MacroAssembler::target_addr_for_insn(old_addr));
  }
}

Should be sufficient to simply remove these cases, possibly you could move an assert into the "unreachable" branch (for "precision").

} else {
  assert(!NativeInstruction::is_ldrw_to_zr(<addr>), "Unexpected poll read");
  ShouldNotReachHere();
}

(The code above in fix_relocation_after_move() might also be dead...)

Chip in @theRealAph ?

Copy link
Member Author

Choose a reason for hiding this comment

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

@phedlin - Thanks for chiming in on this review thread.

Choose a reason for hiding this comment

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

I wondered if target_addr_for_insn ever gets the ldrw_to_zr instruction.
Anyway, I am Ok to move it to target_addr_for_insn_allow_null_ret (target_addr_for_insn_or_null?).
Thank you.

Choose a reason for hiding this comment

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

Since we moved to using per-thread safepoints, I don't think we'll ever see a reloc against a safepoint poll. I've just looked through the AArch64 back end, and as far as I can see the old safepoint code is gone.

Choose a reason for hiding this comment

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

@bulasevich - I've made another pass through the code and checked the calls to MacroAssembler::target_addr_for_insn() and I don't see any of those calls in areas related to safepoint polling. From the other POV, I took a look at the aarch64 safepoint polling code and I don't see a way into MacroAssembler::target_addr_for_insn() .

It is entirely possible that I'm missing something here and would appreciate it if you could sanity check my conclusions here.

I think you're right. As far as I can see, this code is dead since
8253180: ZGC: Implementation of JEP 376: ZGC: Concurrent Thread-Stack Processing

which took out the code that generated safepoint relocs, but not the code here that relocated them.

Copy link
Member Author

Choose a reason for hiding this comment

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

I've filed the following new RFE to track the dead compiler code:

JDK-8280283 dead compiler code found during the JDK-8272058 code review
https://bugs.openjdk.java.net/browse/JDK-8280283

@dcubed-ojdk
Copy link
Member Author

dcubed-ojdk commented Jan 5, 2022

Mach5 Tier[1-3] testing on v02 is clean (no failures).

Update: Mach5 Tier[4-6] test on v02 is clean (1 known, unrelated client test failure).

@dcubed-ojdk
Copy link
Member Author

@bulasevich and/or @theRealAph - pinging for reviews...

1 similar comment
@dcubed-ojdk
Copy link
Member Author

@bulasevich and/or @theRealAph - pinging for reviews...

@dcubed-ojdk
Copy link
Member Author

@bulasevich - Please re-review this PR. The JDK18 RDP2 cut off is next week (01.20) and
I would like to have this PR integrated before then.

@theRealAph - Since I'm changing code that you integrated, I would prefer to hear from
you on this PR. Please review these changes soon. The JDK18 RDP2 cut off is next week
(01.20) and I would like to have this PR integrated before then.

@dcubed-ojdk
Copy link
Member Author

dcubed-ojdk commented Jan 14, 2022

Mach5 Tier[1-3] on the latest bits had no failures.

Copy link
Contributor

@coleenp coleenp left a comment

Choose a reason for hiding this comment

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

I walked through the changes that you made in my local code base and by inspection and your testing, this change looks good. Thanks for fixing the problem.

@openjdk
Copy link

openjdk bot commented Jan 18, 2022

@dcubed-ojdk 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:

8272058: 25 Null pointer dereference defect groups in 4 files

Reviewed-by: gziemski, coleenp, dlong

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 no new commits pushed to the master branch. If another commit should be pushed before you perform the /integrate command, your PR will be automatically rebased. If you prefer to avoid any potential 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 added the ready Pull request is ready to be integrated label Jan 18, 2022
@dcubed-ojdk
Copy link
Member Author

@coleenp - Thanks for the review and the approval.

@dean-long
Copy link
Member

/cc hotspot-compiler

@openjdk openjdk bot added the hotspot-compiler hotspot-compiler-dev@openjdk.java.net label Jan 19, 2022
@openjdk
Copy link

openjdk bot commented Jan 19, 2022

@dean-long
The hotspot-compiler label was successfully added.

@dean-long
Copy link
Member

I'm glad you didn't have to change all the Got and Plt call sites that parfait was complaining about. It seems to be all dead code left over from AOT.

@@ -606,10 +606,15 @@ class MacroAssembler: public Assembler {
static bool uses_implicit_null_check(void* address);

static address target_addr_for_insn(address insn_addr, unsigned insn);
static address target_addr_for_insn_allow_null_ret(address insn_addr, unsigned insn);
static address target_addr_for_insn(address insn_addr) {
Copy link
Member

Choose a reason for hiding this comment

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

The or_null suffix that we use in shared code reads a little better to me.

@bulasevich
Copy link

The change looks good for me (I'm not a reviewer). Thank you.

@dcubed-ojdk
Copy link
Member Author

@dean-long - Thanks for the review and for the rename suggestion. I'm making
that change. Retesting the build now.

@bulasevich - Thanks for the re-review!

@theRealAph - Thanks for chiming in on the review thread.

@dcubed-ojdk
Copy link
Member Author

This latest version has been tested with a Mach5 Tier1 job set.
No failures in either linux-aarch64 or macosx-aarch64.

/integrate

@openjdk
Copy link

openjdk bot commented Jan 19, 2022

Going to push as commit f5de6fa.

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

openjdk bot commented Jan 19, 2022

@dcubed-ojdk Pushed as commit f5de6fa.

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

@dcubed-ojdk dcubed-ojdk deleted the JDK-8272058 branch January 20, 2022 22:16
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
hotspot-compiler hotspot-compiler-dev@openjdk.java.net hotspot-runtime hotspot-runtime-dev@openjdk.java.net integrated Pull request has been integrated
7 participants