Skip to content

[llvm-objcopy] Remove references for empty section groups #98106

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

Merged
merged 1 commit into from
Jul 9, 2024

Conversation

pranavk
Copy link
Contributor

@pranavk pranavk commented Jul 9, 2024

Otherwise, llvm-objcopy fails with use-after-free when built under sanitizers. Simple repro: run the test ELF/remove-section-in-group.test under asan. This is due to symbol table references to empty section groups that must be removed.

@llvmbot
Copy link
Member

llvmbot commented Jul 9, 2024

@llvm/pr-subscribers-llvm-binary-utilities

Author: Pranav Kant (pranavk)

Changes

Otherwise, llvm-objcopy fails with use-after-free when built under sanitizers. Simple repro can be running the test ELF/remove-section-in-group.test under asan. This is due to symbol table references to empty section groups.


Full diff: https://github.com/llvm/llvm-project/pull/98106.diff

2 Files Affected:

  • (modified) llvm/lib/ObjCopy/ELF/ELFObject.cpp (+5-8)
  • (modified) llvm/lib/ObjCopy/ELF/ELFObject.h (+6-1)
diff --git a/llvm/lib/ObjCopy/ELF/ELFObject.cpp b/llvm/lib/ObjCopy/ELF/ELFObject.cpp
index f9c5d2579be69..d222aa4f2cf3d 100644
--- a/llvm/lib/ObjCopy/ELF/ELFObject.cpp
+++ b/llvm/lib/ObjCopy/ELF/ELFObject.cpp
@@ -2203,6 +2203,11 @@ Error Object::removeSections(
           if (auto ToRelSec = RelSec->getSection())
             return !ToRemove(*ToRelSec);
         }
+        // Remove empty group sections.
+        if (Sec->Type == ELF::SHT_GROUP) {
+          auto GroupSec = cast<GroupSection>(Sec.get());
+          return !llvm::all_of(GroupSec->members(), ToRemove);
+        }
         return true;
       });
   if (SymbolTable != nullptr && ToRemove(*SymbolTable))
@@ -2242,14 +2247,6 @@ Error Object::removeSections(
   // Now get rid of them altogether.
   Sections.erase(Iter, std::end(Sections));
 
-  // Finally erase empty SHT_GROUP sections.
-  llvm::erase_if(Sections, [](const SecPtr &Sec) {
-    if (auto GroupSec = dyn_cast<GroupSection>(Sec.get()))
-      return GroupSec->getMembersCount() == 0;
-
-    return false;
-  });
-
   return Error::success();
 }
 
diff --git a/llvm/lib/ObjCopy/ELF/ELFObject.h b/llvm/lib/ObjCopy/ELF/ELFObject.h
index 2a9f337c3f323..fd119cabcc92b 100644
--- a/llvm/lib/ObjCopy/ELF/ELFObject.h
+++ b/llvm/lib/ObjCopy/ELF/ELFObject.h
@@ -941,6 +941,9 @@ class GroupSection : public SectionBase {
   SmallVector<SectionBase *, 3> GroupMembers;
 
 public:
+  template <class T>
+  using ConstRange = iterator_range<pointee_iterator<
+      typename llvm::SmallVector<T *, 3>::const_iterator>>;
   // TODO: Contents is present in several classes of the hierarchy.
   // This needs to be refactored to avoid duplication.
   ArrayRef<uint8_t> Contents;
@@ -964,7 +967,9 @@ class GroupSection : public SectionBase {
       const DenseMap<SectionBase *, SectionBase *> &FromTo) override;
   void onRemove() override;
 
-  size_t getMembersCount() const { return GroupMembers.size(); }
+  ConstRange<SectionBase> members() const {
+    return make_pointee_range(GroupMembers);
+  }
 
   static bool classof(const SectionBase *S) {
     return S->OriginalType == ELF::SHT_GROUP;

@pranavk
Copy link
Contributor Author

pranavk commented Jul 9, 2024

Earlier fix was in #97141

Copy link

github-actions bot commented Jul 9, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

@hokein hokein requested a review from jh7370 July 9, 2024 06:28
@hokein
Copy link
Collaborator

hokein commented Jul 9, 2024

cc @chestnykh

@MaskRay
Copy link
Member

MaskRay commented Jul 9, 2024

Thanks! I think the approach is fine, but @jh7370 and I might take more time to think about it.
I am reverting the original patch instead.

MaskRay added a commit that referenced this pull request Jul 9, 2024
This reverts commit 359c64f.

This caused heap-use-after-free. See #98106.
@chestnykh
Copy link
Contributor

Sorry for this, i haven't tested my changes with asan

Copy link
Collaborator

@jh7370 jh7370 left a comment

Choose a reason for hiding this comment

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

I think this looks good to me. It's the "proper" way of marking something for removal.

@MaskRay
Copy link
Member

MaskRay commented Jul 9, 2024

Since #97141 has been reverted, this now needs a rebase and restoring the original test file:)

@MaskRay
Copy link
Member

MaskRay commented Jul 9, 2024

Sorry for this, i haven't tested my changes with asan

No worries. This case was difficult to analyze and we don't have asan premerge bots (the existing bots are underwhelmed even without asan).

You can test asan with -DCMAKE_BUILD_TYPE=RelWithDebInfo -DLLVM_USE_SANITIZER=Address. Since it is slow, perhaps test it with targeted testing check-llvm-tools-llvm-objcopy.

Otherwise, llvm-objcopy fails with use-after-free when built under
sanitizers. Simple repro can be running the test ELF/remove-section-in-group.test
under asan. This is due to symbol table references to empty section groups.
@pranavk
Copy link
Contributor Author

pranavk commented Jul 9, 2024

Rebased

@pranavk
Copy link
Contributor Author

pranavk commented Jul 9, 2024

Agree with Fangrui. Pretty hard to figure out with naked eye. We have internal tests that run everything with Asan enabled. So that's how I figured this out :)

Once you have sanitizer output, it's easy to figure out what went wrong.

@pranavk pranavk merged commit e142a55 into llvm:main Jul 9, 2024
7 checks passed
aaryanshukla pushed a commit to aaryanshukla/llvm-project that referenced this pull request Jul 14, 2024
This reverts commit 359c64f.

This caused heap-use-after-free. See llvm#98106.
aaryanshukla pushed a commit to aaryanshukla/llvm-project that referenced this pull request Jul 14, 2024
Otherwise, llvm-objcopy fails with use-after-free when built under
sanitizers. Simple repro: run the test
`ELF/remove-section-in-group.test` under asan. This is due to symbol
table references to empty section groups that must be removed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants