EMILUA(3em)
πΈ NAME πΈ
okay so welcome to the EMILUA(3em) manual page β part 1 of the Emilua reference, bestie π«Ά. This is Emilua, the Lua execution engine, and we're about to make the C API for init.script make sense. More parts follow, so buckle up β¨.
β¨ SYNOPSIS β¨
spawn_vm{ subprocess = { init = { script = init.script } } }
π DESCRIPTION π
This whole page is giving the C API exposed to init.script π.
π arg: integer|nil π
The file descriptor passed (if any) at the time the call to spawn_vm() was made as the parameter subprocess.init.arg. That's it β that's the arg πΈ.
π errexit: boolean = true π
We do not want to accidentally ignore errors from the C API exposed to init.script, okay? Thatβs why we borrow an idea from BASH π. One common folklore among BASH programmers is the unofficial strict mode. Among other things, this mode dictates the use of BASHβs set -o errexit.
And errexit exists for init.script as well. For init.script, errexit is just a global boolean. Every time the C API fails, the Emilua wrapper for the function will check its value. On errexit=true (the default when the script starts), the process will abort whenever some C API fails. Thatβs specially important when youβre using the API to drop process credentials/rights. Like, genuinely important β no cap π₯.
π₯οΈ THE CONTROLLING TERMINAL π₯οΈ
The Emilua runtime wonβt call setsid() nor setpgid() by itself, so the process will stay in the same session as its parent, and itβll have access to the same controlling terminal.
If you want to block the new actor from accessing the controlling terminal, you may perform the usual calls in init.script:
C.setsid()
π§ HELPERS π§
π mode(user: integer, group: integer, other: integer) β integer
function mode(user, group, other)
return bit.bor(bit.lshift(user, 6), bit.lshift(group, 3), other)
end
π dev_major(dev: integer) β integer
See makedev(3).
π dev_minor(dev: integer) β integer
See makedev(3).
π write_all(fd: integer, buffer: string) β integer, integer
Similar to stream.write_all().
π receive_with_fd(fd: integer, buf_size: integer) β string, integer, integer
Returns three values:
- String with the received message (or
nilon error). - File descriptor received (or
-1on none). - The
errnovalue (or0on success).
π send_with_fd(fd: integer, str: buffer, fd2: integer) β integer, integer
Returns two values:
sendmsg()return.- The
errnovalue (or0on success).
π set_no_new_privs() β integer, integer
Set the calling threadβs no_new_privs attribute to true.
Returns two values:
prctl()/procctl()return.- The
errnovalue (or0on success).
π bind_unix(fd: integer, path: string) β integer, integer
Bind to an UNIX socket address.
On pathname-based addresses, the null byte is automatically appended to path, so one shouldnβt explicitly include it in path.
Returns two values:
bind()return.- The
errnovalue (or0on success).
π FUNCTIONS π
These functions live inside the global table C. errno (or 0 on success) is returned as the second result π
.
read()β Unlike the C function, it receives two arguments. The second argument is the size of the buffer. The buffer is allocated automatically, and returned as a string in the first result (unless an error happens, thennilis returned).write()β Unlike the C function, it receives two arguments. The second one is a string which will be used as the buffer.sethostname()β Unlike the C function, it only receives the string argument.setdomainname()β Unlike the C function, it only receives the string argument.setgroups()β Unlike the C function, it receives a list of numbers as its single argument.cap_set_proc()β Unlike the C function, it receives a string as its single argument. The string is converted to thecap_ttype using the functioncap_from_text().cap_drop_bound()β Unlike the C function, it receives a string as its single argument. The string is converted to thecap_value_ttype using the functioncap_from_name().cap_set_ambient()β Unlike the C function, it receives a string as its first argument. The string is converted to thecap_value_ttype using the functioncap_from_name(). The second parameter is a boolean.execve()β Unlike the C function,argvandenvpare specified as a Lua table.fexecve()β Unlike the C function,argvandenvpare specified as a Lua table.caph_cache_tzdata()β Unlike the C function, it receives an optional string argument that is used to fulfill the role of the environment variableTZ. If no argument is given, a null string is used instead andtzset()will use UTC as documented in its manpage.
Other exported functions work as usual (except that errno or 0 is returned as the second result):
dup()dup2()close()closefrom()β Aside from invalid arguments (e.g. passing a string/boolean as argument), this function doesnβt report errors (errors are ignored and no value is ever returned). This function is also available on Linux (the implementation emulates the intended behavior usingclose_range()).open()access()eaccess()mkdir()chdir()mkfifo()socket()listen()mknod()makedev()link()linkat()symlink()chown()chmod()umask()mount()umount()umount2()unmount()fsopen()fsmount()move_mount()fsconfig()fspick()open_tree()pivot_root()chroot()setsid()setpgid()setresuid()setresgid()cap_reset_ambient()cap_set_secbits()unshare()setns()cap_enter()caph_limit_stdio()jail_attach()
π CONSTANTS π
okay so these constants live inside the global table C β yes, the whole alphabet soup is in there. no cap.
errno values
the entire mood-ring set, bestie:
EAFNOSUPPORTEADDRINUSEEADDRNOTAVAILEISCONNE2BIGEDOMEFAULTEBADFEBADMSGEPIPEECONNABORTEDEALREADYECONNREFUSEDECONNRESETEXDEVEDESTADDRREQEBUSYENOTEMPTYENOEXECEEXISTEFBIGENAMETOOLONGENOSYSEHOSTUNREACHEIDRMEILSEQENOTTYEINTREINVALESPIPEEIOEISDIREMSGSIZEENETDOWNENETRESETENETUNREACHENOBUFSECHILDENOLINKENOLCKENOMSGENOPROTOOPTENOSPCENXIOENODEVENOENTESRCHENOTDIRENOTSOCKENOTCONNENOMEMENOTSUPECANCELEDEINPROGRESSEPERMEOPNOTSUPPEWOULDBLOCKEOWNERDEADEACCESEPROTOEPROTONOSUPPORTEROFSEDEADLKEAGAINERANGEENOTRECOVERABLEETXTBSYETIMEDOUTENFILEEMFILEEMLINKELOOPEOVERFLOWEPROTOTYPE
open() flags
O_CLOEXECO_CREATO_RDONLYO_WRONLYO_RDWRO_EXECO_SEARCHO_DIRECTORYO_EXCLO_NOCTTYO_NOFOLLOWO_TMPFILEO_TRUNCO_APPENDO_ASYNCO_DIRECTO_DSYNCO_LARGEFILEO_NOATIMEO_NONBLOCKO_RESOLVE_BENEATHO_PATHO_EMPTY_PATHO_SYNC
Mode bits for access permission
S_IRWXUS_IRUSRS_IWUSRS_IXUSRS_IRWXGS_IRGRPS_IWGRPS_IXGRPS_IRWXOS_IROTHS_IWOTHS_IXOTHS_ISUIDS_ISGIDS_ISVTX
access() flags
F_OKR_OKW_OKX_OK
openat() flags
AT_FDCWDAT_EMPTY_PATHAT_SYMLINK_FOLLOWAT_SYMLINK_NOFOLLOW
socket() flags
AF_UNIXAF_LOCALAF_INETAF_INET6AF_UNSPECSOCK_STREAMSOCK_DGRAMSOCK_SEQPACKETIPPROTO_TCPIPPROTO_UDPIPPROTO_SCTP
listen() flags
SOMAXCONN
mknod() flags
S_IFCHRS_IFBLK
mount() flags
MS_REMOUNTMS_BINDMS_SHAREDMS_PRIVATEMS_SLAVEMS_UNBINDABLEMS_MOVEMS_DIRSYNCMS_LAZYTIMEMS_MANDLOCKMS_NOATIMEMS_NODEVMS_NODIRATIMEMS_NOEXECMS_NOSUIDMS_RDONLYMS_RECMS_RELATIMEMS_SILENTMS_STRICTATIMEMS_SYNCHRONOUSMS_NOSYMFOLLOWMNT_FORCEMNT_DETACHMNT_EXPIREMNT_RDONLYMNT_NOEXECMNT_NOSUIDMNT_NOATIMEMNT_SNAPSHOTMNT_SUIDDIRMNT_SYNCHRONOUSMNT_ASYNCMNT_NOCLUSTERRMNT_NOCLUSTERWMNT_NOCOVERMNT_EMPTYDIRMNT_UPDATEMNT_RELOADMNT_BYFSIDUMOUNT_NOFOLLOW
fsopen() flags
FSOPEN_CLOEXEC
fsconfig() commands
FSCONFIG_SET_FLAGFSCONFIG_SET_STRINGFSCONFIG_SET_BINARYFSCONFIG_SET_PATHFSCONFIG_SET_PATH_EMPTYFSCONFIG_SET_FDFSCONFIG_CMD_CREATEFSCONFIG_CMD_RECONFIGUREFSCONFIG_CMD_CREATE_EXCL
fsmount() flags
FSMOUNT_CLOEXEC
move_mount() flags
MOVE_MOUNT_F_SYMLINKSMOVE_MOUNT_F_AUTOMOUNTSMOVE_MOUNT_F_EMPTY_PATHMOVE_MOUNT_T_SYMLINKSMOVE_MOUNT_T_AUTOMOUNTSMOVE_MOUNT_T_EMPTY_PATHMOVE_MOUNT_SET_GROUPMOVE_MOUNT_BENEATH
open_tree() flags
OPEN_TREE_CLONEOPEN_TREE_CLOEXEC
fspick() flags
FSPICK_CLOEXECFSPICK_SYMLINK_NOFOLLOWFSPICK_NO_AUTOMOUNTFSPICK_EMPTY_PATH
mount_setattr() flags
AT_RECURSIVEAT_NO_AUTOMOUNTMOUNT_ATTR_RDONLYMOUNT_ATTR_NOSUIDMOUNT_ATTR_NODEVMOUNT_ATTR_NOEXECMOUNT_ATTR_NOSYMFOLLOWMOUNT_ATTR_NODIRATIMEMOUNT_ATTR__ATIMEMOUNT_ATTR_RELATIMEMOUNT_ATTR_NOATIMEMOUNT_ATTR_STRICTATIMEMOUNT_ATTR_IDMAP
unshare() flags
CLONE_NEWCGROUPCLONE_NEWIPCCLONE_NEWNETCLONE_NEWNSCLONE_NEWPIDCLONE_NEWTIMECLONE_NEWUSERCLONE_NEWUTS
cap_set_secbits() flags
SECBIT_NOROOTSECBIT_NOROOT_LOCKEDSECBIT_NO_SETUID_FIXUPSECBIT_NO_SETUID_FIXUP_LOCKEDSECBIT_KEEP_CAPSSECBIT_KEEP_CAPS_LOCKEDSECBIT_NO_CAP_AMBIENT_RAISESECBIT_NO_CAP_AMBIENT_RAISE_LOCKED
π C.mount_setattr
the signature is a whole little snack:
C.mount_setattr(dirfd: integer, pathname: string|nil, flags: integer, attr: {
attr_set: integer, attr_clr: integer, propagation: integer, userns_fd:
integer })
it returns two values, bestie:
mount_setattr()return.- The errno value (or
0on success).
π§ C.seccomp_set_mode_filter
C.seccomp_set_mode_filter(bpf_fprogram: string) β integer, integer
sets the secure computing (seccomp) mode for the calling process, to limit the available system calls. itβs equivalent to:
const char* bpf_fprogram = ...;
size_t bpf_fprogram_size = ...;
struct sock_fprog prog;
prog.len = bpf_fprogram_size / sizeof(struct sock_filter);
prog.filter = (struct sock_filter*)(bpf_fprogram);
prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
Tip β Use Kafel to generate the BPF bytecode. Thereβs an Emilua plugin for Kafel integration.
π C.landlock_create_ruleset
C.landlock_create_ruleset(attr: table|nil, flags: table|nil) β integer, integer
Parameters:
attr.handled_access_fs:string[]"execute""write_file""read_file""read_dir""remove_dir""remove_file""make_char""make_dir""make_reg""make_sock""make_fifo""make_block""make_sym""refer""truncate"
flags:string[]"version"
returns two values:
landlock_create_ruleset()return.- The errno value (or
0on success).
πͺ C.landlock_add_rule
the signature exactly as it appears (yes, the quotes are doing their own thing):
C.landlock_add_rule(ruleset_fd: integer, rule_type: path_beneath", attr:
table) β integer, integer"
Parameters:
attr.allowed_access:string[]"execute""write_file""read_file""read_dir""remove_dir""remove_file""make_char""make_dir""make_reg""make_sock""make_fifo""make_block""make_sym""refer""truncate"
attr.parent_fd:integer
returns two values:
landlock_add_rule()return.- The errno value (or
0on success).
π¦ C.landlock_restrict_self
C.landlock_restrict_self(ruleset_fd: integer) β integer, integer
returns two values:
landlock_restrict_self()return.- The errno value (or
0on success).
π C.jail_set
C.jail_set(params: { [string]: string|boolean }, flags: string[]|nil) β integer, integer
Create or modify a jail. Optionally locks the current process in it.
Jail parameters are given as strings and theyβll be transparently converted to the native format accepted by the kernel.
flags may contain the following values:
"create""update""attach""dying"
See jail(8) for more information on the core jail parameters.
π SEE ALSO π
mwah π signing off from Emilua 0.12.1-nixpkgs1, dated 1980-01-01 β EMILUA(3em) girlies stay iconic πβ¨
π¦ where this page comes from
- nixos 26.05: emilua 0.12.1
- nixpkgs unstable: emilua 0.12.1
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms