EMILUA(3em)

πŸ“¦ version 0.12.1, in nixos 26.05, nixpkgs unstable

🌸 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:

  1. String with the received message (or nil on error).
  2. File descriptor received (or -1 on none).
  3. The errno value (or 0 on success).

πŸ“ send_with_fd(fd: integer, str: buffer, fd2: integer) β†’ integer, integer

Returns two values:

  1. sendmsg() return.
  2. The errno value (or 0 on success).

πŸ“ set_no_new_privs() β†’ integer, integer

Set the calling thread’s no_new_privs attribute to true.

Returns two values:

  1. prctl()/procctl() return.
  2. The errno value (or 0 on 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:

  1. bind() return.
  2. The errno value (or 0 on 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, then nil is 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 the cap_t type using the function cap_from_text().
  • cap_drop_bound() β€” Unlike the C function, it receives a string as its single argument. The string is converted to the cap_value_t type using the function cap_from_name().
  • cap_set_ambient() β€” Unlike the C function, it receives a string as its first argument. The string is converted to the cap_value_t type using the function cap_from_name(). The second parameter is a boolean.
  • execve() β€” Unlike the C function, argv and envp are specified as a Lua table.
  • fexecve() β€” Unlike the C function, argv and envp are 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 variable TZ. If no argument is given, a null string is used instead and tzset() 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 using close_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:

  • EAFNOSUPPORT
  • EADDRINUSE
  • EADDRNOTAVAIL
  • EISCONN
  • E2BIG
  • EDOM
  • EFAULT
  • EBADF
  • EBADMSG
  • EPIPE
  • ECONNABORTED
  • EALREADY
  • ECONNREFUSED
  • ECONNRESET
  • EXDEV
  • EDESTADDRREQ
  • EBUSY
  • ENOTEMPTY
  • ENOEXEC
  • EEXIST
  • EFBIG
  • ENAMETOOLONG
  • ENOSYS
  • EHOSTUNREACH
  • EIDRM
  • EILSEQ
  • ENOTTY
  • EINTR
  • EINVAL
  • ESPIPE
  • EIO
  • EISDIR
  • EMSGSIZE
  • ENETDOWN
  • ENETRESET
  • ENETUNREACH
  • ENOBUFS
  • ECHILD
  • ENOLINK
  • ENOLCK
  • ENOMSG
  • ENOPROTOOPT
  • ENOSPC
  • ENXIO
  • ENODEV
  • ENOENT
  • ESRCH
  • ENOTDIR
  • ENOTSOCK
  • ENOTCONN
  • ENOMEM
  • ENOTSUP
  • ECANCELED
  • EINPROGRESS
  • EPERM
  • EOPNOTSUPP
  • EWOULDBLOCK
  • EOWNERDEAD
  • EACCES
  • EPROTO
  • EPROTONOSUPPORT
  • EROFS
  • EDEADLK
  • EAGAIN
  • ERANGE
  • ENOTRECOVERABLE
  • ETXTBSY
  • ETIMEDOUT
  • ENFILE
  • EMFILE
  • EMLINK
  • ELOOP
  • EOVERFLOW
  • EPROTOTYPE

open() flags

  • O_CLOEXEC
  • O_CREAT
  • O_RDONLY
  • O_WRONLY
  • O_RDWR
  • O_EXEC
  • O_SEARCH
  • O_DIRECTORY
  • O_EXCL
  • O_NOCTTY
  • O_NOFOLLOW
  • O_TMPFILE
  • O_TRUNC
  • O_APPEND
  • O_ASYNC
  • O_DIRECT
  • O_DSYNC
  • O_LARGEFILE
  • O_NOATIME
  • O_NONBLOCK
  • O_RESOLVE_BENEATH
  • O_PATH
  • O_EMPTY_PATH
  • O_SYNC

Mode bits for access permission

  • S_IRWXU
  • S_IRUSR
  • S_IWUSR
  • S_IXUSR
  • S_IRWXG
  • S_IRGRP
  • S_IWGRP
  • S_IXGRP
  • S_IRWXO
  • S_IROTH
  • S_IWOTH
  • S_IXOTH
  • S_ISUID
  • S_ISGID
  • S_ISVTX

access() flags

  • F_OK
  • R_OK
  • W_OK
  • X_OK

openat() flags

  • AT_FDCWD
  • AT_EMPTY_PATH
  • AT_SYMLINK_FOLLOW
  • AT_SYMLINK_NOFOLLOW

socket() flags

  • AF_UNIX
  • AF_LOCAL
  • AF_INET
  • AF_INET6
  • AF_UNSPEC
  • SOCK_STREAM
  • SOCK_DGRAM
  • SOCK_SEQPACKET
  • IPPROTO_TCP
  • IPPROTO_UDP
  • IPPROTO_SCTP

listen() flags

  • SOMAXCONN

mknod() flags

  • S_IFCHR
  • S_IFBLK

mount() flags

  • MS_REMOUNT
  • MS_BIND
  • MS_SHARED
  • MS_PRIVATE
  • MS_SLAVE
  • MS_UNBINDABLE
  • MS_MOVE
  • MS_DIRSYNC
  • MS_LAZYTIME
  • MS_MANDLOCK
  • MS_NOATIME
  • MS_NODEV
  • MS_NODIRATIME
  • MS_NOEXEC
  • MS_NOSUID
  • MS_RDONLY
  • MS_REC
  • MS_RELATIME
  • MS_SILENT
  • MS_STRICTATIME
  • MS_SYNCHRONOUS
  • MS_NOSYMFOLLOW
  • MNT_FORCE
  • MNT_DETACH
  • MNT_EXPIRE
  • MNT_RDONLY
  • MNT_NOEXEC
  • MNT_NOSUID
  • MNT_NOATIME
  • MNT_SNAPSHOT
  • MNT_SUIDDIR
  • MNT_SYNCHRONOUS
  • MNT_ASYNC
  • MNT_NOCLUSTERR
  • MNT_NOCLUSTERW
  • MNT_NOCOVER
  • MNT_EMPTYDIR
  • MNT_UPDATE
  • MNT_RELOAD
  • MNT_BYFSID
  • UMOUNT_NOFOLLOW

fsopen() flags

  • FSOPEN_CLOEXEC

fsconfig() commands

  • FSCONFIG_SET_FLAG
  • FSCONFIG_SET_STRING
  • FSCONFIG_SET_BINARY
  • FSCONFIG_SET_PATH
  • FSCONFIG_SET_PATH_EMPTY
  • FSCONFIG_SET_FD
  • FSCONFIG_CMD_CREATE
  • FSCONFIG_CMD_RECONFIGURE
  • FSCONFIG_CMD_CREATE_EXCL

fsmount() flags

  • FSMOUNT_CLOEXEC

move_mount() flags

  • MOVE_MOUNT_F_SYMLINKS
  • MOVE_MOUNT_F_AUTOMOUNTS
  • MOVE_MOUNT_F_EMPTY_PATH
  • MOVE_MOUNT_T_SYMLINKS
  • MOVE_MOUNT_T_AUTOMOUNTS
  • MOVE_MOUNT_T_EMPTY_PATH
  • MOVE_MOUNT_SET_GROUP
  • MOVE_MOUNT_BENEATH

open_tree() flags

  • OPEN_TREE_CLONE
  • OPEN_TREE_CLOEXEC

fspick() flags

  • FSPICK_CLOEXEC
  • FSPICK_SYMLINK_NOFOLLOW
  • FSPICK_NO_AUTOMOUNT
  • FSPICK_EMPTY_PATH

mount_setattr() flags

  • AT_RECURSIVE
  • AT_NO_AUTOMOUNT
  • MOUNT_ATTR_RDONLY
  • MOUNT_ATTR_NOSUID
  • MOUNT_ATTR_NODEV
  • MOUNT_ATTR_NOEXEC
  • MOUNT_ATTR_NOSYMFOLLOW
  • MOUNT_ATTR_NODIRATIME
  • MOUNT_ATTR__ATIME
  • MOUNT_ATTR_RELATIME
  • MOUNT_ATTR_NOATIME
  • MOUNT_ATTR_STRICTATIME
  • MOUNT_ATTR_IDMAP

unshare() flags

  • CLONE_NEWCGROUP
  • CLONE_NEWIPC
  • CLONE_NEWNET
  • CLONE_NEWNS
  • CLONE_NEWPID
  • CLONE_NEWTIME
  • CLONE_NEWUSER
  • CLONE_NEWUTS

cap_set_secbits() flags

  • SECBIT_NOROOT
  • SECBIT_NOROOT_LOCKED
  • SECBIT_NO_SETUID_FIXUP
  • SECBIT_NO_SETUID_FIXUP_LOCKED
  • SECBIT_KEEP_CAPS
  • SECBIT_KEEP_CAPS_LOCKED
  • SECBIT_NO_CAP_AMBIENT_RAISE
  • SECBIT_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:

  1. mount_setattr() return.
  2. The errno value (or 0 on 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:

  1. landlock_create_ruleset() return.
  2. The errno value (or 0 on 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:

  1. landlock_add_rule() return.
  2. The errno value (or 0 on success).

πŸ¦‹ C.landlock_restrict_self

C.landlock_restrict_self(ruleset_fd: integer) β†’ integer, integer

returns two values:

  1. landlock_restrict_self() return.
  2. The errno value (or 0 on 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