View Source alcove (alcove v0.40.6)
Link to this section Summary
Functions
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
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
umount2(2): unmount filesystem with flags
umount2(2): unmount filesystem with flags
umount(2): unmount a filesystem
umount(2): unmount a filesystem
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
-type alcove_pid() :: #alcove_pid{}.
-type alcove_pid_field() :: pid | flowcontrol | signaloneof | fdctl | stdin | stdout | stderr.
-type alcove_rlimit() :: #alcove_rlimit{}.
-type alcove_timeval() :: #alcove_timeval{}.
-type constant() :: atom() | integer().
-type cstruct() :: [binary() | {ptr, binary() | non_neg_integer()}, ...].
-type fd() :: int32_t().
-type fd_set() :: [fd()].
-type filter() :: alcove_proto:calls() | [] | {deny, alcove_proto:calls() | []} | {allow, alcove_proto:calls() | []}.
-type gid_t() :: uint32_t().
-type int8_t() :: -127..127.
-type int16_t() :: -32767..32767.
-type int32_t() :: -2147483647..2147483647.
-type int64_t() :: -9223372036854775807..9223372036854775807.
-type mode_t() :: uint32_t().
-type off_t() :: uint64_t().
-type pid_t() :: int32_t().
-type 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.
-type ptr_val() :: binary() | integer() | cstruct().
-type size_t() :: uint64_t().
-type ssize_t() :: int64_t().
-type uid_t() :: uint32_t().
-type uint8_t() :: 0..255.
-type uint16_t() :: 0..65535.
-type uint32_t() :: 0..4294967295.
-type uint64_t() :: 0..18446744073709551615.
-type waitstatus() :: {exit_status, int32_t()} | {termsig, atom()} | {stopsig, atom()} | continued.
Link to this section Functions
-spec audit_arch() -> atom().
Get seccomp system architecture
examples
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
-spec cap_constant(alcove_drv:ref(), [pid_t()], Symbol :: atom()) -> integer() | unknown.
Convert capsicum constants to integer
support
Support
• FreeBSD
examples
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.208.0>}
2> alcove:cap_constant(Drv, [], cap_fcntl_setfl).
16
-spec cap_constant(alcove_drv:ref(), [pid_t()], Symbol :: atom(), timeout()) -> integer() | unknown.
Convert capsicum constants to integer
support
Support
• FreeBSD
examples
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.208.0>}
2> alcove:cap_constant(Drv, [], cap_fcntl_setfl).
16
-spec cap_enter(alcove_drv:ref(), [pid_t()]) -> ok | {error, posix()}.
cap_enter(2): place process into capability mode
support
Support
• FreeBSD
examples
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
-spec cap_enter(alcove_drv:ref(), [pid_t()], timeout()) -> ok | {error, posix()}.
cap_enter(2): place process into capability mode
support
Support
• FreeBSD
examples
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
-spec 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
Support
• FreeBSD
examples
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}
-spec 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
Support
• FreeBSD
examples
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}
-spec 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
Support
• FreeBSD
examples
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}
-spec 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
Support
• FreeBSD
examples
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}
-spec cap_getmode(alcove_drv:ref(), [pid_t()]) -> {ok, 0 | 1} | {error, posix()}.
cap_getmode(2): check if capability mode is enabled
• 0
: false
• 1
: true
support
Support
• FreeBSD
examples
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}
-spec cap_getmode(alcove_drv:ref(), [pid_t()], timeout()) -> {ok, 0 | 1} | {error, posix()}.
cap_getmode(2): check if capability mode is enabled
• 0
: false
• 1
: true
support
Support
• FreeBSD
examples
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}
-spec cap_ioctls_limit(alcove_drv:ref(), [pid_t()], FD :: fd(), Rights :: constant()) -> ok | {error, posix()}.
cap_ioctls_limit(2): manage allowed ioctl commands
support
Support
• FreeBSD
examples
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], "/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,<<>>}
-spec 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
Support
• FreeBSD
examples
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], "/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,<<>>}
-spec cap_rights_limit(alcove_drv:ref(), [pid_t()], FD :: fd(), Rights :: constant()) -> ok | {error, posix()}.
cap_rights_limit(2): manage process capabilities
support
Support
• FreeBSD
examples
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}
-spec cap_rights_limit(alcove_drv:ref(), [pid_t()], FD :: fd(), Rights :: constant(), timeout()) -> ok | {error, posix()}.
cap_rights_limit(2): manage process capabilities
support
Support
• FreeBSD
examples
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}
-spec chdir(alcove_drv:ref(), [pid_t()], Path :: iodata()) -> ok | {error, posix()}.
chdir(2): change process current working directory
examples
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,<<"/">>}
-spec chdir(alcove_drv:ref(), [pid_t()], Path :: iodata(), timeout()) -> ok | {error, posix()}.
chdir(2): change process current working directory
examples
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,<<"/">>}
-spec chmod(alcove_drv:ref(), [pid_t()], Path :: iodata(), Mode :: mode_t()) -> ok | {error, posix()}.
chmod(2): change file permissions
examples
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
-spec chmod(alcove_drv:ref(), [pid_t()], Path :: iodata(), Mode :: mode_t(), timeout()) -> ok | {error, posix()}.
chmod(2): change file permissions
examples
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
-spec chown(alcove_drv:ref(), [pid_t()], Path :: iodata(), Owner :: uid_t(), Group :: gid_t()) -> ok | {error, posix()}.
chown(2): change file ownership
examples
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
-spec chown(alcove_drv:ref(), [pid_t()], Path :: iodata(), Owner :: uid_t(), Group :: gid_t(), timeout()) -> ok | {error, posix()}.
chown(2): change file ownership
examples
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
-spec chroot(alcove_drv:ref(), [pid_t()], Path :: iodata()) -> ok | {error, posix()}.
chroot(2): change root directory
examples
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,<<"/">>}
-spec chroot(alcove_drv:ref(), [pid_t()], Path :: iodata(), timeout()) -> ok | {error, posix()}.
chroot(2): change root directory
examples
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,<<"/">>}
-spec clearenv(alcove_drv:ref(), [pid_t()]) -> ok | {error, posix()}.
clearenv(3): zero process environment
examples
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]).
[]
-spec clearenv(alcove_drv:ref(), [pid_t()], timeout()) -> ok | {error, posix()}.
clearenv(3): zero process environment
examples
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]).
[]
-spec clone(alcove_drv:ref(), [pid_t()], Flags :: int32_t() | [constant()]) -> {ok, pid_t()} | {error, posix()}.
clone(2): create a new process
support
Support
• Linux
examples
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
-spec clone(alcove_drv:ref(), [pid_t()], Flags :: int32_t() | [constant()], timeout()) -> {ok, pid_t()} | {error, posix()}.
clone(2): create a new process
support
Support
• Linux
examples
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
-spec clone_constant(alcove_drv:ref(), [pid_t()], Symbol :: atom()) -> unknown | int32_t().
Map clone(2) symbols to integer constants
support
Support
• Linux
examples
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
-spec clone_constant(alcove_drv:ref(), [pid_t()], Symbol :: atom(), timeout()) -> unknown | int32_t().
Map clone(2) symbols to integer constants
support
Support
• Linux
examples
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
-spec close(alcove_drv:ref(), [pid_t()], FD :: fd()) -> ok | {error, posix()}.
close(2): close a file descriptor
examples
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
-spec close(alcove_drv:ref(), [pid_t()], FD :: fd(), timeout()) -> ok | {error, posix()}.
close(2): close a file descriptor
examples
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
-spec connect(alcove_drv:ref(), [pid_t()], FD :: fd(), Sockaddr :: [] | cstruct()) -> ok | {error, posix()}.
connect(2): initiate a connection on a socket
examples
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.
-spec connect(alcove_drv:ref(), [pid_t()], FD :: fd(), Sockaddr :: [] | cstruct(), timeout()) -> ok | {error, posix()}.
connect(2): initiate a connection on a socket
examples
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.
-spec cpid(alcove_drv:ref(), [pid_t()]) -> [alcove_pid()].
Returns the list of child PIDs for this process
examples
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}]
-spec cpid(alcove_drv:ref(), [pid_t()], timeout()) -> [alcove_pid()].
Returns the list of child PIDs for this process
examples
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}]
-spec define(alcove_drv:ref(), [pid_t()], atom() | [atom()]) -> integer().
Convert constant to integer
examples
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.176.0>}
2> alcove:define(Drv, [], clone_newns).
131072
-spec environ(alcove_drv:ref(), [pid_t()]) -> [binary()].
environ(7): return the process environment variables
examples
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">>]
-spec environ(alcove_drv:ref(), [pid_t()], timeout()) -> [binary()].
environ(7): return the process environment variables
examples
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">>]
-spec eof(alcove_drv:ref(), [pid_t()]) -> ok | {error, posix()}.
Close stdin of the process
examples
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}
-spec eof(alcove_drv:ref(), [pid_t()], stdin | stdout | stderr) -> ok | {error, posix()}.
Close stdin, stdout or stderr of the process
examples
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}
-spec errno_id(alcove_drv:ref(), [pid_t()], Errno :: int32_t()) -> posix().
Convert errno integer to atom
examples
Examples
1> alcove:errno_id(Drv, [], 1).
eperm
-spec errno_id(alcove_drv:ref(), [pid_t()], Errno :: int32_t(), timeout()) -> posix().
Convert errno integer to atom
examples
Examples
1> alcove:errno_id(Drv, [], 1).
eperm
-spec 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,...>>}
-spec 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
-spec 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
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
-spec 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
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
-spec 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
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
-spec 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
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
-spec exit(alcove_drv:ref(), [pid_t()], Status :: int32_t()) -> ok.
exit(3): cause an alcove control process to exit
examples
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
-spec exit(alcove_drv:ref(), [pid_t()], Status :: int32_t(), timeout()) -> ok.
exit(3): cause an alcove control process to exit
examples
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
-spec 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
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}
-spec 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
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}
-spec fcntl_constant(alcove_drv:ref(), [pid_t()], Symbol :: atom()) -> integer() | unknown.
Convert fnctl(2) constant to integer
examples
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.176.0>}
2> alcove:fcntl_constant(Drv, [], fd_cloexec).
1
-spec fcntl_constant(alcove_drv:ref(), [pid_t()], Symbol :: atom(), timeout()) -> integer() | unknown.
Convert fnctl(2) constant to integer
examples
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.176.0>}
2> alcove:fcntl_constant(Drv, [], fd_cloexec).
1
-spec 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
Support
• Linux
• FreeBSD
examples
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
-spec 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
Support
• Linux
• FreeBSD
examples
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
-spec file_constant(alcove_drv:ref(), [pid_t()], Symbol :: atom()) -> non_neg_integer() | unknown.
Constants for open(2)
examples
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:file_constant(Drv, [], o_rdonly).
0
-spec file_constant(alcove_drv:ref(), [pid_t()], Symbol :: atom(), timeout()) -> non_neg_integer() | unknown.
Constants for open(2)
examples
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:file_constant(Drv, [], o_rdonly).
0
-spec 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
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>>
-spec 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 binary (<<>>
) will not modify the current filter set.
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
-spec 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
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, getcwd
% 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, <<"/">>}
-spec 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
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, getcwd
% 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, <<"/">>}
-spec fork(alcove_drv:ref(), [pid_t()]) -> {ok, pid_t()} | {error, posix()}.
fork(2): create a new process
examples
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
-spec fork(alcove_drv:ref(), [pid_t()], timeout()) -> {ok, pid_t()} | {error, posix()}.
fork(2): create a new process
examples
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
-spec 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
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
-spec getcwd(alcove_drv:ref(), [pid_t()]) -> {ok, binary()} | {error, posix()}.
getcwd(3): return the current working directory
examples
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,<<"/">>}
-spec getcwd(alcove_drv:ref(), [pid_t()], timeout()) -> {ok, binary()} | {error, posix()}.
getcwd(3): return the current working directory
examples
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,<<"/">>}
-spec getenv(alcove_drv:ref(), [pid_t()], Name :: iodata()) -> binary() | false.
getenv(3): retrieve an environment variable
examples
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:getenv(Drv, [], "TERM").
<<"screen">>
-spec getenv(alcove_drv:ref(), [pid_t()], Name :: iodata(), timeout()) -> binary() | false.
getenv(3): retrieve an environment variable
examples
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:getenv(Drv, [], "TERM").
<<"screen">>
-spec getgid(alcove_drv:ref(), [pid_t()]) -> gid_t().
getgid(2): retrieve the process group ID
examples
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:getgid(Drv, []).
1000
-spec getgid(alcove_drv:ref(), [pid_t()], timeout()) -> gid_t().
getgid(2): retrieve the process group ID
examples
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:getgid(Drv, []).
1000
-spec getgroups(alcove_drv:ref(), [pid_t()]) -> {ok, [gid_t()]} | {error, posix()}.
getgroups(2): retrieve the list of supplementary groups
examples
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:getgroups(Drv, []).
{ok,[24,20,1000]}
-spec getgroups(alcove_drv:ref(), [pid_t()], timeout()) -> {ok, [gid_t()]} | {error, posix()}.
getgroups(2): retrieve the list of supplementary groups
examples
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:getgroups(Drv, []).
{ok,[24,20,1000]}
-spec gethostname(alcove_drv:ref(), [pid_t()]) -> {ok, binary()} | {error, posix()}.
gethostname(2): retrieve the system hostname
examples
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:gethostname(Drv, []).
{ok,<<"host1">>}
-spec gethostname(alcove_drv:ref(), [pid_t()], timeout()) -> {ok, binary()} | {error, posix()}.
gethostname(2): retrieve the system hostname
examples
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:gethostname(Drv, []).
{ok,<<"host1">>}
-spec 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() : 64
Number of child processes allowed for this control process. The value can be modified using setopt/4,5. Additionally, reducing RLIMIT_NOFILE for the process may result in a reduced maxchild value.
• 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
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:getopt(Drv, [], maxforkdepth).
16
-spec 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() : 64
Number of child processes allowed for this control process. The value can be modified using setopt/4,5. Additionally, reducing RLIMIT_NOFILE for the process may result in a reduced maxchild value.
• 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
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:getopt(Drv, [], maxforkdepth).
16
-spec getpgrp(alcove_drv:ref(), [pid_t()]) -> pid_t().
getpgrp(2): retrieve the process group
examples
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:getpgrp(Drv, []).
3924
-spec getpgrp(alcove_drv:ref(), [pid_t()], timeout()) -> pid_t().
getpgrp(2): retrieve the process group
examples
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:getpgrp(Drv, []).
3924
-spec getpid(alcove_drv:ref(), [pid_t()]) -> pid_t().
getpid(2): retrieve the system PID of the process
examples
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:getpid(Drv, []).
3924
-spec getpid(alcove_drv:ref(), [pid_t()], timeout()) -> pid_t().
getpid(2): retrieve the system PID of the process
examples
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:getpid(Drv, []).
3924
-spec 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
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:getpriority(Drv, [], prio_process, 0).
{ok,0}
-spec 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
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:getpriority(Drv, [], prio_process, 0).
{ok,0}
-spec 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
Support
• Linux
• OpenBSD
• FreeBSD
examples
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:getresgid(Drv, []).
{ok,1000,1000,1000}
-spec 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
Support
• Linux
• OpenBSD
• FreeBSD
examples
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:getresgid(Drv, []).
{ok,1000,1000,1000}
-spec 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
Support
• Linux
• OpenBSD
• FreeBSD
examples
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:getresuid(Drv, []).
{ok,1000,1000,1000}
-spec 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
Support
• Linux
• OpenBSD
• FreeBSD
examples
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:getresuid(Drv, []).
{ok,1000,1000,1000}
-spec 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
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}}
-spec 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
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}}
-spec getsid(alcove_drv:ref(), [pid_t()], OSPid :: pid_t()) -> {ok, pid_t()} | {error, posix()}.
getsid(2): retrieve the session ID
examples
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:getsid(Drv, [], 0).
{ok,3924}
-spec getsid(alcove_drv:ref(), [pid_t()], OSPid :: pid_t(), timeout()) -> {ok, pid_t()} | {error, posix()}.
getsid(2): retrieve the session ID
examples
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:getsid(Drv, [], 0).
{ok,3924}
-spec getuid(alcove_drv:ref(), [pid_t()]) -> uid_t().
getuid(2): returns the process user ID
examples
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:getuid(Drv, []).
1000
-spec getuid(alcove_drv:ref(), [pid_t()], timeout()) -> uid_t().
getuid(2): returns the process user ID
examples
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:getuid(Drv, []).
1000
-spec 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
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,...>>}
-spec 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
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,...>>}
-spec ioctl_constant(alcove_drv:ref(), [pid_t()], Symbol :: atom()) -> integer() | unknown.
Convert ioctl constant to integer
examples
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:ioctl_constant(Drv, [], siocgifaddr).
35093
-spec ioctl_constant(alcove_drv:ref(), [pid_t()], Symbol :: atom(), timeout()) -> integer() | unknown.
Convert ioctl constant to integer
examples
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:ioctl_constant(Drv, [], siocgifaddr).
35093
-spec jail(alcove_drv:ref(), [pid_t()], Jail :: cstruct()) -> {ok, int32_t()} | {error, posix()}.
jail(2): restrict the current process in a system jail
support
Support
• FreeBSD
examples
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">>}
-spec jail(alcove_drv:ref(), [pid_t()], Jail :: cstruct(), timeout()) -> {ok, int32_t()} | {error, posix()}.
jail(2): restrict the current process in a system jail
support
Support
• FreeBSD
examples
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">>}
-spec jail_attach(alcove_drv:ref(), [pid_t()], JID :: int32_t()) -> ok | {error, posix()}.
jail_attach(2): join a jailed process
support
Support
• FreeBSD
examples
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
-spec jail_attach(alcove_drv:ref(), [pid_t()], JID :: int32_t(), timeout()) -> ok | {error, posix()}.
jail_attach(2): join a jailed process
support
Support
• FreeBSD
examples
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
-spec jail_remove(alcove_drv:ref(), [pid_t()], JID :: int32_t()) -> ok | {error, posix()}.
jail_remove(2): destroy a jailed process
support
Support
• FreeBSD
examples
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
-spec jail_remove(alcove_drv:ref(), [pid_t()], JID :: int32_t(), timeout()) -> ok | {error, posix()}.
jail_remove(2): destroy a jailed process
support
Support
• FreeBSD
examples
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
-spec kill(alcove_drv:ref(), [pid_t()], OSPid :: pid_t(), Signal :: constant()) -> ok | {error, posix()}.
kill(2): terminate a process
examples
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}}
-spec kill(alcove_drv:ref(), [pid_t()], OSPID :: pid_t(), Signal :: constant(), timeout()) -> ok | {error, posix()}.
kill(2): terminate a process
examples
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}}
-spec link(alcove_drv:ref(), [pid_t()], OldPath :: iodata(), NewPath :: iodata()) -> ok | {error, posix()}.
link(2) : create a hard link
examples
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
-spec link(alcove_drv:ref(), [pid_t()], OldPath :: iodata(), NewPath :: iodata(), timeout()) -> ok | {error, posix()}.
link(2) : create a hard link
examples
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
-spec 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
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
-spec 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
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
-spec mkdir(alcove_drv:ref(), [pid_t()], Path :: iodata(), Mode :: mode_t()) -> ok | {error, posix()}.
mkdir(2): create a directory
examples
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:mkdir(Drv, [], "/tmp/alcove-mkdir-test", 8#755).
ok
-spec mkdir(alcove_drv:ref(), [pid_t()], Path :: iodata(), Mode :: mode_t(), timeout()) -> ok | {error, posix()}.
mkdir(2): create a directory
examples
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:mkdir(Drv, [], "/tmp/alcove-mkdir-test", 8#755).
ok
-spec mkfifo(alcove_drv:ref(), [pid_t()], Path :: iodata(), Mode :: mode_t()) -> ok | {error, posix()}.
mkfifo(3): make named pipe file
examples
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:mkfifo(Drv, [], "/tmp/alcove-fifo-test", 8#700).
ok
-spec mkfifo(alcove_drv:ref(), [pid_t()], Path :: iodata(), Mode :: mode_t(), timeout()) -> ok | {error, posix()}.
mkfifo(3): make named pipe file
examples
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:mkfifo(Drv, [], "/tmp/alcove-fifo-test", 8#700).
ok
-spec 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
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 Source-spec 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
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
-spec 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
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:mount_constant(Drv, [], rdonly).
1
-spec 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
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:mount_constant(Drv, [], rdonly).
1
-spec 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
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}
-spec 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
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}
-spec 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.
To use an arbitrary directory as a mount point:
• mark the mount namespace as private
• create a mount point by bind mounting the new root directory over itself
• change the current working directory to the new root directory
• call pivot_root(2) with new and old root set to the current working directory
• unmount the current working directory
support
Support
• Linux
examples
Examples
1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
{ok,<0.198.0>}
2> alcove:mkdir(Drv, [], "/tmp/alcove-root", 8#755).
ok
3> {ok, Pid} = alcove:clone(Drv, [], [clone_newns]).
{ok,29739}
4> alcove:mount(Drv, [Pid], "none", "/", [], [ms_rec, ms_private], [], []).
ok
5> alcove:mount(Drv, [Pid], "/tmp/alcove-root", "/tmp/alcove-root", [], [ms_bind], [], []).
ok
6> alcove:chdir(Drv, [Pid], "/tmp/alcove-root").
ok
7> alcove:pivot_root(Drv, [Pid], ".", ".").
ok
8> alcove:umount2(Drv, [Pid], ".", [mnt_detach]).
ok
-spec 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.
To use an arbitrary directory as a mount point:
• mark the mount namespace as private
• create a mount point by bind mounting the new root directory over itself
• change the current working directory to the new root directory
• call pivot_root(2) with new and old root set to the current working directory
• unmount the current working directory
support
Support
• Linux
examples
Examples
1> {ok, Drv} = alcove_drv:start([{exec, "sudo -n"}]).
{ok,<0.198.0>}
2> alcove:mkdir(Drv, [], "/tmp/alcove-root", 8#755).
ok
3> {ok, Pid} = alcove:clone(Drv, [], [clone_newns]).
{ok,29739}
4> alcove:mount(Drv, [Pid], "none", "/", [], [ms_rec, ms_private], [], []).
ok
5> alcove:mount(Drv, [Pid], "/tmp/alcove-root", "/tmp/alcove-root", [], [ms_bind], [], []).
ok
6> alcove:chdir(Drv, [Pid], "/tmp/alcove-root").
ok
7> alcove:pivot_root(Drv, [Pid], ".", ".").
ok
8> alcove:umount2(Drv, [Pid], ".", [mnt_detach]).
ok
-spec 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
Support
• OpenBSD
examples
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
-spec 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
Support
• OpenBSD
examples
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
-spec 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
Support
• Linux
examples
Examples
To enforce a seccomp filter:
-module(seccomp).
-include_lib("alcove/include/alcove_seccomp.hrl").
-export([run/2, run/3, filter/3]).
-define(DENY_SYSCALL(Syscall), [
?BPF_JUMP(?BPF_JMP + ?BPF_JEQ + ?BPF_K, (Syscall), 0, 1),
?BPF_STMT(?BPF_RET + ?BPF_K, ?SECCOMP_RET_KILL)
]).
filter(Drv, Pid, Syscall) ->
Arch = alcove:define(Drv, Pid, alcove:audit_arch()),
NR = alcove:syscall_constant(Drv, Pid, syscall_constant, Syscall),
[
?VALIDATE_ARCHITECTURE(Arch),
?EXAMINE_SYSCALL,
?DENY_SYSCALL(NR),
?BPF_STMT(?BPF_RET + ?BPF_K, ?SECCOMP_RET_ALLOW)
].
run(Drv, Pid) ->
run(Drv, Pid, sys_getcwd).
run(Drv, Pid, Syscall) ->
Filter = filter(Drv, Pid, Syscall),
{ok, _, _, _, _, _} = alcove:prctl(Drv, Pid, 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, Pid, seccomp_set_mode_filter, 0, Prog)
alcove:prctl(Drv, Pid, pr_set_seccomp, seccomp_mode_filter, Prog, 0, 0).
See also: seccomp/5.
-spec 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
Support
• Linux
examples
Examples
To enforce a seccomp filter:
-module(seccomp).
-include_lib("alcove/include/alcove_seccomp.hrl").
-export([run/2, run/3, filter/3]).
-define(DENY_SYSCALL(Syscall), [
?BPF_JUMP(?BPF_JMP + ?BPF_JEQ + ?BPF_K, (Syscall), 0, 1),
?BPF_STMT(?BPF_RET + ?BPF_K, ?SECCOMP_RET_KILL)
]).
filter(Drv, Pid, Syscall) ->
Arch = alcove:define(Drv, Pid, alcove:audit_arch()),
NR = alcove:syscall_constant(Drv, Pid, syscall_constant, Syscall),
[
?VALIDATE_ARCHITECTURE(Arch),
?EXAMINE_SYSCALL,
?DENY_SYSCALL(NR),
?BPF_STMT(?BPF_RET + ?BPF_K, ?SECCOMP_RET_ALLOW)
].
run(Drv, Pid) ->
run(Drv, Pid, sys_getcwd).
run(Drv, Pid, Syscall) ->
Filter = filter(Drv, Pid, Syscall),
{ok, _, _, _, _, _} = alcove:prctl(Drv, Pid, 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, Pid, seccomp_set_mode_filter, 0, Prog)
alcove:prctl(Drv, Pid, pr_set_seccomp, seccomp_mode_filter, Prog, 0, 0).
See also: seccomp/5.
-spec prctl_constant(alcove_drv:ref(), [pid_t()], Symbol :: atom()) -> unknown | non_neg_integer().
Convert prctl option names to integers
examples
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:prctl_constant(Drv, [], pr_set_name).
15
-spec prctl_constant(alcove_drv:ref(), [pid_t()], Symbol :: atom(), timeout()) -> unknown | non_neg_integer().
Convert prctl option names to integers
examples
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:prctl_constant(Drv, [], pr_set_name).
15
-spec 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
Support
• FreeBSD
examples
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">>]}
-spec 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
Support
• FreeBSD
examples
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">>]}
-spec 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
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,
[]
).
-spec 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
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,
[]
).
-spec ptrace_constant(alcove_drv:ref(), [pid_t()], Symbol :: atom()) -> unknown | integer().
Convert ptrace constant to integer
examples
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:ptrace_constant(Drv, [], ptrace_traceme).
0
-spec ptrace_constant(alcove_drv:ref(), [pid_t()], Symbol :: atom(), timeout()) -> unknown | integer().
Convert ptrace constant to integer
examples
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:ptrace_constant(Drv, [], ptrace_traceme).
0
-spec read(alcove_drv:ref(), [pid_t()], FD :: fd(), Count :: size_t()) -> {ok, binary()} | {error, posix()}.
read(2): read bytes from a file descriptor
examples
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">>}
-spec 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
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">>}
-spec readdir(alcove_drv:ref(), [pid_t()], Path :: iodata()) -> {ok, [binary()]} | {error, posix()}.
readdir(3): retrieve list of objects in a directory
examples
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">>,<<...>>|...]}
-spec readdir(alcove_drv:ref(), [pid_t()], Path :: iodata(), timeout()) -> {ok, [binary()]} | {error, posix()}.
readdir(3): retrieve list of objects in a directory
examples
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">>,<<...>>|...]}
-spec rlimit_constant(alcove_drv:ref(), [pid_t()], Symbol :: atom()) -> unknown | non_neg_integer().
Convert an RLIMIT_* flag to an integer
examples
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:rlimit_constant(Drv, [], rlimit_nofile).
7
-spec rlimit_constant(alcove_drv:ref(), [pid_t()], Symbol :: atom(), timeout()) -> unknown | non_neg_integer().
Convert an RLIMIT_* flag to an integer
examples
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:rlimit_constant(Drv, [], rlimit_nofile).
7
-spec rmdir(alcove_drv:ref(), [pid_t()], Path :: iodata()) -> ok | {error, posix()}.
rmdir(2): delete a directory
examples
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
-spec rmdir(alcove_drv:ref(), [pid_t()], Path :: iodata(), timeout()) -> ok | {error, posix()}.
rmdir(2): delete a directory
examples
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
-spec seccomp(alcove_drv:ref(), [pid_t()], Operation :: constant(), Flags :: constant(), Prog :: cstruct()) -> ok | {error, posix()}.
seccomp(2): restrict system operations
support
Support
• Linux
examples
Examples
''' %% Equivalent to: %% alcove:prctl(Drv, Pid, pr_set_seccomp, seccomp_mode_filter, Prog, 0, 0) alcove:seccomp(Drv, Pid, seccomp_set_mode_filter, 0, Prog) '''See also: prctl/7.
-spec seccomp(alcove_drv:ref(), [pid_t()], Operation :: constant(), Flags :: constant(), Prog :: cstruct(), timeout()) -> ok | {error, posix()}.
seccomp(2): restrict system operations
support
Support
• Linux
examples
Examples
''' %% Equivalent to: %% alcove:prctl(Drv, Pid, pr_set_seccomp, seccomp_mode_filter, Prog, 0, 0) alcove:seccomp(Drv, Pid, seccomp_set_mode_filter, 0, Prog) '''See also: prctl/7.
-spec seccomp_constant(alcove_drv:ref(), [pid_t()], Symbol :: atom()) -> unknown | non_neg_integer().
Convert seccomp option name to integer
examples
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:seccomp_constant(Drv, [], seccomp_set_mode_strict).
0
-spec seccomp_constant(alcove_drv:ref(), [pid_t()], Symbol :: atom(), timeout()) -> unknown | non_neg_integer().
Convert seccomp option name to integer
examples
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:seccomp_constant(Drv, [], seccomp_set_mode_strict).
0
-spec select(alcove_drv:ref(), [pid_t()], Readfds :: fd_set(), Writefds :: fd_set(), Exceptfds :: fd_set(), Timeval :: [] | 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:
• an empty list ([]): causes select to block indefinitely (no timeout)
• an alcove_timeval record
An alcove_timeval record contains these fields:
• sec : number of seconds to wait
• usec : number of microseconds to wait
examples
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],[]}
-spec select(alcove_drv:ref(), [pid_t()], Readfds :: fd_set(), Writefds :: fd_set(), Exceptfds :: fd_set(), Timeval :: [] | 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:
• an empty list ([]): causes select to block indefinitely (no timeout)
• an alcove_timeval record
An alcove_timeval record contains these fields:
• sec : number of seconds to wait
• usec : number of microseconds to wait
examples
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],[]}
-spec 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
enables 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
delivers a signal to any subprocesses when the alcove control process shuts down (default: 15 (SIGTERM))
examples
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
-spec 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
enables 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
delivers a signal to any subprocesses when the alcove control process shuts down (default: 15 (SIGTERM))
examples
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
-spec setenv(alcove_drv:ref(), [pid_t()], Name :: iodata(), Value :: iodata(), Overwrite :: int32_t()) -> ok | {error, posix()}.
setenv(3): set an environment variable
examples
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">>
-spec setenv(alcove_drv:ref(), [pid_t()], Name :: iodata(), Value :: iodata(), Overwrite :: int32_t(), timeout()) -> ok | {error, posix()}.
setenv(3): set an environment variable
examples
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">>
-spec setgid(alcove_drv:ref(), [pid_t()], Gid :: gid_t()) -> ok | {error, posix()}.
setgid(2): set the GID of the process
examples
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
-spec setgid(alcove_drv:ref(), [pid_t()], Gid :: gid_t(), timeout()) -> ok | {error, posix()}.
setgid(2): set the GID of the process
examples
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
-spec setgroups(alcove_drv:ref(), [pid_t()], Groups :: [gid_t()]) -> ok | {error, posix()}.
setgroups(2): set the supplementary groups of the process
examples
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,[]}
-spec setgroups(alcove_drv:ref(), [pid_t()], Groups :: [gid_t()], timeout()) -> ok | {error, posix()}.
setgroups(2): set the supplementary groups of the process
examples
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,[]}
-spec 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
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">>}
-spec 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
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">>}
-spec 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
Support
• Linux
examples
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).
-spec 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
Support
• Linux
examples
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).
-spec setopt(alcove_drv:ref(), [pid_t()], Opt :: atom(), Val :: int32_t()) -> boolean().
Set port options
examples
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:setopt(Drv, [], maxforkdepth, 128).
true
See also: getopt/3.
-spec setopt(alcove_drv:ref(), [pid_t()], Opt :: atom(), Val :: int32_t(), timeout()) -> boolean().
Set port options
examples
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:setopt(Drv, [], maxforkdepth, 128).
true
See also: getopt/3.
-spec setpgid(alcove_drv:ref(), [pid_t()], OSPid :: pid_t(), Pgid :: pid_t()) -> ok | {error, posix()}.
setpgid(2): set process group
examples
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
-spec setpgid(alcove_drv:ref(), [pid_t()], OSPid :: pid_t(), Pgid :: pid_t(), timeout()) -> ok | {error, posix()}.
setpgid(2): set process group
examples
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
-spec 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
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}
-spec 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
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}
-spec 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
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
-spec 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
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
-spec 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
Support
• Linux
• FreeBSD
• OpenBSD
examples
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
-spec 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
Support
• Linux
• FreeBSD
• OpenBSD
examples
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
-spec 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
Support
• Linux
• FreeBSD
• OpenBSD
examples
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
-spec 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
Support
• Linux
• FreeBSD
• OpenBSD
examples
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
-spec setrlimit(alcove_drv:ref(), [pid_t()], Resource :: constant(), Limit :: alcove_rlimit()) -> ok | {error, posix()}.
setrlimit(2): set a resource limit
Note on rlimit_nofile
:
The control process requires a fixed number of file descriptors for each subprocess. Reducing the number of file descriptors will reduce the limit on child processes.
If the file descriptor limit is below the number of file descriptors currently used, setrlimit/4,5 will return {error, einval}
.
examples
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}}
-spec setrlimit(alcove_drv:ref(), [pid_t()], Resource :: constant(), Limit :: alcove_rlimit(), timeout()) -> ok | {error, posix()}.
setrlimit(2): set a resource limit
Note on rlimit_nofile
:
The control process requires a fixed number of file descriptors for each subprocess. Reducing the number of file descriptors will reduce the limit on child processes.
If the file descriptor limit is below the number of file descriptors currently used, setrlimit/4,5 will return {error, einval}
.
examples
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}}
-spec setsid(alcove_drv:ref(), [pid_t()]) -> {ok, OSPid :: pid_t()} | {error, posix()}.
setsid(2): create a new session
examples
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}
-spec setsid(alcove_drv:ref(), [pid_t()], timeout()) -> {ok, OSPid :: pid_t()} | {error, posix()}.
setsid(2): create a new session
examples
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}
-spec setuid(alcove_drv:ref(), [pid_t()], User :: uid_t()) -> ok | {error, posix()}.
setuid(2): change UID
examples
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
See also: setresuid/5.
-spec setuid(alcove_drv:ref(), [pid_t()], User :: uid_t(), timeout()) -> ok | {error, posix()}.
setuid(2): change UID
examples
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
See also: setresuid/5.
-spec 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
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
-spec 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
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
-spec signal_constant(alcove_drv:ref(), [pid_t()], Symbol :: atom()) -> unknown | non_neg_integer().
Convert signal names to integers
examples
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:signal_constant(Drv, [], sighup).
1
-spec signal_constant(alcove_drv:ref(), [pid_t()], Symbol :: atom(), timeout()) -> unknown | non_neg_integer().
Convert signal names to integers
examples
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:signal_constant(Drv, [], sighup).
1
-spec 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
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
-spec 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
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
-spec stderr(alcove_drv:ref(), [pid_t()]) -> [binary()].
Read stderr from the process
examples
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">>]
-spec stderr(alcove_drv:ref(), [pid_t()], timeout()) -> [binary()].
-spec stdin(alcove_drv:ref(), [pid_t()], iodata()) -> ok.
Send data to stdin of the process
examples
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">>]
-spec stdout(alcove_drv:ref(), [pid_t()]) -> [binary()].
Read stdout from the process
examples
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">>]
-spec stdout(alcove_drv:ref(), [pid_t()], timeout()) -> [binary()].
-spec symlink(alcove_drv:ref(), [pid_t()], OldPath :: iodata(), NewPath :: iodata()) -> ok | {error, posix()}.
symlink(2): create a symbolic link
examples
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:symlink(Drv, [], "/etc/hosts", "/tmp/hosts.tmp").
ok
-spec symlink(alcove_drv:ref(), [pid_t()], OldPath :: iodata(), NewPath :: iodata(), timeout()) -> ok | {error, posix()}.
symlink(2): create a symbolic link
examples
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:symlink(Drv, [], "/etc/hosts", "/tmp/hosts.tmp").
ok
-spec syscall_constant(alcove_drv:ref(), [pid_t()], Symbol :: atom()) -> unknown | non_neg_integer().
Convert syscall name to integer
examples
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:syscall_constant(Drv, [], sys_exit).
60
-spec syscall_constant(alcove_drv:ref(), [pid_t()], Symbol :: atom(), timeout()) -> unknown | non_neg_integer().
Convert syscall name to integer
examples
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:syscall_constant(Drv, [], sys_exit).
60
-spec umount2(alcove_drv:ref(), [pid_t()], Path :: iodata(), Flags :: int32_t() | [constant()]) -> ok | {error, posix()}.
umount2(2): unmount filesystem with flags
support
Support
• Linux
examples
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
-spec umount2(alcove_drv:ref(), [pid_t()], Path :: iodata(), Flags :: int32_t() | [constant()], timeout()) -> ok | {error, posix()}.
umount2(2): unmount filesystem with flags
support
Support
• Linux
examples
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
-spec umount(alcove_drv:ref(), [pid_t()], Path :: iodata()) -> ok | {error, posix()}.
umount(2): unmount a filesystem
On BSD systems, calls unmount(2).
examples
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
-spec umount(alcove_drv:ref(), [pid_t()], Path :: iodata(), timeout()) -> ok | {error, posix()}.
umount(2): unmount a filesystem
On BSD systems, calls unmount(2).
examples
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
-spec unlink(alcove_drv:ref(), [pid_t()], Path :: iodata()) -> ok | {error, posix()}.
unlink(2): delete a name from the filesystem
examples
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
-spec unlink(alcove_drv:ref(), [pid_t()], Path :: iodata(), timeout()) -> ok | {error, posix()}.
unlink(2): delete a name from the filesystem
examples
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
-spec unsetenv(alcove_drv:ref(), [pid_t()], Name :: iodata()) -> ok | {error, posix()}.
unsetenv(3): remove an environment variable
examples
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
-spec unsetenv(alcove_drv:ref(), [pid_t()], Name :: iodata(), timeout()) -> ok | {error, posix()}.
unsetenv(3): remove an environment variable
examples
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
-spec 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
Support
• OpenBSD
examples
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, [Pid], [], []).
ok
5> alcove:readdir(Drv, [Pid], "/etc").
{ok,[<<".">>,<<"..">>,<<"acme">>,<<"amd">>,<<"authpf">>,
<<"daily">>,<<"disktab">>,<<"examples">>,<<"firmware">>,
<<"hotplug">>,<<"iked">>,<<"isakmpd">>,<<"ldap">>,
<<"magic">>,<<"mail">>,<<"moduli">>,<<"monthly">>,
<<"mtree">>,<<"netstart">>,<<"npppd">>,<<"pf.os">>,
<<"ppp">>,<<"protocols">>,<<"rc">>,<<"rc.conf">>,<<"rc.d">>,
<<...>>|...]}
6> alcove:readdir(Drv, [Pid], "/tmp").
{error,enoent}
-spec 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
Support
• OpenBSD
examples
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, [Pid], [], []).
ok
5> alcove:readdir(Drv, [Pid], "/etc").
{ok,[<<".">>,<<"..">>,<<"acme">>,<<"amd">>,<<"authpf">>,
<<"daily">>,<<"disktab">>,<<"examples">>,<<"firmware">>,
<<"hotplug">>,<<"iked">>,<<"isakmpd">>,<<"ldap">>,
<<"magic">>,<<"mail">>,<<"moduli">>,<<"monthly">>,
<<"mtree">>,<<"netstart">>,<<"npppd">>,<<"pf.os">>,
<<"ppp">>,<<"protocols">>,<<"rc">>,<<"rc.conf">>,<<"rc.d">>,
<<...>>|...]}
6> alcove:readdir(Drv, [Pid], "/tmp").
{error,enoent}
-spec version(alcove_drv:ref(), [pid_t()]) -> binary().
Retrieve the alcove version
examples
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:version(Drv, []).
<<"0.37.0">>
-spec version(alcove_drv:ref(), [pid_t()], timeout()) -> binary().
Retrieve the alcove version
examples
Examples
1> {ok, Drv} = alcove_drv:start().
{ok,<0.177.0>}
2> alcove:version(Drv, []).
<<"0.37.0">>
-spec 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
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}]}
-spec 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
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}]}
-spec 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
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}
-spec 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
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}