From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from pigeon.gentoo.org ([208.92.234.80] helo=lists.gentoo.org) by finch.gentoo.org with esmtp (Exim 4.60) (envelope-from ) id 1QUvTb-0006Rj-Cl for garchives@archives.gentoo.org; Fri, 10 Jun 2011 06:45:51 +0000 Received: from pigeon.gentoo.org (localhost [127.0.0.1]) by pigeon.gentoo.org (Postfix) with SMTP id 355821C005; Fri, 10 Jun 2011 06:45:40 +0000 (UTC) Received: from smtp.gentoo.org (smtp.gentoo.org [140.211.166.183]) by pigeon.gentoo.org (Postfix) with ESMTP id CFB0A1C005 for ; Fri, 10 Jun 2011 06:45:38 +0000 (UTC) Received: from pelican.gentoo.org (unknown [66.219.59.40]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by smtp.gentoo.org (Postfix) with ESMTPS id 107271B4022 for ; Fri, 10 Jun 2011 06:45:38 +0000 (UTC) Received: from localhost.localdomain (localhost [127.0.0.1]) by pelican.gentoo.org (Postfix) with ESMTP id 2934A8003C for ; Fri, 10 Jun 2011 06:45:37 +0000 (UTC) From: "Александр Берсенев" To: gentoo-commits@lists.gentoo.org Content-type: text/plain; charset=UTF-8 Reply-To: gentoo-dev@lists.gentoo.org, "Александр Берсенев" Message-ID: <8b8b0e496ae3676790215f1eb94e233403f06936.bay@gentoo> Subject: [gentoo-commits] proj/autodep:master commit in: logger/src/autodep/logfs/, logger/src/hook_fusefs/, logger/src/autodep/ X-VCS-Repository: proj/autodep X-VCS-Files: logger/src/autodep/logfs/fstracer.py logger/src/autodep/logfs/logger_fusefs.py logger/src/autodep/logfs/test_fstracer.py logger/src/autodep/showfsevents.py logger/src/hook_fusefs/hookfs.c X-VCS-Directories: logger/src/autodep/logfs/ logger/src/hook_fusefs/ logger/src/autodep/ X-VCS-Committer: bay X-VCS-Committer-Name: Александр Берсенев X-VCS-Revision: 8b8b0e496ae3676790215f1eb94e233403f06936 Date: Fri, 10 Jun 2011 06:45:37 +0000 (UTC) Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-Id: Gentoo Linux mail X-BeenThere: gentoo-commits@lists.gentoo.org Content-Transfer-Encoding: quoted-printable X-Archives-Salt: X-Archives-Hash: 89c5085a766d2ec4d4e7f05194d74fef commit: 8b8b0e496ae3676790215f1eb94e233403f06936 Author: Alexander Bersenev hackerdom ru> AuthorDate: Fri Jun 10 12:45:13 2011 +0000 Commit: =D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B0=D0=BD=D0=B4=D1=80 =D0=91= =D0=B5=D1=80=D1=81=D0=B5=D0=BD=D0=B5=D0=B2 hackerdom ru> CommitDate: Fri Jun 10 12:45:13 2011 +0000 URL: http://git.overlays.gentoo.org/gitweb/?p=3Dproj/autodep.git;a= =3Dcommit;h=3D8b8b0e49 Finalized format of communications. Fiexed a very annoying bug with lost = ALLOW packet. Fixed tests --- logger/src/autodep/logfs/fstracer.py | 102 +++++++++++++++++++++++= ++---- logger/src/autodep/logfs/logger_fusefs.py | 6 +- logger/src/autodep/logfs/test_fstracer.py | 41 +++++++----- logger/src/autodep/showfsevents.py | 30 ++++++++- logger/src/hook_fusefs/hookfs.c | 74 ++++++++++++++++++--- 5 files changed, 210 insertions(+), 43 deletions(-) diff --git a/logger/src/autodep/logfs/fstracer.py b/logger/src/autodep/lo= gfs/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 =20 try: pid_child,exitcode =3D os.waitpid(pid, os.WNOHANG) except OSError, e: if e.errno =3D=3D 10:=20 - return (False,0) + return False else: raise =20 if pid_child=3D=3D0: - return (False,0) - return (True,exitcode) + return False + return True + +#check if process is zombie +def iszombie(pid): + try: + statfile=3Dopen("/proc/%d/stat" % pid,"r") + line=3Dstatfile.readline() + statfile.close() + line=3Dline.rsplit(")")[1] # find last ")" char + line=3Dline.strip() + match=3Dre.match(r"(\w)",line) + if match=3D=3DNone: + print "Failed to get check if process is zombie. Format of /proc//stat is incorrect. Did you change a kernel?" + return False +=09 + return match.group(1)=3D=3D"Z" +=09 + except IOError,e: + return True + =20 + +# uses /proc filesystem to get pid of parent +def getparentpid(pid): + try: + statfile=3Dopen("/proc/%d/stat" % pid,"r") + line=3Dstatfile.readline() + statfile.close() + line=3Dline.rsplit(")")[1] # find last ")" char + line=3Dline.strip() + match=3Dre.match(r"\w\s(\d+)",line) + if match=3D=3DNone: + print "Failed to get parent process. Format of /proc//stat is in= correct. Did you change a kernel?" + return 1 +=09 + return int(match.group(1)) +=09 + 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=3D=3D1 or getparentpid(child)=3D=3D1: + return True + =20 + currpid=3Dchild +# for(pid=3Dgetpid();pid!=3D0;pid=3D__getparentpid(pid)) + while getparentpid(currpid)!=3D1: + currpid=3Dgetparentpid(currpid) + if currpid=3D=3Dparent: + return True + =20 + 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): =20 -# default access filter. Allow always =20 -def defaultfilter(time, filename, pid): return True =20 # run the program and get file access events @@ -59,7 +113,7 @@ def getfsevents(prog_name,arguments,approach=3D"hookli= b",filterproc=3Ddefaultfilter) sock_listen=3Dsocket.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=3D"hookl= ib",filterproc=3Ddefaultfilter) input.append(client) buffers[client]=3D'' else: - data=3Ds.recv(65536) + data=3Ds.recv(4096) =09 buffers[s]+=3Ddata =20 @@ -131,26 +185,50 @@ def getfsevents(prog_name,arguments,approach=3D"hoo= klib",filterproc=3Ddefaultfilter) #print "datalen: %d" % len(data) message=3Dparse_message(record) =20 + =20 try: if message[4]=3D=3D"ASKING": - if filterproc(message[1],message[2],message[3]): + #print "ASKING %s"%message[2] + if message[2]=3D=3D"/" or ( # always allow acces to "/" because of= some processes like ksysguardd + True):#checkparent(pid,int(message[3])) and filterproc(message[1],m= essage[2],message[3])): s.sendall("ALLOW\n"); # TODO: think about flush here + #print "ALLOWING %s"%message[2] + =09 else: print "Blocking an access to %s" % message[2] s.sendall("DENY\n"); # TODO: think about flush here =09 else: - events.append([message[1],message[2]]); + # check previous five messages for possible repeats + for prevevent in events[-5:]: + if prevevent[1:]=3D=3Dmessage[1:]: + break + else: + pass + #events.append(message) except IndexError: print "IndexError while parsing %s"%record #print "!!"+data+"!!" #print parse_message(data) =20 - if len(input)=3D=3D1 and connects=3D=3D0: + =09 + if len(input)=3D=3D1 and connects=3D=3D0: #or=20 # 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 t= o 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 =20 os.wait() + =20 + if len(events)=3D=3D0: + return [] +=09 + timeofstart=3Dint(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]=3Dint(events[event_num][0])-timeofstart return events + diff --git a/logger/src/autodep/logfs/logger_fusefs.py b/logger/src/autod= ep/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) =20 except OSError, e: diff --git a/logger/src/autodep/logfs/test_fstracer.py b/logger/src/autod= ep/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 =20 import fstracer =20 +def simple_getfsevents(prog,args,approach=3D"hooklib"): + ret=3D[] + events =3D 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): =20 class fusefs_simple_tests(unittest.TestCase): def test_open_unexists(self): - eventslist=3Dfstracer.getfsevents('/bin/cat', ['/bin/cat','/f1','/f2'],= approach=3D"fusefs") - self.assertTrue(eventslist.count(['stat', '/f1'])=3D=3D1) - def test_open_exists(self): - eventslist=3Dfstracer.getfsevents('/bin/cat', ['/bin/cat','/etc/passw= d'],approach=3D"fusefs") - self.assertTrue(eventslist.count(['stat', '/etc/passwd'])>=3D1) + eventslist=3Dsimple_getfsevents('/bin/cat', ['/bin/cat','/f1','/f2'],ap= proach=3D"fusefs") + print eventslist + self.assertTrue(eventslist.count(['stat', '/f1',"ERR/2"])=3D=3D1) + self.assertTrue(eventslist.count(['stat', '/f2',"ERR/2"])=3D=3D1) +=09 + def test_open_exists(self): + eventslist=3Dsimple_getfsevents('/bin/cat', ['/bin/cat','/etc/passwd'= ],approach=3D"fusefs") + self.assertTrue(eventslist.count(['stat', '/etc/passwd',"OK"])>=3D1) =20 def test_open_many(self): filesnum=3D200 - eventslist=3Dfstracer.getfsevents('/bin/cat',['/bin/cat']+ + eventslist=3Dsimple_getfsevents('/bin/cat',['/bin/cat']+ map(lambda x: '/file'+str(x),range(0,filesnum)), approach=3D"fu= sefs") - 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) =20 def test_parralel(self): @@ -72,21 +82,20 @@ class fusefs_simple_tests(unittest.TestCase): for f in xrange(0,filesnum): command+=3D"/file_%d_%d " % (p,f) command+=3D"& " - command+=3D" >/dev/null 2>&1" + command+=3D" 2>/dev/null" #command+=3D" "+"A"*65536 =09 - resultarray=3Dfstracer.getfsevents('/bin/sh', ['/bin/sh','-c',command],= approach=3D"fusefs") - - #self.assertTrue(resultarray.count(['execve', '/bin/cat'])=3D=3Dprocnum= ) - - print resultarray + resultarray=3Dsimple_getfsevents('/bin/sh', ['/bin/sh','-c',command],ap= proach=3D"fusefs") =20 for p in xrange(0,procnum): for f in xrange(0,filesnum): - self.assertTrue(resultarray.count(['stat', '/file_%d_%d' % (p,f)])=3D=3D= 1) - - + self.assertTrue(resultarray.count(['stat', '/file_%d_%d' % (p,f),"ERR/= 2"])=3D=3D1) =20 + def test_open_very_many(self): + resultarray=3Dsimple_getfsevents('/bin/sh', ['/bin/sh','-c', + "for i in `seq 1 10`; do cat /testmany;done 2> /dev/null"],appr= oach=3D"fusefs") + print resultarray + self.assertTrue(resultarray.count(['stat','/testmany',"ERR/2"])>=3D1000= ) =20 if __name__ =3D=3D '__main__': #unittest.main() diff --git a/logger/src/autodep/showfsevents.py b/logger/src/autodep/show= fsevents.py index 25bf1ff..0fba98a 100755 --- a/logger/src/autodep/showfsevents.py +++ b/logger/src/autodep/showfsevents.py @@ -5,6 +5,10 @@ import sys =20 import logfs.fstracer =20 +def printevents(events): + for event in events: + print "%s %s"%(event[1],event[2]) +=09 #logfs.fstracer.getfsevents("/bin/sh", ["sh" , "-c", "/usr/bin/tac bay_s= uccess; /usr/bin/tac bay_god bay_god2"]) #events=3Dlogfs.fstracer.getfsevents("/bin/cat", ["cat" , "l l l"]) if len(sys.argv)<2: @@ -12,5 +16,29 @@ if len(sys.argv)<2: exit(1) =20 events=3Dlogfs.fstracer.getfsevents(sys.argv[1], sys.argv[1:],approach=3D= "fusefs") -print events + +succ_events=3D[] +err_events=3D[] +deny_events=3D[] + +for event in events: + if event[4]=3D=3D"OK": + succ_events.append(event) + elif event[4]=3D=3D"DENIED": + deny_events.append(event) + else: + err_events.append(event) +=09 + =20 +=09 +print "Report:"=09 +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/hoo= kfs.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)!=3D0; s++) { if(*s=3D=3D' ') fprintf(fh,"\\ "); @@ -78,10 +78,25 @@ void __print_escaped(FILE *fh ,const char *s){ } =20 /* - * Format of log string: time event file flags result parents -*/ -void log_event(const char *event_type, const char *filename, char *resul= t,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")=3D=3D0) + return 1; + if(strcmp(filename,"/etc/ld.so.cache")=3D=3D0) + return 1; + if(strcmp(filename,"/usr/lib64/locale/locale-archive")=3D=3D0) + return 1; + if(strcmp(filename,"/usr/lib64/locale")=3D=3D0) + return 1; + =20 + 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; + =20 fprintf(log_file,"%lld ",(unsigned long long)time(NULL)); =20 @@ -97,6 +112,14 @@ void log_event(const char *event_type, const char *fi= lename, char *result,int er fprintf(log_file,"\n"); fflush(log_file); =20 +} + +/* + * 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 ); } =20 @@ -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 ); + =20 + raw_log_event(event_type,filename,"ASKING",0,pid); char answer[8]; =20 - pthread_mutex_lock( &socketblock ); fscanf(log_file,"%7s",answer); + fflush(log_file); // yes, it is here too pthread_mutex_unlock( &socketblock ); =20 if(strcmp(answer,"ALLOW")=3D=3D0) @@ -122,7 +149,6 @@ int is_event_allowed(const char *event_type,const cha= r *filename, pid_t pid) { return 0; } =20 - static char * malloc_relative_path(const char *path) { int len =3D strlen(path); char * buf =3D malloc(1 + len + 1); @@ -149,6 +175,14 @@ static int hookfs_getattr(const char *path, struct s= tat *stbuf) { struct fuse_context * context =3D fuse_get_context(); =20 + if(! is_event_allowed("stat",path,context->pid)) { + errno=3D2; // not found + log_event("stat",path,"DENIED",errno,context->pid); + + return -errno; + } + +=09 char * rel_path =3D 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; =20 struct fuse_context * context =3D fuse_get_context(); + if(! is_event_allowed("stat",path,context->pid)) { + errno=3D2; // not found + log_event("stat",path,"DENIED",errno,context->pid); + + return -errno; + } =20 +=09 res =3D fstat(fi->fh, stbuf); =09 if (res =3D=3D -1) { @@ -188,6 +229,14 @@ static int hookfs_access(const char *path, int mask) { struct fuse_context * context =3D fuse_get_context(); =20 + if(! is_event_allowed("stat",path,context->pid)) { + errno=3D2; // not found + log_event("stat",path,"DENIED",errno,context->pid); + + return -errno; + } + +=09 char * rel_path =3D malloc_relative_path(path); if (! rel_path) { return -errno; @@ -348,7 +397,7 @@ static int hookfs_unlink(const char *path) =20 int res =3D unlink(rel_path); free(rel_path); - //NOTIFY(post_unlink, path, res); + if (res =3D=3D -1) return -errno; =20 @@ -556,6 +605,8 @@ static int hookfs_create(const char *path, mode_t mod= e, struct fuse_file_info *f =20 if(! is_event_allowed("create",path,context->pid)) { errno=3D2; // not found + log_event("create",path,"DENIED",errno,context->pid); + return -errno; } =20 @@ -587,6 +638,8 @@ static int hookfs_open(const char *path, struct fuse_= file_info *fi) =20 if(! is_event_allowed("open",path,context->pid)) { errno=3D2; // not found + log_event("open",path,"DENIED",errno,context->pid); + return -errno; } =09 @@ -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"