From 20c648026a4513c44e3b0e6ca1fd2d846aebb259 Mon Sep 17 00:00:00 2001 From: dma Date: Sat, 10 Nov 2018 00:24:25 -0500 Subject: [PATCH] additional fixes for citadel support + performance --- sgfw/dns.go | 5 ++ sgfw/ipc.go | 17 ++-- sgfw/iptables.go | 6 +- sgfw/policy.go | 87 +++++++++++-------- sgfw/prompt.go | 15 ++-- sgfw/sgfw.go | 5 +- sgfw/snitch-ext.go | 7 +- .../subgraph/go-procsnitch/proc_pid.go | 39 +++++---- .../subgraph/go-procsnitch/socket.go | 4 + 9 files changed, 113 insertions(+), 72 deletions(-) diff --git a/sgfw/dns.go b/sgfw/dns.go index 335bac9..371fd91 100644 --- a/sgfw/dns.go +++ b/sgfw/dns.go @@ -68,6 +68,9 @@ func (dc *dnsCache) processDNS(pkt *nfqueue.NFQPacket) { pinfo := getEmptyPInfo() if !isNSTrusted(srcip) { pinfo, _ = findProcessForPacket(pkt, true, procsnitch.MATCH_LOOSEST) + if pinfo == nil { + findProcessForPacket(pkt, false, procsnitch.MATCH_LOOSEST) + } if pinfo == nil { if !FirewallConfig.LogRedact { @@ -77,6 +80,8 @@ func (dc *dnsCache) processDNS(pkt *nfqueue.NFQPacket) { } return + } else { + log.Warningf("%v", pinfo) } } //log.Notice("XXX: PROCESS LOOKUP -> ", pinfo) diff --git a/sgfw/ipc.go b/sgfw/ipc.go index e20ddd5..5772352 100644 --- a/sgfw/ipc.go +++ b/sgfw/ipc.go @@ -18,13 +18,14 @@ const ReceiverSocketPath = "/var/run/fw-daemon/fwoz.sock" type OzInitProc struct { Name string Pid int + Address net.IP SandboxID int } var OzInitPids []OzInitProc = []OzInitProc{} var OzInitPidsLock = sync.Mutex{} -func addInitPid(pid int, name string, sboxid int) { +func addInitPid(pid int, name string, sboxid int, address net.IP) { fmt.Println("::::::::::: init pid added: ", pid, " -> ", name) OzInitPidsLock.Lock() defer OzInitPidsLock.Unlock() @@ -35,7 +36,7 @@ func addInitPid(pid int, name string, sboxid int) { } } - ozi := OzInitProc{Name: name, Pid: pid, SandboxID: sboxid} + ozi := OzInitProc{Name: name, Pid: pid, SandboxID: sboxid, Address:address} OzInitPids = append(OzInitPids, ozi) } @@ -160,7 +161,7 @@ func ReceiverLoop(fw *Firewall, c net.Conn) { if tokens[0] == "register-init" && len(tokens) >= 3 { initp := tokens[1] - initpid, err := strconv.Atoi(initp) + //initpid, err := strconv.Atoi(initp) if err != nil { log.Notice("IPC received invalid oz-init pid: ", initp) @@ -168,7 +169,7 @@ func ReceiverLoop(fw *Firewall, c net.Conn) { return } - sboxid, err := strconv.Atoi(tokens[3]) + //sboxid, err := strconv.Atoi(tokens[3]) if err != nil { log.Notice("IPC received invalid oz sbox number: ", tokens[3]) log.Notice("Data: %v", data) @@ -178,12 +179,12 @@ func ReceiverLoop(fw *Firewall, c net.Conn) { // ozname := strings.Join(tokens[2:], " ") log.Notice("IPC message for register-init OK.") - addInitPid(initpid, tokens[2], sboxid) + //addInitPid(initpid, tokens[2], sboxid) c.Write([]byte("OK")) return } else if tokens[0] == "unregister-init" && len(tokens) == 2 { initp := tokens[1] - initpid, err := strconv.Atoi(initp) + //initpid, err := strconv.Atoi(initp) if err != nil { log.Notice("IPC received invalid oz-init pid: ", initp) @@ -191,7 +192,7 @@ func ReceiverLoop(fw *Firewall, c net.Conn) { return } - removeInitPid(initpid) + //removeInitPid(initpid) c.Write([]byte("OK.\n")) } @@ -283,7 +284,7 @@ func OzReceiver(fw *Firewall) { log.Warning("Adding existing Oz sandbox init pids...") for s := 0; s < len(sboxes); s++ { //profname := fmt.Sprintf("%s (%d)", sboxes[s].Profile, sboxes[s].Id) - addInitPid(sboxes[s].InitPid, sboxes[s].Name, sboxes[s].Id) + addInitPid(sboxes[s].InitPid, sboxes[s].Name, sboxes[s].Id, sboxes[s].Address) } } else { log.Warning("It does not appear there were any Oz sandboxed processes already launched.") diff --git a/sgfw/iptables.go b/sgfw/iptables.go index d9cede2..aa6edc4 100644 --- a/sgfw/iptables.go +++ b/sgfw/iptables.go @@ -9,14 +9,18 @@ import ( const iptablesRule = "OUTPUT -t mangle -m conntrack --ctstate NEW -j NFQUEUE --queue-num 0 --queue-bypass" const realmsRule = "FORWARD -t mangle -m conntrack --ctstate NEW -j NFQUEUE --queue-num 0 --queue-bypass" +const dnsRule2 = "FORWARD --protocol udp --sport 53 -j NFQUEUE --queue-num 0 --queue-bypass" const dnsRule = "INPUT --protocol udp --sport 53 -j NFQUEUE --queue-num 0 --queue-bypass" //const logRule = "OUTPUT --protocol tcp -m mark --mark 1 -j LOG" const blockRule = "OUTPUT --protocol tcp -m mark --mark 1 -j REJECT" +const blockRule2 = "FORWARD --protocol tcp -m mark --mark 1 -j REJECT" func setupIPTables() { // addIPTRules(iptablesRule, dnsRule, logRule, blockRule) - addIPTRules(iptablesRule, realmsRule, dnsRule, blockRule) +// addIPTRules(iptablesRule, realmsRule, dnsRule, dnsRule2, blockRule,blockRule2) + //addIPTRules(iptablesRule, realmsRule, dnsRule, blockRule) + addIPTRules(iptablesRule, realmsRule, dnsRule, dnsRule2, blockRule,blockRule2) } func addIPTRules(rules ...string) { diff --git a/sgfw/policy.go b/sgfw/policy.go index 979560d..b8c0e50 100644 --- a/sgfw/policy.go +++ b/sgfw/policy.go @@ -606,7 +606,7 @@ func (fw *Firewall) filterPacket(pkt *nfqueue.NFQPacket, timestamp time.Time) { // return } else { ppath = pinfo.ExePath - optstring = fmt.Sprintf("Realm: %s", pinfo.Realm); + optstring = fmt.Sprintf("Realm: %s", pinfo.Realm) cf := strings.Fields(pinfo.CmdLine) if len(cf) > 1 && strings.HasPrefix(cf[1], "/") { for _, intp := range _interpreters { @@ -846,53 +846,61 @@ func findProcessForPacket(pkt *nfqueue.NFQPacket, reverse bool, strictness int) res = procsnitch.LookupICMPSocketProcessAll(srcip, dstip, icode, nil) } + if res != nil { + res.Sandbox = "citadel" + res.Realm = "citadel" + } + if res == nil { removePids := make([]int, 0) OzInitPidsLock.Lock() - + for i := 0; i < len(OzInitPids); i++ { - data := "" - fname := fmt.Sprintf("/proc/%d/root/proc/1/net/%s", OzInitPids[i].Pid, proto) - //fmt.Println("XXX: opening: ", fname) - bdata, err := readFileDirect(fname) + if OzInitPids[i].Address.Equal(srcip) { + data := "" + fname := fmt.Sprintf("/proc/%d/root/proc/1/net/%s", OzInitPids[i].Pid, proto) + //fmt.Println("XXX: opening: ", fname) + bdata, err := readFileDirect(fname) - if err != nil { - fmt.Println("Error reading proc data from ", fname, ": ", err) + if err != nil { + fmt.Println("Error reading proc data from ", fname, ": ", err) - if err == syscall.ENOENT { - removePids = append(removePids, OzInitPids[i].Pid) - } + if err == syscall.ENOENT { + removePids = append(removePids, OzInitPids[i].Pid) + } - continue - } else { - data = string(bdata) - lines := strings.Split(data, "\n") - rlines := make([]string, 0) + continue + } else { + data = string(bdata) + lines := strings.Split(data, "\n") + rlines := make([]string, 0) - for l := 0; l < len(lines); l++ { - lines[l] = strings.TrimSpace(lines[l]) - ssplit := strings.Split(lines[l], ":") + for l := 0; l < len(lines); l++ { + lines[l] = strings.TrimSpace(lines[l]) + ssplit := strings.Split(lines[l], ":") - if len(ssplit) != 6 { - continue - } + if len(ssplit) != 6 { + continue + } - rlines = append(rlines, strings.Join(ssplit, ":")) - } + rlines = append(rlines, strings.Join(ssplit, ":")) + } - if proto == "tcp" { - //res = procsnitch.LookupTCPSocketProcessAll(srcip, srcp, dstip, dstp, rlines) - res = procsnitch.L2(srcp, dstip, dstp, rlines) - } else if proto == "udp" { - res = procsnitch.LookupUDPSocketProcessAll(srcip, srcp, dstip, dstp, rlines, strictness) - } else if proto == "icmp" { - res = procsnitch.LookupICMPSocketProcessAll(srcip, dstip, icode, rlines) - } + if proto == "tcp" { + //res = procsnitch.LookupTCPSocketProcessAll(srcip, srcp, dstip, dstp, rlines) + res = procsnitch.L2(srcp, dstip, dstp, rlines) + } else if proto == "udp" { + res = procsnitch.LookupUDPSocketProcessAll(srcip, srcp, dstip, dstp, rlines, strictness) + } else if proto == "icmp" { + res = procsnitch.LookupICMPSocketProcessAll(srcip, dstip, icode, rlines) + } - if res != nil { - optstr = "Realm: " + OzInitPids[i].Name - res.ExePath = GetRealRoot(res.ExePath, OzInitPids[i].Pid) - break + if res != nil { + optstr = "Realm: " + OzInitPids[i].Name + res.Sandbox = OzInitPids[i].Name + res.ExePath = GetRealRoot(res.ExePath, OzInitPids[i].Pid) + break + } } } @@ -912,10 +920,15 @@ func findProcessForPacket(pkt *nfqueue.NFQPacket, reverse bool, strictness int) func basicAllowPacket(pkt *nfqueue.NFQPacket) bool { srcip, dstip := getPacketIPAddrs(pkt) if pkt.Packet.Layer(layers.LayerTypeUDP) != nil { - _, dport := getPacketUDPPorts(pkt) + sport, dport := getPacketUDPPorts(pkt) if dport == 53 { // fw.dns.processDNS(pkt) return true + } else { + if sport == 53 { + // fw.dns.processDNS(pkt) + return true + } } } if pkt.Packet.Layer(layers.LayerTypeICMPv4) != nil && srcip.Equal(dstip) { diff --git a/sgfw/prompt.go b/sgfw/prompt.go index 464cc01..a8cb987 100644 --- a/sgfw/prompt.go +++ b/sgfw/prompt.go @@ -150,6 +150,7 @@ var PC2FDMapLock = &sync.Mutex{} func monitorPromptFDs(pc pendingConnection) { guid := pc.getGUID() pid := pc.procInfo().Pid + //leaderpid := pc.procInfo().LeaderPid inode := pc.procInfo().Inode fd := pc.procInfo().FD prompter := pc.getPrompter() @@ -157,17 +158,21 @@ func monitorPromptFDs(pc pendingConnection) { //fmt.Printf("ADD TO MONITOR: %v | %v / %v / %v\n", pc.policy().application, guid, pid, fd) if pid == -1 || fd == -1 || prompter == nil { - log.Warning("Unexpected error condition occurred while adding socket fd to monitor: %d %d %v",pid, fd, prompter) + log.Warningf("Unexpected error condition occurred while adding socket fd to monitor: %d %d %v",pid, fd, prompter) return - } else - { + } else { log.Warning("No unexpected errors"); } PC2FDMapLock.Lock() defer PC2FDMapLock.Unlock() - - fdpath := fmt.Sprintf("/proc/%d/fd/%d", pid, fd) + var fdpath string +// log.Warning("leaderpid:",pc.procInfo().LeaderPid) + //if pc.procInfo().LeaderPid != "" { +// fdpath = fmt.Sprintf("/proc/%s/root/%d/fd/%d", leaderpid, pid, fd) +// } else { + fdpath = fmt.Sprintf("/proc/%d/fd/%d", pid, fd) +// } PC2FDMap[guid] = PC2FDMapping{guid: guid, inode: inode, fd: fd, fdpath: fdpath, prompter: prompter} return } diff --git a/sgfw/sgfw.go b/sgfw/sgfw.go index a29acd5..750fc84 100644 --- a/sgfw/sgfw.go +++ b/sgfw/sgfw.go @@ -123,8 +123,9 @@ func (fw *Firewall) runFilter() { p.Packet = ip6p } - - fw.filterPacket(p, timestamp) + var pkt nfqueue.NFQPacket + pkt = *p + go fw.filterPacket(&pkt, timestamp) } else { p.Accept() } diff --git a/sgfw/snitch-ext.go b/sgfw/snitch-ext.go index d64fcec..617436f 100644 --- a/sgfw/snitch-ext.go +++ b/sgfw/snitch-ext.go @@ -7,6 +7,7 @@ import ( "os" "bufio" "strconv" + "net" "github.com/godbus/dbus" ) @@ -16,7 +17,7 @@ type ListSandboxesMsg struct { type SandboxInfo struct { Id int - Address string + Address net.IP Name string Profile string Mounts []string @@ -53,8 +54,8 @@ func getSandboxes() ([]SandboxInfo, error) { s := strings.Split(scanner.Text(), ":") obj.Call("com.subgraph.realms.Manager.LeaderPidFromIP", 0, s[1]).Store(&leaderpid) p, _ := strconv.Atoi(leaderpid) - sboxes = append(sboxes,SandboxInfo{Id: i, Name: s[0], Address: s[1], InitPid: p}) - fmt.Print(s[0], s[1], leaderpid) + sboxes = append(sboxes,SandboxInfo{Id: i, Name: s[0], Address: net.ParseIP(s[1]), InitPid: p}) + log.Warningf("Found realm, name=%v ip=%v leader pid=%v ", s[0], s[1], leaderpid) i++; } diff --git a/vendor/github.com/subgraph/go-procsnitch/proc_pid.go b/vendor/github.com/subgraph/go-procsnitch/proc_pid.go index b6d9dcd..104d963 100644 --- a/vendor/github.com/subgraph/go-procsnitch/proc_pid.go +++ b/vendor/github.com/subgraph/go-procsnitch/proc_pid.go @@ -9,7 +9,7 @@ import ( "strings" "sync" "syscall" - "github.com/godbus/dbus" + //"github.com/godbus/dbus" ) // Info is a struct containing the result of a socket proc query @@ -25,7 +25,8 @@ type Info struct { ParentCmdLine string ParentExePath string Realm string - Sandbox string + Sandbox string + LeaderPid string Inode uint64 FD int } @@ -139,13 +140,24 @@ func (pi *Info) loadProcessInfo() bool { if pi.loaded { return true } - - exePath, err := os.Readlink(fmt.Sprintf("/proc/%d/exe", pi.Pid)) + leaderpid := "" + realm := "unknown" + //conn, _ := dbus.SystemBus() + //obj := conn.Object("com.subgraph.realms", "/") + //obj.Call("com.subgraph.realms.Manager.RealmFromContainerPid", 0, fmt.Sprintf("%d",pi.Pid)).Store(&realm) + //obj.Call("com.subgraph.realms.Manager.LeaderPidFromRealm", 0, realm).Store(&leaderpid) + pi.LeaderPid = leaderpid + prefix := "" + if leaderpid != "" { + prefix = fmt.Sprintf("/proc/%s/root",leaderpid) + } + prefix = "" + exePath, err := os.Readlink(fmt.Sprintf("%s/proc/%d/exe", prefix, pi.Pid)) if err != nil { log.Warningf("Error reading exe link for pid %d: %v", pi.Pid, err) return false } - bcs, err := ioutil.ReadFile(fmt.Sprintf("/proc/%d/cmdline", pi.Pid)) + bcs, err := ioutil.ReadFile(fmt.Sprintf("%s/proc/%d/cmdline", prefix, pi.Pid)) if err != nil { log.Warningf("Error reading cmdline for pid %d: %v", pi.Pid, err) return false @@ -156,7 +168,7 @@ func (pi *Info) loadProcessInfo() bool { } } - bs, err := ioutil.ReadFile(fmt.Sprintf("/proc/%d/stat", pi.Pid)) + bs, err := ioutil.ReadFile(fmt.Sprintf("%s/proc/%d/stat", prefix, pi.Pid)) if err != nil { log.Warningf("Error reading cmdline for pid %d: %v", pi.Pid, err) return false @@ -168,12 +180,12 @@ func (pi *Info) loadProcessInfo() bool { } ppid := toPid(fs[3]) - pexePath, err := os.Readlink(fmt.Sprintf("/proc/%d/exe", ppid)) + pexePath, err := os.Readlink(fmt.Sprintf("%s/proc/%d/exe", prefix, ppid)) if err != nil { log.Warningf("Error reading exe link for parent pid %d: %v", ppid, err) return false } - pbs, err := ioutil.ReadFile(fmt.Sprintf("/proc/%d/cmdline", ppid)) + pbs, err := ioutil.ReadFile(fmt.Sprintf("%s/proc/%d/cmdline", prefix, ppid)) if err != nil { log.Warningf("Error reading cmdline for parent pid %d: %v", ppid, err) return false @@ -184,14 +196,9 @@ func (pi *Info) loadProcessInfo() bool { } } - conn, _ := dbus.SystemBus() - obj := conn.Object("com.subgraph.realms", "/") - realm := "unknown" - //leaderpid := "" - - obj.Call("com.subgraph.realms.Manager.RealmFromContainerPid", 0, fmt.Sprintf("%d",pi.Pid)).Store(&realm) - finfo, err := os.Stat(fmt.Sprintf("/proc/%d", pi.Pid)) + + finfo, err := os.Stat(fmt.Sprintf("%s/proc/%d", prefix, pi.Pid)) if err != nil { log.Warningf("Could not stat /proc/%d: %v", pi.Pid, err) return false @@ -205,7 +212,7 @@ func (pi *Info) loadProcessInfo() bool { pi.ExePath = exePath pi.Realm = realm pi.Sandbox = realm - //pi.Leaderpid = leaderpid + pi.LeaderPid = leaderpid pi.CmdLine = string(bcs) pi.loaded = true return true diff --git a/vendor/github.com/subgraph/go-procsnitch/socket.go b/vendor/github.com/subgraph/go-procsnitch/socket.go index 7faa815..56ba3f8 100644 --- a/vendor/github.com/subgraph/go-procsnitch/socket.go +++ b/vendor/github.com/subgraph/go-procsnitch/socket.go @@ -254,6 +254,10 @@ func findTCPSocketAll(srcAddr net.IP, srcPort uint16, dstAddr net.IP, dstPort ui func f2(srcPort uint16, dstAddr net.IP, dstPort uint16, custdata[]string) *socketStatus { proto := "tcp" +/* if dstAddr.To4() == nil { + proto += "6" + } +*/ return findSocketCustom(proto, custdata, func(ss socketStatus) bool { return ss.remote.port == dstPort && ss.remote.ip.Equal(dstAddr) && ss.local.port == srcPort })