Skip to content

Commit

Permalink
i#5437 glibc2.34: Workaround for SIGFPE
Browse files Browse the repository at this point in the history
Adds a workaround for the SIGFPE in glibc 2.34+ __libc_early_init() by
setting two ld.so globals located via hardcoded offsets, making this
fragile and considered temporary.

Tested on glibc 2.34 where every libc-using client crashes with SIGFPE
but they work with this fix.

Adds an Ubuntu22 GA CI run but if we have failures due to other
reasons the plan is to drastically shrink the tests run or abandon if
it's too much work right now.

Issue: #5437
  • Loading branch information
derekbruening committed Oct 21, 2022
1 parent 13ff46c commit ac66ab8
Show file tree
Hide file tree
Showing 2 changed files with 120 additions and 5 deletions.
63 changes: 63 additions & 0 deletions .github/workflows/ci-x86.yml
Original file line number Diff line number Diff line change
Expand Up @@ -196,3 +196,66 @@ jobs:
See more details on github.com/DynamoRIO/dynamorio/actions/runs/${{github.run_id}}
to: dynamorio-devs@googlegroups.com
from: Github Action CI

# Ubuntu22 64-bit Linux build with gcc and run tests:
x86-64:
runs-on: ubuntu-22.04

steps:
- uses: actions/checkout@v2
with:
submodules: true

# Cancel any prior runs for a PR (but do not cancel master branch runs).
- uses: n1hility/cancel-previous-runs@v2
with:
token: ${{ secrets.GITHUB_TOKEN }}
if: ${{ github.event_name == 'pull_request' }}

- run: git fetch --no-tags --depth=1 origin master

# Install multilib for non-cross-compiling Linux build.
- name: Create Build Environment
run: |
sudo apt update
sudo apt-get -y install doxygen vera++ zlib1g-dev libsnappy-dev \
liblz4-dev g++-multilib libunwind-dev
echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope
# Use a newer cmake to avoid 32-bit toolchain problems (i#4830).
- name: Setup newer cmake
uses: jwlawson/actions-setup-cmake@v1.8
with:
cmake-version: '3.19.7'

- name: Run Suite
working-directory: ${{ github.workspace }}
run: ./suite/runsuite_wrapper.pl automated_ci 64_only
env:
DYNAMORIO_CROSS_AARCHXX_LINUX_ONLY: no
CI_TRIGGER: ${{ github.event_name }}
CI_BRANCH: ${{ github.ref }}

- name: Send failure mail to dynamorio-devs
if: failure() && github.ref == 'refs/heads/master'
uses: dawidd6/action-send-mail@v2
with:
server_address: smtp.gmail.com
server_port: 465
username: ${{secrets.DYNAMORIO_NOTIFICATION_EMAIL_USERNAME}}
password: ${{secrets.DYNAMORIO_NOTIFICATION_EMAIL_PASSWORD}}
subject: |
[${{github.repository}}] ${{github.workflow}} FAILED
on ${{github.event_name}} at ${{github.ref}}
body: |
Github Actions CI workflow run FAILED!
Workflow: ${{github.workflow}}/x86-64
Repository: ${{github.repository}}
Branch ref: ${{github.ref}}
SHA: ${{github.sha}}
Triggering actor: ${{github.actor}}
Triggering event: ${{github.event_name}}
Run Id: ${{github.run_id}}
See more details on github.com/DynamoRIO/dynamorio/actions/runs/${{github.run_id}}
to: dynamorio-devs@googlegroups.com
from: Github Action CI
62 changes: 57 additions & 5 deletions core/unix/loader.c
Original file line number Diff line number Diff line change
Expand Up @@ -675,6 +675,16 @@ privload_os_finalize(privmod_t *privmod)
#ifndef LINUX
return; /* Nothing to do. */
#else
static privmod_t *privmod_ld_linux;
if (strstr(privmod->name, "ld-linux") == privmod->name) {
/* We need to first get the libc version before we clobber ld vars.
* (We could instead look for versioned symbols with "@GLIBC_2.34" in ld
* but we do not have version parsing code in place.)
* We assume ld will not be unloaded.
*/
privmod_ld_linux = privmod;
return;
}
if (strstr(privmod->name, "libc.so") != privmod->name)
return;
os_privmod_data_t *opd = (os_privmod_data_t *)privmod->os_privmod_data;
Expand All @@ -690,12 +700,54 @@ privload_os_finalize(privmod_t *privmod)
*/
void (*libc_early_init)(bool) = (void (*)(bool))get_proc_address_from_os_data(
&opd->os_data, opd->load_delta, LIBC_EARLY_INIT_NAME, NULL);
if (libc_early_init != NULL) {
LOG(GLOBAL, LOG_LOADER, 2, "%s: calling %s\n", __FUNCTION__,
LIBC_EARLY_INIT_NAME);
(*libc_early_init)(true);
if (libc_early_init == NULL) {
return;
}
#endif
/* XXX i#5437: Temporary workaround to avoid a SIGFPE in glibc 2.34+
* __libc_early_init(). As we cannot let ld/libc initialize their own TLS with the
* current design, we must explicitly initialize a few variables. Unfortunately
* we have to hardcode their offsets, making this fragile. Long-term we should try
* to find a better solution.
*/
/* Do not try to clobber vars unless we have to: get the libc version. */
# define LIBC_GET_VERSION_NAME "gnu_get_libc_version"
const char *(*libc_ver)(void) = (const char *(*)(void))get_proc_address_from_os_data(
&opd->os_data, opd->load_delta, LIBC_GET_VERSION_NAME, NULL);
if (libc_ver == NULL)
return;
LOG(GLOBAL, LOG_LOADER, 2, "%s: calling %s\n", __FUNCTION__, LIBC_GET_VERSION_NAME);
const char *ver = (*libc_ver)();
LOG(GLOBAL, LOG_LOADER, 2, "%s: libc version is |%s|\n", __FUNCTION__, ver);
if ((ver[0] == '\0' || ver[0] < '2') || ver[1] != '.' || ver[2] < '3')
return;
if (privmod_ld_linux == NULL) {
SYSLOG_INTERNAL_WARNING("glibc 2.34+ i#5437 workaround failed: missed ld");
return;
}
os_privmod_data_t *ld_opd = (os_privmod_data_t *)privmod_ld_linux->os_privmod_data;
byte *glro = get_proc_address_from_os_data(&ld_opd->os_data, ld_opd->load_delta,
"_rtld_global_ro", NULL);
if (glro == NULL) {
SYSLOG_INTERNAL_WARNING("glibc 2.34+ i#5437 workaround failed: missed glro");
return;
}
# define GLRO_dl_tls_static_size_OFFS 0x2a8
# define GLRO_dl_tls_static_align_OFFS 0x2b0
size_t val = 4096, written;
if (!safe_write_ex(glro + GLRO_dl_tls_static_size_OFFS, sizeof(val), &val,
&written) ||
written != sizeof(val) ||
!safe_write_ex(glro + GLRO_dl_tls_static_align_OFFS, sizeof(val), &val,
&written) ||
written != sizeof(val)) {
SYSLOG_INTERNAL_WARNING("glibc 2.34+ i#5437 workaround failed: missed write");
} else {
LOG(GLOBAL, LOG_LOADER, 2, "%s: glibc 2.34+ workaround succeeded\n",
__FUNCTION__);
}
LOG(GLOBAL, LOG_LOADER, 2, "%s: calling %s\n", __FUNCTION__, LIBC_EARLY_INIT_NAME);
(*libc_early_init)(true);
#endif /* LINUX */
}

static void
Expand Down

0 comments on commit ac66ab8

Please sign in to comment.