qemu-user uses fixed stack size and ignores RLIMIT_STACK request, causing some guest programs to crash

Host environment

  • Operating system: Arch Linux
  • OS/kernel version: Linux 6.4.12-arch1-1 #1 SMP PREEMPT_DYNAMIC Thu, 24 Aug 2023 00:38:14 +0000 x86_64 GNU/Linux
  • Architecture: x86_64
  • QEMU flavor: qemu-riscv64-static
  • QEMU version: qemu-riscv64 version 8.1.0
  • QEMU command line: (Unfortunately, it is hard for me to provide a single commandline that exhibits the problem)

Emulated/Virtualized environment

  • Operating system: Arch Linux riscv64
  • OS/kernel version: Linux 6.4.12-arch1-1 #1 SMP PREEMPT_DYNAMIC Thu, 24 Aug 2023 00:38:14 +0000 riscv64 GNU/Linux
  • Architecture: riscv64

Description of problem

When compiling a source file, g++ segmentation faults in qemu-user riscv64. But it doesn't fail on real riscv64 boards.

We discovered this problem while compiling nodejs-lts-hydrogen. The source file has been reduced to 5KB by cvise.

Steps to reproduce

  1. Setup an Arch Linux riscv64 qemu-user container: https://github.com/felixonmars/archriscv-packages/wiki/Setup-Arch-Linux-RISC-V-Development-Environment
  2. Start the container: sudo systemd-nspawn -D ./archriscv -a -U
  3. Install gcc inside the container: sudo pacman -Syu gcc
  4. Run the following command in the container: g++ -S testcase.i -w -fpreprocessed -o /dev/null testcase.i
  5. g++ segmentation faults: g++: internal compiler error: Segmentation fault signal terminated program cc1plus

Additional information

Initially I thought this is a g++ bug. But I can't reproduce this bug on real riscv64 hardware.

g++ version: g++ (GCC) 13.2.1 20230801

testcase.i:

namespace std {
typedef long unsigned size_t;
inline namespace __cxx11 {}
} // namespace std
typedef char uint8_t;
namespace std {
template <typename _Default, typename, template <typename> class>
struct __detector {
  using type = _Default;
};
template <typename _Default, template <typename> class _Op>
using __detected_or = __detector<_Default, void, _Op>;
template <typename _Default, template <typename> class _Op>
using __detected_or_t = typename __detected_or<_Default, _Op>::type;
template <typename> class allocator;
namespace __cxx11 {
template <typename _CharT, typename = _CharT, typename = allocator<_CharT>>
class basic_string;
}
typedef basic_string<char> string;
} // namespace std
template <typename _Tp> class __new_allocator {
public:
  typedef _Tp value_type;
};
namespace std {
template <typename _Tp> using __allocator_base = __new_allocator<_Tp>;
template <typename _Tp> class allocator : public __allocator_base<_Tp> {};
template <class _E> class initializer_list {
  typedef size_t size_type;
  typedef _E *iterator;
  iterator _M_array;
  size_type _M_len;
};
struct __allocator_traits_base {
  template <typename _Tp> using __pointer = typename _Tp::const_pointer;
};
template <typename _Alloc> struct allocator_traits : __allocator_traits_base {
  typedef typename _Alloc::value_type value_type;
  using pointer = __detected_or_t<value_type, __pointer>;
};
} // namespace std
namespace __gnu_cxx {
template <typename _Alloc>
struct __alloc_traits : std::allocator_traits<_Alloc> {};
} // namespace __gnu_cxx
namespace std {
namespace __cxx11 {
template <typename _CharT, typename, typename _Alloc> class basic_string {
  typedef __gnu_cxx::__alloc_traits<_Alloc> _Alloc_traits;

public:
  typedef typename _Alloc_traits::pointer pointer;
  struct _Alloc_hider {
    _Alloc_hider(pointer, _Alloc);
  } _M_dataplus;
  pointer _M_local_data();
  basic_string(_CharT *, _Alloc __a = _Alloc())
      : _M_dataplus(_M_local_data(), __a) {}
  ~basic_string();
};
} // namespace __cxx11
} // namespace std
namespace v8 {
class StartupData {};
} // namespace v8
namespace std {
template <typename _Tp> class vector {
public:
  typedef _Tp value_type;
  vector(initializer_list<value_type>);
};
namespace builtins {
struct CodeCacheInfo {
  string id;
  vector<uint8_t> data;
};
} // namespace builtins
struct IsolateDataSerializeInfo {};
struct EnvSerializeInfo {};
struct SnapshotMetadata {
  enum { kDefault } type;
  string node_version;
  string node_arch;
  string v8_cache_version_tag;
};
struct SnapshotData {
  enum { kNotOwned } data_ownership;
  SnapshotMetadata metadata;
  v8::StartupData v8_snapshot_blob_data;
  IsolateDataSerializeInfo isolate_data_info;
  EnvSerializeInfo env_info;
  vector<builtins::CodeCacheInfo> code_cache;
} snapshot_data{
    SnapshotData::kNotOwned,
    SnapshotMetadata::kDefault,
    "",
    "",
    "",
    {},
    {},
    {},
    {{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
     {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
     {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
     {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
     {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
     {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
     {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
     {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
     {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
     {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
     {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
     {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
     {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
     {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
     {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
     {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
     {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
     {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
     {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
     {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
     {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
     {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
     {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}}};
} // namespace std