alcove (alcove v0.38.0) View Source
Link to this section Summary
Functions
Allocate memory
Allocate memory
Get seccomp system architecture
Convert capsicum constants to integer
Convert capsicum constants to integer
cap_enter(2): place process into capability mode
cap_enter(2): place process into capability mode
cap_fcntls_get(2): get allowed fcntl commands in capability mode
cap_fcntls_get(2): get allowed fcntl commands in capability mode
cap_fcntls_limit(2): manage fcntl commands in capability mode
cap_fcntls_limit(2): manage fcntl commands in capability mode
cap_getmode(2): check if capability mode is enabled
cap_getmode(2): check if capability mode is enabled
cap_ioctls_limit(2): manage allowed ioctl commands
cap_ioctls_limit(2): manage allowed ioctl commands
cap_rights_limit(2): manage process capabilities
cap_rights_limit(2): manage process capabilities
chdir(2): change process current working directory
chdir(2): change process current working directory
chmod(2): change file permissions
chmod(2): change file permissions
chown(2): change file ownership
chown(2): change file ownership
chroot(2): change root directory
chroot(2): change root directory
clearenv(3): zero process environment
clearenv(3): zero process environment
clone(2): create a new process
clone(2): create a new process
Map clone(2) symbols to integer constants
Map clone(2) symbols to integer constants
close(2): close a file descriptor
close(2): close a file descriptor
connect(2): initiate a connection on a socket
connect(2): initiate a connection on a socket
Returns the list of child PIDs for this process
Returns the list of child PIDs for this process
Convert constant to integer
environ(7): return the process environment variables
environ(7): return the process environment variables
Close stdin of the process
Close stdin, stdout or stderr of the process
Convert errno integer to atom
Convert errno integer to atom
Get events generated by alcove port process
Get events generated by alcove port process
execve(2): replace process image with environment
execve(2): replace process image with environment
execvp(2): replace the current process image using the search path
execvp(2): replace the current process image using the search path
exit(3): cause an alcove control process to exit
exit(3): cause an alcove control process to exit
fcntl(2): perform operations on a file descriptor
fcntl(2): perform operations on a file descriptor
Convert fnctl(2) constant to integer
Convert fnctl(2) constant to integer
fexecve(2): replace the process image
fexecve(2): replace the process image
Constants for open(2)
Constants for open(2)
Create a call filter list
Restrict calls available to an alcove control process
Restrict available calls for control and subprocess
Restrict available calls for control and subprocess
fork(2): create a new process
fork(2): create a new process
Get control process attributes
getcwd(3): return the current working directory
getcwd(3): return the current working directory
getenv(3): retrieve an environment variable
getenv(3): retrieve an environment variable
getgid(2): retrieve the process group ID
getgid(2): retrieve the process group ID
getgroups(2): retrieve the list of supplementary groups
getgroups(2): retrieve the list of supplementary groups
gethostname(2): retrieve the system hostname
gethostname(2): retrieve the system hostname
Retrieve port options for event loop
Retrieve port options for event loop
getpgrp(2): retrieve the process group
getpgrp(2): retrieve the process group
getpid(2): retrieve the system PID of the process
getpid(2): retrieve the system PID of the process
getpriority(2): retrieve scheduling priority of process, process group or user
getpriority(2): retrieve scheduling priority of process, process group or user
getresgid(2): get real, effective and saved group ID
getresgid(2): get real, effective and saved group ID
getresuid(2): get real, effective and saved user ID
getresuid(2): get real, effective and saved user ID
getrlimit(2): retrieve the resource limits for a process
getrlimit(2): retrieve the resource limits for a process
getsid(2): retrieve the session ID
getsid(2): retrieve the session ID
getuid(2): returns the process user ID
getuid(2): returns the process user ID
ioctl(2): control device
ioctl(2): control device
Convert ioctl constant to integer
Convert ioctl constant to integer
Convert iolist to binary
Convert iolist to binary
jail(2): restrict the current process in a system jail
jail(2): restrict the current process in a system jail
jail_attach(2): join a jailed process
jail_attach(2): join a jailed process
jail_remove(2): destroy a jailed process
jail_remove(2): destroy a jailed process
kill(2): terminate a process
kill(2): terminate a process
link(2) : create a hard link
link(2) : create a hard link
lseek(2): set file offset for read/write
lseek(2): set file offset for read/write
mkdir(2): create a directory
mkdir(2): create a directory
mkfifo(3): make named pipe file
mkfifo(3): make named pipe file
mount(2): mount a filesystem, Linux style
mount(2): mount a filesystem, Linux style
Convert flag names to integers
Convert flag names to integers
open(2): returns a file descriptor associated with a file
open(2): returns a file descriptor associated with a file
pivot_root(2): change the root mount
pivot_root(2): change the root mount
pledge(2): restrict system operations
pledge(2): restrict system operations
prctl(2): operations on a process
prctl(2): operations on a process
Convert prctl option names to integers
Convert prctl option names to integers
procctl(2): control processes
procctl(2): control processes
ptrace(2): process trace
ptrace(2): process trace
Convert ptrace constant to integer
Convert ptrace constant to integer
read(2): read bytes from a file descriptor
read(2): read bytes from a file descriptor
readdir(3): retrieve list of objects in a directory
readdir(3): retrieve list of objects in a directory
Convert an RLIMIT_* flag to an integer
Convert an RLIMIT_* flag to an integer
rmdir(2): delete a directory
rmdir(2): delete a directory
seccomp(2): restrict system operations
seccomp(2): restrict system operations
Convert seccomp option name to integer
Convert seccomp option name to integer
select(2): poll a list of file descriptor for events
select(2): poll a list of file descriptor for events
Set options for child process of alcove control process
Set options for child process of alcove control process
setenv(3): set an environment variable
setenv(3): set an environment variable
setgid(2): set the GID of the process
setgid(2): set the GID of the process
setgroups(2): set the supplementary groups of the process
setgroups(2): set the supplementary groups of the process
sethostname(2): set the system hostname
sethostname(2): set the system hostname
setns(2): attach to a namespace
setns(2): attach to a namespace
Set port options
Set port options
setpgid(2): set process group
setpgid(2): set process group
setpriority(2): set scheduling priority of process, process group or user
setpriority(2): set scheduling priority of process, process group or user
setproctitle(3): set the process title
setproctitle(3): set the process title
setresgid(2): set real, effective and saved group ID
setresgid(2): set real, effective and saved group ID
setresuid(2): set real, effective and saved user ID
setresuid(2): set real, effective and saved user ID
setrlimit(2): set a resource limit
setrlimit(2): set a resource limit
setsid(2): create a new session
setsid(2): create a new session
setuid(2): change UID
setuid(2): change UID
sigaction(2): set process behaviour for signals
sigaction(2): set process behaviour for signals
Convert signal names to integers
Convert signal names to integers
socket(2): returns a file descriptor for a communication endpoint
socket(2): returns a file descriptor for a communication endpoint
Read stderr from the process
Send data to stdin of the process
Read stdout from the process
symlink(2): create a symbolic link
symlink(2): create a symbolic link
Convert syscall name to integer
Convert syscall name to integer
umount(2): unmount a filesystem
umount(2): unmount a filesystem
umount2(2): unmount filesystem with flags
umount2(2): unmount filesystem with flags
unlink(2): delete a name from the filesystem
unlink(2): delete a name from the filesystem
unsetenv(3): remove an environment variable
unsetenv(3): remove an environment variable
unshare(2): create a new namespace in the current process
unshare(2): create a new namespace in the current process
unveil(2): restrict filesystem view
unveil(2): restrict filesystem view
Retrieve the alcove version
Retrieve the alcove version
waitpid(2): wait for process to change state
waitpid(2): wait for process to change state
write(2): write to a file descriptor
write(2): write to a file descriptor
Link to this section Types
Specs
alcove_pid() :: #alcove_pid{}.
Specs
alcove_pid_field() :: pid | flowcontrol | signaloneof | fdctl | stdin | stdout | stderr.
Specs
alcove_rlimit() :: #alcove_rlimit{}.
Specs
alcove_timeval() :: #alcove_timeval{}.
Specs
constant() :: atom() | integer().
Specs
cstruct() :: [binary() | {ptr, binary() | non_neg_integer()}, ...].
Specs
fd() :: int32_t().
Specs
fd_set() :: [fd()].
Specs
filter() :: alcove_proto:calls() | [] | {deny, alcove_proto:calls() | []} | {allow, alcove_proto:calls() | []}.
Specs
gid_t() :: uint32_t().
Specs
int16_t() :: - 32767..32767.
Specs
int32_t() :: - 2147483647..2147483647.
Specs
int64_t() :: - 9223372036854775807..9223372036854775807.
Specs
int8_t() :: - 127..127.
Specs
mode_t() :: uint32_t().
Specs
off_t() :: uint64_t().
Specs
pid_t() :: int32_t().
Specs
posix() :: e2big | eacces | eaddrinuse | eaddrnotavail | eadv | eafnosupport | eagain | ealign | ealready | ebade | ebadf | ebadfd | ebadmsg | ebadr | ebadrpc | ebadrqc | ebadslt | ebfont | ebusy | ecapmode | echild | echrng | ecomm | econnaborted | econnrefused | econnreset | edeadlk | edeadlock | edestaddrreq | edirty | edom | edotdot | edquot | eduppkg | eexist | efault | efbig | ehostdown | ehostunreach | eidrm | einit | einprogress | eintr | einval | eio | eisconn | eisdir | eisnam | el2hlt | el2nsync | el3hlt | el3rst | elbin | elibacc | elibbad | elibexec | elibmax | elibscn | elnrng | eloop | emfile | emlink | emsgsize | emultihop | enametoolong | enavail | enet | enetdown | enetreset | enetunreach | enfile | enoano | enobufs | enocsi | enodata | enodev | enoent | enoexec | enolck | enolink | enomem | enomsg | enonet | enopkg | enoprotoopt | enospc | enosr | enostr | enosym | enosys | enotblk | enotcapable | enotconn | enotdir | enotempty | enotnam | enotrecoverable | enotsock | enotsup | enotty | enotuniq | enxio | eopnotsupp | eoverflow | eownerdead | eperm | epfnosupport | epipe | eproclim | eprocunavail | eprogmismatch | eprogunavail | eproto | eprotonosupport | eprototype | erange | erefused | eremchg | eremdev | eremote | eremoteio | eremoterelease | erofs | erpcmismatch | erremote | eshutdown | esocktnosupport | espipe | esrch | esrmnt | estale | esuccess | etime | etimedout | etoomanyrefs | etxtbsy | euclean | eunatch | eusers | eversion | ewouldblock | exdev | exfull.
Specs
Specs
ptr_val() :: binary() | integer() | cstruct().
Specs
size_t() :: uint64_t().
Specs
ssize_t() :: int64_t().
Specs
uid_t() :: uint32_t().
Specs
uint16_t() :: 0..65535.
Specs
uint32_t() :: 0..4294967295.
Specs
uint64_t() :: 0..18446744073709551615.
Specs
uint8_t() :: 0..255.
Specs
waitstatus() :: {exit_status, int32_t()} | {termsig, atom()} | {stopsig, atom()} | continued.
Link to this section Functions
Specs
alloc(alcove_drv:ref(), [pid_t()], Ptr :: cstruct()) -> {ok, binary(), iodata()}.
Allocate memory
Test memory allocation.
Memory is allocated using a cstruct which is a list containing:
* binary: a value to be allocated and initialized in the memory
* {ptr, integer()}: create a pointer to 0 initialized memory
* {ptr, binary()}: create a pointer to memory initialized to the binary
The return value is an ok tuple:
* the atom ok
* a binary with the raw memory
* an initialized cstruct
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.182.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,4040}
3> alcove:alloc(Drv, [Pid], [<<"initialized">>, {ptr, 16}, {ptr, <<"initialized">>}]).
{ok,<<105,110,105,116,105,97,108,105,122,101,100,48,238,
23,162,165,87,0,0,80,238,23,162,165,87,0,0>>,
[<<"initialized">>,
{ptr,<<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0>>},
{ptr,<<"initialized">>}]}
% <<"initialized">>: 105,110,105,116,105,97,108,105,122,101,100
% {ptr,<<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0>>}: 48,238,23,162,165,87,0,0 (pointer)
% {ptr,<<"initialized">>}: 80,238,23,162,165,87,0,0 (pointer)
Specs
alloc(alcove_drv:ref(), [pid_t()], Ptr :: cstruct(), timeout()) -> {ok, binary(), iodata()}.
Allocate memory
Test memory allocation.
Memory is allocated using a cstruct which is a list containing:
* binary: a value to be allocated and initialized in the memory
* {ptr, integer()}: create a pointer to 0 initialized memory
* {ptr, binary()}: create a pointer to memory initialized to the binary
The return value is an ok tuple:
* the atom ok
* a binary with the raw memory
* an initialized cstruct
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.182.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,4040}
3> alcove:alloc(Drv, [Pid], [<<"initialized">>, {ptr, 16}, {ptr, <<"initialized">>}]).
{ok,<<105,110,105,116,105,97,108,105,122,101,100,48,238,
23,162,165,87,0,0,80,238,23,162,165,87,0,0>>,
[<<"initialized">>,
{ptr,<<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0>>},
{ptr,<<"initialized">>}]}
% <<"initialized">>: 105,110,105,116,105,97,108,105,122,101,100
% {ptr,<<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0>>}: 48,238,23,162,165,87,0,0 (pointer)
% {ptr,<<"initialized">>}: 80,238,23,162,165,87,0,0 (pointer)
Specs
audit_arch() -> atom().
Get seccomp system architecture
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.176.0>}
2> alcove:audit_arch().
audit_arch_x86_64
3> alcove:define(Drv, [], alcove:audit_arch()).
3221225534
Specs
cap_constant(alcove_drv:ref(), [pid_t()], Symbol :: atom()) -> integer() | unknown.
Convert capsicum constants to integer
Support
* FreeBSD
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.208.0>}
2> alcove:cap_constant(Drv, [], cap_fcntl_setfl).
16
Specs
cap_constant(alcove_drv:ref(), [pid_t()], Symbol :: atom(), timeout()) -> integer() | unknown.
Convert capsicum constants to integer
Support
* FreeBSD
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.208.0>}
2> alcove:cap_constant(Drv, [], cap_fcntl_setfl).
16
Specs
cap_enter(alcove_drv:ref(), [pid_t()]) -> ok | {error, posix()}.
cap_enter(2): place process into capability mode
Support
* FreeBSD
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.208.0>}
2> {ok, Pid1} = alcove:fork(Drv, []).
{ok,75331}
3> {ok, Pid2} = alcove:fork(Drv, []).
{ok,75332}
4> ok = alcove:cap_enter(Drv, [Pid1]).
ok
5> alcove:kill(Drv, [Pid1], 0, 0).
{error,ecapmode}
6> alcove:kill(Drv, [Pid2], 0, 0).
ok
7> alcove:kill(Drv, [], 0, 0).
ok
Specs
cap_enter(alcove_drv:ref(), [pid_t()], timeout()) -> ok | {error, posix()}.
cap_enter(2): place process into capability mode
Support
* FreeBSD
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.208.0>}
2> {ok, Pid1} = alcove:fork(Drv, []).
{ok,75331}
3> {ok, Pid2} = alcove:fork(Drv, []).
{ok,75332}
4> ok = alcove:cap_enter(Drv, [Pid1]).
ok
5> alcove:kill(Drv, [Pid1], 0, 0).
{error,ecapmode}
6> alcove:kill(Drv, [Pid2], 0, 0).
ok
7> alcove:kill(Drv, [], 0, 0).
ok
Specs
cap_fcntls_get(alcove_drv:ref(), [pid_t()], FD :: fd()) -> {ok, integer()} | {error, posix()}.
cap_fcntls_get(2): get allowed fcntl commands in capability mode
Support
* FreeBSD
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.209.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,77853}
3> {ok, FD} = alcove:open(Drv, [Pid], "/etc/passwd", [o_rdonly], 0).
{ok,6}
4> ok = alcove:cap_enter(Drv, [Pid]).
ok
5> alcove:cap_fcntls_get(Drv, [Pid], FD).
{ok,120}
Specs
cap_fcntls_get(alcove_drv:ref(), [pid_t()], FD :: fd(), timeout()) -> {ok, integer()} | {error, posix()}.
cap_fcntls_get(2): get allowed fcntl commands in capability mode
Support
* FreeBSD
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.209.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,77853}
3> {ok, FD} = alcove:open(Drv, [Pid], "/etc/passwd", [o_rdonly], 0).
{ok,6}
4> ok = alcove:cap_enter(Drv, [Pid]).
ok
5> alcove:cap_fcntls_get(Drv, [Pid], FD).
{ok,120}
Specs
cap_fcntls_limit(alcove_drv:ref(), [pid_t()], FD :: fd(), Rights :: constant()) -> ok | {error, posix()}.
cap_fcntls_limit(2): manage fcntl commands in capability mode
Support
* FreeBSD
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.209.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,77853}
3> {ok, FD} = alcove:open(Drv, [Pid], "/etc/passwd", [o_rdonly], 0).
{ok,6}
4> ok = alcove:cap_enter(Drv, [Pid]).
ok
5> alcove:cap_fcntls_get(Drv, [Pid], FD).
{ok,120}
6> ok = alcove:cap_fcntls_limit(Drv, [Pid], FD, [cap_fcntl_setfl]).
ok
7> alcove:cap_fcntls_get(Drv, [Pid], FD).
{ok,16}
Specs
cap_fcntls_limit(alcove_drv:ref(), [pid_t()], FD :: fd(), Rights :: constant(), timeout()) -> ok | {error, posix()}.
cap_fcntls_limit(2): manage fcntl commands in capability mode
Support
* FreeBSD
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.209.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,77853}
3> {ok, FD} = alcove:open(Drv, [Pid], "/etc/passwd", [o_rdonly], 0).
{ok,6}
4> ok = alcove:cap_enter(Drv, [Pid]).
ok
5> alcove:cap_fcntls_get(Drv, [Pid], FD).
{ok,120}
6> ok = alcove:cap_fcntls_limit(Drv, [Pid], FD, [cap_fcntl_setfl]).
ok
7> alcove:cap_fcntls_get(Drv, [Pid], FD).
{ok,16}
Specs
cap_getmode(alcove_drv:ref(), [pid_t()]) -> {ok, 0 | 1} | {error, posix()}.
cap_getmode(2): check if capability mode is enabled
Support
* FreeBSD
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.209.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,75710}
3> ok = alcove:cap_enter(Drv, [Pid]).
ok
4> alcove:cap_getmode(Drv, [Pid]).
{ok,1}
5> alcove:cap_getmode(Drv, []).
{ok,0}
Specs
cap_getmode(alcove_drv:ref(), [pid_t()], timeout()) -> {ok, 0 | 1} | {error, posix()}.
cap_getmode(2): check if capability mode is enabled
Support
* FreeBSD
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.209.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,75710}
3> ok = alcove:cap_enter(Drv, [Pid]).
ok
4> alcove:cap_getmode(Drv, [Pid]).
{ok,1}
5> alcove:cap_getmode(Drv, []).
{ok,0}
Specs
cap_ioctls_limit(alcove_drv:ref(), [pid_t()], FD :: fd(), Rights :: constant()) -> ok | {error, posix()}.
cap_ioctls_limit(2): manage allowed ioctl commands
Support
* FreeBSD
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.209.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,75710}
3> {ok, Pty} = alcove:open(Drv, [Pid], "/dev/pts/1", [o_rdwr, o_nonblock], 0).
{ok,6}
4> alcove:cap_enter(Drv, [Pid]).
ok
5> alcove:cap_ioctls_limit(Drv, [Pid], FD, [tiocmget, tiocgwinsz]).
ok
6> alcove:ioctl(Drv, [Pid], FD, tiocmset, <<>>).
{error,enotcapable}
7> alcove:ioctl(Drv, [Pid], FD, tiocmget, <<>>).
{ok,0,<<>>}
Specs
cap_ioctls_limit(alcove_drv:ref(), [pid_t()], FD :: fd(), Rights :: constant(), timeout()) -> ok | {error, posix()}.
cap_ioctls_limit(2): manage allowed ioctl commands
Support
* FreeBSD
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.209.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,75710}
3> {ok, Pty} = alcove:open(Drv, [Pid], "/dev/pts/1", [o_rdwr, o_nonblock], 0).
{ok,6}
4> alcove:cap_enter(Drv, [Pid]).
ok
5> alcove:cap_ioctls_limit(Drv, [Pid], FD, [tiocmget, tiocgwinsz]).
ok
6> alcove:ioctl(Drv, [Pid], FD, tiocmset, <<>>).
{error,enotcapable}
7> alcove:ioctl(Drv, [Pid], FD, tiocmget, <<>>).
{ok,0,<<>>}
Specs
cap_rights_limit(alcove_drv:ref(), [pid_t()], FD :: fd(), Rights :: constant()) -> ok | {error, posix()}.
cap_rights_limit(2): manage process capabilities
Support
* FreeBSD
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.209.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,75710}
3> {ok, FD} = alcove:open(Drv, [Pid], "/etc/passwd", [o_rdonly], 0).
{ok,6}
4> alcove:cap_enter(Drv, [Pid]).
ok
5> alcove:cap_rights_limit(Drv, [Pid], FD, [cap_read]).
ok
6> alcove:read(Drv, [Pid], FD, 64).
{ok,<<"# $FreeBSD$\n#\nroot:*:0:0:Charlie &:/root:/bin/csh\ntoor:*:0:0:Bou">>}
7> alcove:lseek(Drv, [Pid], FD, 0, 0).
{error,enotcapable}
8> alcove:open(Drv, [Pid], "/etc/passwd", [o_rdonly], 0).
{error,ecapmode}
Specs
cap_rights_limit(alcove_drv:ref(), [pid_t()], FD :: fd(), Rights :: constant(), timeout()) -> ok | {error, posix()}.
cap_rights_limit(2): manage process capabilities
Support
* FreeBSD
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.209.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,75710}
3> {ok, FD} = alcove:open(Drv, [Pid], "/etc/passwd", [o_rdonly], 0).
{ok,6}
4> alcove:cap_enter(Drv, [Pid]).
ok
5> alcove:cap_rights_limit(Drv, [Pid], FD, [cap_read]).
ok
6> alcove:read(Drv, [Pid], FD, 64).
{ok,<<"# $FreeBSD$\n#\nroot:*:0:0:Charlie &:/root:/bin/csh\ntoor:*:0:0:Bou">>}
7> alcove:lseek(Drv, [Pid], FD, 0, 0).
{error,enotcapable}
8> alcove:open(Drv, [Pid], "/etc/passwd", [o_rdonly], 0).
{error,ecapmode}
Specs
chdir(alcove_drv:ref(), [pid_t()], Path :: iodata()) -> ok | {error, posix()}.
chdir(2): change process current working directory
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.176.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,18617}
3> alcove:chdir(Drv, [Pid], "/tmp").
ok
4> alcove:chdir(Drv, [], "/").
ok
5> alcove:getcwd(Drv, [Pid]).
{ok,<<"/tmp">>}
6> alcove:getcwd(Drv, []).
{ok,<<"/">>}
Specs
chdir(alcove_drv:ref(), [pid_t()], Path :: iodata(), timeout()) -> ok | {error, posix()}.
chdir(2): change process current working directory
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.176.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,18617}
3> alcove:chdir(Drv, [Pid], "/tmp").
ok
4> alcove:chdir(Drv, [], "/").
ok
5> alcove:getcwd(Drv, [Pid]).
{ok,<<"/tmp">>}
6> alcove:getcwd(Drv, []).
{ok,<<"/">>}
Specs
chmod(alcove_drv:ref(), [pid_t()], Path :: iodata(), Mode :: mode_t()) -> ok | {error, posix()}.
chmod(2): change file permissions
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,18820}
3> {ok, FD} = alcove:open(Drv, [Pid], "/tmp/foo123.txt", [o_wronly, o_creat], 8#644).
{ok,6}
4> alcove:chmod(Drv, [Pid], "/tmp/foo123.txt", 8#400).
ok
Specs
chmod(alcove_drv:ref(), [pid_t()], Path :: iodata(), Mode :: mode_t(), timeout()) -> ok | {error, posix()}.
chmod(2): change file permissions
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,18820}
3> {ok, FD} = alcove:open(Drv, [Pid], "/tmp/foo123.txt", [o_wronly, o_creat], 8#644).
{ok,6}
4> alcove:chmod(Drv, [Pid], "/tmp/foo123.txt", 8#400).
ok
Specs
chown(alcove_drv:ref(), [pid_t()], Path :: iodata(), Owner :: uid_t(), Group :: gid_t()) -> ok | {error, posix()}.
chown(2): change file ownership
Examples
1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
{ok,<0.177.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,18820}
3> {ok, FD} = alcove:open(Drv, [Pid], "/tmp/foo123.txt", [o_wronly, o_creat], 8#644).
{ok,6}
6> alcove:chown(Drv, [Pid], "/tmp/foo123.txt", 0, 0).
ok
Specs
chown(alcove_drv:ref(), [pid_t()], Path :: iodata(), Owner :: uid_t(), Group :: gid_t(), timeout()) -> ok | {error, posix()}.
chown(2): change file ownership
Examples
1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
{ok,<0.177.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,18820}
3> {ok, FD} = alcove:open(Drv, [Pid], "/tmp/foo123.txt", [o_wronly, o_creat], 8#644).
{ok,6}
6> alcove:chown(Drv, [Pid], "/tmp/foo123.txt", 0, 0).
ok
Specs
chroot(alcove_drv:ref(), [pid_t()], Path :: iodata()) -> ok | {error, posix()}.
chroot(2): change root directory
Examples
1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
{ok,<0.176.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,19048}
3> alcove:chroot(Drv, [Pid], "/tmp").
ok
4> alcove:chdir(Drv, [Pid], "/").
ok
5> alcove:getcwd(Drv, [Pid]).
{ok,<<"/">>}
Specs
chroot(alcove_drv:ref(), [pid_t()], Path :: iodata(), timeout()) -> ok | {error, posix()}.
chroot(2): change root directory
Examples
1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
{ok,<0.176.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,19048}
3> alcove:chroot(Drv, [Pid], "/tmp").
ok
4> alcove:chdir(Drv, [Pid], "/").
ok
5> alcove:getcwd(Drv, [Pid]).
{ok,<<"/">>}
Specs
clearenv(alcove_drv:ref(), [pid_t()]) -> ok | {error, posix()}.
clearenv(3): zero process environment
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.176.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,19048}
3> alcove:clearenv(Drv, [Pid]).
ok
4> alcove:environ(Drv, [Pid]).
[]
Specs
clearenv(alcove_drv:ref(), [pid_t()], timeout()) -> ok | {error, posix()}.
clearenv(3): zero process environment
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.176.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,19048}
3> alcove:clearenv(Drv, [Pid]).
ok
4> alcove:environ(Drv, [Pid]).
[]
Specs
clone(alcove_drv:ref(), [pid_t()], Flags :: int32_t() | [constant()]) -> {ok, pid_t()} | {error, posix()}.
clone(2): create a new process
Support
* Linux
Examples
1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
{ok,<0.176.0>}
2> {ok, Pid} = alcove:clone(Drv, [], [clone_newns, clone_newpid, clone_newipc, clone_newuts, clone_newnet]).
{ok,19127}
3> alcove:getpid(Drv, [Pid]).
1
Specs
clone(alcove_drv:ref(), [pid_t()], Flags :: int32_t() | [constant()], timeout()) -> {ok, pid_t()} | {error, posix()}.
clone(2): create a new process
Support
* Linux
Examples
1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
{ok,<0.176.0>}
2> {ok, Pid} = alcove:clone(Drv, [], [clone_newns, clone_newpid, clone_newipc, clone_newuts, clone_newnet]).
{ok,19127}
3> alcove:getpid(Drv, [Pid]).
1
Specs
clone_constant(alcove_drv:ref(), [pid_t()], Symbol :: atom()) -> unknown | int32_t().
Map clone(2) symbols to integer constants
Support
* Linux
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.176.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,19048}
3> alcove:clone_constant(Drv, [19127], clone_newuts).
67108864
Specs
clone_constant(alcove_drv:ref(), [pid_t()], Symbol :: atom(), timeout()) -> unknown | int32_t().
Map clone(2) symbols to integer constants
Support
* Linux
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.176.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,19048}
3> alcove:clone_constant(Drv, [19127], clone_newuts).
67108864
Specs
close(alcove_drv:ref(), [pid_t()], FD :: fd()) -> ok | {error, posix()}.
close(2): close a file descriptor
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,18820}
3> {ok, FD} = alcove:open(Drv, [Pid], "/tmp/foo123.txt", [o_wronly, o_creat], 8#644).
{ok,6}
4> alcove:close(Drv, [Pid], FD).
ok
Specs
close(alcove_drv:ref(), [pid_t()], FD :: fd(), timeout()) -> ok | {error, posix()}.
close(2): close a file descriptor
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,18820}
3> {ok, FD} = alcove:open(Drv, [Pid], "/tmp/foo123.txt", [o_wronly, o_creat], 8#644).
{ok,6}
4> alcove:close(Drv, [Pid], FD).
ok
Specs
connect(alcove_drv:ref(), [pid_t()], FD :: fd(), Sockaddr :: [] | cstruct()) -> ok | {error, posix()}.
connect(2): initiate a connection on a socket
Examples
-module(unix_socket).
-export([connect]).
connect(Data) when is_binary(Data) ->
{ok, Drv} = alcove:start(),
{ok, NC} = alcove:fork(Drv, []),
{ok, Process} = alcove:fork(Drv, []),
Sockname = <<"/tmp/test.", (integer_to_binary(alcove:getpid(Drv, [])))/binary>>,
ok = alcove:execvp(Drv, [NC], "nc", ["nc", "-l", "-U", Sockname]),
ok = waitfor(Sockname),
{ok, Socket} = alcove:socket(Drv, [Process], af_unix, sock_stream, 0),
% #define UNIX_PATH_MAX 108
% struct sockaddr_un {
% __kernel_sa_family_t sun_family; /* AF_UNIX */
% char sun_path[UNIX_PATH_MAX]; /* pathname */
% };
AF_UNIX = 1,
SocknameLen = byte_size(Sockname),
Len = (unix_path_max() - SocknameLen) * 8,
ok = alcove:connect(Drv, [Process], Socket, [
sockaddr_common(AF_UNIX, SocknameLen),
Sockname,
<<0:Len>>
]),
% alcove process -> nc
{ok, N} = alcove:write(Drv, [Process], Socket, Data),
receive
{alcove_stdout, Drv, [NC], Stdout} ->
Stdout
end.
% UNIX_PATH_MAX
unix_path_max() ->
case erlang:system_info(os_type) of
{unix, BSD} when BSD == darwin; BSD == openbsd; BSD == netbsd; BSD == freebsd ->
104;
{unix, _} ->
108
end.
% struct sockaddr
sockaddr_common(Family, Length) ->
case erlang:system_info(os_type) of
{unix, BSD} when BSD == darwin; BSD == openbsd; BSD == netbsd; BSD == freebsd ->
<<Length:8, Family:8>>;
{unix, _} ->
<<Family:16/native>>
end.
waitfor(Sockname) ->
case file:read_file_info(Sockname) of
{ok, _} ->
ok;
{error, enoent} ->
timer:sleep(1),
waitfor(Sockname);
{error, eperm} ->
ok;
Error ->
Error
end.
Specs
connect(alcove_drv:ref(), [pid_t()], FD :: fd(), Sockaddr :: [] | cstruct(), timeout()) -> ok | {error, posix()}.
connect(2): initiate a connection on a socket
Examples
-module(unix_socket).
-export([connect]).
connect(Data) when is_binary(Data) ->
{ok, Drv} = alcove:start(),
{ok, NC} = alcove:fork(Drv, []),
{ok, Process} = alcove:fork(Drv, []),
Sockname = <<"/tmp/test.", (integer_to_binary(alcove:getpid(Drv, [])))/binary>>,
ok = alcove:execvp(Drv, [NC], "nc", ["nc", "-l", "-U", Sockname]),
ok = waitfor(Sockname),
{ok, Socket} = alcove:socket(Drv, [Process], af_unix, sock_stream, 0),
% #define UNIX_PATH_MAX 108
% struct sockaddr_un {
% __kernel_sa_family_t sun_family; /* AF_UNIX */
% char sun_path[UNIX_PATH_MAX]; /* pathname */
% };
AF_UNIX = 1,
SocknameLen = byte_size(Sockname),
Len = (unix_path_max() - SocknameLen) * 8,
ok = alcove:connect(Drv, [Process], Socket, [
sockaddr_common(AF_UNIX, SocknameLen),
Sockname,
<<0:Len>>
]),
% alcove process -> nc
{ok, N} = alcove:write(Drv, [Process], Socket, Data),
receive
{alcove_stdout, Drv, [NC], Stdout} ->
Stdout
end.
% UNIX_PATH_MAX
unix_path_max() ->
case erlang:system_info(os_type) of
{unix, BSD} when BSD == darwin; BSD == openbsd; BSD == netbsd; BSD == freebsd ->
104;
{unix, _} ->
108
end.
% struct sockaddr
sockaddr_common(Family, Length) ->
case erlang:system_info(os_type) of
{unix, BSD} when BSD == darwin; BSD == openbsd; BSD == netbsd; BSD == freebsd ->
<<Length:8, Family:8>>;
{unix, _} ->
<<Family:16/native>>
end.
waitfor(Sockname) ->
case file:read_file_info(Sockname) of
{ok, _} ->
ok;
{error, enoent} ->
timer:sleep(1),
waitfor(Sockname);
{error, eperm} ->
ok;
Error ->
Error
end.
Specs
cpid(alcove_drv:ref(), [pid_t()]) -> [alcove_pid()].
Returns the list of child PIDs for this process
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.176.0>}
2> {ok, Pid1} = alcove:fork(Drv, []).
{ok,19048}
3> {ok, Pid2} = alcove:fork(Drv, []).
{ok,19127}
4> rr(alcove).
[alcove_jail,alcove_pid,alcove_rlimit,alcove_timeval]
5> alcove:cpid(Drv, [Pid1]).
[]
6> alcove:cpid(Drv, []).
[#alcove_pid{pid = 19048,flowcontrol = -1,signaloneof = 15,
fdctl = 7,stdin = 9,stdout = 10,stderr = 12},
#alcove_pid{pid = 19127,flowcontrol = -1,signaloneof = 15,
fdctl = 8,stdin = 13,stdout = 14,stderr = 16}]
Specs
cpid(alcove_drv:ref(), [pid_t()], timeout()) -> [alcove_pid()].
Returns the list of child PIDs for this process
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.176.0>}
2> {ok, Pid1} = alcove:fork(Drv, []).
{ok,19048}
3> {ok, Pid2} = alcove:fork(Drv, []).
{ok,19127}
4> rr(alcove).
[alcove_jail,alcove_pid,alcove_rlimit,alcove_timeval]
5> alcove:cpid(Drv, [Pid1]).
[]
6> alcove:cpid(Drv, []).
[#alcove_pid{pid = 19048,flowcontrol = -1,signaloneof = 15,
fdctl = 7,stdin = 9,stdout = 10,stderr = 12},
#alcove_pid{pid = 19127,flowcontrol = -1,signaloneof = 15,
fdctl = 8,stdin = 13,stdout = 14,stderr = 16}]
Specs
define(alcove_drv:ref(), [pid_t()], atom() | [atom()]) -> integer().
Convert constant to integer
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.176.0>}
2> alcove:define(Drv, [], clone_newns).
131072
Specs
environ(alcove_drv:ref(), [pid_t()]) -> [binary()].
environ(7): return the process environment variables
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.176.0>}
2> alcove:environ(Drv, []).
[<<"LANG=C.UTF-8">>,
<<"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin">>,
<<"TERM=screen">>, <<"SHELL=/bin/bash">>]
Specs
environ(alcove_drv:ref(), [pid_t()], timeout()) -> [binary()].
environ(7): return the process environment variables
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.176.0>}
2> alcove:environ(Drv, []).
[<<"LANG=C.UTF-8">>,
<<"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin">>,
<<"TERM=screen">>, <<"SHELL=/bin/bash">>]
Specs
eof(alcove_drv:ref(), [pid_t()]) -> ok | {error, posix()}.
Close stdin of the process
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.176.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,19048}
3> alcove:execvp(Drv, [Pid], "cat", ["cat"]).
ok
4> alcove:eof(Drv, [Pid]).
ok
5> alcove:event(Drv, [Pid]).
{exit_status,0}
Specs
eof(alcove_drv:ref(), [pid_t()], stdin | stdout | stderr) -> ok | {error, posix()}.
Close stdin, stdout or stderr of the process
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.176.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,19048}
3> alcove:execvp(Drv, [Pid], "cat", ["cat"]).
ok
4> alcove:eof(Drv, [Pid], stdin).
ok
5> alcove:event(Drv, [Pid]).
{exit_status,0}
Specs
errno_id(alcove_drv:ref(), [pid_t()], Errno :: int32_t()) -> posix().
Convert errno integer to atom
Examples
1> alcove:errno_id(Drv, [], 1).
eperm
Specs
errno_id(alcove_drv:ref(), [pid_t()], Errno :: int32_t(), timeout()) -> posix().
Convert errno integer to atom
Examples
1> alcove:errno_id(Drv, [], 1).
eperm
Specs
event(alcove_drv:ref(), [pid_t()]) -> term().
Get events generated by alcove port process
event/1,2 is used to retrieve async messages returned from the port, such as caught signals, the exit status or the termination signal.
1> {ok, Drv} = alcove_drv:start().
{ok,<0.176.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,19048}
3> alcove:kill(Drv, [], Pid, 15).
ok
4> alcove:event(Drv, [Pid]).
{signal,sigterm,
<<15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,74,0,0,0,0,0,0,0,
0,...>>}
Specs
event(alcove_drv:ref(), [pid_t()], timeout()) -> term().
Get events generated by alcove port process
1> {ok, Drv} = alcove_drv:start().
{ok,<0.176.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,19048}
3> alcove:kill(Drv, [], Pid, 15).
ok
4> alcove:event(Drv, [Pid], 5000).
{signal,sigterm,
<<15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,74,0,0,0,0,0,0,0,
0,...>>}
5> alcove:event(Drv, [Pid], 5000).
false
Specs
execve(alcove_drv:ref(), [pid_t()], Arg0 :: iodata(), Argv :: [iodata()], Env :: [iodata()]) -> ok | {error, posix()}.
execve(2): replace process image with environment
Replace the process image, specifying the environment for the new process image.
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.176.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,29037}
3> alcove:execve(Drv, [Pid], "/usr/bin/env", ["env"], ["FOO=123"]).
ok
% Shell got {alcove_stdout,<0.176.0>,[29037],<<"FOO=123\n">>}
% Shell got {alcove_event,<0.176.0>,[29037],{exit_status,0}}
4> alcove:stdout(Drv, [Pid]).
[<<"FOO=123\n">>]
5> alcove:event(Drv, [Pid], 5000).
{exit_status,0}
ok
Specs
execve(alcove_drv:ref(), [pid_t()], Arg0 :: iodata(), Argv :: [iodata()], Env :: [iodata()], timeout()) -> ok | {error, posix()}.
execve(2): replace process image with environment
Replace the process image, specifying the environment for the new process image.
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.176.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,29037}
3> alcove:execve(Drv, [Pid], "/usr/bin/env", ["env"], ["FOO=123"]).
ok
% Shell got {alcove_stdout,<0.176.0>,[29037],<<"FOO=123\n">>}
% Shell got {alcove_event,<0.176.0>,[29037],{exit_status,0}}
4> alcove:stdout(Drv, [Pid]).
[<<"FOO=123\n">>]
5> alcove:event(Drv, [Pid], 5000).
{exit_status,0}
ok
Specs
execvp(alcove_drv:ref(), [pid_t()], Arg0 :: iodata(), Argv :: [iodata()]) -> ok | {error, posix()}.
execvp(2): replace the current process image using the search path
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.176.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,29087}
3> alcove:execvp(Drv, [Pid], "cat", ["cat"]).
ok
4> alcove:stdin(Drv, [Pid], "test\n").
ok
5> alcove:stdout(Drv, [Pid]).
[<<"test\n">>]
6> alcove:stdin(Drv, [Pid], "123\n").
ok
7> flush().
Shell got {alcove_stdout,<0.176.0>,[29087],<<"123\n">>}
ok
Specs
execvp(alcove_drv:ref(), [pid_t()], Arg0 :: iodata(), Argv :: [iodata()], timeout()) -> ok | {error, posix()}.
execvp(2): replace the current process image using the search path
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.176.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,29087}
3> alcove:execvp(Drv, [Pid], "cat", ["cat"]).
ok
4> alcove:stdin(Drv, [Pid], "test\n").
ok
5> alcove:stdout(Drv, [Pid]).
[<<"test\n">>]
6> alcove:stdin(Drv, [Pid], "123\n").
ok
7> flush().
Shell got {alcove_stdout,<0.176.0>,[29087],<<"123\n">>}
ok
Specs
exit(alcove_drv:ref(), [pid_t()], Status :: int32_t()) -> ok.
exit(3): cause an alcove control process to exit
Examples
1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
{ok,<0.176.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,30973}
3> alcove:exit(Drv, [Pid], 111).
ok
4> flush().
Shell got {alcove_event,<0.176.0>,[30973],{exit_status,111}}
ok
Specs
exit(alcove_drv:ref(), [pid_t()], Status :: int32_t(), timeout()) -> ok.
exit(3): cause an alcove control process to exit
Examples
1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
{ok,<0.176.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,30973}
3> alcove:exit(Drv, [Pid], 111).
ok
4> flush().
Shell got {alcove_event,<0.176.0>,[30973],{exit_status,111}}
ok
Specs
fcntl(alcove_drv:ref(), [pid_t()], FD :: fd(), Cmd :: constant(), Arg :: int64_t()) -> {ok, int64_t()} | {error, posix()}.
fcntl(2): perform operations on a file descriptor
Examples
1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
{ok,<0.176.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,31012}
% stdin = 0
3> alcove:fcntl(Drv, [Pid], 0, f_getfd, 0).
{ok,0}
Specs
fcntl(alcove_drv:ref(), [pid_t()], FD :: fd(), Cmd :: constant(), Arg :: int64_t(), timeout()) -> {ok, int64_t()} | {error, posix()}.
fcntl(2): perform operations on a file descriptor
Examples
1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
{ok,<0.176.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,31012}
% stdin = 0
3> alcove:fcntl(Drv, [Pid], 0, f_getfd, 0).
{ok,0}
Specs
fcntl_constant(alcove_drv:ref(), [pid_t()], Symbol :: atom()) -> integer() | unknown.
Convert fnctl(2) constant to integer
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.176.0>}
2> alcove:fcntl_constant(Drv, [], fd_cloexec).
1
Specs
fcntl_constant(alcove_drv:ref(), [pid_t()], Symbol :: atom(), timeout()) -> integer() | unknown.
Convert fnctl(2) constant to integer
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.176.0>}
2> alcove:fcntl_constant(Drv, [], fd_cloexec).
1
Specs
fexecve(alcove_drv:ref(), [pid_t()], FD :: fd(), Argv :: [iodata()], Env :: [iodata()]) -> ok | {error, posix()}.
fexecve(2): replace the process image
Replace the process image, specifying the environment for the new process image, using a previously opened file descriptor. The file descriptor can be set to close after exec() by passing the O_CLOEXEC flag to open:
{ok, Pid} = alcove:fork(Drv, []),
{ok, FD} = alcove:open(Drv, [Pid], "/bin/ls", [o_rdonly,o_cloexec], 0),
ok = alcove:fexecve(Drv, [Pid], FD, ["ls", "-al"], ["FOO=123"]).
Linux requires an environment to be set unlike with execve(2). The environment can be empty:
% Environment required on Linux
ok = alcove:fexecve(Drv, [Pid], FD, ["ls", "-al"], [""]).
Support
* Linux
* FreeBSD
Examples
1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
{ok,<0.177.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,31491}
3> {ok, FD} = alcove:open(Drv, [Pid], "/usr/bin/env", [o_rdonly,o_cloexec], 0).
{ok,6}
4> alcove:fexecve(Drv, [Pid], FD, ["env", "-0"], ["FOO=123"]).
ok
5> flush().
Shell got {alcove_stdout,<0.177.0>,[31491],<<70,79,79,61,49,50,51,0>>}
Shell got {alcove_event,<0.177.0>,[31491],{exit_status,0}}
ok
Specs
fexecve(alcove_drv:ref(), [pid_t()], FD :: fd(), Argv :: [iodata()], Env :: [iodata()], timeout()) -> ok | {error, posix()}.
fexecve(2): replace the process image
Replace the process image, specifying the environment for the new process image, using a previously opened file descriptor. The file descriptor can be set to close after exec() by passing the O_CLOEXEC flag to open:
{ok, Pid} = alcove:fork(Drv, []),
{ok, FD} = alcove:open(Drv, [Pid], "/bin/ls", [o_rdonly,o_cloexec], 0),
ok = alcove:fexecve(Drv, [Pid], FD, ["ls", "-al"], ["FOO=123"]).
Linux requires an environment to be set unlike with execve(2). The environment can be empty:
% Environment required on Linux
ok = alcove:fexecve(Drv, [Pid], FD, ["ls", "-al"], [""]).
Support
* Linux
* FreeBSD
Examples
1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
{ok,<0.177.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,31491}
3> {ok, FD} = alcove:open(Drv, [Pid], "/usr/bin/env", [o_rdonly,o_cloexec], 0).
{ok,6}
4> alcove:fexecve(Drv, [Pid], FD, ["env", "-0"], ["FOO=123"]).
ok
5> flush().
Shell got {alcove_stdout,<0.177.0>,[31491],<<70,79,79,61,49,50,51,0>>}
Shell got {alcove_event,<0.177.0>,[31491],{exit_status,0}}
ok
Specs
file_constant(alcove_drv:ref(), [pid_t()], Symbol :: atom()) -> non_neg_integer() | unknown.
Constants for open(2)
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:file_constant(Drv, [], o_rdonly).
0
Specs
file_constant(alcove_drv:ref(), [pid_t()], Symbol :: atom(), timeout()) -> non_neg_integer() | unknown.
Constants for open(2)
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:file_constant(Drv, [], o_rdonly).
0
Specs
filter(filter()) -> binary().
Create a call filter list
Generate a list of calls to filter for filter/3,4. By default, calls are blocked. To restrict the alcove control process to a subset of calls, use the allow tuple:
# alcove process restricted to fork, clone, getpid
alcove:filter({allow, [fork, clone, getpid]})
Examples
1> alcove:filter({allow, [fork, clone, getpid]}).
<<255,223,255,239,239,255,255,255,255,255,255,255,15>>
2> alcove:filter([fork, clone, getpid]).
<<0,32,0,16,16>>
3> alcove:filter({deny, [fork, clone, getpid]}).
<<0,32,0,16,16>>
Specs
filter(alcove_drv:ref(), [pid_t()], [] | binary()) -> ok | {error, einval}.
Restrict calls available to an alcove control process
filter/3 restrict calls available to an alcove control process. Restricted control processes continue to proxy data and monitor and reap subprocesses.
Invoking a filtered call will crash the process with 'undef'.
If the filter call is filtered, subsequent calls to filter/3,4 will fail.
Once added, the call cannot be removed from the filter set. Passing an empty list ([]) specifies the current filter set should not be modified.
Filters are inherited by the child process from the parent. filter/3 specifies the subprocess should use the same filter as the parent:
1> catch_exception(true).
false
2> {ok, Drv} = alcove_drv:start().
{ok,<0.179.0>}
3> {ok, Pid} = alcove:fork(Drv, []).
{ok,16464}
4> Filter = alcove:filter([fork]).
<<0,0,0,16>>
% equivalent to: alcove:filter(Drv, [], Filter, Filter)
5> alcove:filter(Drv, [], Filter).
ok
6> alcove:fork(Drv, [Pid]).
* exception error: undefined function alcove:fork/2
Specs
filter(alcove_drv:ref(), [pid_t()], Calls :: [] | binary(), Calls :: [] | binary()) -> ok | {error, einval}.
Restrict available calls for control and subprocess
filter/4 allows setting different filters for the control and subprocesses:
Examples
1> catch_exception(true).
false
2> {ok, Drv} = alcove_drv:start().
{ok,<0.189.0>}
3> F1 = alcove:filter({allow, [fork,filter,getcwd]}).
<<255,255,255,231,239,255,255,255,255,255,255,255,15>>
4> F2 = alcove:filter({allow, [getpid,gethostname]}).
<<255,255,255,223,237,255,255,255,255,255,255,255,15>>
% Control process: restricted to: fork, filter
% Any forked control subprocess: restricted to: getpid, gethostname
5> alcove:filter(Drv, [], F1, F2).
ok
6> {ok, Pid} = alcove:fork(Drv, []).
{ok,18721}
7> alcove:getpid(Drv, [Pid]).
18721
8> alcove:getpid(Drv, []).
* exception error: undefined function alcove:getpid/2
9> alcove:getcwd(Drv, [Pid]).
* exception error: undefined function alcove:getcwd/2
10> alcove:getcwd(Drv, []).
{ok, <<"/">>}
Specs
filter(alcove_drv:ref(), [pid_t()], Calls :: [] | binary(), Calls :: [] | binary(), timeout()) -> ok | {error, einval}.
Restrict available calls for control and subprocess
filter/4 allows setting different filters for the control and subprocesses:
Examples
1> catch_exception(true).
false
2> {ok, Drv} = alcove_drv:start().
{ok,<0.189.0>}
3> F1 = alcove:filter({allow, [fork,filter,getcwd]}).
<<255,255,255,231,239,255,255,255,255,255,255,255,15>>
4> F2 = alcove:filter({allow, [getpid,gethostname]}).
<<255,255,255,223,237,255,255,255,255,255,255,255,15>>
% Control process: restricted to: fork, filter
% Any forked control subprocess: restricted to: getpid, gethostname
5> alcove:filter(Drv, [], F1, F2).
ok
6> {ok, Pid} = alcove:fork(Drv, []).
{ok,18721}
7> alcove:getpid(Drv, [Pid]).
18721
8> alcove:getpid(Drv, []).
* exception error: undefined function alcove:getpid/2
9> alcove:getcwd(Drv, [Pid]).
* exception error: undefined function alcove:getcwd/2
10> alcove:getcwd(Drv, []).
{ok, <<"/">>}
Specs
fork(alcove_drv:ref(), [pid_t()]) -> {ok, pid_t()} | {error, posix()}.
fork(2): create a new process
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.189.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,18721}
3> alcove:getpid(Drv, [Pid]).
18721
Specs
fork(alcove_drv:ref(), [pid_t()], timeout()) -> {ok, pid_t()} | {error, posix()}.
fork(2): create a new process
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.189.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,18721}
3> alcove:getpid(Drv, [Pid]).
18721
Specs
getcpid(alcove_drv:ref(), [pid_t()], pid_t(), alcove_pid_field()) -> false | int32_t().
Get control process attributes
Retrieves attributes set by the alcove control process for a child process.
* flowcontrol
Number of messages allowed from process:
-1 : flowcontrol disabled
0 : stdout/stderr for process is not read
1+ : read this many messages from the process
* signaloneof
Signal sent to child process on shutdown.
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,3925}
3> alcove:getcpid(Drv, [], Pid, flowcontrol).
-1
Specs
getcwd(alcove_drv:ref(), [pid_t()]) -> {ok, binary()} | {error, posix()}.
getcwd(3): return the current working directory
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,3925}
3> alcove:chdir(Drv, [Pid], "/").
ok
4> alcove:getcwd(Drv, [Pid]).
{ok,<<"/">>}
Specs
getcwd(alcove_drv:ref(), [pid_t()], timeout()) -> {ok, binary()} | {error, posix()}.
getcwd(3): return the current working directory
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,3925}
3> alcove:chdir(Drv, [Pid], "/").
ok
4> alcove:getcwd(Drv, [Pid]).
{ok,<<"/">>}
Specs
getenv(alcove_drv:ref(), [pid_t()], Name :: iodata()) -> binary() | false.
getenv(3): retrieve an environment variable
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:getenv(Drv, [], "TERM").
<<"screen">>
Specs
getenv(alcove_drv:ref(), [pid_t()], Name :: iodata(), timeout()) -> binary() | false.
getenv(3): retrieve an environment variable
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:getenv(Drv, [], "TERM").
<<"screen">>
Specs
getgid(alcove_drv:ref(), [pid_t()]) -> gid_t().
getgid(2): retrieve the process group ID
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:getgid(Drv, []).
1000
Specs
getgid(alcove_drv:ref(), [pid_t()], timeout()) -> gid_t().
getgid(2): retrieve the process group ID
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:getgid(Drv, []).
1000
Specs
getgroups(alcove_drv:ref(), [pid_t()]) -> {ok, [gid_t()]} | {error, posix()}.
getgroups(2): retrieve the list of supplementary groups
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:getgroups(Drv, []).
{ok,[24,20,1000]}
Specs
getgroups(alcove_drv:ref(), [pid_t()], timeout()) -> {ok, [gid_t()]} | {error, posix()}.
getgroups(2): retrieve the list of supplementary groups
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:getgroups(Drv, []).
{ok,[24,20,1000]}
Specs
gethostname(alcove_drv:ref(), [pid_t()]) -> {ok, binary()} | {error, posix()}.
gethostname(2): retrieve the system hostname
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:gethostname(Drv, []).
{ok,<<"host1">>}
Specs
gethostname(alcove_drv:ref(), [pid_t()], timeout()) -> {ok, binary()} | {error, posix()}.
gethostname(2): retrieve the system hostname
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:gethostname(Drv, []).
{ok,<<"host1">>}
Specs
getopt(alcove_drv:ref(), [pid_t()], Opt :: atom()) -> false | int32_t().
Retrieve port options for event loop
Options are configurable per process, with the default settings inherited from the parent.
The initial values for these options are set for the port by alcove_drv:start/1.
* maxchild : non_neg_integer() : (ulimit -n) / 4 - 4
Number of child processes allowed for this process. This value can be modified by adjusting RLIMIT_NOFILE for the process.
* exit_status : 1 | 0 : 1
Controls whether the controlling Erlang process is informed of a process exit value.
* maxforkdepth : non_neg_integer() : 16
Sets the maximum length of the alcove process pipeline.
* termsig : 1 | 0 : 1
If a child process exits because of a signal, notify the controlling Erlang process.
* flowcontrol : int32_t() : -1 (disabled)
Sets the default flow control behaviour for a newly forked process. Flow control is applied after the child process calls exec().
See setcpid/5.
* signaloneof : 0-255 : 15
Send a signal to a child process on shutdown (stdin of the alcove control process is closed).
See setcpid/5.
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:getopt(Drv, [], maxforkdepth).
16
Specs
getopt(alcove_drv:ref(), [pid_t()], Opt :: atom(), timeout()) -> false | int32_t().
Retrieve port options for event loop
Options are configurable per process, with the default settings inherited from the parent.
The initial values for these options are set for the port by alcove_drv:start/1.
* maxchild : non_neg_integer() : (ulimit -n) / 4 - 4
Number of child processes allowed for this process. This value can be modified by adjusting RLIMIT_NOFILE for the process.
* exit_status : 1 | 0 : 1
Controls whether the controlling Erlang process is informed of a process exit value.
* maxforkdepth : non_neg_integer() : 16
Sets the maximum length of the alcove process pipeline.
* termsig : 1 | 0 : 1
If a child process exits because of a signal, notify the controlling Erlang process.
* flowcontrol : int32_t() : -1 (disabled)
Sets the default flow control behaviour for a newly forked process. Flow control is applied after the child process calls exec().
See setcpid/5.
* signaloneof : 0-255 : 15
Send a signal to a child process on shutdown (stdin of the alcove control process is closed).
See setcpid/5.
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:getopt(Drv, [], maxforkdepth).
16
Specs
getpgrp(alcove_drv:ref(), [pid_t()]) -> pid_t().
getpgrp(2): retrieve the process group
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:getpgrp(Drv, []).
3924
Specs
getpgrp(alcove_drv:ref(), [pid_t()], timeout()) -> pid_t().
getpgrp(2): retrieve the process group
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:getpgrp(Drv, []).
3924
Specs
getpid(alcove_drv:ref(), [pid_t()]) -> pid_t().
getpid(2): retrieve the system PID of the process
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:getpid(Drv, []).
3924
Specs
getpid(alcove_drv:ref(), [pid_t()], timeout()) -> pid_t().
getpid(2): retrieve the system PID of the process
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:getpid(Drv, []).
3924
Specs
getpriority(alcove_drv:ref(), [pid_t()], Which :: constant(), Who :: int32_t()) -> {ok, int32_t()} | {error, posix()}.
getpriority(2): retrieve scheduling priority of process, process group or user
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:getpriority(Drv, [], prio_process, 0).
{ok,0}
Specs
getpriority(alcove_drv:ref(), [pid_t()], Which :: constant(), Who :: int32_t(), timeout()) -> {ok, int32_t()} | {error, posix()}.
getpriority(2): retrieve scheduling priority of process, process group or user
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:getpriority(Drv, [], prio_process, 0).
{ok,0}
Specs
getresgid(alcove_drv:ref(), [pid_t()]) -> {ok, Real :: gid_t(), Effective :: gid_t(), Saved :: gid_t()} | {error, posix()}.
getresgid(2): get real, effective and saved group ID
Support
* Linux
* OpenBSD
* FreeBSD
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:getresgid(Drv, []).
{ok,1000,1000,1000}
Specs
getresgid(alcove_drv:ref(), [pid_t()], timeout()) -> {ok, Real :: gid_t(), Effective :: gid_t(), Saved :: gid_t()} | {error, posix()}.
getresgid(2): get real, effective and saved group ID
Support
* Linux
* OpenBSD
* FreeBSD
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:getresgid(Drv, []).
{ok,1000,1000,1000}
Specs
getresuid(alcove_drv:ref(), [pid_t()]) -> {ok, Real :: uid_t(), Effective :: uid_t(), Saved :: uid_t()} | {error, posix()}.
getresuid(2): get real, effective and saved user ID
Support
* Linux
* OpenBSD
* FreeBSD
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:getresuid(Drv, []).
{ok,1000,1000,1000}
Specs
getresuid(alcove_drv:ref(), [pid_t()], timeout()) -> {ok, Real :: uid_t(), Effective :: uid_t(), Saved :: uid_t()} | {error, posix()}.
getresuid(2): get real, effective and saved user ID
Support
* Linux
* OpenBSD
* FreeBSD
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:getresuid(Drv, []).
{ok,1000,1000,1000}
Specs
getrlimit(alcove_drv:ref(), [pid_t()], Resource :: constant()) -> {ok, alcove_rlimit()} | {error, posix()}.
getrlimit(2): retrieve the resource limits for a process
Returns a record:
-include_lib("alcove/include/alcove.hrl").
#alcove_rlimit{
cur = integer(),
max = integer()
}
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> rr(alcove).
[alcove_jail,alcove_pid,alcove_rlimit,alcove_timeval]
3> alcove:getrlimit(Drv, [], rlimit_nofile).
{ok,#alcove_rlimit{cur = 1024,max = 1048576}}
Specs
getrlimit(alcove_drv:ref(), [pid_t()], Resource :: constant(), timeout()) -> {ok, alcove_rlimit()} | {error, posix()}.
getrlimit(2): retrieve the resource limits for a process
Returns a record:
-include_lib("alcove/include/alcove.hrl").
#alcove_rlimit{
cur = integer(),
max = integer()
}
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> rr(alcove).
[alcove_jail,alcove_pid,alcove_rlimit,alcove_timeval]
3> alcove:getrlimit(Drv, [], rlimit_nofile).
{ok,#alcove_rlimit{cur = 1024,max = 1048576}}
Specs
getsid(alcove_drv:ref(), [pid_t()], OSPid :: pid_t()) -> {ok, pid_t()} | {error, posix()}.
getsid(2): retrieve the session ID
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:getsid(Drv, [], 0).
{ok,3924}
Specs
getsid(alcove_drv:ref(), [pid_t()], OSPid :: pid_t(), timeout()) -> {ok, pid_t()} | {error, posix()}.
getsid(2): retrieve the session ID
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:getsid(Drv, [], 0).
{ok,3924}
Specs
getuid(alcove_drv:ref(), [pid_t()]) -> uid_t().
getuid(2): returns the process user ID
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:getuid(Drv, []).
1000
Specs
getuid(alcove_drv:ref(), [pid_t()], timeout()) -> uid_t().
getuid(2): returns the process user ID
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:getuid(Drv, []).
1000
Specs
ioctl(alcove_drv:ref(), [pid_t()], FD :: fd(), Request :: constant(), Argp :: cstruct()) -> {ok, integer(), iodata()} | {error, posix()}.
ioctl(2): control device
Controls a device using a file descriptor previously obtained using open/5.
Argp can be either a binary or a list representation of a C struct. See prctl/7 below for a description of the list elements.
On success, ioctl/5 returns a 3-tuple:
* Result: an integer equal to the return value of the ioctl
Usually 0 but some ioctls may use the return value as the output parameter.
* Bin: the value depends on the type of the input parameter Argp
* cstruct: contains the contents of the memory pointed to by Argp
* integer/binary: an empty binary
Examples
An example of creating a tap device in a net namespace on Linux:
1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
{ok,<0.177.0>}
2> {ok, Pid} = alcove:clone(Drv, [], [clone_newnet]).
{ok,8288}
3> {ok, FD} = alcove:open(Drv, [Pid], "/dev/net/tun", [o_rdwr], 0).
{ok,6}
4> {ok, 0, <<"tap", _/binary>>} = alcove:ioctl(Drv, [Pid], FD, tunsetiff, <<
4> % generate a tuntap device name
4> 0:(16 * 8),
4> % IFF_TAP, IFF_NO_PI
4> (16#0002 bor 16#1000):2/native-unsigned-integer-unit:8,
4> 0:(14 * 8)
4> >>).
{ok,0,
<<116,97,112,48,0,0,0,0,0,0,0,0,0,0,0,0,2,16,0,0,0,0,0,0,
0,0,...>>}
Specs
ioctl(alcove_drv:ref(), [pid_t()], FD :: fd(), Request :: constant(), Argp :: cstruct(), timeout()) -> {ok, integer(), iodata()} | {error, posix()}.
ioctl(2): control device
Controls a device using a file descriptor previously obtained using open/5.
Argp can be either a binary or a list representation of a C struct. See prctl/7 below for a description of the list elements.
On success, ioctl/5 returns a 3-tuple:
* Result: an integer equal to the return value of the ioctl
Usually 0 but some ioctls may use the return value as the output parameter.
* Bin: the value depends on the type of the input parameter Argp
* cstruct: contains the contents of the memory pointed to by Argp
* integer/binary: an empty binary
Examples
An example of creating a tap device in a net namespace on Linux:
1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
{ok,<0.177.0>}
2> {ok, Pid} = alcove:clone(Drv, [], [clone_newnet]).
{ok,8288}
3> {ok, FD} = alcove:open(Drv, [Pid], "/dev/net/tun", [o_rdwr], 0).
{ok,6}
4> {ok, 0, <<"tap", _/binary>>} = alcove:ioctl(Drv, [Pid], FD, tunsetiff, <<
4> % generate a tuntap device name
4> 0:(16 * 8),
4> % IFF_TAP, IFF_NO_PI
4> (16#0002 bor 16#1000):2/native-unsigned-integer-unit:8,
4> 0:(14 * 8)
4> >>).
{ok,0,
<<116,97,112,48,0,0,0,0,0,0,0,0,0,0,0,0,2,16,0,0,0,0,0,0,
0,0,...>>}
Specs
ioctl_constant(alcove_drv:ref(), [pid_t()], Symbol :: atom()) -> integer() | unknown.
Convert ioctl constant to integer
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:ioctl_constant(Drv, [], siocgifaddr).
35093
3> alcove:ioctl_constant(Drv, [], 'SIOCGIFADDR').
35093
Specs
ioctl_constant(alcove_drv:ref(), [pid_t()], Symbol :: atom(), timeout()) -> integer() | unknown.
Convert ioctl constant to integer
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:ioctl_constant(Drv, [], siocgifaddr).
35093
3> alcove:ioctl_constant(Drv, [], 'SIOCGIFADDR').
35093
Specs
iolist_to_bin(alcove_drv:ref(), [pid_t()], iodata()) -> binary().
Convert iolist to binary
Test conversion of iolists to binary in a control process.
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:iolist_to_bin(Drv, [], ["foo", [<<"1">>, <<"2">>, [<<"3">>], ["bar"]]]).
<<"foo123bar">>
Specs
iolist_to_bin(alcove_drv:ref(), [pid_t()], iodata(), timeout()) -> binary().
Convert iolist to binary
Test conversion of iolists to binary in a control process.
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:iolist_to_bin(Drv, [], ["foo", [<<"1">>, <<"2">>, [<<"3">>], ["bar"]]]).
<<"foo123bar">>
Specs
jail(alcove_drv:ref(), [pid_t()], cstruct()) -> {ok, int32_t()} | {error, posix()}.
jail(2): restrict the current process in a system jail
Support
* FreeBSD
Examples
1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
{ok,<0.208.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,44378}
3> rr(alcove).
[alcove_jail,alcove_pid,alcove_rlimit,alcove_timeval]
4> Jail0 = alcove_cstruct:jail(#alcove_jail{
4> path = "/rescue",
4> hostname = "test0",
4> jailname = "jail0"
4> }).
[<<2,0,0,0>>,
<<0,0,0,0>>,
{ptr,<<47,114,101,115,99,117,101,0>>},
{ptr,<<116,101,115,116,48,0>>},
{ptr,<<106,97,105,108,48,0>>},
<<0,0,0,0,0,0,0,0>>,
{ptr,<<>>},
{ptr,<<>>}]
5> {ok, JID0} = alcove:jail(Drv, [Pid], Jail0).
{ok,21}
6> alcove:gethostname(Drv, [Pid]).
{ok,<<"test0">>}
Specs
jail(alcove_drv:ref(), [pid_t()], cstruct(), timeout()) -> {ok, int32_t()} | {error, posix()}.
jail(2): restrict the current process in a system jail
Support
* FreeBSD
Examples
1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
{ok,<0.208.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,44378}
3> rr(alcove).
[alcove_jail,alcove_pid,alcove_rlimit,alcove_timeval]
4> Jail0 = alcove_cstruct:jail(#alcove_jail{
4> path = "/rescue",
4> hostname = "test0",
4> jailname = "jail0"
4> }).
[<<2,0,0,0>>,
<<0,0,0,0>>,
{ptr,<<47,114,101,115,99,117,101,0>>},
{ptr,<<116,101,115,116,48,0>>},
{ptr,<<106,97,105,108,48,0>>},
<<0,0,0,0,0,0,0,0>>,
{ptr,<<>>},
{ptr,<<>>}]
5> {ok, JID0} = alcove:jail(Drv, [Pid], Jail0).
{ok,21}
6> alcove:gethostname(Drv, [Pid]).
{ok,<<"test0">>}
Specs
jail_attach(alcove_drv:ref(), [pid_t()], int32_t()) -> ok | {error, posix()}.
jail_attach(2): join a jailed process
Support
* FreeBSD
Examples
1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
{ok,<0.208.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,44378}
3> rr(alcove).
[alcove_jail,alcove_pid,alcove_rlimit,alcove_timeval]
4> Jail0 = alcove_cstruct:jail(#alcove_jail{
4> path = "/rescue",
4> hostname = "test0",
4> jailname = "jail0"
4> }).
[<<2,0,0,0>>,
<<0,0,0,0>>,
{ptr,<<47,114,101,115,99,117,101,0>>},
{ptr,<<116,101,115,116,48,0>>},
{ptr,<<106,97,105,108,48,0>>},
<<0,0,0,0,0,0,0,0>>,
{ptr,<<>>},
{ptr,<<>>}]
5> {ok, JID0} = alcove:jail(Drv, [Pid], Jail0).
{ok,21}
6> {ok, Pid0} = alcove:fork(Drv, []).
{ok,44379}
7> ok = alcove:jail_attach(Drv, [Pid0], JID0).
ok
8> alcove:gethostname(Drv, [Pid0]).
{ok,<<"test0">>}
9> ok = alcove:jail_remove(Drv, [], JID0).
ok
Specs
jail_attach(alcove_drv:ref(), [pid_t()], int32_t(), timeout()) -> ok | {error, posix()}.
jail_attach(2): join a jailed process
Support
* FreeBSD
Examples
1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
{ok,<0.208.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,44378}
3> rr(alcove).
[alcove_jail,alcove_pid,alcove_rlimit,alcove_timeval]
4> Jail0 = alcove_cstruct:jail(#alcove_jail{
4> path = "/rescue",
4> hostname = "test0",
4> jailname = "jail0"
4> }).
[<<2,0,0,0>>,
<<0,0,0,0>>,
{ptr,<<47,114,101,115,99,117,101,0>>},
{ptr,<<116,101,115,116,48,0>>},
{ptr,<<106,97,105,108,48,0>>},
<<0,0,0,0,0,0,0,0>>,
{ptr,<<>>},
{ptr,<<>>}]
5> {ok, JID0} = alcove:jail(Drv, [Pid], Jail0).
{ok,21}
6> {ok, Pid0} = alcove:fork(Drv, []).
{ok,44379}
7> ok = alcove:jail_attach(Drv, [Pid0], JID0).
ok
8> alcove:gethostname(Drv, [Pid0]).
{ok,<<"test0">>}
9> ok = alcove:jail_remove(Drv, [], JID0).
ok
Specs
jail_remove(alcove_drv:ref(), [pid_t()], int32_t()) -> ok | {error, posix()}.
jail_remove(2): destroy a jailed process
Support
* FreeBSD
Examples
1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
{ok,<0.208.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,44378}
3> rr(alcove).
[alcove_jail,alcove_pid,alcove_rlimit,alcove_timeval]
4> Jail0 = alcove_cstruct:jail(#alcove_jail{
4> path = "/rescue",
4> hostname = "test0",
4> jailname = "jail0"
4> }).
[<<2,0,0,0>>,
<<0,0,0,0>>,
{ptr,<<47,114,101,115,99,117,101,0>>},
{ptr,<<116,101,115,116,48,0>>},
{ptr,<<106,97,105,108,48,0>>},
<<0,0,0,0,0,0,0,0>>,
{ptr,<<>>},
{ptr,<<>>}]
5> {ok, JID0} = alcove:jail(Drv, [Pid], Jail0).
{ok,21}
6> {ok, Pid0} = alcove:fork(Drv, []).
{ok,44379}
7> ok = alcove:jail_attach(Drv, [Pid0], JID0).
ok
8> alcove:gethostname(Drv, [Pid0]).
{ok,<<"test0">>}
9> ok = alcove:jail_remove(Drv, [], JID0).
ok
Specs
jail_remove(alcove_drv:ref(), [pid_t()], int32_t(), timeout()) -> ok | {error, posix()}.
jail_remove(2): destroy a jailed process
Support
* FreeBSD
Examples
1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
{ok,<0.208.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,44378}
3> rr(alcove).
[alcove_jail,alcove_pid,alcove_rlimit,alcove_timeval]
4> Jail0 = alcove_cstruct:jail(#alcove_jail{
4> path = "/rescue",
4> hostname = "test0",
4> jailname = "jail0"
4> }).
[<<2,0,0,0>>,
<<0,0,0,0>>,
{ptr,<<47,114,101,115,99,117,101,0>>},
{ptr,<<116,101,115,116,48,0>>},
{ptr,<<106,97,105,108,48,0>>},
<<0,0,0,0,0,0,0,0>>,
{ptr,<<>>},
{ptr,<<>>}]
5> {ok, JID0} = alcove:jail(Drv, [Pid], Jail0).
{ok,21}
6> {ok, Pid0} = alcove:fork(Drv, []).
{ok,44379}
7> ok = alcove:jail_attach(Drv, [Pid0], JID0).
ok
8> alcove:gethostname(Drv, [Pid0]).
{ok,<<"test0">>}
9> ok = alcove:jail_remove(Drv, [], JID0).
ok
Specs
kill(alcove_drv:ref(), [pid_t()], OSPid :: pid_t(), Signal :: constant()) -> ok | {error, posix()}.
kill(2): terminate a process
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:kill(Drv, [], 0, 0).
ok
3> alcove:kill(Drv, [], 12345, 0).
{error,esrch}
4> {ok, Pid} = alcove:fork(Drv, []).
{ok,8288}
5> alcove:kill(Drv, [], Pid, 0).
ok
6> alcove:kill(Drv, [], Pid, sigkill).
ok
7> alcove:kill(Drv, [], Pid, 0).
{error,esrch}
8> flush().
Shell got {alcove_ctl,<0.177.0>,[8288],fdctl_closed}
Shell got {alcove_event,<0.177.0>,[8288],{termsig,sigkill}}
Specs
kill(alcove_drv:ref(), [pid_t()], OSPID :: pid_t(), Signal :: constant(), timeout()) -> ok | {error, posix()}.
kill(2): terminate a process
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:kill(Drv, [], 0, 0).
ok
3> alcove:kill(Drv, [], 12345, 0).
{error,esrch}
4> {ok, Pid} = alcove:fork(Drv, []).
{ok,8288}
5> alcove:kill(Drv, [], Pid, 0).
ok
6> alcove:kill(Drv, [], Pid, sigkill).
ok
7> alcove:kill(Drv, [], Pid, 0).
{error,esrch}
8> flush().
Shell got {alcove_ctl,<0.177.0>,[8288],fdctl_closed}
Shell got {alcove_event,<0.177.0>,[8288],{termsig,sigkill}}
Specs
link(alcove_drv:ref(), [pid_t()], OldPath :: iodata(), NewPath :: iodata()) -> ok | {error, posix()}.
link(2) : create a hard link
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,18820}
3> {ok, FD} = alcove:open(Drv, [Pid], "/tmp/alcove-link-test.txt", [o_wronly, o_creat], 8#644).
{ok,6}
4> alcove:link(Drv, [Pid], "/tmp/alcove-link-test.txt", "/tmp/alcove-link-test.link").
ok
Specs
link(alcove_drv:ref(), [pid_t()], OldPath :: iodata(), NewPath :: iodata(), timeout()) -> ok | {error, posix()}.
link(2) : create a hard link
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,18820}
3> {ok, FD} = alcove:open(Drv, [Pid], "/tmp/alcove-link-test.txt", [o_wronly, o_creat], 8#644).
{ok,6}
4> alcove:link(Drv, [Pid], "/tmp/alcove-link-test.txt", "/tmp/alcove-link-test.link").
ok
Specs
lseek(alcove_drv:ref(), [pid_t()], FD :: fd(), Offset :: off_t(), Whence :: int32_t()) -> ok | {error, posix()}.
lseek(2): set file offset for read/write
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,18820}
3> {ok, FD} = alcove:open(Drv, [Pid], "/etc/passwd", [o_rdonly], 0).
{ok,6}
4> alcove:lseek(Drv, [Pid], FD, 0, 0).
ok
Specs
lseek(alcove_drv:ref(), [pid_t()], FD :: fd(), Offset :: off_t(), Whence :: int32_t(), timeout()) -> ok | {error, posix()}.
lseek(2): set file offset for read/write
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,18820}
3> {ok, FD} = alcove:open(Drv, [Pid], "/etc/passwd", [o_rdonly], 0).
{ok,6}
4> alcove:lseek(Drv, [Pid], FD, 0, 0).
ok
Specs
mkdir(alcove_drv:ref(), [pid_t()], Path :: iodata(), Mode :: mode_t()) -> ok | {error, posix()}.
mkdir(2): create a directory
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:mkdir(Drv, [], "/tmp/alcove-mkdir-test", 8#755).
ok
Specs
mkdir(alcove_drv:ref(), [pid_t()], Path :: iodata(), Mode :: mode_t(), timeout()) -> ok | {error, posix()}.
mkdir(2): create a directory
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:mkdir(Drv, [], "/tmp/alcove-mkdir-test", 8#755).
ok
Specs
mkfifo(alcove_drv:ref(), [pid_t()], Path :: iodata(), Mode :: mode_t()) -> ok | {error, posix()}.
mkfifo(3): make named pipe file
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:mkfifo(Drv, [], "/tmp/alcove-fifo-test", 8#700).
ok
Specs
mkfifo(alcove_drv:ref(), [pid_t()], Path :: iodata(), Mode :: mode_t(), timeout()) -> ok | {error, posix()}.
mkfifo(3): make named pipe file
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:mkfifo(Drv, [], "/tmp/alcove-fifo-test", 8#700).
ok
Specs
mount(alcove_drv:ref(), [pid_t()], Source :: iodata(), Target :: iodata(), FSType :: iodata(), Flags :: uint64_t() | [constant()], Data :: iodata(), Options :: iodata()) -> ok | {error, posix()}.
mount(2): mount a filesystem, Linux style
The arguments are:
* source
* target
* filesystem type
* flags
* data
An empty list may be used to specify NULL.
For example, filesystems mounted in a Linux mount namespace may be visible in the global mount namespace. To avoid this, first remount the root filesystem within a mount namespace using the MS_REC|MS_PRIVATE flags:
{ok, Task} = alcove:clone(Drv, [], [clone_newns]),
ok = alcove:mount(Drv, [Task], "none", "/", [], [ms_rec, ms_private], []).
On BSD systems, the Source argument is ignored and passed to the system mount call as:
mount(FSType, Target, Flags, Data);
On Solaris, some mount options are passed in the Options argument as a string of comma separated values terminated by a NULL. Other platforms ignore the Options parameter.
Examples
An example of bind mounting a directory within a linux mount namespace:
1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
{ok,<0.177.0>}
2> {ok, Pid} = alcove:clone(Drv, [], [clone_newns]).
{ok,10059}
3> alcove:mount(Drv, [Pid], "/tmp", "/mnt", "", [ms_bind, ms_rdonly, ms_noexec], "", "").
ok
4> alcove:umount(Drv, [Pid], "/mnt").
ok
mount(Drv, Pids, Source, Target, FSType, Flags, Data, Options, Timeout)
View SourceSpecs
mount(alcove_drv:ref(), [pid_t()], Source :: iodata(), Target :: iodata(), FSType :: iodata(), Flags :: uint64_t() | [constant()], Data :: iodata(), Options :: iodata(), timeout()) -> ok | {error, posix()}.
mount(2): mount a filesystem, Linux style
The arguments are:
* source
* target
* filesystem type
* flags
* data
An empty list may be used to specify NULL.
For example, filesystems mounted in a Linux mount namespace may be visible in the global mount namespace. To avoid this, first remount the root filesystem within a mount namespace using the MS_REC|MS_PRIVATE flags:
{ok, Task} = alcove:clone(Drv, [], [clone_newns]),
ok = alcove:mount(Drv, [Task], "none", "/", [], [ms_rec, ms_private], []).
On BSD systems, the Source argument is ignored and passed to the system mount call as:
mount(FSType, Target, Flags, Data);
On Solaris, some mount options are passed in the Options argument as a string of comma separated values terminated by a NULL. Other platforms ignore the Options parameter.
Examples
An example of bind mounting a directory within a linux mount namespace:
1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
{ok,<0.177.0>}
2> {ok, Pid} = alcove:clone(Drv, [], [clone_newns]).
{ok,10059}
3> alcove:mount(Drv, [Pid], "/tmp", "/mnt", "", [ms_bind, ms_rdonly, ms_noexec], "", "").
ok
4> alcove:umount(Drv, [Pid], "/mnt").
ok
Specs
mount_constant(alcove_drv:ref(), [pid_t()], Symbol :: atom()) -> unknown | uint64_t().
Convert flag names to integers
Names are derived from the C macro name with the underscore prefix removed. For example, rdonly
is mapped to MS_RDONLY on Linux and MNT_RDONLY on FreeBSD.
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:mount_constant(Drv, [], rdonly).
1
3> alcove:mount_constant(Drv, [], 'RDONLY').
1
Specs
mount_constant(alcove_drv:ref(), [pid_t()], Symbol :: atom(), timeout()) -> unknown | uint64_t().
Convert flag names to integers
Names are derived from the C macro name with the underscore prefix removed. For example, rdonly
is mapped to MS_RDONLY on Linux and MNT_RDONLY on FreeBSD.
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:mount_constant(Drv, [], rdonly).
1
3> alcove:mount_constant(Drv, [], 'RDONLY').
1
Specs
open(alcove_drv:ref(), [pid_t()], Path :: iodata(), Flags :: int32_t() | [constant()], Mode :: mode_t()) -> {ok, fd()} | {error, posix()}.
open(2): returns a file descriptor associated with a file
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:open(Drv, [], "/tmp/alcove-open-test", [o_wronly,o_creat], 8#644).
{ok,6}
Specs
open(alcove_drv:ref(), [pid_t()], Path :: iodata(), Flags :: int32_t() | [constant()], Mode :: mode_t(), timeout()) -> {ok, fd()} | {error, posix()}.
open(2): returns a file descriptor associated with a file
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:open(Drv, [], "/tmp/alcove-open-test", [o_wronly,o_creat], 8#644).
{ok,6}
Specs
pivot_root(alcove_drv:ref(), [pid_t()], NewRoot :: iodata(), PutOld :: iodata()) -> ok | {error, posix()}.
pivot_root(2): change the root mount
Use pivot_root(2) in a Linux mount namespace to change the root filesystem.
Warning: using pivot_root(2) in the global namespace may have unexpected effects.
Support
* Linux
Examples
The new root must be a mount point. /tmp or /run are usually mounted as tmpfs.
1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
{ok,<0.177.0>}
2> alcove:mkdir(Drv, [], "/run/alcove-old-root", 8#755).
ok
3> {ok, Pid} = alcove:clone(Drv, [], [clone_newns]).
{ok,1371}
4> alcove:pivot_root(Drv, [Pid], "/run", "/run/alcove-old-root").
ok
Specs
pivot_root(alcove_drv:ref(), [pid_t()], NewRoot :: iodata(), PutOld :: iodata(), timeout()) -> ok | {error, posix()}.
pivot_root(2): change the root mount
Use pivot_root(2) in a Linux mount namespace to change the root filesystem.
Warning: using pivot_root(2) in the global namespace may have unexpected effects.
Support
* Linux
Examples
The new root must be a mount point. /tmp or /run are usually mounted as tmpfs.
1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
{ok,<0.177.0>}
2> alcove:mkdir(Drv, [], "/run/alcove-old-root", 8#755).
ok
3> {ok, Pid} = alcove:clone(Drv, [], [clone_newns]).
{ok,1371}
4> alcove:pivot_root(Drv, [Pid], "/run", "/run/alcove-old-root").
ok
Specs
pledge(alcove_drv:ref(), [pid_t()], Promises :: iodata(), ExecPromises :: iodata()) -> ok | {error, posix()}.
pledge(2): restrict system operations
An empty list ([]) specifies promises should not be changed. Warning: an empty string ("") is equivalent to an empty list.
To specify no capabilities, use an empty binary: <<>>>
or <<"">>
Support
* OpenBSD
Examples
Fork a control process:
* restricted to stdio, proc and exec capabilities * unrestricted after calling exec
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,10059}
3> alcove:pledge(Drv, [Pid], <<"stdio proc exec">>, []).
ok
Specs
pledge(alcove_drv:ref(), [pid_t()], Promises :: iodata(), ExecPromises :: iodata(), timeout()) -> ok | {error, posix()}.
pledge(2): restrict system operations
An empty list ([]) specifies promises should not be changed. Warning: an empty string ("") is equivalent to an empty list.
To specify no capabilities, use an empty binary: <<>>>
or <<"">>
Support
* OpenBSD
Examples
Fork a control process:
* restricted to stdio, proc and exec capabilities * unrestricted after calling exec
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,10059}
3> alcove:pledge(Drv, [Pid], <<"stdio proc exec">>, []).
ok
Specs
prctl(alcove_drv:ref(), [pid_t()], constant(), ptr_arg(), ptr_arg(), ptr_arg(), ptr_arg()) -> {ok, integer(), ptr_val(), ptr_val(), ptr_val(), ptr_val()} | {error, posix()}.
prctl(2): operations on a process
This function can be used to set BPF syscall filters on processes (seccomp mode).
A list can be used for prctl operations requiring a C structure as an argument. List elements are used to contiguously populate a buffer (it is up to the caller to add padding):
* binary(): the element is copied directly into the buffer
On return, the contents of the binary is returned to the caller.
* {ptr, N}: N bytes of memory is allocated and zeroed. The pointer is placed in the buffer.
On return, the contents of the memory is returned to the caller.
* {ptr, binary()}
Memory equal to the size of the binary is allocated and initialized with the contents of the binary.
On return, the contents of the memory is returned to the caller.
Support
* Linux
Examples
To enforce a seccomp filter:
% NOTE: this filter will cause the port to receive a SIGSYS
% See test/alcove_seccomp_tests.erl for all the syscalls
% required for the port process to run
Arch = alcove:define(Drv, [], alcove:audit_arch()),
Filter = [
?VALIDATE_ARCHITECTURE(Arch),
?EXAMINE_SYSCALL,
sys_read,
sys_write
],
{ok,_,_,_,_,_} = alcove:prctl(Drv, [], pr_set_no_new_privs, 1, 0, 0, 0),
Pad = (erlang:system_info({wordsize,external}) - 2) * 8,
Prog = [
<<(iolist_size(Filter) div 8):2/native-unsigned-integer-unit:8>>,
<<0:Pad>>,
{ptr, list_to_binary(Filter)}
],
alcove:prctl(Drv, [], pr_set_seccomp, seccomp_mode_filter, Prog, 0, 0).
Specs
prctl(alcove_drv:ref(), [pid_t()], constant(), ptr_arg(), ptr_arg(), ptr_arg(), ptr_arg(), timeout()) -> {ok, integer(), ptr_val(), ptr_val(), ptr_val(), ptr_val()} | {error, posix()}.
prctl(2): operations on a process
This function can be used to set BPF syscall filters on processes (seccomp mode).
A list can be used for prctl operations requiring a C structure as an argument. List elements are used to contiguously populate a buffer (it is up to the caller to add padding):
* binary(): the element is copied directly into the buffer
On return, the contents of the binary is returned to the caller.
* {ptr, N}: N bytes of memory is allocated and zeroed. The pointer is placed in the buffer.
On return, the contents of the memory is returned to the caller.
* {ptr, binary()}
Memory equal to the size of the binary is allocated and initialized with the contents of the binary.
On return, the contents of the memory is returned to the caller.
Support
* Linux
Examples
To enforce a seccomp filter:
% NOTE: this filter will cause the port to receive a SIGSYS
% See test/alcove_seccomp_tests.erl for all the syscalls
% required for the port process to run
Arch = alcove:define(Drv, [], alcove:audit_arch()),
Filter = [
?VALIDATE_ARCHITECTURE(Arch),
?EXAMINE_SYSCALL,
sys_read,
sys_write
],
{ok,_,_,_,_,_} = alcove:prctl(Drv, [], pr_set_no_new_privs, 1, 0, 0, 0),
Pad = (erlang:system_info({wordsize,external}) - 2) * 8,
Prog = [
<<(iolist_size(Filter) div 8):2/native-unsigned-integer-unit:8>>,
<<0:Pad>>,
{ptr, list_to_binary(Filter)}
],
alcove:prctl(Drv, [], pr_set_seccomp, seccomp_mode_filter, Prog, 0, 0).
Specs
prctl_constant(alcove_drv:ref(), [pid_t()], Symbol :: atom()) -> unknown | non_neg_integer().
Convert prctl option names to integers
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:prctl_constant(Drv, [], pr_set_name).
15
Specs
prctl_constant(alcove_drv:ref(), [pid_t()], Symbol :: atom(), timeout()) -> unknown | non_neg_integer().
Convert prctl option names to integers
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:prctl_constant(Drv, [], pr_set_name).
15
Specs
procctl(alcove_drv:ref(), [pid_t()], IDType :: constant(), ID :: pid_t(), Cmd :: constant(), Data :: [] | cstruct()) -> {ok, binary(), cstruct()} | {error, posix()}.
procctl(2): control processes
Support
* FreeBSD
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.208.0>}
2> {ok, Pid} = alcove:fork(Pid, []).
{ok,44378}
3> alcove:procctl(Drv, [Pid], 0, Pid, 'PROC_REAP_ACQUIRE', []).
{ok,<<>>,[]}
4> alcove:procctl(Drv, [Pid], p_pid, Pid, 'PROC_REAP_STATUS', [
4> <<0,0,0,0>>, % rs_flags
4> <<0,0,0,0>>, % rs_children
4> <<0,0,0,0>>, % rs_descendants
4> <<0,0,0,0>>, % rs_reaper
4> <<0,0,0,0>> % rs_pid
4> ]).
{ok,<<1,0,0,0,0,0,0,0,0,0,0,0,118,173,0,0,255,255,255,255>>,
[<<1,0,0,0>>,
<<0,0,0,0>>,
<<0,0,0,0>>,
<<118,173,0,0>>,
<<"\377\377\377\377">>]}
Specs
procctl(alcove_drv:ref(), [pid_t()], IDType :: constant(), ID :: pid_t(), Cmd :: constant(), Data :: [] | cstruct(), timeout()) -> {ok, binary(), cstruct()} | {error, posix()}.
procctl(2): control processes
Support
* FreeBSD
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.208.0>}
2> {ok, Pid} = alcove:fork(Pid, []).
{ok,44378}
3> alcove:procctl(Drv, [Pid], 0, Pid, 'PROC_REAP_ACQUIRE', []).
{ok,<<>>,[]}
4> alcove:procctl(Drv, [Pid], p_pid, Pid, 'PROC_REAP_STATUS', [
4> <<0,0,0,0>>, % rs_flags
4> <<0,0,0,0>>, % rs_children
4> <<0,0,0,0>>, % rs_descendants
4> <<0,0,0,0>>, % rs_reaper
4> <<0,0,0,0>> % rs_pid
4> ]).
{ok,<<1,0,0,0,0,0,0,0,0,0,0,0,118,173,0,0,255,255,255,255>>,
[<<1,0,0,0>>,
<<0,0,0,0>>,
<<0,0,0,0>>,
<<118,173,0,0>>,
<<"\377\377\377\377">>]}
Specs
ptrace(alcove_drv:ref(), [pid_t()], Request :: constant(), OSPid :: pid_t(), Addr :: ptr_arg(), Data :: ptr_arg()) -> {ok, integer(), ptr_val(), ptr_val()} | {error, posix()}.
ptrace(2): process trace
Examples
-module(ptrace).
-export([run/0]).
run() ->
{ok, Drv} = alcove_drv:start_link(),
{ok, Pid1} = alcove:fork(Drv, []),
{ok, Pid2} = alcove:fork(Drv, [Pid1]),
% disable the alcove event loop: child process must be managed by
% the caller
{ok, sig_dfl} = alcove:sigaction(Drv, [Pid1], sigchld, sig_info),
% enable ptracing in the child process and exec() a command
{ok, 0, <<>>, <<>>} = alcove:ptrace(
Drv,
[Pid1, Pid2],
ptrace_traceme,
0,
0,
0
),
ok = alcove:execvp(Drv, [Pid1, Pid2], "cat", ["cat"]),
% the parent is notified
{signal, sigchld, _} = alcove:event(Drv, [Pid1], 5000),
{ok, Pid2, _, [{stopsig, sigtrap}]} = alcove:waitpid(
Drv,
[Pid1],
-1,
[wnohang]
),
% should be no other events
{ok, 0, 0, []} = alcove:waitpid(Drv, [Pid1], -1, [wnohang]),
% allow the process to continue
{ok, 0, <<>>, <<>>} = alcove:ptrace(Drv, [Pid1], ptrace_cont, Pid2, 0, 0),
ok = alcove:stdin(Drv, [Pid1, Pid2], "test\n"),
ok =
receive
{alcove_stdout, Drv, [Pid1, Pid2], <<"test\n">>} ->
ok
after 5000 -> timeout
end,
% Send a SIGTERM and re-write it to a harmless SIGWINCH
ok = alcove:kill(Drv, [Pid1], Pid2, sigterm),
{signal, sigchld, _} = alcove:event(Drv, [Pid1], 5000),
{ok, Pid2, _, [{stopsig, sigterm}]} = alcove:waitpid(
Drv,
[Pid1],
-1,
[wnohang]
),
{ok, 0, <<>>, <<>>} = alcove:ptrace(
Drv,
[Pid1],
ptrace_cont,
Pid2,
0,
28
),
% Convert a SIGWINCH to SIGTERM
ok = alcove:kill(Drv, [Pid1], Pid2, sigwinch),
{signal, sigchld, _} = alcove:event(Drv, [Pid1], 5000),
{ok, 0, <<>>, <<>>} = alcove:ptrace(
Drv,
[Pid1],
ptrace_cont,
Pid2,
0,
15
),
{ok, Pid2, _, [{termsig, sigterm}]} = alcove:waitpid(
Drv,
[Pid1],
-1,
[]
).
Specs
ptrace(alcove_drv:ref(), [pid_t()], Request :: constant(), OSPid :: pid_t(), Addr :: ptr_arg(), Data :: ptr_arg(), timeout()) -> {ok, integer(), ptr_val(), ptr_val()} | {error, posix()}.
ptrace(2): process trace
Examples
-module(ptrace).
-export([run/0]).
run() ->
{ok, Drv} = alcove_drv:start_link(),
{ok, Pid1} = alcove:fork(Drv, []),
{ok, Pid2} = alcove:fork(Drv, [Pid1]),
% disable the alcove event loop: child process must be managed by
% the caller
{ok, sig_dfl} = alcove:sigaction(Drv, [Pid1], sigchld, sig_info),
% enable ptracing in the child process and exec() a command
{ok, 0, <<>>, <<>>} = alcove:ptrace(
Drv,
[Pid1, Pid2],
ptrace_traceme,
0,
0,
0
),
ok = alcove:execvp(Drv, [Pid1, Pid2], "cat", ["cat"]),
% the parent is notified
{signal, sigchld, _} = alcove:event(Drv, [Pid1], 5000),
{ok, Pid2, _, [{stopsig, sigtrap}]} = alcove:waitpid(
Drv,
[Pid1],
-1,
[wnohang]
),
% should be no other events
{ok, 0, 0, []} = alcove:waitpid(Drv, [Pid1], -1, [wnohang]),
% allow the process to continue
{ok, 0, <<>>, <<>>} = alcove:ptrace(Drv, [Pid1], ptrace_cont, Pid2, 0, 0),
ok = alcove:stdin(Drv, [Pid1, Pid2], "test\n"),
ok =
receive
{alcove_stdout, Drv, [Pid1, Pid2], <<"test\n">>} ->
ok
after 5000 -> timeout
end,
% Send a SIGTERM and re-write it to a harmless SIGWINCH
ok = alcove:kill(Drv, [Pid1], Pid2, sigterm),
{signal, sigchld, _} = alcove:event(Drv, [Pid1], 5000),
{ok, Pid2, _, [{stopsig, sigterm}]} = alcove:waitpid(
Drv,
[Pid1],
-1,
[wnohang]
),
{ok, 0, <<>>, <<>>} = alcove:ptrace(
Drv,
[Pid1],
ptrace_cont,
Pid2,
0,
28
),
% Convert a SIGWINCH to SIGTERM
ok = alcove:kill(Drv, [Pid1], Pid2, sigwinch),
{signal, sigchld, _} = alcove:event(Drv, [Pid1], 5000),
{ok, 0, <<>>, <<>>} = alcove:ptrace(
Drv,
[Pid1],
ptrace_cont,
Pid2,
0,
15
),
{ok, Pid2, _, [{termsig, sigterm}]} = alcove:waitpid(
Drv,
[Pid1],
-1,
[]
).
Specs
ptrace_constant(alcove_drv:ref(), [pid_t()], Symbol :: atom()) -> unknown | integer().
Convert ptrace constant to integer
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:ptrace_constant(Drv, [], ptrace_traceme).
0
Specs
ptrace_constant(alcove_drv:ref(), [pid_t()], Symbol :: atom(), timeout()) -> unknown | integer().
Convert ptrace constant to integer
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:ptrace_constant(Drv, [], ptrace_traceme).
0
Specs
read(alcove_drv:ref(), [pid_t()], FD :: fd(), Count :: size_t()) -> {ok, binary()} | {error, posix()}.
read(2): read bytes from a file descriptor
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.209.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,75710}
3> {ok, FD} = alcove:open(Drv, [Pid], "/etc/passwd", [o_rdonly], 0).
{ok,6}
4> alcove:read(Drv, [Pid], FD, 64).
{ok,<<"# $FreeBSD$\n#\nroot:*:0:0:Charlie &:/root:/bin/csh\ntoor:*:0:0:Bou">>}
Specs
read(alcove_drv:ref(), [pid_t()], FD :: fd(), Count :: size_t(), timeout()) -> {ok, binary()} | {error, posix()}.
read(2): read bytes from a file descriptor
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.209.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,75710}
3> {ok, FD} = alcove:open(Drv, [Pid], "/etc/passwd", [o_rdonly], 0).
{ok,6}
4> alcove:read(Drv, [Pid], FD, 64).
{ok,<<"# $FreeBSD$\n#\nroot:*:0:0:Charlie &:/root:/bin/csh\ntoor:*:0:0:Bou">>}
Specs
readdir(alcove_drv:ref(), [pid_t()], Path :: iodata()) -> {ok, [binary()]} | {error, posix()}.
readdir(3): retrieve list of objects in a directory
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.209.0>}
2> alcove:readdir(Drv, [], "/dev/pts").
{ok,[<<".">>,<<"..">>,<<"50">>,<<"49">>,<<"45">>,<<"48">>,
<<"47">>,<<"46">>,<<"44">>,<<"43">>,<<"42">>,<<"41">>,
<<"40">>,<<"39">>,<<"38">>,<<"37">>,<<"36">>,<<"35">>,
<<"34">>,<<"33">>,<<"32">>,<<"31">>,<<"30">>,<<"29">>,
<<"28">>,<<"27">>,<<...>>|...]}
Specs
readdir(alcove_drv:ref(), [pid_t()], Path :: iodata(), timeout()) -> {ok, [binary()]} | {error, posix()}.
readdir(3): retrieve list of objects in a directory
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.209.0>}
2> alcove:readdir(Drv, [], "/dev/pts").
{ok,[<<".">>,<<"..">>,<<"50">>,<<"49">>,<<"45">>,<<"48">>,
<<"47">>,<<"46">>,<<"44">>,<<"43">>,<<"42">>,<<"41">>,
<<"40">>,<<"39">>,<<"38">>,<<"37">>,<<"36">>,<<"35">>,
<<"34">>,<<"33">>,<<"32">>,<<"31">>,<<"30">>,<<"29">>,
<<"28">>,<<"27">>,<<...>>|...]}
Specs
rlimit_constant(alcove_drv:ref(), [pid_t()], Symbol :: atom()) -> unknown | non_neg_integer().
Convert an RLIMIT_* flag to an integer
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:rlimit_constant(Drv, [], rlimit_nofile).
7
Specs
rlimit_constant(alcove_drv:ref(), [pid_t()], Symbol :: atom(), timeout()) -> unknown | non_neg_integer().
Convert an RLIMIT_* flag to an integer
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:rlimit_constant(Drv, [], rlimit_nofile).
7
Specs
rmdir(alcove_drv:ref(), [pid_t()], Path :: iodata()) -> ok | {error, posix()}.
rmdir(2): delete a directory
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:mkdir(Drv, [], "/tmp/alcove-rmdir-test", 8#755).
ok
3> alcove:rmdir(Drv, [], "/tmp/alcove-rmdir-test").
ok
Specs
rmdir(alcove_drv:ref(), [pid_t()], Path :: iodata(), timeout()) -> ok | {error, posix()}.
rmdir(2): delete a directory
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:mkdir(Drv, [], "/tmp/alcove-rmdir-test", 8#755).
ok
3> alcove:rmdir(Drv, [], "/tmp/alcove-rmdir-test").
ok
Specs
seccomp(alcove_drv:ref(), [pid_t()], Operation :: constant(), Flags :: constant(), Prog :: cstruct()) -> ok | {error, posix()}.
seccomp(2): restrict system operations
Also see prctl/7.
Support
* Linux
Examples
To enforce a seccomp filter:
% NOTE: this filter will cause the port to receive a SIGSYS
% See test/alcove_seccomp_tests.erl for all the syscalls
% required for the port process to run
Arch = alcove:define(Drv, [], alcove:audit_arch()),
Filter = [
?VALIDATE_ARCHITECTURE(Arch),
?EXAMINE_SYSCALL,
sys_read,
sys_write
],
{ok,_,_,_,_,_} = alcove:prctl(Drv, [], pr_set_no_new_privs, 1, 0, 0, 0),
Pad = (erlang:system_info({wordsize,external}) - 2) * 8,
Prog = [
<<(iolist_size(Filter) div 8):2/native-unsigned-integer-unit:8>>,
<<0:Pad>>,
{ptr, list_to_binary(Filter)}
],
alcove:seccomp(Drv, [], seccomp_set_mode_filter, 0, Prog).
Specs
seccomp(alcove_drv:ref(), [pid_t()], Operation :: constant(), Flags :: constant(), Prog :: cstruct(), timeout()) -> ok | {error, posix()}.
seccomp(2): restrict system operations
Also see prctl/7.
Support
* Linux
Examples
To enforce a seccomp filter:
% NOTE: this filter will cause the port to receive a SIGSYS
% See test/alcove_seccomp_tests.erl for all the syscalls
% required for the port process to run
Arch = alcove:define(Drv, [], alcove:audit_arch()),
Filter = [
?VALIDATE_ARCHITECTURE(Arch),
?EXAMINE_SYSCALL,
sys_read,
sys_write
],
{ok,_,_,_,_,_} = alcove:prctl(Drv, [], pr_set_no_new_privs, 1, 0, 0, 0),
Pad = (erlang:system_info({wordsize,external}) - 2) * 8,
Prog = [
<<(iolist_size(Filter) div 8):2/native-unsigned-integer-unit:8>>,
<<0:Pad>>,
{ptr, list_to_binary(Filter)}
],
alcove:seccomp(Drv, [], seccomp_set_mode_filter, 0, Prog).
Specs
seccomp_constant(alcove_drv:ref(), [pid_t()], Symbol :: atom()) -> unknown | non_neg_integer().
Convert seccomp option name to integer
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:seccomp_constant(Drv, [], 'SECCOMP_SET_MODE_STRICT').
0
Specs
seccomp_constant(alcove_drv:ref(), [pid_t()], Symbol :: atom(), timeout()) -> unknown | non_neg_integer().
Convert seccomp option name to integer
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:seccomp_constant(Drv, [], 'SECCOMP_SET_MODE_STRICT').
0
Specs
select(alcove_drv:ref(), [pid_t()], Readfds :: fd_set(), Writefds :: fd_set(), Exceptfds :: fd_set(), Timeval :: [] | null | alcove_timeval()) -> {ok, Readset :: fd_set(), Writeset :: fd_set(), Exceptset :: fd_set()} | {error, posix()}.
select(2): poll a list of file descriptor for events
select/6 will block until an event occurs on a file descriptor, a timeout is reached or interrupted by a signal.
The Timeout value may be:
* passing an empty list ([]) causes select to block indefinitely (no timeout)
* an alcove_timeval record with these fields:
* sec : number of seconds to wait
* usec : number of microseconds to wait
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> {ok, FD} = alcove:open(Drv, [], "/dev/null", [o_rdwr], 0).
{ok,6}
3> alcove:select(Drv, [], [FD], [FD], [FD], []).
{ok,[6],[6],[]}
4> rr(alcove).
[alcove_jail,alcove_pid,alcove_rlimit,alcove_timeval]
5> alcove:select(Drv, [], [FD], [FD], [FD], #alcove_timeval{sec = 1, usec = 1}).
{ok,[6],[6],[]}
Specs
select(alcove_drv:ref(), [pid_t()], Readfds :: fd_set(), Writefds :: fd_set(), Exceptfds :: fd_set(), Timeval :: [] | null | alcove_timeval(), timeout()) -> {ok, Readset :: fd_set(), Writeset :: fd_set(), Exceptset :: fd_set()} | {error, posix()}.
select(2): poll a list of file descriptor for events
select/6 will block until an event occurs on a file descriptor, a timeout is reached or interrupted by a signal.
The Timeout value may be:
* passing an empty list ([]) causes select to block indefinitely (no timeout)
* an alcove_timeval record with these fields:
* sec : number of seconds to wait
* usec : number of microseconds to wait
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> {ok, FD} = alcove:open(Drv, [], "/dev/null", [o_rdwr], 0).
{ok,6}
3> alcove:select(Drv, [], [FD], [FD], [FD], []).
{ok,[6],[6],[]}
4> rr(alcove).
[alcove_jail,alcove_pid,alcove_rlimit,alcove_timeval]
5> alcove:select(Drv, [], [FD], [FD], [FD], #alcove_timeval{sec = 1, usec = 1}).
{ok,[6],[6],[]}
Specs
setcpid(alcove_drv:ref(), [pid_t()], Child :: pid_t(), Opt :: alcove_pid_field(), Val :: int32_t()) -> boolean().
Set options for child process of alcove control process
* flowcontrol
Enable rate limiting of the stdout and stderr of a child process. stdin is not rate limited (default: -1 (disabled))
* 0 : stdout/stderr for process is not read * 1-2147483646 : read this many messages from the process * -1 : disable flow control
NOTE: the limit applies to stdout and stderr. If the limit is set to 1, it is possible to get:
* 1 message from stdout * 1 message from stderr * 1 message from stdout and stderr
* signaloneof
The alcove control process sends this signal to the child process on shutdown (default: 15 (SIGTERM))
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,24440}
3> alcove:setcpid(Drv, [], Pid, flowcontrol, 0).
true
4> alcove:getcpid(Drv, [], Pid, flowcontrol).
0
Specs
setcpid(alcove_drv:ref(), [pid_t()], Child :: pid_t(), Opt :: alcove_pid_field(), Val :: int32_t(), timeout()) -> boolean().
Set options for child process of alcove control process
* flowcontrol
Enable rate limiting of the stdout and stderr of a child process. stdin is not rate limited (default: -1 (disabled))
* 0 : stdout/stderr for process is not read * 1-2147483646 : read this many messages from the process * -1 : disable flow control
NOTE: the limit applies to stdout and stderr. If the limit is set to 1, it is possible to get:
* 1 message from stdout * 1 message from stderr * 1 message from stdout and stderr
* signaloneof
The alcove control process sends this signal to the child process on shutdown (default: 15 (SIGTERM))
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,24440}
3> alcove:setcpid(Drv, [], Pid, flowcontrol, 0).
true
4> alcove:getcpid(Drv, [], Pid, flowcontrol).
0
Specs
setenv(alcove_drv:ref(), [pid_t()], Name :: iodata(), Value :: iodata(), Overwrite :: int32_t()) -> ok | {error, posix()}.
setenv(3): set an environment variable
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:setenv(Drv, [], "ALCOVE_TEST", "foo", 0).
ok
3> alcove:getenv(Drv, [], "ALCOVE_TEST").
<<"foo">>
4> alcove:setenv(Drv, [], "ALCOVE_TEST", "bar", 0).
ok
5> alcove:getenv(Drv, [], "ALCOVE_TEST").
<<"foo">>
6> alcove:setenv(Drv, [], "ALCOVE_TEST", "bar", 1).
ok
7> alcove:getenv(Drv, [], "ALCOVE_TEST").
<<"bar">>
Specs
setenv(alcove_drv:ref(), [pid_t()], Name :: iodata(), Value :: iodata(), Overwrite :: int32_t(), timeout()) -> ok | {error, posix()}.
setenv(3): set an environment variable
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:setenv(Drv, [], "ALCOVE_TEST", "foo", 0).
ok
3> alcove:getenv(Drv, [], "ALCOVE_TEST").
<<"foo">>
4> alcove:setenv(Drv, [], "ALCOVE_TEST", "bar", 0).
ok
5> alcove:getenv(Drv, [], "ALCOVE_TEST").
<<"foo">>
6> alcove:setenv(Drv, [], "ALCOVE_TEST", "bar", 1).
ok
7> alcove:getenv(Drv, [], "ALCOVE_TEST").
<<"bar">>
Specs
setgid(alcove_drv:ref(), [pid_t()], Gid :: gid_t()) -> ok | {error, posix()}.
setgid(2): set the GID of the process
Examples
1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
{ok,<0.208.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,44378}
72> alcove:setgid(Drv, [Pid], 123).
ok
73> alcove:getgid(Drv, [Pid]).
123
Specs
setgid(alcove_drv:ref(), [pid_t()], Gid :: gid_t(), timeout()) -> ok | {error, posix()}.
setgid(2): set the GID of the process
Examples
1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
{ok,<0.208.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,44378}
72> alcove:setgid(Drv, [Pid], 123).
ok
73> alcove:getgid(Drv, [Pid]).
123
Specs
setgroups(alcove_drv:ref(), [pid_t()], Groups :: [gid_t()]) -> ok | {error, posix()}.
setgroups(2): set the supplementary groups of the process
Examples
1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
{ok,<0.208.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,44378}
75> alcove:setgroups(Drv, [Pid], []).
ok
76> alcove:getgroups(Drv, [Pid]).
{ok,[]}
Specs
setgroups(alcove_drv:ref(), [pid_t()], Groups :: [gid_t()], timeout()) -> ok | {error, posix()}.
setgroups(2): set the supplementary groups of the process
Examples
1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
{ok,<0.208.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,44378}
75> alcove:setgroups(Drv, [Pid], []).
ok
76> alcove:getgroups(Drv, [Pid]).
{ok,[]}
Specs
sethostname(alcove_drv:ref(), [pid_t()], Hostname :: iodata()) -> ok | {error, posix()}.
sethostname(2): set the system hostname
This function is probably only useful if running in a uts namespace or a jail.
Examples
1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
{ok,<0.208.0>}
2> {ok, Pid} = alcove:clone(Drv, [], [clone_newuts]).
{ok,44378}
3> alcove:sethostname(Drv, [Pid], "test").
ok
4> alcove:gethostname(Drv, []).
{ok,<<"host1">>}
5> alcove:gethostname(Drv, [Pid]).
{ok,<<"test">>}
Specs
sethostname(alcove_drv:ref(), [pid_t()], Hostname :: iodata(), timeout()) -> ok | {error, posix()}.
sethostname(2): set the system hostname
This function is probably only useful if running in a uts namespace or a jail.
Examples
1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
{ok,<0.208.0>}
2> {ok, Pid} = alcove:clone(Drv, [], [clone_newuts]).
{ok,44378}
3> alcove:sethostname(Drv, [Pid], "test").
ok
4> alcove:gethostname(Drv, []).
{ok,<<"host1">>}
5> alcove:gethostname(Drv, [Pid]).
{ok,<<"test">>}
Specs
setns(alcove_drv:ref(), [pid_t()], FD :: fd(), NSType :: constant()) -> ok | {error, posix()}.
setns(2): attach to a namespace
A process namespace is represented as a path in the /proc filesystem. The path is /proc/<pid>/ns/<ns>
, where:
* pid: the system PID
* ns: a file representing the namespace
The available namespaces is dependent on the kernel version. You can see which are supported by running:
ls -al /proc/$$/ns
Support
* Linux
Examples
Attach a process to an existing network namespace:
1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
{ok,<0.208.0>}
2> {ok, Pid1} = alcove:clone(Drv, [], [clone_newnet]).
{ok,27125}
3> {ok, Pid2} = alcove:fork(Drv, []).
{ok,27126}
% Move Pid2 into the Pid1 network namespace
4> {ok, FD} = alcove:open(Drv, [Pid2], ["/proc/", integer_to_list(Pid1), "/ns/net"], [o_rdonly], 0).
{ok,8}
5> alcove:setns(Drv, [Pid2], FD, 0).
ok
6> alcove:close(Drv, [Pid2], FD).
Specs
setns(alcove_drv:ref(), [pid_t()], FD :: fd(), NSType :: constant(), timeout()) -> ok | {error, posix()}.
setns(2): attach to a namespace
A process namespace is represented as a path in the /proc filesystem. The path is /proc/<pid>/ns/<ns>
, where:
* pid: the system PID
* ns: a file representing the namespace
The available namespaces is dependent on the kernel version. You can see which are supported by running:
ls -al /proc/$$/ns
Support
* Linux
Examples
Attach a process to an existing network namespace:
1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
{ok,<0.208.0>}
2> {ok, Pid1} = alcove:clone(Drv, [], [clone_newnet]).
{ok,27125}
3> {ok, Pid2} = alcove:fork(Drv, []).
{ok,27126}
% Move Pid2 into the Pid1 network namespace
4> {ok, FD} = alcove:open(Drv, [Pid2], ["/proc/", integer_to_list(Pid1), "/ns/net"], [o_rdonly], 0).
{ok,8}
5> alcove:setns(Drv, [Pid2], FD, 0).
ok
6> alcove:close(Drv, [Pid2], FD).
Specs
setopt(alcove_drv:ref(), [pid_t()], Opt :: atom(), Val :: int32_t()) -> boolean().
Set port options
See getopt/2,3 for the list of options.
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:setopt(Drv, [], maxforkdepth, 128).
true
Specs
setopt(alcove_drv:ref(), [pid_t()], Opt :: atom(), Val :: int32_t(), timeout()) -> boolean().
Set port options
See getopt/2,3 for the list of options.
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:setopt(Drv, [], maxforkdepth, 128).
true
Specs
setpgid(alcove_drv:ref(), [pid_t()], OSPid :: pid_t(), Pgid :: pid_t()) -> ok | {error, posix()}.
setpgid(2): set process group
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,28210}
3> alcove:setpgid(Drv, [Pid], 0, 0).
ok
Specs
setpgid(alcove_drv:ref(), [pid_t()], OSPid :: pid_t(), Pgid :: pid_t(), timeout()) -> ok | {error, posix()}.
setpgid(2): set process group
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,28210}
3> alcove:setpgid(Drv, [Pid], 0, 0).
ok
Specs
setpriority(alcove_drv:ref(), [pid_t()], Which :: constant(), Who :: int32_t(), Prio :: int32_t()) -> ok | {error, posix()}.
setpriority(2): set scheduling priority of process, process group or user
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,28210}
3> alcove:setpriority(Drv, [Pid], prio_process, 0, 10).
ok
4> alcove:getpriority(Drv, [Pid], prio_process, 0).
{ok,10}
Specs
setpriority(alcove_drv:ref(), [pid_t()], Which :: constant(), Who :: int32_t(), Prio :: int32_t(), timeout()) -> ok | {error, posix()}.
setpriority(2): set scheduling priority of process, process group or user
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,28210}
3> alcove:setpriority(Drv, [Pid], prio_process, 0, 10).
ok
4> alcove:getpriority(Drv, [Pid], prio_process, 0).
{ok,10}
Specs
setproctitle(alcove_drv:ref(), [pid_t()], Title :: iodata()) -> ok.
setproctitle(3): set the process title
Overwrites arg0.
On Linux, prctl/6,7 can be used to set the command name:
{ok,Fork} = alcove:fork(Drv, []),
alcove:prctl(Drv, [Fork], pr_set_name, <<"pseudonym">>, 0,0,0).
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,28210}
3> alcove:setproctitle(Drv, [Pid], "new process name").
ok
Specs
setproctitle(alcove_drv:ref(), [pid_t()], Title :: iodata(), timeout()) -> ok.
setproctitle(3): set the process title
Overwrites arg0.
On Linux, prctl/6,7 can be used to set the command name:
{ok,Fork} = alcove:fork(Drv, []),
alcove:prctl(Drv, [Fork], pr_set_name, <<"pseudonym">>, 0,0,0).
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,28210}
3> alcove:setproctitle(Drv, [Pid], "new process name").
ok
Specs
setresgid(alcove_drv:ref(), [pid_t()], Real :: gid_t(), Effective :: gid_t(), Saved :: gid_t()) -> ok | {error, posix()}.
setresgid(2): set real, effective and saved group ID
Support
* Linux
* FreeBSD
* OpenBSD
Examples
1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
{ok,<0.177.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,28493}
3> alcove:setresgid(Drv, [Pid], 123, 123, 123).
ok
Specs
setresgid(alcove_drv:ref(), [pid_t()], Real :: gid_t(), Effective :: gid_t(), Saved :: gid_t(), timeout()) -> ok | {error, posix()}.
setresgid(2): set real, effective and saved group ID
Support
* Linux
* FreeBSD
* OpenBSD
Examples
1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
{ok,<0.177.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,28493}
3> alcove:setresgid(Drv, [Pid], 123, 123, 123).
ok
Specs
setresuid(alcove_drv:ref(), [pid_t()], Real :: uid_t(), Effective :: uid_t(), Saved :: uid_t()) -> ok | {error, posix()}.
setresuid(2): set real, effective and saved user ID
Support
* Linux
* FreeBSD
* OpenBSD
Examples
1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
{ok,<0.177.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,28493}
3> alcove:setresuid(Drv, [Pid], 123, 123, 123).
ok
Specs
setresuid(alcove_drv:ref(), [pid_t()], Real :: uid_t(), Effective :: uid_t(), Saved :: uid_t(), timeout()) -> ok | {error, posix()}.
setresuid(2): set real, effective and saved user ID
Support
* Linux
* FreeBSD
* OpenBSD
Examples
1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
{ok,<0.177.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,28493}
3> alcove:setresuid(Drv, [Pid], 123, 123, 123).
ok
Specs
setrlimit(alcove_drv:ref(), [pid_t()], Resource :: constant(), Limit :: alcove_rlimit()) -> ok | {error, posix()}.
setrlimit(2): set a resource limit
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> rr(alcove).
[alcove_jail,alcove_pid,alcove_rlimit,alcove_timeval]
3> {ok, Pid} = alcove:fork(Drv, []).
{ok,28493}
4> alcove:getrlimit(Drv, [Pid], rlimit_nofile).
{ok,#alcove_rlimit{cur = 1024,max = 1048576}}
5> alcove:setrlimit(Drv, [Pid], rlimit_nofile, #alcove_rlimit{cur = 64, max = 64}).
ok
6> alcove:getrlimit(Drv, [Pid], rlimit_nofile).
{ok,#alcove_rlimit{cur = 64,max = 64}}
Specs
setrlimit(alcove_drv:ref(), [pid_t()], Resource :: constant(), Limit :: alcove_rlimit(), timeout()) -> ok | {error, posix()}.
setrlimit(2): set a resource limit
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> rr(alcove).
[alcove_jail,alcove_pid,alcove_rlimit,alcove_timeval]
3> {ok, Pid} = alcove:fork(Drv, []).
{ok,28493}
4> alcove:getrlimit(Drv, [Pid], rlimit_nofile).
{ok,#alcove_rlimit{cur = 1024,max = 1048576}}
5> alcove:setrlimit(Drv, [Pid], rlimit_nofile, #alcove_rlimit{cur = 64, max = 64}).
ok
6> alcove:getrlimit(Drv, [Pid], rlimit_nofile).
{ok,#alcove_rlimit{cur = 64,max = 64}}
Specs
setsid(alcove_drv:ref(), [pid_t()]) -> {ok, OSPid :: pid_t()} | {error, posix()}.
setsid(2): create a new session
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,28493}
3> alcove:setsid(Drv, [Pid]).
{ok,28493}
Specs
setsid(alcove_drv:ref(), [pid_t()], timeout()) -> {ok, OSPid :: pid_t()} | {error, posix()}.
setsid(2): create a new session
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,28493}
3> alcove:setsid(Drv, [Pid]).
{ok,28493}
Specs
setuid(alcove_drv:ref(), [pid_t()], User :: uid_t()) -> ok | {error, posix()}.
setuid(2): change UID
Examples
1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
{ok,<0.208.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,44378}
72> alcove:setuid(Drv, [Pid], 123).
ok
73> alcove:getuid(Drv, [Pid]).
123
Specs
setuid(alcove_drv:ref(), [pid_t()], User :: uid_t(), timeout()) -> ok | {error, posix()}.
setuid(2): change UID
Examples
1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
{ok,<0.208.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,44378}
72> alcove:setuid(Drv, [Pid], 123).
ok
73> alcove:getuid(Drv, [Pid]).
123
Specs
sigaction(alcove_drv:ref(), [pid_t()], Signum :: constant(), Handler :: [] | atom()) -> {ok, OldHandler :: atom()} | {error, posix()}.
sigaction(2): set process behaviour for signals
* sig_dfl
Uses the default behaviour for the signal
* sig_ign
Ignores the signal
* sig_info
Catches the signal and sends the controlling Erlang process an event:
{signal, atom(), Info}
Info is a binary containing the siginfo_t structure. See sigaction(2) for details.
* []
Returns the current handler for the signal.
Multiple caught signals of the same type may be reported as one event.
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> rr(alcove).
[alcove_jail,alcove_pid,alcove_rlimit,alcove_timeval]
3> {ok, Pid} = alcove:fork(Drv, []).
{ok,28493}
4> alcove:kill(Drv, [], Pid, sigterm).
ok
5> flush().
Shell got {alcove_event,<0.177.0>,
[28493],
{signal,sigterm,
<<15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,76,111,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0>>}}
ok
6> alcove:sigaction(Drv, [Pid], sigterm, sig_ign).
{ok,sig_info}
7> alcove:kill(Drv, [], Pid, sigterm).
ok
8> flush().
ok
9> alcove:sigaction(Drv, [Pid], sigterm, sig_info).
{ok,sig_ign}
10> alcove:kill(Drv, [], Pid, sigterm).
ok
11> flush().
Shell got {alcove_event,<0.177.0>,
[28493],
{signal,sigterm,
<<15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,76,111,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0>>}}
ok
Specs
sigaction(alcove_drv:ref(), [pid_t()], Signum :: constant(), Handler :: [] | atom(), timeout()) -> {ok, OldHandler :: atom()} | {error, posix()}.
sigaction(2): set process behaviour for signals
* sig_dfl
Uses the default behaviour for the signal
* sig_ign
Ignores the signal
* sig_info
Catches the signal and sends the controlling Erlang process an event:
{signal, atom(), Info}
Info is a binary containing the siginfo_t structure. See sigaction(2) for details.
* []
Returns the current handler for the signal.
Multiple caught signals of the same type may be reported as one event.
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> rr(alcove).
[alcove_jail,alcove_pid,alcove_rlimit,alcove_timeval]
3> {ok, Pid} = alcove:fork(Drv, []).
{ok,28493}
4> alcove:kill(Drv, [], Pid, sigterm).
ok
5> flush().
Shell got {alcove_event,<0.177.0>,
[28493],
{signal,sigterm,
<<15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,76,111,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0>>}}
ok
6> alcove:sigaction(Drv, [Pid], sigterm, sig_ign).
{ok,sig_info}
7> alcove:kill(Drv, [], Pid, sigterm).
ok
8> flush().
ok
9> alcove:sigaction(Drv, [Pid], sigterm, sig_info).
{ok,sig_ign}
10> alcove:kill(Drv, [], Pid, sigterm).
ok
11> flush().
Shell got {alcove_event,<0.177.0>,
[28493],
{signal,sigterm,
<<15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,76,111,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0>>}}
ok
Specs
signal_constant(alcove_drv:ref(), [pid_t()], Symbol :: atom()) -> unknown | non_neg_integer().
Convert signal names to integers
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:signal_constant(Drv, [], 'SIGHUP').
1
3> alcove:signal_constant(Drv, [], sighup).
1
Specs
signal_constant(alcove_drv:ref(), [pid_t()], Symbol :: atom(), timeout()) -> unknown | non_neg_integer().
Convert signal names to integers
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:signal_constant(Drv, [], 'SIGHUP').
1
3> alcove:signal_constant(Drv, [], sighup).
1
Specs
socket(alcove_drv:ref(), [pid_t()], Domain :: constant(), Type :: constant(), Protocol :: int32_t()) -> {ok, fd()} | {error, posix()}.
socket(2): returns a file descriptor for a communication endpoint
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> {ok, Socket} = alcove:socket(Drv, [], af_inet, sock_stream, 0).
{ok,6}
3> alcove:close(Drv, [], Socket).
ok
Specs
socket(alcove_drv:ref(), [pid_t()], Domain :: constant(), Type :: constant(), Protocol :: int32_t(), timeout()) -> {ok, fd()} | {error, posix()}.
socket(2): returns a file descriptor for a communication endpoint
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> {ok, Socket} = alcove:socket(Drv, [], af_inet, sock_stream, 0).
{ok,6}
3> alcove:close(Drv, [], Socket).
ok
Specs
stderr(alcove_drv:ref(), [pid_t()]) -> [binary()].
Read stderr from the process
Examples
1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
{ok,<0.177.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,28493}
3> alcove:execvp(Drv, [Pid], "cat", ["cat", "/nonexistent"]).
ok
4> alcove:stderr(Drv, [Pid]).
[<<"cat: /nonexistent: No such file or directoryn">>]
Specs
stderr(alcove_drv:ref(), [pid_t()], timeout()) -> [binary()].
Specs
stdin(alcove_drv:ref(), [pid_t()], iodata()) -> ok.
Send data to stdin of the process
Examples
1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
{ok,<0.177.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,28493}
3> alcove:execvp(Drv, [Pid], "cat", ["cat"]).
ok
4> alcove:stdin(Drv, [Pid], "testn").
ok
5> alcove:stdout(Drv, [Pid]).
[<<"testn">>]
Specs
stdout(alcove_drv:ref(), [pid_t()]) -> [binary()].
Read stdout from the process
Examples
1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
{ok,<0.177.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,28493}
3> alcove:execvp(Drv, [Pid], "cat", ["cat"]).
ok
4> alcove:stdin(Drv, [Pid], "testn").
ok
5> alcove:stdout(Drv, [Pid]).
[<<"testn">>]
Specs
stdout(alcove_drv:ref(), [pid_t()], timeout()) -> [binary()].
Specs
symlink(alcove_drv:ref(), [pid_t()], OldPath :: iodata(), NewPath :: iodata()) -> ok | {error, posix()}.
symlink(2): create a symbolic link
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:symlink(Drv, [], "/etc/hosts", "/tmp/hosts.tmp").
ok
Specs
symlink(alcove_drv:ref(), [pid_t()], OldPath :: iodata(), NewPath :: iodata(), timeout()) -> ok | {error, posix()}.
symlink(2): create a symbolic link
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:symlink(Drv, [], "/etc/hosts", "/tmp/hosts.tmp").
ok
Specs
syscall_constant(alcove_drv:ref(), [pid_t()], Symbol :: atom()) -> unknown | non_neg_integer().
Convert syscall name to integer
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:syscall_constant(Drv, [], 'SYS_exit').
60
3> alcove:syscall_constant(Drv, [], sys_exit).
60
Specs
syscall_constant(alcove_drv:ref(), [pid_t()], Symbol :: atom(), timeout()) -> unknown | non_neg_integer().
Convert syscall name to integer
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:syscall_constant(Drv, [], 'SYS_exit').
60
3> alcove:syscall_constant(Drv, [], sys_exit).
60
Specs
umount(alcove_drv:ref(), [pid_t()], Path :: iodata()) -> ok | {error, posix()}.
umount(2): unmount a filesystem
On BSD systems, calls unmount(2).
Examples
An example of bind mounting a directory within a linux mount namespace:
1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
{ok,<0.177.0>}
2> {ok, Pid} = alcove:clone(Drv, [], [clone_newns]).
{ok,10059}
3> alcove:mount(Drv, [Pid], "/tmp", "/mnt", "", [ms_bind, ms_rdonly, ms_noexec], "", "").
ok
4> alcove:umount(Drv, [Pid], "/mnt").
ok
Specs
umount(alcove_drv:ref(), [pid_t()], Path :: iodata(), timeout()) -> ok | {error, posix()}.
umount(2): unmount a filesystem
On BSD systems, calls unmount(2).
Examples
An example of bind mounting a directory within a linux mount namespace:
1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
{ok,<0.177.0>}
2> {ok, Pid} = alcove:clone(Drv, [], [clone_newns]).
{ok,10059}
3> alcove:mount(Drv, [Pid], "/tmp", "/mnt", "", [ms_bind, ms_rdonly, ms_noexec], "", "").
ok
4> alcove:umount(Drv, [Pid], "/mnt").
ok
Specs
umount2(alcove_drv:ref(), [pid_t()], Path :: iodata(), Flags :: int32_t() | [constant()]) -> ok | {error, posix()}.
umount2(2): unmount filesystem with flags
Support
* Linux
Examples
An example of bind mounting a directory within a linux mount namespace:
1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
{ok,<0.177.0>}
2> {ok, Pid} = alcove:clone(Drv, [], [clone_newns]).
{ok,10059}
3> alcove:mount(Drv, [Pid], "/tmp", "/mnt", "", [ms_bind, ms_rdonly, ms_noexec], "", "").
ok
4> alcove:umount2(Drv, [Pid], "/mnt", [mnt_detach]).
ok
Specs
umount2(alcove_drv:ref(), [pid_t()], Path :: iodata(), Flags :: int32_t() | [constant()], timeout()) -> ok | {error, posix()}.
umount2(2): unmount filesystem with flags
Support
* Linux
Examples
An example of bind mounting a directory within a linux mount namespace:
1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
{ok,<0.177.0>}
2> {ok, Pid} = alcove:clone(Drv, [], [clone_newns]).
{ok,10059}
3> alcove:mount(Drv, [Pid], "/tmp", "/mnt", "", [ms_bind, ms_rdonly, ms_noexec], "", "").
ok
4> alcove:umount2(Drv, [Pid], "/mnt", [mnt_detach]).
ok
Specs
unlink(alcove_drv:ref(), [pid_t()], Path :: iodata()) -> ok | {error, posix()}.
unlink(2): delete a name from the filesystem
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:open(Drv, [], "/tmp/alcove-open-test", [o_wronly,o_creat], 8#644).
{ok,6}
3> alcove:unlink(Drv, [], "/tmp/alcove-open-test").
ok
Specs
unlink(alcove_drv:ref(), [pid_t()], Path :: iodata(), timeout()) -> ok | {error, posix()}.
unlink(2): delete a name from the filesystem
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:open(Drv, [], "/tmp/alcove-open-test", [o_wronly,o_creat], 8#644).
{ok,6}
3> alcove:unlink(Drv, [], "/tmp/alcove-open-test").
ok
Specs
unsetenv(alcove_drv:ref(), [pid_t()], Name :: iodata()) -> ok | {error, posix()}.
unsetenv(3): remove an environment variable
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:setenv(Drv, [], "ALCOVE_TEST", "foo", 0).
ok
3> alcove:getenv(Drv, [], "ALCOVE_TEST").
<<"foo">>
4> alcove:unsetenv(Drv, [], "ALCOVE_TEST").
ok
5> alcove:getenv(Drv, [], "ALCOVE_TEST").
false
Specs
unsetenv(alcove_drv:ref(), [pid_t()], Name :: iodata(), timeout()) -> ok | {error, posix()}.
unsetenv(3): remove an environment variable
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:setenv(Drv, [], "ALCOVE_TEST", "foo", 0).
ok
3> alcove:getenv(Drv, [], "ALCOVE_TEST").
<<"foo">>
4> alcove:unsetenv(Drv, [], "ALCOVE_TEST").
ok
5> alcove:getenv(Drv, [], "ALCOVE_TEST").
false
Specs
unveil(alcove_drv:ref(), [pid_t()], Path :: iodata(), Permissions :: iodata()) -> ok | {error, posix()}.
unveil(2): restrict filesystem view
To disable unveil calls, use an empty list ([]) or, equivalently, an empty string ("").
alcove:unveil(Drv, [Task], <<"/etc">>, <<"r">>),
alcove:unveil(Drv, [Task], [], []).
Support
* OpenBSD
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,28978}
3> alcove:unveil(Drv, [Pid], <<"/etc">>, <<"r">>).
ok
4> alcove:unveil(Drv, [Task], [], []).
ok
Specs
unveil(alcove_drv:ref(), [pid_t()], Path :: iodata(), Permissions :: iodata(), timeout()) -> ok | {error, posix()}.
unveil(2): restrict filesystem view
To disable unveil calls, use an empty list ([]) or, equivalently, an empty string ("").
alcove:unveil(Drv, [Task], <<"/etc">>, <<"r">>),
alcove:unveil(Drv, [Task], [], []).
Support
* OpenBSD
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,28978}
3> alcove:unveil(Drv, [Pid], <<"/etc">>, <<"r">>).
ok
4> alcove:unveil(Drv, [Task], [], []).
ok
Specs
version(alcove_drv:ref(), [pid_t()]) -> binary().
Retrieve the alcove version
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:version(Drv, []).
<<"0.37.0">>
Specs
version(alcove_drv:ref(), [pid_t()], timeout()) -> binary().
Retrieve the alcove version
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:version(Drv, []).
<<"0.37.0">>
Specs
waitpid(alcove_drv:ref(), [pid_t()], OSPid :: pid_t(), Options :: int32_t() | [constant()]) -> {ok, pid_t(), WaitStatus :: [waitstatus()]} | {error, posix()}.
waitpid(2): wait for process to change state
Process state changes are handled by the alcove SIGCHLD event handler by default. To use waitpid/4,5, disable the signal handler:
alcove:sigaction(Drv, [Pid], sigchld, sig_info)
Note: if the default SIGCHLD handler is disabled, waitpid/4,5 should be called to reap zombie processes:
alcove:waitpid(Drv, [], -1, [wnohang])
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,28978}
3> alcove:sigaction(Drv, [Pid], sigchld, sig_info).
{ok,sig_dfl}
4> alcove:execvp(Drv, [Pid], "sleep", ["sleep", "20"]).
ok
5> alcove:waitpid(Drv, [], -1, []).
{ok,28978,0,[{exit_status,0}]}
Specs
waitpid(alcove_drv:ref(), [pid_t()], OSPid :: pid_t(), Options :: int32_t() | [constant()], timeout()) -> {ok, pid_t(), WaitStatus :: [waitstatus()]} | {error, posix()}.
waitpid(2): wait for process to change state
Process state changes are handled by the alcove SIGCHLD event handler by default. To use waitpid/4,5, disable the signal handler:
alcove:sigaction(Drv, [Pid], sigchld, sig_info)
Note: if the default SIGCHLD handler is disabled, waitpid/4,5 should be called to reap zombie processes:
alcove:waitpid(Drv, [], -1, [wnohang])
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> {ok, Pid} = alcove:fork(Drv, []).
{ok,28978}
3> alcove:sigaction(Drv, [Pid], sigchld, sig_info).
{ok,sig_dfl}
4> alcove:execvp(Drv, [Pid], "sleep", ["sleep", "20"]).
ok
5> alcove:waitpid(Drv, [], -1, []).
{ok,28978,0,[{exit_status,0}]}
Specs
write(alcove_drv:ref(), [pid_t()], FD :: fd(), Buf :: iodata()) -> {ok, Count :: ssize_t()} | {error, posix()}.
write(2): write to a file descriptor
Writes a buffer to a file descriptor and returns the number of bytes written.
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> {ok, FD} = alcove:open(Drv, [], "/tmp/alcove-write-test", [o_wronly,o_creat], 8#644).
{ok,6}
3> alcove:write(Drv, [], FD, <<"test">>).
{ok,4}
Specs
write(alcove_drv:ref(), [pid_t()], FD :: fd(), Buf :: iodata(), timeout()) -> {ok, Count :: ssize_t()} | {error, posix()}.
write(2): write to a file descriptor
Writes a buffer to a file descriptor and returns the number of bytes written.
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> {ok, FD} = alcove:open(Drv, [], "/tmp/alcove-write-test", [o_wronly,o_creat], 8#644).
{ok,6}
3> alcove:write(Drv, [], FD, <<"test">>).
{ok,4}