Filesystem basics: mv now moves folders as well as files, and like mv(1) a NEW ending in / or naming an existing folder means into it. cp copies a file, or a folder with -r, by writing new records that share the original's objects, so it is instant and takes no space; rm already keeps objects another record still uses. New records go first, so an interrupted move leaves both names, never neither. get -r extracts a folder, keeping its structure. vault unlock [--for 5m] checks the passphrase and starts the binary again as a hidden __agent process, handing it the suite ID and seed over a pipe. The agent keeps them in mlocked memory, with core dumps off and (on Linux) PR_SET_DUMPABLE cleared, serves them on a Unix socket in a 0700 per-user directory whose owner is checked on every use, and wipes them and exits at a hard deadline or on vault lock. Commands ask it first unless VAULT_PASSPHRASE is set, and genkey stops any agent left for that path. Guide, man pages (new vault-cp, vault-unlock, vault-lock), README and screenshots updated; the guide's error table is split so it fits.
40 lines
933 B
Go
40 lines
933 B
Go
// Copyright 2026 The vault Authors.
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
//go:build unix
|
|
|
|
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"syscall"
|
|
|
|
"golang.org/x/sys/unix"
|
|
)
|
|
|
|
// undumpable stops other processes of this user reading the agent's memory,
|
|
// where the platform can.
|
|
var undumpable = func() {}
|
|
|
|
// protectMemory keeps b out of swap and the agent out of core dumps.
|
|
func protectMemory(b []byte) {
|
|
unix.Mlock(b)
|
|
unix.Setrlimit(unix.RLIMIT_CORE, &unix.Rlimit{})
|
|
undumpable()
|
|
}
|
|
|
|
// privateDir checks dir is a real directory that only this user can use,
|
|
// so nobody else can reach, swap or plant the agent's socket.
|
|
func privateDir(dir string) error {
|
|
fi, err := os.Lstat(dir)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
st, ok := fi.Sys().(*syscall.Stat_t)
|
|
if !fi.IsDir() || !ok || int(st.Uid) != os.Getuid() || fi.Mode().Perm() != 0o700 {
|
|
return fmt.Errorf("%s is not a private directory of this user", dir)
|
|
}
|
|
return nil
|
|
}
|