1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
|
#!/usr/bin/env python2
import subprocess
import time
import os
import sys
import signal
class logger:
socketname=''
readytolaunch=False
mountlist=["/dev/","/dev/pts","/dev/shm","/proc/","/sys/"]
rootmountpath="/mnt/logfs_root_"+str(time.time())+"/"
currpid=-1
# rootmountpath="/mnt/logfs_roott_"+"/"
def __init__(self, socketname, accuracy=False):
if os.geteuid() != 0:
print "only root user can use FUSE approach for logging"
exit(1)
self.socketname=socketname
self.currpid=os.getpid()
if accuracy==False:
self.mountlist=self.mountlist+["/lib64/", "/lib32/","/var/tmp/portage/"]
print "mounting root filesystem into %s. External access to this folder will be blocked. Please, DON'T DELETE THIS FOLDER !!" % self.rootmountpath
try:
os.mkdir(self.rootmountpath)
except OSError,e:
if e.errno==17: # 17 is a "file exists" errno
pass # all is ok
else:
print "failed to make mount directory %s: %s" % (self.rootmountpath,e)
print "this error is fatal"
exit(1)
ret=subprocess.call(['mount','-o','bind','/',self.rootmountpath])
if ret!=0:
print "failed to bind root filesystem to %s. Check messages above"%self.rootmountpath
exit(1)
os.environ["LOG_SOCKET"]=self.socketname
os.environ["PARENT_PID"]=str(self.currpid)
# TODO: change
ret=subprocess.call(['/home/bay/gsoc/src/hook_fusefs/hookfs',self.rootmountpath,
'-o','allow_other,suid'])
if ret!=0:
print "failed to launch FUSE logger. Check messages above"
exit(1)
for mount in self.mountlist:
if not os.path.exists(mount):
continue
ret=subprocess.call(['mount','-o','bind',mount,self.rootmountpath+mount])
if ret!=0:
print "failed to mount bind %s directory to %s. Check messages above" % (
mount,self.rootmountpath)
exit(1)
self.readytolaunch=True;
def __del__(self):
#we will delete the object manually after execprog
pass
# launches command, if it returns not 0 waits for 1 or 2 second and launches again
# for various umounts
def smartcommandlauncher(self,args):
for waittime in (1,1,2):
ret=subprocess.call(args)
if ret==0:
return
print "Auto-retrying after %d sec" % waittime
time.sleep(waittime)
print "Giving up. Command %s failed" % args
def execprog(self,prog_name,arguments):
if self.currpid!=os.getpid():
print "Detected an attempt to execute execproc in other thread"
sys.exit(1)
pid=os.fork()
if pid==0:
try:
cwd=os.getcwd()
os.chroot(self.rootmountpath)
os.chdir(cwd)
env=os.environ.copy()
env["LOGGER_PROCESS_IS_INTERNAL"]="YES"
os.execvpe(prog_name, arguments, env)
sys.exit(1)
except OSError, e:
print "Error while chrooting and starting a program: %s" % e
sys.exit(1)
else:
exitcode=2; # if ctrl-c pressed then returning this value
needtokillself=False
try:
exitcode=os.wait()[1]/256;
except KeyboardInterrupt:
needtokillself=True
try:
print "Unmounting partitions"
self.mountlist.reverse()
for mount in self.mountlist:
if not os.path.exists(self.rootmountpath+mount):
continue
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:
print "Error while unmounting fuse filesystem: %s" % e
sys.exit(1)
if needtokillself: # we kill self for report the status correct
signal.signal(signal.SIGINT,signal.SIG_DFL)
os.kill(os.getpid(),signal.SIGINT)
os._exit(exitcode)
|