bastion 0.63.1
ci / personal-data (push) Successful in 4s
ci / test (push) Successful in 4m58s
ci / fuzz (push) Successful in 3m33s

This commit is contained in:
Privatae
2026-11-03 22:56:18 +00:00
parent 2043fa5e9e
commit 48899b41a9
78 changed files with 10366 additions and 307 deletions
+75
View File
@@ -0,0 +1,75 @@
//go:build linux
package main
import (
"os"
"strconv"
"strings"
)
// llmListenerTrusted: the program listening on the loopback port addr names
// runs as root, as this bastion's own user, or as the machine's recorded
// owner. Found without anyone setting PRIVATAE_LLM_ADDR, a model server is
// handed the Host's prompts, and any account on the machine can listen on
// 127.0.0.1:8080 while llama.cpp is not running; a server of another account
// is not taken (the variable still names one on purpose). The kernel's own
// table says who owns each listening socket (/proc/net/tcp, tcp6).
func llmListenerTrusted(addr string) bool {
port := portOfAddr(addr)
if port <= 0 {
return false
}
var uids []uint32
for _, f := range []string{"/proc/net/tcp", "/proc/net/tcp6"} {
if raw, err := os.ReadFile(f); err == nil {
uids = append(uids, loopbackListenerUIDs(string(raw), port)...)
}
}
owner, _, ownerKnown, _ := ownerAccountLoad()
return listenersTrusted(uids, uint32(os.Getuid()), owner, ownerKnown)
}
// listenersTrusted: there is a listener, and every one is root's, self's or
// the owner's.
func listenersTrusted(uids []uint32, self, owner uint32, ownerKnown bool) bool {
if len(uids) == 0 {
return false
}
for _, u := range uids {
if u != 0 && u != self && (!ownerKnown || u != owner) {
return false
}
}
return true
}
// loopbackListenerUIDs reads a /proc/net/tcp table: the uid of every socket
// LISTENing on port at a loopback or any-address local address.
func loopbackListenerUIDs(table string, port int) []uint32 {
var out []uint32
for _, line := range strings.Split(table, "\n")[1:] {
f := strings.Fields(line)
if len(f) < 8 || f[3] != "0A" {
continue
}
host, p, ok := strings.Cut(f[1], ":")
if !ok {
continue
}
if n, err := strconv.ParseUint(p, 16, 16); err != nil || int(n) != port {
continue
}
switch host {
case "0100007F", "00000000", "00000000000000000000000001000000", "00000000000000000000000000000000":
default:
if !strings.HasSuffix(host, "7F") || len(host) != 8 { // 127.x.y.z, little-endian
continue
}
}
if u, err := strconv.ParseUint(f[7], 10, 32); err == nil {
out = append(out, uint32(u))
}
}
return out
}