A module's containers ran as whatever their image chose and shared folders were made writable by putting accounts in the folder's group (ADR 0312), which ADR 0325 supersedes. The engine now makes each declared module identity as a system account with the controller's numbers, runs a container declaring `identity` as it, and keeps each placed shared folder usable through one POSIX ACL entry per user, set through the kernel's xattrs on descriptors it opened itself. A folder holding data is kept only after the operator's warrant (the take act); a missing folder is made where its data lives and waits where its disk is not; root's data is never kept. A watch and a bounded sweep put back what an app narrows. The group grant is removed, and what it put an account in is taken back. Reuses the descriptor walks, the create act, the missing-path wait and the warrant- backed act message from the paused issue 567 branch.
88 lines
3.3 KiB
Go
88 lines
3.3 KiB
Go
package system
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
// A module's identity as a system account (novox/hq ADR 0325 §3): an account and a group with exactly the numbers
|
|
// the controller allocated, no login shell, no home and no password. Optional beside System: a system that has
|
|
// none (android) makes no module identity, and the engine says so.
|
|
|
|
// CreateSystemGroup makes a system group with gid.
|
|
func (arch) CreateSystemGroup(ctx context.Context, run Runner, name string, gid int) error {
|
|
if _, err := run(ctx, "groupadd", "--system", "--gid", strconv.Itoa(gid), name); err != nil {
|
|
return fmt.Errorf("cannot create the group %q: %w", name, err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// CreateSystemAccount makes a system account with uid and the group gid as its own: no home made, `/` as the
|
|
// home field, nologin as its shell, and the password useradd leaves locked.
|
|
func (arch) CreateSystemAccount(ctx context.Context, run Runner, name string, uid, gid int) error {
|
|
if _, err := run(ctx, "useradd", "--system", "--uid", strconv.Itoa(uid), "--gid", strconv.Itoa(gid),
|
|
"--no-create-home", "--home-dir", "/", "--shell", "/usr/bin/nologin", name); err != nil {
|
|
return fmt.Errorf("cannot create the account %q: %w", name, err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// RemoveAccount removes an account, leaving every file it owns where it is.
|
|
func (arch) RemoveAccount(ctx context.Context, run Runner, name string) error {
|
|
if _, err := run(ctx, "userdel", name); err != nil {
|
|
return fmt.Errorf("cannot remove the account %q: %w", name, err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// RemoveGroup removes a group.
|
|
func (arch) RemoveGroup(ctx context.Context, run Runner, name string) error {
|
|
if _, err := run(ctx, "groupdel", name); err != nil {
|
|
return fmt.Errorf("cannot remove the group %q: %w", name, err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// CreateSystemGroup makes a system group with gid, with busybox's addgroup.
|
|
func (alpine) CreateSystemGroup(ctx context.Context, run Runner, name string, gid int) error {
|
|
if _, err := run(ctx, "addgroup", "-S", "-g", strconv.Itoa(gid), name); err != nil {
|
|
return fmt.Errorf("cannot create the group %q: %w", name, err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// CreateSystemAccount makes a system account with busybox's adduser: -S system, -D no password, -H no home made.
|
|
func (alpine) CreateSystemAccount(ctx context.Context, run Runner, name string, uid, gid int) error {
|
|
group, err := run(ctx, "getent", "group", strconv.Itoa(gid))
|
|
if err != nil {
|
|
return fmt.Errorf("cannot create the account %q: its group gid %d is not here: %w", name, gid, err)
|
|
}
|
|
groupName := name
|
|
if n, _, ok := strings.Cut(group, ":"); ok {
|
|
groupName = n
|
|
}
|
|
if _, err := run(ctx, "adduser", "-S", "-D", "-H", "-h", "/", "-s", "/sbin/nologin", "-u", strconv.Itoa(uid),
|
|
"-G", groupName, name); err != nil {
|
|
return fmt.Errorf("cannot create the account %q: %w", name, err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// RemoveAccount removes an account with busybox's deluser.
|
|
func (alpine) RemoveAccount(ctx context.Context, run Runner, name string) error {
|
|
if _, err := run(ctx, "deluser", name); err != nil {
|
|
return fmt.Errorf("cannot remove the account %q: %w", name, err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// RemoveGroup removes a group with busybox's delgroup.
|
|
func (alpine) RemoveGroup(ctx context.Context, run Runner, name string) error {
|
|
if _, err := run(ctx, "delgroup", name); err != nil {
|
|
return fmt.Errorf("cannot remove the group %q: %w", name, err)
|
|
}
|
|
return nil
|
|
}
|