#!/usr/bin/env dub
/+ dub.sdl:
name "android-research-app-probe"
platforms "linux"
dflags "-betterC"
targetPath "build"
+/
/**
* libc-only probe suitable for a Bionic Android executable (-betterC).
* Run from the real terminal UI, not adb shell or run-as.
* Evidence: ../index.md#app-domain-probe.
* Namespace changes occur only in forked children; no mounts are made.
*/
module (module) app_probelibc-only probe suitable for a Bionic Android executable (-betterC).
Run from the real terminal UI, not adb shell or run-as.
Evidence
../index.md#app-domain-probe.
Namespace changes occur only in forked children; no mounts are made.
app_probe;
import (package) corecore.(package) core.stdcstdc.(module) core.stdc.stdioD header file for C99 <stdio.h>
pubs.opengroup.org/onlinepubs/009695399/basedefs/stdio.h.html, stdio.h
Source
core/stdc/stdio.d
stdio : (alias) app_probe.printf = int core.stdc.stdio.printf(scope const(char*) format, scope const ...) nothrow @nogcprintf, (alias) app_probe.fflush = int core.stdc.stdio.fflush(shared(core.stdc.stdio._IO_FILE)* stream) nothrow @nogc @trustedfflush;
import (package) corecore.(package) core.stdcstdc.(module) core.stdc.errnoD header file for C99.
pubs.opengroup.org/onlinepubs/009695399/basedefs/errno.h.html, errno.h
Source
core/stdc/errno.d
errno : (alias) app_probe.errno = int core.stdc.errno.__errno_location() nothrow @nogc ref @trustederrno;
import (package) corecore.(package) core.syssys.(package) core.sys.posixposix.(module) core.sys.posix.unistdD header file for POSIX.
unistd : (alias) app_probe.getuid = uint core.sys.posix.unistd.getuid() nothrow @nogc @trustedgetuid, (alias) app_probe.getgid = uint core.sys.posix.unistd.getgid() nothrow @nogc @trustedgetgid, (alias) app_probe.fork = int core.sys.posix.unistd.fork() nothrow @nogc @trustedfork, (alias) app_probe.read = long core.sys.posix.unistd.read(int, void*, ulong) nothrow @nogcread, (alias) app_probe.close = int core.sys.posix.unistd.close(int) nothrow @nogc @trustedclose, (alias) app_probe._exit = noreturn core.sys.posix.unistd._exit(int) nothrow @nogc @trusted_exit;
import (package) corecore.(package) core.syssys.(package) core.sys.posixposix.(module) core.sys.posix.fcntlD header file for POSIX.
fcntl : open, (alias constant) app_probe.O_RDONLY = int core.sys.posix.fcntl.O_RDONLY = 0O_RDONLY;
import (package) corecore.(package) core.syssys.(package) core.sys.posixposix.(package) core.sys.posix.syssys.(module) core.sys.posix.sys.waitD header file for POSIX.
wait : (alias) app_probe.waitpid = int core.sys.posix.sys.wait.waitpid(int, int*, int) nothrow @nogcwaitpid;
import (package) corecore.(package) core.syssys.(package) core.sys.posixposix.(package) core.sys.posix.syssys.(module) core.sys.posix.sys.socketD header file for POSIX.
socket : (alias) app_probe.socket = int core.sys.posix.sys.socket.socket(int, int, int) nothrow @nogc @safesocket, (alias enum value) app_probe.SOCK_STREAM = core.sys.posix.sys.socket.SOCK_STREAM = 1SOCK_STREAM;
extern(C) int int app_probe.unshare(int flags) nothrow @nogcunshare(int (parameter) int flagsflags) @nogc nothrow;
void void app_probe.showFile(const(char)* path) nothrow @nogcshowFile(const(char)* (parameter) const(char)* pathpath) @nogc nothrow
{
char[4096] (local variable) char[4096] bufferbuffer;
const (local variable) const(int) fdfd = open(int core.sys.posix.fcntl.open64(scope const(char*), int, ...) nothrow @nogcpath, (constant) int core.sys.posix.fcntl.O_RDONLY = 0O_RDONLY);
if ((local variable) const(int) fdfd < 0)
{
int core.stdc.stdio.printf(scope const(char*) format, scope const ...) nothrow @nogcprintf("%s: errno=%d\n", (parameter) const(char)* pathpath, int core.stdc.errno.__errno_location() nothrow @nogc ref @trustederrno);
return;
}
int core.stdc.stdio.printf(scope const(char*) format, scope const ...) nothrow @nogcprintf("%s:\n", (parameter) const(char)* pathpath);
while (true)
{
const (local variable) const(long) sizesize = long core.sys.posix.unistd.read(int, void*, ulong) nothrow @nogcread((local variable) const(int) fdfd, (local variable) char[4096] bufferbuffer.(constant) char* char[4096].ptr = &bufferptr, (local variable) char[4096] bufferbuffer.(constant) ulong char[4096].length = 4096LUlength - 1);
if ((local variable) const(long) sizesize <= 0)
break;
(local variable) char[4096] bufferbuffer[(local variable) const(long) sizesize] = 0;
int core.stdc.stdio.printf(scope const(char*) format, scope const ...) nothrow @nogcprintf("%s", (local variable) char[4096] bufferbuffer.(constant) char* char[4096].ptr = &bufferptr);
}
int core.stdc.stdio.printf(scope const(char*) format, scope const ...) nothrow @nogcprintf("\n");
int core.sys.posix.unistd.close(int) nothrow @nogc @trustedclose((local variable) const(int) fdfd);
}
int int app_probe.namespaceAttempt(int flags, const(char)* name) nothrow @nogcnamespaceAttempt(int (parameter) int flagsflags, const(char)* (parameter) const(char)* namename) @nogc nothrow
{
int core.stdc.stdio.fflush(shared(core.stdc.stdio._IO_FILE)* stream) nothrow @nogc @trustedfflush(null);
const (local variable) const(int) childchild = int core.sys.posix.unistd.fork() nothrow @nogc @trustedfork();
if ((local variable) const(int) childchild < 0)
{
int core.stdc.stdio.printf(scope const(char*) format, scope const ...) nothrow @nogcprintf("fork: errno=%d\n", int core.stdc.errno.__errno_location() nothrow @nogc ref @trustederrno);
return 1;
}
if ((local variable) const(int) childchild == 0)
{
const (local variable) const(int) resultresult = int app_probe.unshare(int flags) nothrow @nogcunshare((parameter) int flagsflags);
const (local variable) const(int) errorerror = int core.stdc.errno.__errno_location() nothrow @nogc ref @trustederrno;
int core.stdc.stdio.printf(scope const(char*) format, scope const ...) nothrow @nogcprintf("unshare(%s): result=%d errno=%d\n", (parameter) const(char)* namename, (local variable) const(int) resultresult, (local variable) const(int) resultresult < 0 ? (local variable) const(int) errorerror : 0);
int core.stdc.stdio.fflush(shared(core.stdc.stdio._IO_FILE)* stream) nothrow @nogc @trustedfflush(null);
noreturn core.sys.posix.unistd._exit(int) nothrow @nogc @trusted_exit(0);
}
int (local variable) int statusstatus;
return int core.sys.posix.sys.wait.waitpid(int, int*, int) nothrow @nogcwaitpid((local variable) const(int) childchild, &(local variable) int statusstatus, 0) != (local variable) const(int) childchild || (local variable) int statusstatus != 0;
}
extern(C) int int app_probe.main() nothrow @nogcmain() @nogc nothrow
{
int core.stdc.stdio.printf(scope const(char*) format, scope const ...) nothrow @nogcprintf("uid=%u gid=%u\n", uint core.sys.posix.unistd.getuid() nothrow @nogc @trustedgetuid(), uint core.sys.posix.unistd.getgid() nothrow @nogc @trustedgetgid());
void app_probe.showFile(const(char)* path) nothrow @nogcshowFile("/proc/self/attr/current");
void app_probe.showFile(const(char)* path) nothrow @nogcshowFile("/proc/self/status");
int (local variable) int failurefailure = int app_probe.namespaceAttempt(int flags, const(char)* name) nothrow @nogcnamespaceAttempt(0x10000000, "CLONE_NEWUSER");
(local variable) int failurefailure |= int app_probe.namespaceAttempt(int flags, const(char)* name) nothrow @nogcnamespaceAttempt(0x00020000, "CLONE_NEWNS");
(local variable) int failurefailure |= int app_probe.namespaceAttempt(int flags, const(char)* name) nothrow @nogcnamespaceAttempt(0x10000000 | 0x00020000, "CLONE_NEWUSER|CLONE_NEWNS");
const (local variable) const(int) fdfd = int core.sys.posix.sys.socket.socket(int, int, int) nothrow @nogc @safesocket(40, (enum value) core.sys.posix.sys.socket.SOCK_STREAM = 1SOCK_STREAM, 0); // Linux AF_VSOCK.
const (local variable) const(int) errorerror = int core.stdc.errno.__errno_location() nothrow @nogc ref @trustederrno;
int core.stdc.stdio.printf(scope const(char*) format, scope const ...) nothrow @nogcprintf("socket(AF_VSOCK): fd=%d errno=%d\n", (local variable) const(int) fdfd, (local variable) const(int) fdfd < 0 ? (local variable) const(int) errorerror : 0);
if ((local variable) const(int) fdfd >= 0)
int core.sys.posix.unistd.close(int) nothrow @nogc @trustedclose((local variable) const(int) fdfd);
int core.stdc.stdio.printf(scope const(char*) format, scope const ...) nothrow @nogcprintf("Capability absence/rejection is a result, not a probe failure.\n");
return (local variable) int failurefailure;
}