mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-11-05 17:07:50 +00:00
107 lines
3.1 KiB
C
107 lines
3.1 KiB
C
/* SPDX-License-Identifier: AGPL-3.0-only */
|
|
/* Copyright 2026 Moritz Angermann <moritz@zw3rk.com>, zw3rk pte. ltd. */
|
|
|
|
#include <inttypes.h>
|
|
#include <pthread.h>
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <sys/utsname.h>
|
|
#include <sys/personality.h>
|
|
#include <sys/wait.h>
|
|
#include <unistd.h>
|
|
|
|
static uint32_t current_persona(void)
|
|
{
|
|
return (uint32_t)personality(UINT32_MAX);
|
|
}
|
|
|
|
static int equal_persona(uint32_t actual, uint32_t expected)
|
|
{
|
|
if (actual == expected) {
|
|
return 0;
|
|
}
|
|
(void)fprintf(stderr, "persona got=%08" PRIx32 " expected=%08" PRIx32 "\n",
|
|
actual, expected);
|
|
return 1;
|
|
}
|
|
|
|
struct thread_case {
|
|
uint32_t initial;
|
|
int result;
|
|
};
|
|
|
|
static void *check_thread(void *opaque)
|
|
{
|
|
struct thread_case *test = opaque;
|
|
uint32_t changed;
|
|
|
|
if (test == NULL) {
|
|
return NULL;
|
|
}
|
|
changed = test->initial ^ UNAME26;
|
|
test->result = equal_persona(current_persona(), test->initial);
|
|
test->result |= equal_persona((uint32_t)personality(changed), test->initial);
|
|
test->result |= equal_persona(current_persona(), changed);
|
|
return NULL;
|
|
}
|
|
|
|
int main(void)
|
|
{
|
|
uint32_t initial = current_persona();
|
|
uint32_t changed = initial ^ UNAME26;
|
|
uint32_t linux_domain = (initial & ~(uint32_t)PER_MASK) | PER_LINUX;
|
|
struct thread_case test = { initial, 1 };
|
|
pthread_t thread;
|
|
pid_t child;
|
|
int status;
|
|
struct utsname names;
|
|
|
|
if ((initial & PER_MASK) != PER_LINUX32) {
|
|
(void)fprintf(stderr, "Android startup did not retain PER_LINUX32\n");
|
|
return 10;
|
|
}
|
|
if (equal_persona((uint32_t)personality(changed), initial) ||
|
|
equal_persona(current_persona(), changed) || uname(&names) != 0) {
|
|
return 11;
|
|
}
|
|
(void)fprintf(stderr, "UNAME26=%u release=%s\n",
|
|
(changed & UNAME26) != 0 ? 1U : 0U, names.release);
|
|
if (((changed & UNAME26) != 0 &&
|
|
strncmp(names.release, "2.6.", 4) != 0) ||
|
|
equal_persona((uint32_t)personality(initial), changed)) {
|
|
return 11;
|
|
}
|
|
if (pthread_create(&thread, NULL, check_thread, &test) != 0) {
|
|
return 12;
|
|
}
|
|
if (pthread_join(thread, NULL) != 0 || test.result != 0 ||
|
|
equal_persona(current_persona(), initial)) {
|
|
return 13;
|
|
}
|
|
child = fork();
|
|
if (child < 0) {
|
|
return 14;
|
|
}
|
|
if (child == 0) {
|
|
int result = equal_persona(current_persona(), initial);
|
|
result |= equal_persona((uint32_t)personality(linux_domain), initial);
|
|
result |= equal_persona(current_persona(), linux_domain);
|
|
_exit(result == 0 ? 0 : 15);
|
|
}
|
|
if (waitpid(child, &status, 0) != child || !WIFEXITED(status) ||
|
|
WEXITSTATUS(status) != 0 || equal_persona(current_persona(), initial)) {
|
|
return 16;
|
|
}
|
|
if (equal_persona((uint32_t)personality(linux_domain), initial) ||
|
|
equal_persona(current_persona(), linux_domain) ||
|
|
equal_persona((uint32_t)personality(initial), linux_domain) ||
|
|
equal_persona(current_persona(), initial)) {
|
|
return 17;
|
|
}
|
|
if (fputs("SIMPLEX_ARMV7_PERSONALITY_CHECK_PASS\n", stderr) < 0) {
|
|
return 18;
|
|
}
|
|
return 0;
|
|
}
|