#!/usr/bin/env dub
/+ dub.sdl:
name "android-research-namespace-probe"
platforms "linux"
targetPath "build"
+/
/**
* Real namespace syscalls, confined to a disposable child process.
* Evidence for ../index.md#namespaces-seccomp-and-selinux.
* Run inside the terminal's actual session for Android app-domain evidence.
*/
module (module) namespace_probeReal namespace syscalls, confined to a disposable child process.
Evidence for ../index.md#namespaces-seccomp-and-selinux.
Run inside the terminal's actual session for Android app-domain evidence.
namespace_probe;
import (package) corecore.(package) core.syssys.(package) core.sys.posixposix.(module) core.sys.posix.unistdD header file for POSIX.
unistd : (alias) namespace_probe.fork = int core.sys.posix.unistd.fork() nothrow @nogc @trustedfork, (alias) namespace_probe.getpid = int core.sys.posix.unistd.getpid() nothrow @nogc @trustedgetpid, (alias) namespace_probe.getuid = uint core.sys.posix.unistd.getuid() nothrow @nogc @trustedgetuid, (alias) namespace_probe.getgid = uint core.sys.posix.unistd.getgid() nothrow @nogc @trustedgetgid, (alias) namespace_probe._exit = noreturn core.sys.posix.unistd._exit(int) nothrow @nogc @trusted_exit;
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) namespace_probe.waitpid = int core.sys.posix.sys.wait.waitpid(int, int*, int) nothrow @nogcwaitpid;
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) namespace_probe.errno = int core.stdc.errno.__errno_location() nothrow @nogc ref @trustederrno;
import (package) stdstd.(module) std.stdioCategory Symbols File handles _popen File isFileHandle openNetwork stderr stdin stdout Reading chunks lines readf readfln readln Writing toFile write writef writefln writeln Misc KeepTerminator LockType StdioException
Standard I/O functions that extend core.stdc.stdio. core.stdc.stdio
is publically imported when importing std.stdio.
There are three layers of I/O:
The lowest layer is the operating system layer. The two main schemes are Windows and Posix.
C's stdio.h which unifies the two operating system schemes.
std.stdio, this module, unifies the various stdio.h implementations into
a high level package for D programs.
Source
std/stdio.d
stdio : (alias template) namespace_probe.writeln = std.stdio.writeln(T...)(T args)Equivalent to write(args, '\n'). Calling writeln without
arguments is valid and just prints a newline to the standard
output.
Example
Reads stdin and writes it to stdout with an argument
counter.
import std.stdio;
void main()
{
string line;
for (size_t count = 0; (line = readln) !is null; count++)
{
writeln("Input ", count, ": ", line);
}
}
writeln, stdout;
import (package) stdstd.(module) std.fileUtilities for manipulating files and scanning directories. Functions
in this module handle files as a unit, e.g., read or write one file
at a time. For opening files and manipulating them via handles refer
to module std.stdio.
Category Functions General exists isDir isFile isSymlink rename thisExePath Directories chdir dirEntries getcwd mkdir mkdirRecurse rmdir rmdirRecurse tempDir Files append copy read readText remove slurp write Symlinks symlink readLink Attributes attrIsDir attrIsFile attrIsSymlink getAttributes getLinkAttributes getSize setAttributes Timestamp getTimes getTimesWin setTimes timeLastModified timeLastAccessed timeStatusChanged Other DirEntry FileException PreserveAttributes SpanMode getAvailableDiskSpace
Source
std/file.d
file : (alias template) namespace_probe.readText = std.file.readText(S = string, R)(auto ref R name) if (isSomeString!S && (isSomeFiniteCharInputRange!R || is(StringTypeOf!R)))Reads and validates (using validate) a text file. S can be
an array of any character type. However, no width or endian conversions are
performed. So, if the width or endianness of the characters in the given
file differ from the width or endianness of the element type of S, then
validation will fail.
readText, (alias template) namespace_probe.readLink = std.file.readLink(R)(R link) if (isSomeFiniteCharInputRange!R || isConvertibleToString!R)This function is POSIX-Only.
Returns the path to the file pointed to by a symlink. Note that the
path could be either relative or absolute depending on the symlink.
If the path is relative, it's relative to the symlink, not the current
working directory.
readLink;
import (package) stdstd.(module) std.stringString handling functions.
Category Functions Searching column indexOf indexOfAny indexOfNeither lastIndexOf lastIndexOfAny lastIndexOfNeither Comparison isNumeric Mutation capitalize Pruning and Filling center chomp chompPrefix chop detabber detab entab entabber leftJustify outdent rightJustify strip stripLeft stripRight wrap Substitution abbrev soundex soundexer succ tr translate Miscellaneous assumeUTF fromStringz lineSplitter representation splitLines toStringz Objects of types string, wstring, and dstring are value types and cannot be mutated element-by-element. For using mutation during building strings, use char[], wchar[], or dchar[]. The xxxstring types are preferable because they don't exhibit undesired aliasing, thus making code more robust.
The following functions are publicly imported:
Module Functions Publicly imported functions std.algorithm cmp, std,algorithm,comparison count, std,algorithm,searching endsWith, std,algorithm,searching startsWith, std,algorithm,searching std.array join, std,array replace, std,array replaceInPlace, std,array split, std,array empty, std,array std.format format, std,format sformat, std,format std.uni icmp, std,uni toLower, std,uni toLowerInPlace, std,uni toUpper, std,uni toUpperInPlace, std,uni There is a rich set of functions for string handling defined in other modules. Functions related to Unicode and ASCII are found in std.uni and std.ascii, respectively. Other functions that have a wider generality than just strings can be found in std.algorithm and std.range.
Source
std/string.d
string : (alias template) namespace_probe.splitLines = std.string.splitLines(C)(C[] s, KeepTerminator keepTerm = No.keepTerminator) if (isSomeChar!C)Split s into an array of lines according to the unicode standard using
'\r', '\n', "\r\n", lineSep,
paraSep, U+0085 (NEL), '\v' and '\f'
as delimiters. If keepTerm is set to KeepTerminator.yes, then the
delimiter is included in the strings returned.
Does not throw on invalid UTF; such is simply passed unchanged
to the output.
Allocates memory; use lineSplitter for an alternative that
does not.
Adheres to Unicode 7.0.
splitLines, (alias template) namespace_probe.startsWith = std.algorithm.searching.startsWith(alias pred = (a, b) => a == b, Range, Needles...)(Range doesThisStart, Needles withOneOfThese) if (isInputRange!Range && (Needles.length > 1) && allSatisfy!(canTestStartsWith!(pred, Range), Needles))Checks whether the given
input range starts with (one
of) the given needle(s) or, if no needles are given,
if its front element fulfils predicate pred.
For more information about pred see find.
startsWith;
import (package) stdstd.(module) std.exceptionThis module defines functions related to exceptions and general error
handling. It also defines functions intended to aid in unit testing.
Category Functions Assumptions assertNotThrown assertThrown assumeUnique assumeWontThrow mayPointTo Enforce doesPointTo enforce errnoEnforce Handlers collectException collectExceptionMsg ifThrown handle Other basicExceptionCtors emptyExceptionMsg ErrnoException RangePrimitive
Source
std/exception.d
Examples
Synopis
import core.stdc.stdlib : malloc, free;
import std.algorithm.comparison : equal;
import std.algorithm.iteration : map, splitter;
import std.algorithm.searching : endsWith;
import std.conv : ConvException, to;
import std.range : front, retro;
// use enforce like assert
int a = 3;
enforce(a > 2, "a needs to be higher than 2.");
// enforce can throw a custom exception
enforce!ConvException(a > 2, "a needs to be higher than 2.");
// enforce will return it's input
enum size = 42;
auto memory = enforce(malloc(size), "malloc failed")[0 .. size];
scope(exit) free(memory.ptr);
// collectException can be used to test for exceptions
Exception e = collectException("abc".to!int);
assert(e.file.endsWith("conv.d"));
// and just for the exception message
string msg = collectExceptionMsg("abc".to!int);
assert(msg == "Unexpected 'a' when converting from type string to type int");
// assertThrown can be used to assert that an exception is thrown
assertThrown!ConvException("abc".to!int);
// ifThrown can be used to provide a default value if an exception is thrown
assert("x".to!int().ifThrown(0) == 0);
// handle is a more advanced version of ifThrown for ranges
auto r = "12,1337z32,54".splitter(',').map!(a => to!int(a));
auto h = r.handle!(ConvException, RangePrimitive.front, (e, r) => 0);
assert(h.equal([12, 0, 54]));
assertThrown!ConvException(h.retro.equal([54, 0, 12]));
// basicExceptionCtors avoids the boilerplate when creating custom exceptions
static class MeaCulpa : Exception
{
mixin basicExceptionCtors;
}
e = collectException((){throw new MeaCulpa("diagnostic message");}());
assert(e.msg == "diagnostic message");
assert(e.file == __FILE__);
assert(e.line == __LINE__ - 3);
// assumeWontThrow can be used to cast throwing code into `nothrow`
void exceptionFreeCode() nothrow
{
// auto-decoding only throws if an invalid UTF char is given
assumeWontThrow("abc".front);
}
// assumeUnique can be used to cast mutable instance to an `immutable` one
// use with care
char[] str = " mutable".dup;
str[0 .. 2] = "im";
immutable res = assumeUnique(str);
assert(res == "immutable");
exception : (alias template) namespace_probe.enforce = std.exception.enforce(E : Throwable = Exception) if (is(typeof(new E("", string.init, size_t.init)) : Throwable) || is(typeof(new E(string.init, size_t.init)) : Throwable))Enforces that the given value is true.
If the given value is false, an exception is thrown.
The
msg - error message as a string
dg - custom delegate that return a string and is only called if an exception occurred
ex - custom exception to be thrown. It is lazy and is only created if an exception occurred
enforce;
extern(C) int int namespace_probe.unshare(int flags)unshare(int (parameter) int flagsflags);
void void D main()main()
{
void std.stdio.writeln!(string, uint, string, uint)(string __param_0, uint __param_1, string __param_2, uint __param_3) @safeEquivalent to write(args, '\n'). Calling writeln without
arguments is valid and just prints a newline to the standard
output.
Example
Reads stdin and writes it to stdout with an argument
counter.
import std.stdio;
void main()
{
string line;
for (size_t count = 0; (line = readln) !is null; count++)
{
writeln("Input ", count, ": ", line);
}
}
writeln("uid=", uint core.sys.posix.unistd.getuid() nothrow @nogc @trustedgetuid(), " gid=", uint core.sys.posix.unistd.getgid() nothrow @nogc @trustedgetgid());
foreach ((parameter) string lineline; string std.file.readText!(string, string)(string name) @safeReads and validates (using validate) a text file. S can be
an array of any character type. However, no width or endian conversions are
performed. So, if the width or endianness of the characters in the given
file differ from the width or endianness of the element type of S, then
validation will fail.
Examples
Read file with UTF-8 text.
write(deleteme, "abc"); // deleteme is the name of a temporary file
scope(exit) remove(deleteme);
string content = readText(deleteme);
assert(content == "abc");
readText("/proc/self/status").string[] std.string.splitLines!(immutable(char))(string s, std.typecons.Flag!"keepTerminator" keepTerm = Flag.no) pure nothrow @safeSplit s into an array of lines according to the unicode standard using
'\r', '\n', "\r\n", lineSep,
paraSep, U+0085 (NEL), '\v' and '\f'
as delimiters. If keepTerm is set to KeepTerminator.yes, then the
delimiter is included in the strings returned.
Does not throw on invalid UTF; such is simply passed unchanged
to the output.
Allocates memory; use lineSplitter for an alternative that
does not.
Adheres to Unicode 7.0.
Examples
string s = "Hello\nmy\rname\nis";
assert(splitLines(s) == ["Hello", "my", "name", "is"]);
splitLines)
if ((local variable) string lineline.bool std.algorithm.searching.startsWith!("a == b", string, string)(string doesThisStart, string withThis) pure nothrow @nogc @safeChecks whether the given
input range starts with (one
of) the given needle(s) or, if no needles are given,
if its front element fulfils predicate pred.
For more information about pred see find.
startsWith("Seccomp:") || (local variable) string lineline.bool std.algorithm.searching.startsWith!("a == b", string, string)(string doesThisStart, string withThis) pure nothrow @nogc @safeChecks whether the given
input range starts with (one
of) the given needle(s) or, if no needles are given,
if its front element fulfils predicate pred.
For more information about pred see find.
startsWith("NoNewPrivs:") || (local variable) string lineline.bool std.algorithm.searching.startsWith!("a == b", string, string)(string doesThisStart, string withThis) pure nothrow @nogc @safeChecks whether the given
input range starts with (one
of) the given needle(s) or, if no needles are given,
if its front element fulfils predicate pred.
For more information about pred see find.
startsWith("CapEff:"))
void std.stdio.writeln!string(string __param_0) @safeEquivalent to write(args, '\n'). Calling writeln without
arguments is valid and just prints a newline to the standard
output.
Example
Reads stdin and writes it to stdout with an argument
counter.
import std.stdio;
void main()
{
string line;
for (size_t count = 0; (line = readln) !is null; count++)
{
writeln("Input ", count, ": ", line);
}
}
writeln((local variable) string lineline);
try
void std.stdio.writeln!(string, string)(string __param_0, string __param_1) @safeEquivalent to write(args, '\n'). Calling writeln without
arguments is valid and just prints a newline to the standard
output.
Example
Reads stdin and writes it to stdout with an argument
counter.
import std.stdio;
void main()
{
string line;
for (size_t count = 0; (line = readln) !is null; count++)
{
writeln("Input ", count, ": ", line);
}
}
writeln("LSM context: ", string std.file.readText!(string, string)(string name) @safeReads and validates (using validate) a text file. S can be
an array of any character type. However, no width or endian conversions are
performed. So, if the width or endianness of the characters in the given
file differ from the width or endianness of the element type of S, then
validation will fail.
Examples
Read file with UTF-8 text.
write(deleteme, "abc"); // deleteme is the name of a temporary file
scope(exit) remove(deleteme);
string content = readText(deleteme);
assert(content == "abc");
readText("/proc/self/attr/current"));
catch ((class) object.ExceptionThe base class of all errors that are safe to catch and handle.
In principle, only thrown objects derived from this class are safe to catch
inside a catch block. Thrown objects not derived from Exception
represent runtime errors that should not be caught, as certain runtime
guarantees may not hold, making it unsafe to continue program execution.
Examples
bool gotCaught;
try
{
throw new Exception("msg");
}
catch (Exception e)
{
gotCaught = true;
assert(e.msg == "msg");
}
assert(gotCaught);
Exception (local variable) object.Exception ee)
void std.stdio.writeln!(string, string)(string __param_0, string __param_1) @safeEquivalent to write(args, '\n'). Calling writeln without
arguments is valid and just prints a newline to the standard
output.
Example
Reads stdin and writes it to stdout with an argument
counter.
import std.stdio;
void main()
{
string line;
for (size_t count = 0; (line = readln) !is null; count++)
{
writeln("Input ", count, ": ", line);
}
}
writeln("LSM context unavailable: ", (local variable) object.Exception ee.(field) string object.Throwable.msgA message describing the error.
msg);
const (local variable) const(string) originaloriginal = string std.file.readLink!string(string link) @safeThis function is POSIX-Only.
Returns the path to the file pointed to by a symlink. Note that the
path could be either relative or absolute depending on the symlink.
If the path is relative, it's relative to the symlink, not the current
working directory.
readLink("/proc/self/ns/mnt");
void std.stdio.writeln!(string, string)(string __param_0, string __param_1) @safeEquivalent to write(args, '\n'). Calling writeln without
arguments is valid and just prints a newline to the standard
output.
Example
Reads stdin and writes it to stdout with an argument
counter.
import std.stdio;
void main()
{
string line;
for (size_t count = 0; (line = readln) !is null; count++)
{
writeln("Input ", count, ": ", line);
}
}
writeln("parent mount namespace: ", (local variable) const(string) originaloriginal);
stdout.std.stdio.File std.stdio.makeGlobal!"core.stdc.stdio.stdout"() nothrow @nogc @property ref @systemflush();
const (local variable) const(int) childchild = int core.sys.posix.unistd.fork() nothrow @nogc @trustedfork();
bool std.exception.enforce!().enforce!bool(bool value, lazy const(char)[] msg = null, string file = __FILE__, ulong line = cast(ulong)__LINE__) pure @safeEnforces that the given value is true.
If the given value is false, an exception is thrown.
The
msg - error message as a string
dg - custom delegate that return a string and is only called if an exception occurred
ex - custom exception to be thrown. It is lazy and is only created if an exception occurred
enforce((local variable) const(int) childchild >= 0, "fork failed");
if ((local variable) const(int) childchild == 0)
{
// CLONE_NEWUSER | CLONE_NEWNS. No mounts and no parent state changes.
const (local variable) const(int) resultresult = int namespace_probe.unshare(int flags)unshare(0x10000000 | 0x00020000);
const (local variable) const(int) errorerror = int core.stdc.errno.__errno_location() nothrow @nogc ref @trustederrno;
if ((local variable) const(int) resultresult == 0)
{
const (local variable) const(string) currentcurrent = string std.file.readLink!string(string link) @safeThis function is POSIX-Only.
Returns the path to the file pointed to by a symlink. Note that the
path could be either relative or absolute depending on the symlink.
If the path is relative, it's relative to the symlink, not the current
working directory.
readLink("/proc/self/ns/mnt");
bool std.exception.enforce!().enforce!bool(bool value, lazy const(char)[] msg = null, string file = __FILE__, ulong line = cast(ulong)__LINE__) pure @safeEnforces that the given value is true.
If the given value is false, an exception is thrown.
The
msg - error message as a string
dg - custom delegate that return a string and is only called if an exception occurred
ex - custom exception to be thrown. It is lazy and is only created if an exception occurred
enforce((local variable) const(string) currentcurrent != (local variable) const(string) originaloriginal, "unshare did not create a distinct mount namespace");
void std.stdio.writeln!(string, string)(string __param_0, string __param_1) @safeEquivalent to write(args, '\n'). Calling writeln without
arguments is valid and just prints a newline to the standard
output.
Example
Reads stdin and writes it to stdout with an argument
counter.
import std.stdio;
void main()
{
string line;
for (size_t count = 0; (line = readln) !is null; count++)
{
writeln("Input ", count, ": ", line);
}
}
writeln("child mount namespace: ", (local variable) const(string) currentcurrent);
void std.stdio.writeln!string(string __param_0) @safeEquivalent to write(args, '\n'). Calling writeln without
arguments is valid and just prints a newline to the standard
output.
Example
Reads stdin and writes it to stdout with an argument
counter.
import std.stdio;
void main()
{
string line;
for (size_t count = 0; (line = readln) !is null; count++)
{
writeln("Input ", count, ": ", line);
}
}
writeln("PASS: unshare succeeded; mount/store access still needs separate validation");
}
else
void std.stdio.writeln!(string, const(int), string)(string __param_0, const(int) __param_1, string __param_2) @safeEquivalent to write(args, '\n'). Calling writeln without
arguments is valid and just prints a newline to the standard
output.
Example
Reads stdin and writes it to stdout with an argument
counter.
import std.stdio;
void main()
{
string line;
for (size_t count = 0; (line = readln) !is null; count++)
{
writeln("Input ", count, ": ", line);
}
}
writeln("SKIP: unshare(CLONE_NEWUSER|CLONE_NEWNS) errno=", (local variable) const(int) errorerror,
" (does not identify which kernel/security gate rejected it)");
stdout.std.stdio.File std.stdio.makeGlobal!"core.stdc.stdio.stdout"() nothrow @nogc @property ref @systemflush();
noreturn core.sys.posix.unistd._exit(int) nothrow @nogc @trusted_exit(0);
}
int (local variable) int statusstatus;
bool std.exception.enforce!().enforce!bool(bool value, lazy const(char)[] msg = null, string file = __FILE__, ulong line = cast(ulong)__LINE__) pure @safeEnforces that the given value is true.
If the given value is false, an exception is thrown.
The
msg - error message as a string
dg - custom delegate that return a string and is only called if an exception occurred
ex - custom exception to be thrown. It is lazy and is only created if an exception occurred
enforce(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, "namespace child failed");
bool std.exception.enforce!().enforce!bool(bool value, lazy const(char)[] msg = null, string file = __FILE__, ulong line = cast(ulong)__LINE__) pure @safeEnforces that the given value is true.
If the given value is false, an exception is thrown.
The
msg - error message as a string
dg - custom delegate that return a string and is only called if an exception occurred
ex - custom exception to be thrown. It is lazy and is only created if an exception occurred
enforce(string std.file.readLink!string(string link) @safeThis function is POSIX-Only.
Returns the path to the file pointed to by a symlink. Note that the
path could be either relative or absolute depending on the symlink.
If the path is relative, it's relative to the symlink, not the current
working directory.
readLink("/proc/self/ns/mnt") == (local variable) const(string) originaloriginal, "parent namespace changed");
void std.stdio.writeln!string(string __param_0) @safeEquivalent to write(args, '\n'). Calling writeln without
arguments is valid and just prints a newline to the standard
output.
Example
Reads stdin and writes it to stdout with an argument
counter.
import std.stdio;
void main()
{
string line;
for (size_t count = 0; (line = readln) !is null; count++)
{
writeln("Input ", count, ": ", line);
}
}
writeln("PASS: parent namespace unchanged");
}