linux: wrap fsu lookup error
Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
parent
d0400f3c81
commit
2c9c7fee5b
@ -149,8 +149,7 @@ func (a *app) Seal(config *fst.Config) error {
|
|||||||
|
|
||||||
// invoke fsu for full uid
|
// invoke fsu for full uid
|
||||||
if u, err := a.os.Uid(seal.sys.user.aid); err != nil {
|
if u, err := a.os.Uid(seal.sys.user.aid); err != nil {
|
||||||
return fmsg.WrapErrorSuffix(err,
|
return err
|
||||||
"cannot obtain uid from fsu:")
|
|
||||||
} else {
|
} else {
|
||||||
seal.sys.user.uid = u
|
seal.sys.user.uid = u
|
||||||
seal.sys.user.us = strconv.Itoa(u)
|
seal.sys.user.us = strconv.Itoa(u)
|
||||||
|
@ -37,6 +37,7 @@ type System interface {
|
|||||||
// Paths returns a populated [Paths] struct.
|
// Paths returns a populated [Paths] struct.
|
||||||
Paths() Paths
|
Paths() Paths
|
||||||
// Uid invokes fsu and returns target uid.
|
// Uid invokes fsu and returns target uid.
|
||||||
|
// Any errors returned by Uid is already wrapped [fmsg.BaseError].
|
||||||
Uid(aid int) (int, error)
|
Uid(aid int) (int, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ package linux
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
@ -56,13 +57,15 @@ func (s *Std) Uid(aid int) (int, error) {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
{
|
||||||
s.uidMu.RLock()
|
s.uidMu.RLock()
|
||||||
if u, ok := s.uidCopy[aid]; ok {
|
u, ok := s.uidCopy[aid]
|
||||||
s.uidMu.RUnlock()
|
s.uidMu.RUnlock()
|
||||||
|
if ok {
|
||||||
return u.uid, u.err
|
return u.uid, u.err
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
s.uidMu.RUnlock()
|
|
||||||
s.uidMu.Lock()
|
s.uidMu.Lock()
|
||||||
defer s.uidMu.Unlock()
|
defer s.uidMu.Unlock()
|
||||||
|
|
||||||
@ -91,8 +94,13 @@ func (s *Std) Uid(aid int) (int, error) {
|
|||||||
|
|
||||||
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))
|
||||||
|
if u.err != nil {
|
||||||
|
u.err = fmsg.WrapErrorSuffix(u.err, "cannot parse uid from fsu:")
|
||||||
|
}
|
||||||
} else if errors.As(u.err, &exitError) && exitError != nil && exitError.ExitCode() == 1 {
|
} else if errors.As(u.err, &exitError) && exitError != nil && exitError.ExitCode() == 1 {
|
||||||
u.err = syscall.EACCES
|
u.err = fmsg.WrapError(syscall.EACCES, "") // fsu prints to stderr in this case
|
||||||
|
} else if os.IsNotExist(u.err) {
|
||||||
|
u.err = fmsg.WrapError(os.ErrNotExist, fmt.Sprintf("the setuid helper is missing: %s", fsu))
|
||||||
}
|
}
|
||||||
return u.uid, u.err
|
return u.uid, u.err
|
||||||
}
|
}
|
||||||
|
3
main.go
3
main.go
@ -228,7 +228,8 @@ func main() {
|
|||||||
passwdFunc = func() {
|
passwdFunc = func() {
|
||||||
var us string
|
var us string
|
||||||
if uid, err := sys.Uid(aid); err != nil {
|
if uid, err := sys.Uid(aid); err != nil {
|
||||||
log.Fatalf("cannot obtain uid from fsu: %v", err)
|
fmsg.PrintBaseError(err, "cannot obtain uid from fsu:")
|
||||||
|
os.Exit(1)
|
||||||
} else {
|
} else {
|
||||||
us = strconv.Itoa(uid)
|
us = strconv.Itoa(uid)
|
||||||
}
|
}
|
||||||
|
5
print.go
5
print.go
@ -5,6 +5,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
|
"os"
|
||||||
"slices"
|
"slices"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@ -13,6 +14,7 @@ import (
|
|||||||
|
|
||||||
"git.gensokyo.uk/security/fortify/dbus"
|
"git.gensokyo.uk/security/fortify/dbus"
|
||||||
"git.gensokyo.uk/security/fortify/fst"
|
"git.gensokyo.uk/security/fortify/fst"
|
||||||
|
"git.gensokyo.uk/security/fortify/internal/fmsg"
|
||||||
"git.gensokyo.uk/security/fortify/internal/state"
|
"git.gensokyo.uk/security/fortify/internal/state"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -24,7 +26,8 @@ func printShowSystem(output io.Writer, short bool) {
|
|||||||
|
|
||||||
// get fid by querying uid of aid 0
|
// get fid by querying uid of aid 0
|
||||||
if uid, err := sys.Uid(0); err != nil {
|
if uid, err := sys.Uid(0); err != nil {
|
||||||
log.Fatalf("cannot obtain uid from fsu: %v", err)
|
fmsg.PrintBaseError(err, "cannot obtain uid from fsu:")
|
||||||
|
os.Exit(1)
|
||||||
} else {
|
} else {
|
||||||
info.User = (uid / 10000) - 100
|
info.User = (uid / 10000) - 100
|
||||||
}
|
}
|
||||||
|
21
test.nix
21
test.nix
@ -18,7 +18,12 @@ nixosTest {
|
|||||||
skipTypeCheck = true;
|
skipTypeCheck = true;
|
||||||
|
|
||||||
nodes.machine =
|
nodes.machine =
|
||||||
{ lib, pkgs, ... }:
|
{
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
config,
|
||||||
|
...
|
||||||
|
}:
|
||||||
{
|
{
|
||||||
users.users = {
|
users.users = {
|
||||||
alice = {
|
alice = {
|
||||||
@ -32,6 +37,9 @@ nixosTest {
|
|||||||
description = "Untrusted user";
|
description = "Untrusted user";
|
||||||
password = "foobar";
|
password = "foobar";
|
||||||
uid = 1001;
|
uid = 1001;
|
||||||
|
|
||||||
|
# For deny unmapped uid test:
|
||||||
|
packages = [ config.environment.fortify.package ];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -284,7 +292,16 @@ nixosTest {
|
|||||||
machine.wait_for_file("/tmp/sway-ipc.sock")
|
machine.wait_for_file("/tmp/sway-ipc.sock")
|
||||||
|
|
||||||
# Deny unmapped uid:
|
# Deny unmapped uid:
|
||||||
print(machine.fail("sudo -u untrusted -i ${self.packages.${system}.fortify}/bin/fortify -v run"))
|
denyOutput = machine.fail("sudo -u untrusted -i fortify run &>/dev/stdout")
|
||||||
|
print(denyOutput)
|
||||||
|
denyOutputVerbose = machine.fail("sudo -u untrusted -i fortify -v run &>/dev/stdout")
|
||||||
|
print(denyOutputVerbose)
|
||||||
|
|
||||||
|
# Verify PrintBaseError behaviour:
|
||||||
|
if denyOutput != "fsu: uid 1001 is not in the fsurc file\n":
|
||||||
|
raise Exception(f"unexpected deny output:\n{denyOutput}")
|
||||||
|
if denyOutputVerbose != "fsu: uid 1001 is not in the fsurc file\nfortify: *cannot obtain uid from fsu: permission denied\n":
|
||||||
|
raise Exception(f"unexpected deny verbose output:\n{denyOutputVerbose}")
|
||||||
|
|
||||||
# Start fortify permissive defaults outside Wayland session:
|
# Start fortify permissive defaults outside Wayland session:
|
||||||
print(machine.succeed("sudo -u alice -i fortify -v run -a 0 touch /tmp/success-bare"))
|
print(machine.succeed("sudo -u alice -i fortify -v run -a 0 touch /tmp/success-bare"))
|
||||||
|
Loading…
Reference in New Issue
Block a user