Skip to content

[CFI] update ignorelist to work with libstdc++ make_shared #118599

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

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

yingcong-wu
Copy link
Contributor

@yingcong-wu yingcong-wu commented Dec 4, 2024

Fixes https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96946.

We had an old issue with libc++ in https://bugs.llvm.org/show_bug.cgi?id=48993, and it is fixed for libc++, but the same reproducer can still be reproduced with libstdc++(https://godbolt.org/z/n3EWvMKEP).

This patch adds an entry to deal with such cases.

@llvmbot llvmbot added compiler-rt compiler-rt:cfi Control Flow Integrity labels Dec 4, 2024
@yingcong-wu yingcong-wu force-pushed the yc/1204-cfi-libstdcpp-sharedptr branch from 2c53a65 to 9a9a538 Compare December 4, 2024 06:59
@yingcong-wu yingcong-wu requested a review from MaskRay December 5, 2024 02:08
@MaskRay
Copy link
Member

MaskRay commented Dec 5, 2024

-fsanitize=cfi isn't a widely used option. The few users I know use libc++. -fsanitize=cfi requires LTO. Can you file a https://gcc.gnu.org/bugzilla/ PR to get this tracked?

It's also not clear that this one entry will work for a non-trivial C++ code base. Do you have more experience with using -fsanitize=cfi with libstdc++?

@yingcong-wu
Copy link
Contributor Author

yingcong-wu commented Dec 5, 2024

Can you file a https://gcc.gnu.org/bugzilla/ PR to get this tracked?

Actually, there is already a bug reported in https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96946. I have included this in the description.

Do you have more experience with using -fsanitize=cfi with libstdc++?

To be honest, my team has been trying to enable CFI recently, and we encountered this issue just like others before. We have this problem with our non-trivial code base, and this patch can also fix the problem for us.

@yingcong-wu
Copy link
Contributor Author

I tried to comment on that GCC bug report page, but I don't have an account and I am working on getting my account setup.

@jwakely
Copy link
Contributor

jwakely commented Dec 9, 2024

Is the correct fix really to just add an allow-list for individual cases of valid code? Doesn't that imply a problem with the sanitizer, or is that by design?

This PR doesn't help this case, which fails using both -stdlib=libstdc++ and -stdlib=libc++, and is valid C++ as far as I can see:

#include <new>

namespace x __attribute__((visibility("default")))
{
template<typename T>
struct buffer
{
  alignas(__alignof__(T)) unsigned char buf[sizeof(T)];

  void* addr() { return static_cast<void*>(buf); }

  T* ptr() { return static_cast<T*>(addr()); }
};
}

struct IReporterFactory {
    virtual ~IReporterFactory() = default;
};

class ReporterFactory : public IReporterFactory {};

int main()
{
  auto p = new x::buffer<ReporterFactory>;
  auto p2 = p->ptr();  // undefined here
  ::new(static_cast<void*>(p2)) ReporterFactory;
  p->ptr()->~ReporterFactory();
  delete p;
}

And it doesn't help for this case which fails using -stdlib=libstdc++:

#include <list>

struct IReporterFactory {
    virtual ~IReporterFactory() = default;
};

class ReporterFactory : public IReporterFactory {};

int main()
{
  std::list<ReporterFactory> l(1);
}

(I plan to change the node-based containers in libstdc++ to use a union for the uninitialized storage, which should fix this case ... one day.)

@jwakely
Copy link
Contributor

jwakely commented Dec 9, 2024

If you add a suppression for __aligned_member as well as __aligned_buffer then that should help the libstdc++ std::list case (and std::set, std::map etc. in libstdc++). It won't help cases like the x::buffer example though.

@yingcong-wu
Copy link
Contributor Author

Is the correct fix really to just add an allow-list for individual cases of valid code? Doesn't that imply a problem with the sanitizer, or is that by design?

Here is the same problem for libc++: https://bugs.llvm.org/show_bug.cgi?id=48993, and it ends up adding _LIBCPP_NO_CFI for it as well, which is not much different than what we do here.

The key problem about this kind of problem is (taken from the LLVM bugzilla) "CFI detects cast confusion bugs by checking that the vtable is correct for the type of the cast, but the vptr slot is still uninitialized.".
I think adding a suppression is the right way here.

If you add a suppression for __aligned_member as well as __aligned_buffer then that should help the libstdc++ std::list case (and std::set, std::map etc. in libstdc++). It won't help cases like the x::buffer example though.

Do you want me to include those in this PR?

@jwakely
Copy link
Contributor

jwakely commented Dec 10, 2024

Do you want me to include those in this PR?

That's for the relevant reviewers to decide, not me. But handling both __aligned_membuf and __aligned_buffer will cover most uses of uninitialized storage in libstdc++.

@yingcong-wu
Copy link
Contributor Author

I'm sorry, I am actually busy with other things right now. I will work on this patch later.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
compiler-rt:cfi Control Flow Integrity compiler-rt
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants