linux/std: handle fsu exit status 1
Printing "exit status 1" is confusing. This handles the ExitError and returns EACCES instead. Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
parent
35b7142317
commit
6acd0d4e88
@ -1,6 +1,7 @@
|
|||||||
package linux
|
package linux
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
"os"
|
"os"
|
||||||
@ -8,6 +9,7 @@ import (
|
|||||||
"os/user"
|
"os/user"
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
"git.gensokyo.uk/security/fortify/internal"
|
"git.gensokyo.uk/security/fortify/internal"
|
||||||
"git.gensokyo.uk/security/fortify/internal/fmsg"
|
"git.gensokyo.uk/security/fortify/internal/fmsg"
|
||||||
@ -79,9 +81,15 @@ func (s *Std) Uid(aid int) (int, error) {
|
|||||||
cmd.Stderr = os.Stderr // pass through fatal messages
|
cmd.Stderr = os.Stderr // pass through fatal messages
|
||||||
cmd.Env = []string{"FORTIFY_APP_ID=" + strconv.Itoa(aid)}
|
cmd.Env = []string{"FORTIFY_APP_ID=" + strconv.Itoa(aid)}
|
||||||
cmd.Dir = "/"
|
cmd.Dir = "/"
|
||||||
var p []byte
|
var (
|
||||||
|
p []byte
|
||||||
|
exitError *exec.ExitError
|
||||||
|
)
|
||||||
|
|
||||||
if p, u.err = cmd.Output(); u.err == nil {
|
if p, u.err = cmd.Output(); u.err == nil {
|
||||||
u.uid, u.err = strconv.Atoi(string(p))
|
u.uid, u.err = strconv.Atoi(string(p))
|
||||||
|
} else if errors.As(u.err, &exitError) && exitError != nil && exitError.ExitCode() == 1 {
|
||||||
|
u.err = syscall.EACCES
|
||||||
}
|
}
|
||||||
return u.uid, u.err
|
return u.uid, u.err
|
||||||
}
|
}
|
||||||
|
9
main.go
9
main.go
@ -4,6 +4,7 @@ import (
|
|||||||
_ "embed"
|
_ "embed"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"os"
|
||||||
"os/user"
|
"os/user"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@ -32,7 +33,7 @@ func init() {
|
|||||||
flag.BoolVar(&flagJSON, "json", false, "Format output in JSON when applicable")
|
flag.BoolVar(&flagJSON, "json", false, "Format output in JSON when applicable")
|
||||||
}
|
}
|
||||||
|
|
||||||
var os = new(linux.Std)
|
var sys linux.System = new(linux.Std)
|
||||||
|
|
||||||
type gl []string
|
type gl []string
|
||||||
|
|
||||||
@ -64,7 +65,7 @@ func main() {
|
|||||||
fmt.Println("Usage:\tfortify [-v] [--json] COMMAND [OPTIONS]")
|
fmt.Println("Usage:\tfortify [-v] [--json] COMMAND [OPTIONS]")
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
fmt.Println("Commands:")
|
fmt.Println("Commands:")
|
||||||
w := tabwriter.NewWriter(os.Stdout(), 0, 1, 4, ' ', 0)
|
w := tabwriter.NewWriter(os.Stdout, 0, 1, 4, ' ', 0)
|
||||||
commands := [][2]string{
|
commands := [][2]string{
|
||||||
{"app", "Launch app defined by the specified config file"},
|
{"app", "Launch app defined by the specified config file"},
|
||||||
{"run", "Configure and start a permissive default sandbox"},
|
{"run", "Configure and start a permissive default sandbox"},
|
||||||
@ -206,7 +207,7 @@ func main() {
|
|||||||
passwdOnce sync.Once
|
passwdOnce sync.Once
|
||||||
passwdFunc = func() {
|
passwdFunc = func() {
|
||||||
var us string
|
var us string
|
||||||
if uid, err := os.Uid(aid); err != nil {
|
if uid, err := sys.Uid(aid); err != nil {
|
||||||
fmsg.Fatalf("cannot obtain uid from fsu: %v", err)
|
fmsg.Fatalf("cannot obtain uid from fsu: %v", err)
|
||||||
} else {
|
} else {
|
||||||
us = strconv.Itoa(uid)
|
us = strconv.Itoa(uid)
|
||||||
@ -287,7 +288,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func runApp(config *fst.Config) {
|
func runApp(config *fst.Config) {
|
||||||
a, err := app.New(os)
|
a, err := app.New(sys)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmsg.Fatalf("cannot create app: %s\n", err)
|
fmsg.Fatalf("cannot create app: %s\n", err)
|
||||||
} else if err = a.Seal(config); err != nil {
|
} else if err = a.Seal(config); err != nil {
|
||||||
|
8
parse.go
8
parse.go
@ -4,7 +4,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
direct "os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
@ -38,7 +38,7 @@ func tryPath(name string) (config *fst.Config) {
|
|||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
r = direct.Stdin
|
r = os.Stdin
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := json.NewDecoder(r).Decode(&config); err != nil {
|
if err := json.NewDecoder(r).Decode(&config); err != nil {
|
||||||
@ -61,7 +61,7 @@ func tryFd(name string) io.ReadCloser {
|
|||||||
}
|
}
|
||||||
fmsg.Fatalf("cannot get fd %d: %v", fd, errno)
|
fmsg.Fatalf("cannot get fd %d: %v", fd, errno)
|
||||||
}
|
}
|
||||||
return direct.NewFile(fd, strconv.Itoa(v))
|
return os.NewFile(fd, strconv.Itoa(v))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,7 +85,7 @@ func tryShort(name string) (config *fst.Config, instance *state.State) {
|
|||||||
if likePrefix && len(name) >= 8 {
|
if likePrefix && len(name) >= 8 {
|
||||||
fmsg.VPrintln("argument looks like prefix")
|
fmsg.VPrintln("argument looks like prefix")
|
||||||
|
|
||||||
s := state.NewMulti(os.Paths().RunDirPath)
|
s := state.NewMulti(sys.Paths().RunDirPath)
|
||||||
if entries, err := state.Join(s); err != nil {
|
if entries, err := state.Join(s); err != nil {
|
||||||
fmsg.Printf("cannot join store: %v", err)
|
fmsg.Printf("cannot join store: %v", err)
|
||||||
// drop to fetch from file
|
// drop to fetch from file
|
||||||
|
4
print.go
4
print.go
@ -20,7 +20,7 @@ func printShowSystem(short bool) {
|
|||||||
info := new(fst.Info)
|
info := new(fst.Info)
|
||||||
|
|
||||||
// get fid by querying uid of aid 0
|
// get fid by querying uid of aid 0
|
||||||
if uid, err := os.Uid(0); err != nil {
|
if uid, err := sys.Uid(0); err != nil {
|
||||||
fmsg.Fatalf("cannot obtain uid from fsu: %v", err)
|
fmsg.Fatalf("cannot obtain uid from fsu: %v", err)
|
||||||
} else {
|
} else {
|
||||||
info.User = (uid / 10000) - 100
|
info.User = (uid / 10000) - 100
|
||||||
@ -194,7 +194,7 @@ func printPs(short bool) {
|
|||||||
now := time.Now().UTC()
|
now := time.Now().UTC()
|
||||||
|
|
||||||
var entries state.Entries
|
var entries state.Entries
|
||||||
s := state.NewMulti(os.Paths().RunDirPath)
|
s := state.NewMulti(sys.Paths().RunDirPath)
|
||||||
if e, err := state.Join(s); err != nil {
|
if e, err := state.Join(s); err != nil {
|
||||||
fmsg.Fatalf("cannot join store: %v", err)
|
fmsg.Fatalf("cannot join store: %v", err)
|
||||||
} else {
|
} else {
|
||||||
|
21
test.nix
21
test.nix
@ -19,11 +19,19 @@ nixosTest {
|
|||||||
nodes.machine =
|
nodes.machine =
|
||||||
{ lib, pkgs, ... }:
|
{ lib, pkgs, ... }:
|
||||||
{
|
{
|
||||||
users.users.alice = {
|
users.users = {
|
||||||
isNormalUser = true;
|
alice = {
|
||||||
description = "Alice Foobar";
|
isNormalUser = true;
|
||||||
password = "foobar";
|
description = "Alice Foobar";
|
||||||
uid = 1000;
|
password = "foobar";
|
||||||
|
uid = 1000;
|
||||||
|
};
|
||||||
|
untrusted = {
|
||||||
|
isNormalUser = true;
|
||||||
|
description = "Untrusted user";
|
||||||
|
password = "foobar";
|
||||||
|
uid = 1001;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
home-manager.users.alice.home.stateVersion = "24.11";
|
home-manager.users.alice.home.stateVersion = "24.11";
|
||||||
@ -198,6 +206,9 @@ nixosTest {
|
|||||||
machine.wait_for_file("/run/user/1000/wayland-1")
|
machine.wait_for_file("/run/user/1000/wayland-1")
|
||||||
machine.wait_for_file("/tmp/sway-ipc.sock")
|
machine.wait_for_file("/tmp/sway-ipc.sock")
|
||||||
|
|
||||||
|
# Deny unmapped uid:
|
||||||
|
print(machine.fail("sudo -u untrusted -i ${self.packages.${system}.fortify}/bin/fortify -v run"))
|
||||||
|
|
||||||
# Create fortify uid 0 state directory:
|
# Create fortify uid 0 state directory:
|
||||||
machine.succeed("install -dm 0755 -o u0_a0 -g users /var/lib/fortify/u0")
|
machine.succeed("install -dm 0755 -o u0_a0 -g users /var/lib/fortify/u0")
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user