From 0d13c7bb9c5a8665327c1fac30999c6a829fcd83 Mon Sep 17 00:00:00 2001 From: Stephen Watt Date: Wed, 27 Sep 2017 16:26:59 -0400 Subject: [PATCH] *WORK IN PROGRESS*: New file descriptor monitor thread removes prompt requests if associated socket closes/dies before user reacts. fw-prompt request entries are now properly tethered to their default rule scope included by SGFW. pendingConnection now operates on prompter instead of raw DBus object. Fixed prompter bug in cycling through pending connections. Fixed inadequacies in SGFW rules parsing/error handling. go fmt. --- TODO | 6 + fw-prompt/dbus.go | 4 +- fw-prompt/fw-prompt.go | 51 +++-- sgfw/dbus.go | 7 +- sgfw/policy.go | 22 +-- sgfw/prompt.go | 187 +++++++++++++++--- sgfw/rules.go | 9 + sgfw/socks_server_chain.go | 6 +- .../github.com/subgraph/go-procsnitch/proc.go | 19 +- .../subgraph/go-procsnitch/proc_pid.go | 22 ++- .../subgraph/go-procsnitch/socket.go | 38 ++-- 11 files changed, 276 insertions(+), 95 deletions(-) create mode 100644 TODO diff --git a/TODO b/TODO new file mode 100644 index 0000000..59791c2 --- /dev/null +++ b/TODO @@ -0,0 +1,6 @@ +fw-prompt: + This function needs to be updated because it no longer works: + func toggleHover() { mainWin.SetKeepAbove(len(decisionWaiters) > 0) } + +new go-procsnitch vendor package changes should be pushed into main project + diff --git a/fw-prompt/dbus.go b/fw-prompt/dbus.go index d9ca0fe..8a300a8 100644 --- a/fw-prompt/dbus.go +++ b/fw-prompt/dbus.go @@ -55,7 +55,7 @@ func newDbusServer() (*dbusServer, error) { func (ds *dbusServer) RequestPrompt(guid, application, icon, path, address string, port int32, ip, origin, proto string, uid, gid int32, username, groupname string, pid int32, sandbox string, is_socks bool, optstring string, expanded, expert bool, action int32) (int32, string, *dbus.Error) { log.Printf("request prompt: app = %s, icon = %s, path = %s, address = %s / ip = %s, is_socks = %v, action = %v\n", application, icon, path, address, ip, is_socks, action) - decision := addRequest(nil, guid, path, icon, proto, int(pid), ip, address, int(port), int(uid), int(gid), origin, is_socks, optstring, sandbox) + decision := addRequest(nil, guid, path, icon, proto, int(pid), ip, address, int(port), int(uid), int(gid), origin, is_socks, optstring, sandbox, int(action)) log.Print("Waiting on decision...") decision.Cond.L.Lock() for !decision.Ready { @@ -69,7 +69,7 @@ func (ds *dbusServer) RequestPrompt(guid, application, icon, path, address strin func (ds *dbusServer) RequestPromptAsync(guid, application, icon, path, address string, port int32, ip, origin, proto string, uid, gid int32, username, groupname string, pid int32, sandbox string, is_socks bool, optstring string, expanded, expert bool, action int32) (bool, *dbus.Error) { log.Printf("ASYNC request prompt: guid = %s, app = %s, icon = %s, path = %s, address = %s / ip = %s, is_socks = %v, action = %v\n", guid, application, icon, path, address, ip, is_socks, action) - addRequestAsync(nil, guid, path, icon, proto, int(pid), ip, address, int(port), int(uid), int(gid), origin, is_socks, optstring, sandbox) + addRequestAsync(nil, guid, path, icon, proto, int(pid), ip, address, int(port), int(uid), int(gid), origin, is_socks, optstring, sandbox, int(action)) return true, nil } diff --git a/fw-prompt/fw-prompt.go b/fw-prompt/fw-prompt.go index 786371d..8c97b17 100644 --- a/fw-prompt/fw-prompt.go +++ b/fw-prompt/fw-prompt.go @@ -314,8 +314,8 @@ func createColumn(title string, id int) *gtk.TreeViewColumn { } func createListStore(general bool) *gtk.ListStore { - colData := []glib.Type{glib.TYPE_INT, glib.TYPE_STRING, glib.TYPE_STRING, glib.TYPE_STRING, glib.TYPE_STRING, glib.TYPE_INT, - glib.TYPE_STRING, glib.TYPE_STRING, glib.TYPE_INT, glib.TYPE_INT, glib.TYPE_INT, glib.TYPE_STRING, glib.TYPE_INT, glib.TYPE_STRING} + colData := []glib.Type{glib.TYPE_INT, glib.TYPE_STRING, glib.TYPE_STRING, glib.TYPE_STRING, glib.TYPE_STRING, glib.TYPE_INT, glib.TYPE_STRING, + glib.TYPE_STRING, glib.TYPE_INT, glib.TYPE_INT, glib.TYPE_INT, glib.TYPE_STRING, glib.TYPE_INT, glib.TYPE_STRING, glib.TYPE_INT} listStore, err := gtk.ListStoreNew(colData...) if err != nil { @@ -350,7 +350,8 @@ func removeRequest(listStore *gtk.ListStore, guid string) { } -func addRequestInc(listStore *gtk.ListStore, guid, path, icon, proto string, pid int, ipaddr, hostname string, port, uid, gid int, origin string, is_socks bool, optstring string, sandbox string) bool { +func addRequestInc(listStore *gtk.ListStore, guid, path, icon, proto string, pid int, ipaddr, hostname string, port, uid, gid int, + origin string, is_socks bool, optstring string, sandbox string, action int) bool { duplicated := false globalPromptLock.Lock() @@ -383,7 +384,8 @@ func addRequestInc(listStore *gtk.ListStore, guid, path, icon, proto string, pid return duplicated } -func addRequestAsync(listStore *gtk.ListStore, guid, path, icon, proto string, pid int, ipaddr, hostname string, port, uid, gid int, origin string, is_socks bool, optstring string, sandbox string) bool { +func addRequestAsync(listStore *gtk.ListStore, guid, path, icon, proto string, pid int, ipaddr, hostname string, port, uid, gid int, + origin string, is_socks bool, optstring string, sandbox string, action int) bool { if listStore == nil { listStore = globalLS waitTimes := []int{1, 2, 5, 10} @@ -410,7 +412,7 @@ func addRequestAsync(listStore *gtk.ListStore, guid, path, icon, proto string, p log.Fatal("SGFW prompter GUI failed to load for unknown reasons") } - if addRequestInc(listStore, guid, path, icon, proto, pid, ipaddr, hostname, port, uid, gid, origin, is_socks, optstring, sandbox) { + if addRequestInc(listStore, guid, path, icon, proto, pid, ipaddr, hostname, port, uid, gid, origin, is_socks, optstring, sandbox, action) { fmt.Println("REQUEST WAS DUPLICATE") return false } else { @@ -428,7 +430,7 @@ func addRequestAsync(listStore *gtk.ListStore, guid, path, icon, proto string, p } } - colVals := make([]interface{}, 14) + colVals := make([]interface{}, 15) colVals[0] = 1 colVals[1] = guid colVals[2] = path @@ -454,6 +456,7 @@ func addRequestAsync(listStore *gtk.ListStore, guid, path, icon, proto string, p } colVals[13] = optstring + colVals[14] = action colNums := make([]int, len(colVals)) @@ -472,7 +475,8 @@ func addRequestAsync(listStore *gtk.ListStore, guid, path, icon, proto string, p return true } -func addRequest(listStore *gtk.ListStore, guid, path, icon, proto string, pid int, ipaddr, hostname string, port, uid, gid int, origin string, is_socks bool, optstring string, sandbox string) *decisionWaiter { +func addRequest(listStore *gtk.ListStore, guid, path, icon, proto string, pid int, ipaddr, hostname string, port, uid, gid int, + origin string, is_socks bool, optstring string, sandbox string, action int) *decisionWaiter { if listStore == nil { listStore = globalLS waitTimes := []int{1, 2, 5, 10} @@ -499,7 +503,7 @@ func addRequest(listStore *gtk.ListStore, guid, path, icon, proto string, pid in log.Fatal("SGFW prompter GUI failed to load for unknown reasons") } - if addRequestInc(listStore, guid, path, icon, proto, pid, ipaddr, hostname, port, uid, gid, origin, is_socks, optstring, sandbox) { + if addRequestInc(listStore, guid, path, icon, proto, pid, ipaddr, hostname, port, uid, gid, origin, is_socks, optstring, sandbox, action) { fmt.Println("REQUEST WAS DUPLICATE") decision := addDecision() toggleHover() @@ -519,7 +523,7 @@ func addRequest(listStore *gtk.ListStore, guid, path, icon, proto string, pid in } } - colVals := make([]interface{}, 14) + colVals := make([]interface{}, 15) colVals[0] = 1 colVals[1] = guid colVals[2] = path @@ -545,6 +549,7 @@ func addRequest(listStore *gtk.ListStore, guid, path, icon, proto string, pid in } colVals[13] = optstring + colVals[14] = action colNums := make([]int, len(colVals)) @@ -774,6 +779,7 @@ func createCurrentRule() (ruleColumns, error) { rule.Uname, rule.Gname = "", "" rule.ForceTLS = chkTLS.GetActive() + /* Pid int Origin string */ @@ -915,6 +921,11 @@ func getRuleByIdx(idx int) (ruleColumns, *gtk.TreeIter, error) { rule.IsSocks = true } + rule.Scope, err = lsGetInt(globalLS, iter, 14) + if err != nil { + return rule, nil, err + } + return rule, iter, nil } @@ -953,7 +964,7 @@ func addPendingPrompts(rules []string) { for _, rule := range rules { fields := strings.Split(rule, "|") - if len(fields) != 17 { + if len(fields) != 18 { log.Printf("Got saved prompt message with strange data: \"%s\"", rule) continue } @@ -1001,7 +1012,13 @@ func addPendingPrompts(rules []string) { optstring := fields[16] - addRequestAsync(nil, guid, path, icon, proto, int(pid), ip, address, int(port), int(uid), int(gid), origin, is_socks, optstring, sandbox) + action, err := strconv.Atoi(fields[17]) + if err != nil { + log.Println("Error converting action in pending prompt message to integer:", err) + continue + } + + addRequestAsync(nil, guid, path, icon, proto, int(pid), ip, address, int(port), int(uid), int(gid), origin, is_socks, optstring, sandbox, action) } } @@ -1206,6 +1223,10 @@ func main() { tv.AppendColumn(createColumn("Details", 13)) + acol := createColumn("Scope", 14) + acol.SetVisible(false) + tv.AppendColumn(acol) + listStore := createListStore(true) globalLS = listStore @@ -1322,12 +1343,12 @@ func main() { } editPort.SetText(strconv.Itoa(seldata.Port)) - radioOnce.SetActive(true) - radioProcess.SetActive(false) + radioOnce.SetActive(seldata.Scope == int(sgfw.APPLY_ONCE)) radioProcess.SetSensitive(seldata.Pid > 0) radioParent.SetActive(false) - radioSession.SetActive(false) - radioPermanent.SetActive(false) + radioSession.SetActive(seldata.Scope == int(sgfw.APPLY_SESSION)) + radioPermanent.SetActive(seldata.Scope == int(sgfw.APPLY_FOREVER)) + comboProto.SetActiveID(seldata.Proto) chkTLS.SetActive(seldata.IsSocks) diff --git a/sgfw/dbus.go b/sgfw/dbus.go index 9abfa99..a853d5e 100644 --- a/sgfw/dbus.go +++ b/sgfw/dbus.go @@ -241,7 +241,8 @@ func (ds *dbusServer) GetPendingRequests(policy string) ([]string, *dbus.Error) pstr += strconv.FormatInt(int64(pc.procInfo().Pid), 10) + "|" pstr += pc.sandbox() + "|" pstr += strconv.FormatBool(pc.socks()) + "|" - pstr += pc.getOptString() + pstr += pc.getOptString() + "|" + pstr += strconv.FormatUint(uint64(FirewallConfig.DefaultActionID), 10) pending_data = append(pending_data, pstr) } @@ -334,10 +335,10 @@ func (ds *dbusServer) SetConfig(key string, val dbus.Variant) *dbus.Error { return nil } -func (ds *dbusServer) prompt(p *Policy) { +/*func (ds *dbusServer) prompt(p *Policy) { log.Info("prompting...") ds.prompter.prompt(p) -} +} */ func (ob *dbusObjectP) alertRule(data string) { ob.Call("com.subgraph.fwprompt.EventNotifier.Alert", 0, data) diff --git a/sgfw/policy.go b/sgfw/policy.go index 2f9858d..03ab932 100644 --- a/sgfw/policy.go +++ b/sgfw/policy.go @@ -50,8 +50,8 @@ type pendingConnection interface { drop() setPrompting(bool) getPrompting() bool - setPrompter(*dbusObjectP) - getPrompter() *dbusObjectP + setPrompter(*prompter) + getPrompter() *prompter getGUID() string print() string } @@ -63,7 +63,7 @@ type pendingPkt struct { pinfo *procsnitch.Info optstring string prompting bool - prompter *dbusObjectP + prompter *prompter guid string } @@ -183,11 +183,11 @@ func (pp *pendingPkt) drop() { pp.pkt.Accept() } -func (pp *pendingPkt) setPrompter(val *dbusObjectP) { +func (pp *pendingPkt) setPrompter(val *prompter) { pp.prompter = val } -func (pp *pendingPkt) getPrompter() *dbusObjectP { +func (pp *pendingPkt) getPrompter() *prompter { return pp.prompter } @@ -320,32 +320,24 @@ func (p *Policy) processPromptResult(pc pendingConnection) { //if DoMultiPrompt || (!DoMultiPrompt && !p.promptInProgress) { // if !p.promptInProgress { p.promptInProgress = true - go p.fw.dbus.prompt(p) + go p.fw.dbus.prompter.prompt(p) // } } func (p *Policy) nextPending() (pendingConnection, bool) { p.lock.Lock() defer p.lock.Unlock() - /* if !DoMultiPrompt { - if len(p.pendingQueue) == 0 { - return nil, true - } - return p.pendingQueue[0], false - }*/ if len(p.pendingQueue) == 0 { return nil, true } - // for len(p.pendingQueue) != 0 { for i := 0; i < len(p.pendingQueue); i++ { fmt.Printf("pendingQueue %v of %v: %v\n", i, len(p.pendingQueue), p.pendingQueue[i]) if !p.pendingQueue[i].getPrompting() { return p.pendingQueue[i], false } } - // } return nil, false } @@ -421,7 +413,7 @@ func (p *Policy) filterPending(rule *Rule) { if prompter == nil { fmt.Println("-------- prompter = NULL") } else { - call := prompter.Call("com.subgraph.FirewallPrompt.RemovePrompt", 0, pc.getGUID()) + call := prompter.dbusObj.Call("com.subgraph.FirewallPrompt.RemovePrompt", 0, pc.getGUID()) fmt.Println("CAAAAAAAAAAAAAAALL = ", call) } diff --git a/sgfw/prompt.go b/sgfw/prompt.go index ee72a13..2705e38 100644 --- a/sgfw/prompt.go +++ b/sgfw/prompt.go @@ -3,10 +3,12 @@ package sgfw import ( "fmt" "net" + "os" "os/user" "strconv" "strings" "sync" + "syscall" "time" "github.com/godbus/dbus" @@ -35,6 +37,7 @@ func (p *prompter) prompt(policy *Policy) { defer p.lock.Unlock() _, ok := p.policyMap[policy.sandbox+"|"+policy.path] if ok { + p.cond.Signal() return } p.policyMap[policy.sandbox+"|"+policy.path] = policy @@ -44,21 +47,23 @@ func (p *prompter) prompt(policy *Policy) { } func (p *prompter) promptLoop() { - p.lock.Lock() + // p.lock.Lock() for { // fmt.Println("XXX: promptLoop() outer") + p.lock.Lock() for p.processNextPacket() { // fmt.Println("XXX: promptLoop() inner") } + p.lock.Unlock() // fmt.Println("promptLoop() wait") - p.cond.Wait() + // p.cond.Wait() } } func (p *prompter) processNextPacket() bool { var pc pendingConnection = nil - if 1 == 2 { + /* if 1 == 2 { // if !DoMultiPrompt { pc, _ = p.nextConnection() if pc == nil { @@ -68,12 +73,12 @@ func (p *prompter) processNextPacket() bool { defer p.lock.Lock() p.processConnection(pc) return true - } + } */ empty := true for { pc, empty = p.nextConnection() - // fmt.Println("XXX: processNextPacket() loop; empty = ", empty, " / pc = ", pc) + fmt.Println("XXX: processNextPacket() loop; empty = ", empty, " / pc = ", pc) if pc == nil && empty { return false } else if pc == nil { @@ -85,27 +90,145 @@ func (p *prompter) processNextPacket() bool { p.lock.Unlock() defer p.lock.Lock() // fmt.Println("XXX: Waiting for prompt lock go...") - for { - - if pc.getPrompting() { - log.Debugf("Skipping over already prompted connection") - continue - } - - break + if pc.getPrompting() { + log.Debugf("Skipping over already prompted connection") } + pc.setPrompting(true) go p.processConnection(pc) return true } +type PC2FDMapping struct { + guid string + inode uint64 + fd int + fdpath string + prompter *prompter +} + +var PC2FDMap = map[string]PC2FDMapping{} +var PC2FDMapLock = &sync.Mutex{} +var PC2FDMapRunning = false + +func monitorPromptFDs(pc pendingConnection) { + guid := pc.getGUID() + pid := pc.procInfo().Pid + inode := pc.procInfo().Inode + fd := pc.procInfo().FD + prompter := pc.getPrompter() + + 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") + return + } + + PC2FDMapLock.Lock() + defer PC2FDMapLock.Unlock() + + fdpath := fmt.Sprintf("/proc/%d/fd/%d", pid, fd) + PC2FDMap[guid] = PC2FDMapping{guid: guid, inode: inode, fd: fd, fdpath: fdpath, prompter: prompter} + return +} + +func monitorPromptFDLoop() { + fmt.Println("++++++++++= monitorPromptFDLoop()") + + for true { + delete_guids := []string{} + PC2FDMapLock.Lock() + fmt.Println("++++ nentries = ", len(PC2FDMap)) + + for guid, fdmon := range PC2FDMap { + fmt.Println("ENTRY:", fdmon) + + lsb, err := os.Stat(fdmon.fdpath) + if err != nil { + log.Warningf("Error looking up socket \"%s\": %v\n", fdmon.fdpath, err) + delete_guids = append(delete_guids, guid) + continue + } + + sb, ok := lsb.Sys().(*syscall.Stat_t) + if !ok { + log.Warning("Not a syscall.Stat_t") + delete_guids = append(delete_guids, guid) + continue + } + + inode := sb.Ino + fmt.Println("+++ INODE = ", inode) + + if inode != fdmon.inode { + fmt.Printf("inode mismatch: %v vs %v\n", inode, fdmon.inode) + delete_guids = append(delete_guids, guid) + } + + } + + fmt.Println("guids to delete: ", delete_guids) + saved_mappings := []PC2FDMapping{} + for _, guid := range delete_guids { + saved_mappings = append(saved_mappings, PC2FDMap[guid]) + delete(PC2FDMap, guid) + } + + PC2FDMapLock.Unlock() + + for _, mapping := range saved_mappings { + call := mapping.prompter.dbusObj.Call("com.subgraph.FirewallPrompt.RemovePrompt", 0, mapping.guid) + fmt.Println("DISPOSING CALL = ", call) + prompter := mapping.prompter + + prompter.lock.Lock() + + for _, policy := range prompter.policyQueue { + policy.lock.Lock() + pcind := 0 + + for pcind < len(policy.pendingQueue) { + + if policy.pendingQueue[pcind].getGUID() == mapping.guid { + fmt.Println("-------------- found guid to remove") + policy.pendingQueue = append(policy.pendingQueue[:pcind], policy.pendingQueue[pcind+1:]...) + } else { + pcind++ + } + + } + + policy.lock.Unlock() + } + + prompter.lock.Unlock() + } + + fmt.Println("++++++++++= monitorPromptFDLoop WAIT") + time.Sleep(5 * time.Second) + } + +} + func (p *prompter) processConnection(pc pendingConnection) { var scope int32 var dres bool var rule string + if !PC2FDMapRunning { + PC2FDMapLock.Lock() + + if !PC2FDMapRunning { + PC2FDMapRunning = true + PC2FDMapLock.Unlock() + go monitorPromptFDLoop() + } + + } + if pc.getPrompter() == nil { - pc.setPrompter(&dbusObjectP{p.dbusObj}) + pc.setPrompter(p) } addr := pc.hostname() @@ -127,6 +250,7 @@ func (p *prompter) processConnection(pc pendingConnection) { // fmt.Println("# outstanding prompt chans = ", len(outstandingPromptChans)) // fmt.Println("ABOUT TO CALL ASYNC PROMPT") + monitorPromptFDs(pc) call := p.dbusObj.Call("com.subgraph.FirewallPrompt.RequestPromptAsync", 0, pc.getGUID(), policy.application, @@ -300,15 +424,23 @@ func (p *prompter) processConnection(pc pendingConnection) { } func (p *prompter) nextConnection() (pendingConnection, bool) { - for { - if len(p.policyQueue) == 0 { - return nil, true - } - policy := p.policyQueue[0] + pind := 0 + + if len(p.policyQueue) == 0 { + return nil, true + } + fmt.Println("policy queue len = ", len(p.policyQueue)) + + for pind < len(p.policyQueue) { + fmt.Printf("pind = %v of %v\n", pind, len(p.policyQueue)) + policy := p.policyQueue[pind] pc, qempty := policy.nextPending() + if pc == nil && qempty { p.removePolicy(policy) + continue } else { + pind++ // if pc == nil && !qempty { if len(policy.rulesPending) > 0 { @@ -360,17 +492,24 @@ func (p *prompter) nextConnection() (pendingConnection, bool) { dbusp.alertRule("sgfw prompt added new rule") } - // } + } - if pc == nil && !qempty { - log.Errorf("FIX ME: I NEED TO SLEEP ON A WAKEABLE CONDITION PROPERLY!!") - time.Sleep(time.Millisecond * 300) - } + if pc == nil && !qempty { + // log.Errorf("FIX ME: I NEED TO SLEEP ON A WAKEABLE CONDITION PROPERLY!!") + time.Sleep(time.Millisecond * 300) + continue + } + if pc != nil && pc.getPrompting() { + fmt.Println("SKIPPING PROMPTED") + continue } + return pc, qempty } } + + return nil, true } func (p *prompter) removePolicy(policy *Policy) { diff --git a/sgfw/rules.go b/sgfw/rules.go index adeb3f7..f5795f8 100644 --- a/sgfw/rules.go +++ b/sgfw/rules.go @@ -479,7 +479,10 @@ func (fw *Firewall) loadRules() { if err != nil { if !os.IsNotExist(err) { log.Warningf("Failed to open %s for reading: %v", p, err) + } else { + log.Warningf("Did not find a rules file at %s: SGFW loaded with no rules\n", p) } + return } var policy *Policy @@ -497,7 +500,13 @@ func (fw *Firewall) loadRules() { func (fw *Firewall) processPathLine(line string) *Policy { pathLine := line[1 : len(line)-1] + toks := strings.Split(pathLine, "|") + if len(toks) != 2 { + log.Warning("Error parsing rules directive:", line) + return nil + } + policy := fw.policyForPathAndSandbox(toks[1], toks[0]) policy.lock.Lock() defer policy.lock.Unlock() diff --git a/sgfw/socks_server_chain.go b/sgfw/socks_server_chain.go index 9a2a2dd..85ee570 100644 --- a/sgfw/socks_server_chain.go +++ b/sgfw/socks_server_chain.go @@ -56,7 +56,7 @@ type pendingSocksConnection struct { pinfo *procsnitch.Info verdict chan int prompting bool - prompter *dbusObjectP + prompter *prompter guid string optstr string } @@ -124,9 +124,9 @@ func (sc *pendingSocksConnection) acceptTLSOnly() { sc.deliverVerdict(socksVerdi func (sc *pendingSocksConnection) drop() { sc.deliverVerdict(socksVerdictDrop) } -func (sc *pendingSocksConnection) setPrompter(val *dbusObjectP) { sc.prompter = val } +func (sc *pendingSocksConnection) setPrompter(val *prompter) { sc.prompter = val } -func (sc *pendingSocksConnection) getPrompter() *dbusObjectP { return sc.prompter } +func (sc *pendingSocksConnection) getPrompter() *prompter { return sc.prompter } func (sc *pendingSocksConnection) getGUID() string { if sc.guid == "" { diff --git a/vendor/github.com/subgraph/go-procsnitch/proc.go b/vendor/github.com/subgraph/go-procsnitch/proc.go index 823850e..fe23232 100644 --- a/vendor/github.com/subgraph/go-procsnitch/proc.go +++ b/vendor/github.com/subgraph/go-procsnitch/proc.go @@ -1,8 +1,8 @@ package procsnitch import ( - "encoding/hex" "encoding/binary" + "encoding/hex" "errors" "fmt" "github.com/op/go-logging" @@ -169,7 +169,7 @@ func ParseIP(ip string) (net.IP, error) { } if isLittleEndian > 0 { - for i := 0; i < len(dst) / 4; i++ { + for i := 0; i < len(dst)/4; i++ { start, end := i*4, (i+1)*4 word := dst[start:end] lval := binary.LittleEndian.Uint32(word) @@ -177,13 +177,13 @@ func ParseIP(ip string) (net.IP, error) { } } -/* if len(dst) == 16 { - dst2 := []byte{dst[3], dst[2], dst[1], dst[0], dst[7], dst[6], dst[5], dst[4], dst[11], dst[10], dst[9], dst[8], dst[15], dst[14], dst[13], dst[12]} - return net.IP(dst2), nil - } - for i, j := 0, len(dst)-1; i < j; i, j = i+1, j-1 { - dst[i], dst[j] = dst[j], dst[i] - } */ + /* if len(dst) == 16 { + dst2 := []byte{dst[3], dst[2], dst[1], dst[0], dst[7], dst[6], dst[5], dst[4], dst[11], dst[10], dst[9], dst[8], dst[15], dst[14], dst[13], dst[12]} + return net.IP(dst2), nil + } + for i, j := 0, len(dst)-1; i < j; i, j = i+1, j-1 { + dst[i], dst[j] = dst[j], dst[i] + } */ return net.IP(dst), nil } @@ -312,6 +312,7 @@ func stripLabel(s string) string { // stolen from github.com/virtao/GoEndian const INT_SIZE int = int(unsafe.Sizeof(0)) + func setEndian() { var i int = 0x1 bs := (*[INT_SIZE]byte)(unsafe.Pointer(&i)) diff --git a/vendor/github.com/subgraph/go-procsnitch/proc_pid.go b/vendor/github.com/subgraph/go-procsnitch/proc_pid.go index a34c9b1..549ea37 100644 --- a/vendor/github.com/subgraph/go-procsnitch/proc_pid.go +++ b/vendor/github.com/subgraph/go-procsnitch/proc_pid.go @@ -23,7 +23,9 @@ type Info struct { FirstArg string ParentCmdLine string ParentExePath string - Sandbox string + Sandbox string + Inode uint64 + FD int } type pidCache struct { @@ -51,10 +53,12 @@ func loadCache() map[uint64]*Info { for _, n := range readdir("/proc") { pid := toPid(n) if pid != 0 { - pinfo := &Info{Pid: pid} - for _, inode := range inodesFromPid(pid) { + inodes, fds := inodesFromPid(pid) + for iind, inode := range inodes { + pinfo := &Info{Inode: inode, Pid: pid, FD: fds[iind]} cmap[inode] = pinfo } + } } return cmap @@ -76,8 +80,9 @@ func toPid(name string) int { return (int)(pid) } -func inodesFromPid(pid int) []uint64 { +func inodesFromPid(pid int) ([]uint64, []int) { var inodes []uint64 + var fds []int fdpath := fmt.Sprintf("/proc/%d/fd", pid) for _, n := range readdir(fdpath) { if link, err := os.Readlink(path.Join(fdpath, n)); err != nil { @@ -85,12 +90,19 @@ func inodesFromPid(pid int) []uint64 { log.Warningf("Error reading link %s: %v", n, err) } } else { + fd, err := strconv.Atoi(n) + if err != nil { + log.Warningf("Error retrieving fd associated with pid %v: %v", pid, err) + fd = -1 + } + if inode := extractSocket(link); inode > 0 { inodes = append(inodes, inode) + fds = append(fds, fd) } } } - return inodes + return inodes, fds } func extractSocket(name string) uint64 { diff --git a/vendor/github.com/subgraph/go-procsnitch/socket.go b/vendor/github.com/subgraph/go-procsnitch/socket.go index f137ed0..f6d40c0 100644 --- a/vendor/github.com/subgraph/go-procsnitch/socket.go +++ b/vendor/github.com/subgraph/go-procsnitch/socket.go @@ -117,21 +117,21 @@ func findUDPSocketAll(srcAddr net.IP, srcPort uint16, dstAddr net.IP, dstPort ui }) } else if strictness == MATCH_LOOSE { return findSocket(proto, func(ss socketStatus) bool { - /* - fmt.Println("Match loose") - fmt.Printf("sock dst = %v pkt dst = %v\n", ss.remote.ip, dstAddr) - fmt.Printf("sock port = %d pkt port = %d\n", ss.local.port, srcPort) - fmt.Printf("local ip: %v\n source ip: %v\n", ss.local.ip, srcAddr) + /* + fmt.Println("Match loose") + fmt.Printf("sock dst = %v pkt dst = %v\n", ss.remote.ip, dstAddr) + fmt.Printf("sock port = %d pkt port = %d\n", ss.local.port, srcPort) + fmt.Printf("local ip: %v\n source ip: %v\n", ss.local.ip, srcAddr) */ - if (ss.local.port == srcPort && (ss.local.ip.Equal(net.IPv4(0,0,0,0)) && ss.remote.ip.Equal(net.IPv4(0,0,0,0)))) { - fmt.Printf("Matching for UDP socket bound to *:%d\n",ss.local.port) + if ss.local.port == srcPort && (ss.local.ip.Equal(net.IPv4(0, 0, 0, 0)) && ss.remote.ip.Equal(net.IPv4(0, 0, 0, 0))) { + fmt.Printf("Matching for UDP socket bound to *:%d\n", ss.local.port) return true - } else if (ss.remote.ip.Equal(dstAddr) && ss.local.port == srcPort && ss.local.ip.Equal(srcAddr)) { + } else if ss.remote.ip.Equal(dstAddr) && ss.local.port == srcPort && ss.local.ip.Equal(srcAddr) { return true } - // Finally, loop through all interfaces if src port matches + // Finally, loop through all interfaces if src port matches if ss.local.port == srcPort { ifs, err := net.Interfaces() @@ -148,13 +148,13 @@ func findUDPSocketAll(srcAddr net.IP, srcPort uint16, dstAddr net.IP, dstPort ui for _, addr := range addrs { var ifip net.IP switch x := addr.(type) { - case *net.IPNet: - ifip = x.IP - case *net.IPAddr: - ifip = x.IP + case *net.IPNet: + ifip = x.IP + case *net.IPAddr: + ifip = x.IP } if ss.local.ip.Equal(ifip) { - fmt.Printf("Matched on UDP socket bound to %v:%d\n",ifip,srcPort) + fmt.Printf("Matched on UDP socket bound to %v:%d\n", ifip, srcPort) return true } } @@ -163,8 +163,8 @@ func findUDPSocketAll(srcAddr net.IP, srcPort uint16, dstAddr net.IP, dstPort ui return false //return (ss.remote.ip.Equal(dstAddr) || ss.remote.ip.Equal(net.IPv4(0,0,0,0))) && ss.local.port == srcPort && (ss.local.ip.Equal(srcAddr) || ss.local.ip.Equal(net.IPv4(0,0,0,0))) /* - return (ss.remote.ip.Equal(dstAddr) || addrMatchesAny(ss.remote.ip)) && ss.local.port == srcPort && ss.local.ip.Equal(srcAddr) || - (ss.local.ip.Equal(dstAddr) || addrMatchesAny(ss.local.ip)) && ss.remote.port == srcPort && ss.remote.ip.Equal(srcAddr) */ + return (ss.remote.ip.Equal(dstAddr) || addrMatchesAny(ss.remote.ip)) && ss.local.port == srcPort && ss.local.ip.Equal(srcAddr) || + (ss.local.ip.Equal(dstAddr) || addrMatchesAny(ss.local.ip)) && ss.remote.port == srcPort && ss.remote.ip.Equal(srcAddr) */ }) } return findSocket(proto, func(ss socketStatus) bool { @@ -367,11 +367,11 @@ func getSocketLines(proto string) []string { } func addrMatchesAny(addr net.IP) bool { - wildcard := net.IP{0,0,0,0} + wildcard := net.IP{0, 0, 0, 0} if addr.To4() == nil { - wildcard = net.IP{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} + wildcard = net.IP{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} } - return wildcard.Equal(addr) + return wildcard.Equal(addr) }