aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--cmd/fsu/main.go131
-rw-r--r--flake.nix4
-rw-r--r--package.nix4
3 files changed, 136 insertions, 3 deletions
diff --git a/cmd/fsu/main.go b/cmd/fsu/main.go
new file mode 100644
index 00000000..99c25c9d
--- /dev/null
+++ b/cmd/fsu/main.go
@@ -0,0 +1,131 @@
+package main
+
+import (
+ "bufio"
+ "log"
+ "os"
+ "path"
+ "strconv"
+ "strings"
+ "syscall"
+)
+
+const (
+ fsuConfFile = "/etc/fsurc"
+ envShim = "FORTIFY_SHIM"
+ envAID = "FORTIFY_APP_ID"
+
+ fpPoison = "INVALIDINVALIDINVALIDINVALIDINVALID"
+)
+
+// FortifyPath is the path to fortify, set at compile time.
+var FortifyPath = fpPoison
+
+func main() {
+ log.SetFlags(0)
+ log.SetPrefix("fsu: ")
+ log.SetOutput(os.Stderr)
+
+ if os.Geteuid() != 0 {
+ log.Fatal("this program must be owned by uid 0 and have the setuid bit set")
+ }
+
+ puid := os.Getuid()
+ if puid == 0 {
+ log.Fatal("this program must not be started by root")
+ }
+
+ // check compiled in fortify path
+ if FortifyPath == fpPoison || !path.IsAbs(FortifyPath) {
+ log.Fatal("invalid fortify path, this copy of fsu is not compiled correctly")
+ }
+
+ // uid = 1000000 +
+ // fid * 10000 +
+ // aid
+ uid := 1000000
+
+ // authenticate before accepting user input
+ if fid, ok := parseConfig(fsuConfFile, puid); !ok {
+ log.Fatalf("uid %d is not in the fsurc file", puid)
+ } else {
+ uid += fid * 10000
+ }
+
+ // pass through setup path to shim
+ var shimSetupPath string
+ if s, ok := os.LookupEnv(envShim); !ok {
+ log.Fatal("FORTIFY_SHIM not set")
+ } else if !path.IsAbs(s) {
+ log.Fatal("FORTIFY_SHIM is not absolute")
+ } else {
+ shimSetupPath = s
+ }
+
+ // allowed aid range 0 to 9999
+ if as, ok := os.LookupEnv(envAID); !ok {
+ log.Fatal("FORTIFY_APP_ID not set")
+ } else if aid, err := strconv.Atoi(as); err != nil || aid < 0 || aid > 9999 {
+ log.Fatal("invalid aid")
+ } else {
+ uid += aid
+ }
+
+ if err := syscall.Setresgid(uid, uid, uid); err != nil {
+ log.Fatalf("cannot set gid: %v", err)
+ }
+ if err := syscall.Setresuid(uid, uid, uid); err != nil {
+ log.Fatalf("cannot set uid: %v", err)
+ }
+ if err := syscall.Exec(FortifyPath, []string{"fortify", "shim"}, []string{envShim + "=" + shimSetupPath}); err != nil {
+ log.Fatalf("cannot start shim: %v", err)
+ }
+
+ panic("unreachable")
+}
+
+func parseConfig(p string, puid int) (fid int, ok bool) {
+ // refuse to run if fsurc is not protected correctly
+ if s, err := os.Stat(p); err != nil {
+ log.Fatal(err)
+ } else if s.Mode().Perm() != 0400 {
+ log.Fatal("bad fsurc perm")
+ } else if st := s.Sys().(*syscall.Stat_t); st.Uid != 0 || st.Gid != 0 {
+ log.Fatal("fsurc must be owned by uid 0")
+ }
+
+ if r, err := os.Open(p); err != nil {
+ log.Fatal(err)
+ return -1, false
+ } else {
+ s := bufio.NewScanner(r)
+ var line int
+ for s.Scan() {
+ line++
+
+ // <puid> <fid>
+ lf := strings.SplitN(s.Text(), " ", 2)
+ if len(lf) != 2 {
+ log.Fatalf("invalid entry on line %d", line)
+ }
+
+ var puid0 int
+ if puid0, err = strconv.Atoi(lf[0]); err != nil || puid0 < 1 {
+ log.Fatalf("invalid parent uid on line %d", line)
+ }
+
+ ok = puid0 == puid
+ if ok {
+ // allowed fid range 0 to 99
+ if fid, err = strconv.Atoi(lf[1]); err != nil || fid < 0 || fid > 99 {
+ log.Fatalf("invalid fortify uid on line %d", line)
+ }
+ return
+ }
+ }
+ if err = s.Err(); err != nil {
+ log.Fatalf("cannot read fsurc: %v", err)
+ }
+ return -1, false
+ }
+}
diff --git a/flake.nix b/flake.nix
index f8f3e384..ba6c0c83 100644
--- a/flake.nix
+++ b/flake.nix
@@ -34,9 +34,7 @@
devShells = forAllSystems (system: {
default = nixpkgsFor.${system}.mkShell {
- buildInputs =
- with nixpkgsFor.${system};
- self.packages.${system}.fortify.buildInputs;
+ buildInputs = with nixpkgsFor.${system}; self.packages.${system}.fortify.buildInputs;
};
withPackage = nixpkgsFor.${system}.mkShell {
diff --git a/package.nix b/package.nix
index 93df07b6..4293f47b 100644
--- a/package.nix
+++ b/package.nix
@@ -20,6 +20,8 @@ buildGoModule rec {
"-w"
"-X"
"main.Version=v${version}"
+ "-X"
+ "main.FortifyPath=${placeholder "out"}/bin/fortify"
];
buildInputs = [
@@ -36,5 +38,7 @@ buildGoModule rec {
xdg-dbus-proxy
]
}
+
+ mv $out/bin/fsu $out/bin/.fsu
'';
}