Information about my system (if it helps)
=========================================

Environment
Ubuntu release:
Description: Ubuntu 24.04.4 LTS
Release: 24.04

Kernel:
Linux 6.17.0-29-generic #29~24.04.1-Ubuntu SMP PREEMPT_DYNAMIC Mon May 11 
10:30:58 UTC 2026 x86_64 x86_64 x86_64 GNU/Linux

Packages:
apparmor 4.0.1really4.0.1-0ubuntu0.24.04.6
apparmor-utils 4.0.1really4.0.1-0ubuntu0.24.04.6

VSCode:
1.121.0
f6cfa2ea2403534de03f069bdf160d06451ed282
x64

Minimal reproducer source (save as repro.c)

#define _GNU_SOURCE
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/personality.h>
#include <unistd.h>

#ifndef ADDR_NO_RANDOMIZE
#define ADDR_NO_RANDOMIZE 0x0040000
#endif

static unsigned long long ParseU64Env(const char *name, unsigned long long 
defVal) {
const char *val = getenv(name);
if (val == NULL || *val == '\0') return defVal;
char *end = NULL;
unsigned long long out = strtoull(val, &end, 10);
if (end == val || *end != '\0') return defVal;
return out;
}

int main(int argc, char **argv) {
(void)argc;
const unsigned long long maxReexec = ParseU64Env("MAX_REEXEC", 20ULL);
unsigned long long reexecCount = ParseU64Env("REEXEC_COUNT", 0ULL);

int localVar = 0;
printf("pid=%d reexec_count=%llu local_var_addr=%p\n", getpid(), reexecCount, 
(void *)&localVar);

long curr = personality(0xffffffffUL);
if (curr == -1) {
printf("personality(read) failed: errno=%d (%s)\n", errno, strerror(errno));
return 2;
}

if (((unsigned long)curr & ADDR_NO_RANDOMIZE) != 0UL) {
printf("ADDR_NO_RANDOMIZE already set -> done\n");
return 0;
}

unsigned long proposed = (unsigned long)curr | ADDR_NO_RANDOMIZE;
long prev = personality(proposed);
if (prev == -1) {
printf("personality(set) failed: errno=%d (%s)\n", errno, strerror(errno));
return 3;
}

long afterSet = personality(0xffffffffUL);
if (afterSet == -1) {
printf("personality(re-read) failed: errno=%d (%s)\n", errno, strerror(errno));
return 4;
}

printf("curr=0x%lx prev=0x%lx after_set=0x%lx add_no_randomize_after_set=%s\n",
(unsigned long)curr,
(unsigned long)prev,
(unsigned long)afterSet,
(((unsigned long)afterSet & ADDR_NO_RANDOMIZE) != 0UL) ? "yes" : "no");

if (((unsigned long)afterSet & ADDR_NO_RANDOMIZE) == 0UL) {
printf("Flag not set after personality(set) -> stop (no exec)\n");
return 0;
}

if (reexecCount >= maxReexec) {
printf("Reached MAX_REEXEC=%llu, stopping to avoid runaway loop\n", maxReexec);
return 5;
}

char countBuf[32];
snprintf(countBuf, sizeof(countBuf), "%llu", reexecCount + 1ULL);
if (setenv("REEXEC_COUNT", countBuf, 1) != 0) {
printf("setenv failed: errno=%d (%s)\n", errno, strerror(errno));
return 6;
}

printf("execv self now...\n");
fflush(stdout);
execv(argv[0], argv);

printf("execv returned: errno=%d (%s)\n", errno, strerror(errno));
return 7;
}

Commands to reproduce

Build
gcc -O0 -g -Wall -Wextra -pedantic repro.c -o repro

Run in VSCode integrated terminal
env -u REEXEC_COUNT MAX_REEXEC=10 ./repro

Run in external terminal on same machine
env -u REEXEC_COUNT MAX_REEXEC=10 ./repro

Expected result
If personality reports ADDR_NO_RANDOMIZE set before exec, then after self-exec 
it should remain effective, and program should stop after first re-exec with:
ADDR_NO_RANDOMIZE already set -> done

Actual result in VSCode integrated terminal
Program repeatedly self-execs until MAX_REEXEC limit:

after_set shows 0x40000 each iteration
next iteration starts with curr=0x0 again
stack/local variable addresses change each iteration
This indicates ASLR still effectively active after exec in this context.
Actual result in external terminal (same host)
Program behaves correctly:
pid=52555 reexec_count=0 local_var_addr=0x7fffc59d2b3c
curr=0x0 prev=0x0 after_set=0x40000 add_no_randomize_after_set=yes
execv self now...
pid=52555 reexec_count=1 local_var_addr=0x7fffffffd06c
ADDR_NO_RANDOMIZE already set -> done

-- 
You received this bug notification because you are a member of Ubuntu
Bugs, which is subscribed to Ubuntu.
https://bugs.launchpad.net/bugs/2153650

Title:
  AppArmor: personality ADDR_NO_RANDOMIZE appears set but not effective
  after exec (causes infinite self-exec loop)

To manage notifications about this bug go to:
https://bugs.launchpad.net/ubuntu/+source/apparmor/+bug/2153650/+subscriptions


-- 
ubuntu-bugs mailing list
[email protected]
https://lists.ubuntu.com/mailman/listinfo/ubuntu-bugs

Reply via email to