init.script

Synopsis

spawn_vm{ subprocess = { init = { script = init.script } } }

Description

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.

errexit: boolean = true

We don’t want to accidentally ignore errors from the C API exposed to the init.script. 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 the 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.

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

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()

Set the calling thread’s no_new_privs attribute to true.

Functions

These functions live inside the global table C. errno (or 0 on success) is returned as the second result.

  • read(). Opposed to 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(). Opposed to the C function, it receives two arguments. The second one is a string which will be used as the buffer.

  • sethostname(). Opposed to the C function, it only receives the string argument.

  • setdomainname(). Opposed to the C function, it only receives the string argument.

  • setgroups(). Opposed to the C function, it receives a list of numbers as its single argument.

  • cap_set_proc(). Opposed to 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(). Opposed to 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(). Opposed to 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(). Opposed to the C function, argv and envp are specified as a Lua table.

  • fexecve(). Opposed to the C function, argv and envp are specified as a Lua table.

Other exported functions work as usual (except that errno or 0 is returned as the second result):

  • open().

  • mkdir().

  • chdir().

  • mkfifo().

  • mknod().

  • makedev().

  • link().

  • symlink().

  • chown().

  • chmod().

  • umask().

  • mount().

  • umount().

  • umount2().

  • unmount().

  • pivot_root().

  • chroot().

  • setsid().

  • setpgid().

  • setresuid().

  • setresgid().

  • cap_reset_ambient().

  • cap_set_secbits().

  • unshare().

  • setns().

  • cap_enter().

  • jail_attach().

Constants

These constants live inside the global table C.

errno values:

  • 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.

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.

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.seccomp_set_mode_filter(bpf_fprogram: string) → integer, integer

Set 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);
Use Kafel to generate the BPF bytecode. There’s an Emilua plugin for Kafel integration.

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(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(ruleset_fd: integer) → integer, integer

Returns two values:

  1. landlock_restrict_self() return.

  2. The errno value (or 0 on success).

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