10#include <sys/personality.h>
11#include <sys/utsname.h>
14#define CHECK(condition) \
17 fprintf(stderr, "PERSONALITY-CONTRACT: line=%d errno=%d\n", __LINE__, errno); \
22static char native_machine[65];
24static int selected(
int expected,
const char* machine) {
26 return personality(0xffffffffUL) == expected && !uname(&name) && !strcmp(name.machine, machine);
29static void* thread_test(
void* unused) {
31 if (!selected(PER_LINUX32,
"i686"))
33 if (personality(PER_LINUX) != PER_LINUX32 || !selected(PER_LINUX, native_machine))
38int main(
int argc,
char** argv) {
39 if (argc == 2 && !strcmp(argv[1],
"--exec-child"))
40 return selected(PER_LINUX32,
"i686") ? 0 : 3;
43 const int original = personality(0xffffffffUL);
45 CHECK(personality(PER_LINUX) == original);
46 CHECK(uname(&name) == 0);
47 memcpy(native_machine, name.machine,
sizeof(native_machine));
48 CHECK(personality(PER_LINUX32) == PER_LINUX);
49 CHECK(selected(PER_LINUX32,
"i686"));
50 const unsigned long unsupported[] = {PER_BSD,
51 PER_LINUX32 | ADDR_LIMIT_3GB,
52 PER_LINUX | ADDR_NO_RANDOMIZE,
53 PER_LINUX | READ_IMPLIES_EXEC,
56 for (
size_t i = 0; i <
sizeof(unsupported) /
sizeof(unsupported[0]); ++i) {
58 CHECK(personality(unsupported[i]) == -1 && errno == EINVAL);
59 CHECK(selected(PER_LINUX32,
"i686"));
62 void* returned = (
void*)9;
63 CHECK(pthread_create(&thread, NULL, thread_test, NULL) == 0);
64 CHECK(pthread_join(thread, &returned) == 0 && returned == NULL);
65 CHECK(selected(PER_LINUX32,
"i686"));
69 if (!selected(PER_LINUX32,
"i686"))
71 execlp(argv[0], argv[0],
"--exec-child", (
char*)NULL);
75 CHECK(waitpid(child, &status, 0) == child && WIFEXITED(status) && WEXITSTATUS(status) == 0);
76 CHECK(personality(PER_LINUX) == PER_LINUX32);
77 CHECK(selected(PER_LINUX, native_machine));
81 personality((
unsigned long)original);
82 puts(result ?
"PERSONALITY-CONTRACT: FAIL" :
"PERSONALITY-CONTRACT: PASS");