*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.
shw_dev
Stephen Watt 7 years ago
parent 2eac4c7dc5
commit 0d13c7bb9c

@ -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

@ -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
}

@ -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)

@ -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)

@ -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)
}

@ -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) {

@ -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()

@ -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 == "" {

@ -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))

@ -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 {

@ -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)
}

Loading…
Cancel
Save