aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Bersenev <bay@hackerdom.ru>2011-06-10 12:45:13 +0000
committerAlexander Bersenev <bay@hackerdom.ru>2011-06-10 12:45:13 +0000
commit8b8b0e496ae3676790215f1eb94e233403f06936 (patch)
treef068bb9646876a987d4dca6bcae44061cd85df67
parentbetter logging system. Finalize format of logs (diff)
downloadautodep-8b8b0e496ae3676790215f1eb94e233403f06936.tar.gz
autodep-8b8b0e496ae3676790215f1eb94e233403f06936.tar.bz2
autodep-8b8b0e496ae3676790215f1eb94e233403f06936.zip
Finalized format of communications. Fiexed a very annoying bug with lost ALLOW packet. Fixed tests
-rw-r--r--logger/src/autodep/logfs/fstracer.py102
-rw-r--r--logger/src/autodep/logfs/logger_fusefs.py6
-rw-r--r--logger/src/autodep/logfs/test_fstracer.py41
-rwxr-xr-xlogger/src/autodep/showfsevents.py30
-rw-r--r--logger/src/hook_fusefs/hookfs.c74
5 files changed, 210 insertions, 43 deletions
diff --git a/logger/src/autodep/logfs/fstracer.py b/logger/src/autodep/logfs/fstracer.py
index cf10e6e..6979b27 100644
--- a/logger/src/autodep/logfs/fstracer.py
+++ b/logger/src/autodep/logfs/fstracer.py
@@ -30,22 +30,76 @@ def parse_message(message):
# check if proccess is finished
def checkfinished(pid):
if not os.path.exists("/proc/%d/stat" % pid):
- return (True,0)
+ return True
try:
pid_child,exitcode = os.waitpid(pid, os.WNOHANG)
except OSError, e:
if e.errno == 10:
- return (False,0)
+ return False
else:
raise
if pid_child==0:
- return (False,0)
- return (True,exitcode)
+ return False
+ return True
+
+#check if process is zombie
+def iszombie(pid):
+ try:
+ statfile=open("/proc/%d/stat" % pid,"r")
+ line=statfile.readline()
+ statfile.close()
+ line=line.rsplit(")")[1] # find last ")" char
+ line=line.strip()
+ match=re.match(r"(\w)",line)
+ if match==None:
+ print "Failed to get check if process is zombie. Format of /proc/<pid>/stat is incorrect. Did you change a kernel?"
+ return False
+
+ return match.group(1)=="Z"
+
+ except IOError,e:
+ return True
+
+
+# uses /proc filesystem to get pid of parent
+def getparentpid(pid):
+ try:
+ statfile=open("/proc/%d/stat" % pid,"r")
+ line=statfile.readline()
+ statfile.close()
+ line=line.rsplit(")")[1] # find last ")" char
+ line=line.strip()
+ match=re.match(r"\w\s(\d+)",line)
+ if match==None:
+ print "Failed to get parent process. Format of /proc/<pid>/stat is incorrect. Did you change a kernel?"
+ return 1
+
+ return int(match.group(1))
+
+ except IOError,e:
+ return 1
+
+#check if message came from one of a child
+def checkparent(parent,child):
+ #print "Parent %s, child %s"%(parent,child)
+ if child==1 or getparentpid(child)==1:
+ return True
+
+ currpid=child
+# for(pid=getpid();pid!=0;pid=__getparentpid(pid))
+ while getparentpid(currpid)!=1:
+ currpid=getparentpid(currpid)
+ if currpid==parent:
+ return True
+
+ print "External actions with filesystem detected pid of external prog is %d" % child
+ return False
+
+# default access filter. Allow acess to all files
+def defaultfilter(eventname, filename, pid):
-# default access filter. Allow always
-def defaultfilter(time, filename, pid):
return True
# run the program and get file access events
@@ -59,7 +113,7 @@ def getfsevents(prog_name,arguments,approach="hooklib",filterproc=defaultfilter)
sock_listen=socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
sock_listen.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock_listen.bind(socketname)
- sock_listen.listen(1024)
+ sock_listen.listen(65536*8)
except socket.error, e:
print "Failed to create a socket for exchange data with the logger: %s" % e
return []
@@ -103,7 +157,7 @@ def getfsevents(prog_name,arguments,approach="hooklib",filterproc=defaultfilter)
input.append(client)
buffers[client]=''
else:
- data=s.recv(65536)
+ data=s.recv(4096)
buffers[s]+=data
@@ -131,26 +185,50 @@ def getfsevents(prog_name,arguments,approach="hooklib",filterproc=defaultfilter)
#print "datalen: %d" % len(data)
message=parse_message(record)
+
try:
if message[4]=="ASKING":
- if filterproc(message[1],message[2],message[3]):
+ #print "ASKING %s"%message[2]
+ if message[2]=="/" or ( # always allow acces to "/" because of some processes like ksysguardd
+ True):#checkparent(pid,int(message[3])) and filterproc(message[1],message[2],message[3])):
s.sendall("ALLOW\n"); # TODO: think about flush here
+ #print "ALLOWING %s"%message[2]
+
else:
print "Blocking an access to %s" % message[2]
s.sendall("DENY\n"); # TODO: think about flush here
else:
- events.append([message[1],message[2]]);
+ # check previous five messages for possible repeats
+ for prevevent in events[-5:]:
+ if prevevent[1:]==message[1:]:
+ break
+ else:
+ pass
+ #events.append(message)
except IndexError:
print "IndexError while parsing %s"%record
#print "!!"+data+"!!"
#print parse_message(data)
- if len(input)==1 and connects==0:
+
+ if len(input)==1 and connects==0: #or
# seems like there is no connect
- print "It seems like a logger module was unable to start." + \
+ print "It seems like a logger module was unable to start or failed to finish" + \
"Check that you are not launching a suid program under non-root user."
return []
+ #if iszombie(pid):
+ # print "Child finished, but connection remains. Closing a connection"
+ # break
os.wait()
+
+ if len(events)==0:
+ return []
+
+ timeofstart=int(events[0][0])
+ # make all event times relative to time 0 - time of start task
+ for event_num in range(0,len(events)):
+ events[event_num][0]=int(events[event_num][0])-timeofstart
return events
+
diff --git a/logger/src/autodep/logfs/logger_fusefs.py b/logger/src/autodep/logfs/logger_fusefs.py
index 11a6f39..ec19b80 100644
--- a/logger/src/autodep/logfs/logger_fusefs.py
+++ b/logger/src/autodep/logfs/logger_fusefs.py
@@ -93,9 +93,9 @@ class logger:
print "Unmounting partitions"
self.mountlist.reverse()
for mount in self.mountlist:
- self.smartcommandlauncher(['umount',self.rootmountpath+mount])
- self.smartcommandlauncher(['fusermount','-u',self.rootmountpath]);
- self.smartcommandlauncher(['umount',self.rootmountpath]);
+ self.smartcommandlauncher(['umount','-l',self.rootmountpath+mount])
+ self.smartcommandlauncher(['fusermount','-z','-u',self.rootmountpath]);
+ self.smartcommandlauncher(['umount','-l',self.rootmountpath]);
os.rmdir(self.rootmountpath)
except OSError, e:
diff --git a/logger/src/autodep/logfs/test_fstracer.py b/logger/src/autodep/logfs/test_fstracer.py
index c254bce..a4c4b56 100644
--- a/logger/src/autodep/logfs/test_fstracer.py
+++ b/logger/src/autodep/logfs/test_fstracer.py
@@ -2,6 +2,13 @@ import unittest
import fstracer
+def simple_getfsevents(prog,args,approach="hooklib"):
+ ret=[]
+ events = fstracer.getfsevents(prog,args,approach)
+ for event in events:
+ ret.append([event[1],event[2],event[4]])
+ return ret
+
class hooklib_simple_tests(unittest.TestCase):
def test_open_unexists(self):
self.assertEqual(fstracer.getfsevents('/bin/cat',
@@ -48,17 +55,20 @@ class hooklib_simple_tests(unittest.TestCase):
class fusefs_simple_tests(unittest.TestCase):
def test_open_unexists(self):
- eventslist=fstracer.getfsevents('/bin/cat', ['/bin/cat','/f1','/f2'],approach="fusefs")
- self.assertTrue(eventslist.count(['stat', '/f1'])==1)
- def test_open_exists(self):
- eventslist=fstracer.getfsevents('/bin/cat', ['/bin/cat','/etc/passwd'],approach="fusefs")
- self.assertTrue(eventslist.count(['stat', '/etc/passwd'])>=1)
+ eventslist=simple_getfsevents('/bin/cat', ['/bin/cat','/f1','/f2'],approach="fusefs")
+ print eventslist
+ self.assertTrue(eventslist.count(['stat', '/f1',"ERR/2"])==1)
+ self.assertTrue(eventslist.count(['stat', '/f2',"ERR/2"])==1)
+
+ def test_open_exists(self):
+ eventslist=simple_getfsevents('/bin/cat', ['/bin/cat','/etc/passwd'],approach="fusefs")
+ self.assertTrue(eventslist.count(['stat', '/etc/passwd',"OK"])>=1)
def test_open_many(self):
filesnum=200
- eventslist=fstracer.getfsevents('/bin/cat',['/bin/cat']+
+ eventslist=simple_getfsevents('/bin/cat',['/bin/cat']+
map(lambda x: '/file'+str(x),range(0,filesnum)), approach="fusefs")
- for f in map(lambda x: ['stat','/file'+str(x)],range(0,filesnum)):
+ for f in map(lambda x: ['stat','/file'+str(x),"ERR/2"],range(0,filesnum)):
self.assertTrue(f in eventslist)
def test_parralel(self):
@@ -72,21 +82,20 @@ class fusefs_simple_tests(unittest.TestCase):
for f in xrange(0,filesnum):
command+="/file_%d_%d " % (p,f)
command+="& "
- command+=" >/dev/null 2>&1"
+ command+=" 2>/dev/null"
#command+=" "+"A"*65536
- resultarray=fstracer.getfsevents('/bin/sh', ['/bin/sh','-c',command],approach="fusefs")
-
- #self.assertTrue(resultarray.count(['execve', '/bin/cat'])==procnum)
-
- print resultarray
+ resultarray=simple_getfsevents('/bin/sh', ['/bin/sh','-c',command],approach="fusefs")
for p in xrange(0,procnum):
for f in xrange(0,filesnum):
- self.assertTrue(resultarray.count(['stat', '/file_%d_%d' % (p,f)])==1)
-
-
+ self.assertTrue(resultarray.count(['stat', '/file_%d_%d' % (p,f),"ERR/2"])==1)
+ def test_open_very_many(self):
+ resultarray=simple_getfsevents('/bin/sh', ['/bin/sh','-c',
+ "for i in `seq 1 10`; do cat /testmany;done 2> /dev/null"],approach="fusefs")
+ print resultarray
+ self.assertTrue(resultarray.count(['stat','/testmany',"ERR/2"])>=1000)
if __name__ == '__main__':
#unittest.main()
diff --git a/logger/src/autodep/showfsevents.py b/logger/src/autodep/showfsevents.py
index 25bf1ff..0fba98a 100755
--- a/logger/src/autodep/showfsevents.py
+++ b/logger/src/autodep/showfsevents.py
@@ -5,6 +5,10 @@ import sys
import logfs.fstracer
+def printevents(events):
+ for event in events:
+ print "%s %s"%(event[1],event[2])
+
#logfs.fstracer.getfsevents("/bin/sh", ["sh" , "-c", "/usr/bin/tac bay_success; /usr/bin/tac bay_god bay_god2"])
#events=logfs.fstracer.getfsevents("/bin/cat", ["cat" , "l l l"])
if len(sys.argv)<2:
@@ -12,5 +16,29 @@ if len(sys.argv)<2:
exit(1)
events=logfs.fstracer.getfsevents(sys.argv[1], sys.argv[1:],approach="fusefs")
-print events
+
+succ_events=[]
+err_events=[]
+deny_events=[]
+
+for event in events:
+ if event[4]=="OK":
+ succ_events.append(event)
+ elif event[4]=="DENIED":
+ deny_events.append(event)
+ else:
+ err_events.append(event)
+
+
+
+print "Report:"
+if len(succ_events)>0:
+ print "Successful events:"
+ printevents(succ_events)
+if len(err_events)>0:
+ print "\nNon-successful events:"
+ printevents(err_events)
+if len(deny_events)>0:
+ print "\nBlocked events:"
+ printevents(deny_events)
#logfs.fstracer.getfsevents("emerge", ["emerge","--info"]) \ No newline at end of file
diff --git a/logger/src/hook_fusefs/hookfs.c b/logger/src/hook_fusefs/hookfs.c
index 16b9a46..45bcd6b 100644
--- a/logger/src/hook_fusefs/hookfs.c
+++ b/logger/src/hook_fusefs/hookfs.c
@@ -60,7 +60,7 @@ struct hookfs_config config;
* Prints a string escaping spaces and '\'
* Does not check input variables
*/
-void __print_escaped(FILE *fh ,const char *s){
+static void __print_escaped(FILE *fh ,const char *s){
for(;(*s)!=0; s++) {
if(*s==' ')
fprintf(fh,"\\ ");
@@ -78,10 +78,25 @@ void __print_escaped(FILE *fh ,const char *s){
}
/*
- * Format of log string: time event file flags result parents
-*/
-void log_event(const char *event_type, const char *filename, char *result,int err, pid_t pid) {
- pthread_mutex_lock( &socketblock );
+ * This is here because launching of a task is very slow without it
+ */
+static int is_file_excluded(const char *filename) {
+ if(strcmp(filename,"/etc/ld.so.preload")==0)
+ return 1;
+ if(strcmp(filename,"/etc/ld.so.cache")==0)
+ return 1;
+ if(strcmp(filename,"/usr/lib64/locale/locale-archive")==0)
+ return 1;
+ if(strcmp(filename,"/usr/lib64/locale")==0)
+ return 1;
+
+ return 0;
+}
+
+
+static void raw_log_event(const char *event_type, const char *filename, char *result,int err, pid_t pid) {
+ if(is_file_excluded(filename)) return;
+
fprintf(log_file,"%lld ",(unsigned long long)time(NULL));
@@ -97,6 +112,14 @@ void log_event(const char *event_type, const char *filename, char *result,int er
fprintf(log_file,"\n");
fflush(log_file);
+}
+
+/*
+ * Format of log string: time event file flags result parents
+*/
+static void log_event(const char *event_type, const char *filename, char *result,int err, pid_t pid) {
+ pthread_mutex_lock( &socketblock );
+ raw_log_event(event_type,filename,result,err,pid);
pthread_mutex_unlock( &socketblock );
}
@@ -104,13 +127,17 @@ void log_event(const char *event_type, const char *filename, char *result,int er
* Ack a python part about an event
* Returns 1 if access is allowed and 0 if denied
*/
-int is_event_allowed(const char *event_type,const char *filename, pid_t pid) {
+static int is_event_allowed(const char *event_type,const char *filename, pid_t pid) {
// sending asking log_event
- log_event(event_type,filename,"ASKING",0,pid);
+ if(is_file_excluded(filename)) return 1;
+ //return 1;
+ pthread_mutex_lock( &socketblock );
+
+ raw_log_event(event_type,filename,"ASKING",0,pid);
char answer[8];
- pthread_mutex_lock( &socketblock );
fscanf(log_file,"%7s",answer);
+ fflush(log_file); // yes, it is here too
pthread_mutex_unlock( &socketblock );
if(strcmp(answer,"ALLOW")==0)
@@ -122,7 +149,6 @@ int is_event_allowed(const char *event_type,const char *filename, pid_t pid) {
return 0;
}
-
static char * malloc_relative_path(const char *path) {
int len = strlen(path);
char * buf = malloc(1 + len + 1);
@@ -149,6 +175,14 @@ static int hookfs_getattr(const char *path, struct stat *stbuf)
{
struct fuse_context * context = fuse_get_context();
+ if(! is_event_allowed("stat",path,context->pid)) {
+ errno=2; // not found
+ log_event("stat",path,"DENIED",errno,context->pid);
+
+ return -errno;
+ }
+
+
char * rel_path = malloc_relative_path(path);
if (! rel_path) {
return -errno;
@@ -172,7 +206,14 @@ static int hookfs_fgetattr(const char *path, struct stat *stbuf,
int res;
struct fuse_context * context = fuse_get_context();
+ if(! is_event_allowed("stat",path,context->pid)) {
+ errno=2; // not found
+ log_event("stat",path,"DENIED",errno,context->pid);
+
+ return -errno;
+ }
+
res = fstat(fi->fh, stbuf);
if (res == -1) {
@@ -188,6 +229,14 @@ static int hookfs_access(const char *path, int mask)
{
struct fuse_context * context = fuse_get_context();
+ if(! is_event_allowed("stat",path,context->pid)) {
+ errno=2; // not found
+ log_event("stat",path,"DENIED",errno,context->pid);
+
+ return -errno;
+ }
+
+
char * rel_path = malloc_relative_path(path);
if (! rel_path) {
return -errno;
@@ -348,7 +397,7 @@ static int hookfs_unlink(const char *path)
int res = unlink(rel_path);
free(rel_path);
- //NOTIFY(post_unlink, path, res);
+
if (res == -1)
return -errno;
@@ -556,6 +605,8 @@ static int hookfs_create(const char *path, mode_t mode, struct fuse_file_info *f
if(! is_event_allowed("create",path,context->pid)) {
errno=2; // not found
+ log_event("create",path,"DENIED",errno,context->pid);
+
return -errno;
}
@@ -587,6 +638,8 @@ static int hookfs_open(const char *path, struct fuse_file_info *fi)
if(! is_event_allowed("open",path,context->pid)) {
errno=2; // not found
+ log_event("open",path,"DENIED",errno,context->pid);
+
return -errno;
}
@@ -895,7 +948,6 @@ static int hookfs_handle_opt(void *data, const char *arg, int key, struct fuse_a
"\n"
"%s options:\n"
" --argv-debug enable argv debugging\n"
- " --flush flush log after each write\n"
"\n"
"general options:\n"
" -o opt,[opt...] mount options\n"