--- makejail-0.0.5.orig/makejail +++ makejail-0.0.5/makejail @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/python # Author: alain@onesite.org # License: GPL @@ -11,7 +11,7 @@ # stat (package stat) # Configuration defaults -# Don't change this file, to define new defaults values create a file /etc/makejail +# Don't change this file, to define new defaults values create a file /etc/makejail/makejail.conf class configClass: def __init__(self): @@ -20,10 +20,11 @@ self.useDepends=0 self.blockDepends=[] self.doNotCopy=["/usr/share/doc", - "/usr/share/info", - "/usr/share/man", - "/etc/fstab", - "/etc/mtab"] + "/usr/share/info", + "/usr/share/man", + "/etc/fstab", + "/etc/mtab", + "/proc"] self.forceCopy=[] self.cleanJailFirst=0 self.preserve=[] @@ -43,30 +44,37 @@ self.groups=[] self.debianDpkgInfoFile="/var/lib/dpkg/info/%s.list" - self.etcFile="/etc/makejail" + self.etcFile="/etc/makejail/makejail.conf" self.pathToLdConfig="/sbin/ldconfig" + # For Ubuntu systems, to prevent copying a bash shell + # we copy ldconfig.real instead + if os.path.exists("/sbin/ldconfig.real"): + self.pathToLdConfig="/sbin/ldconfig.real" self.pathToLdSoConf="/etc/ld.so.conf" self.pathToLdSoCache="/etc/ld.so.cache" self.procPath="/proc" self.userFiles=["/etc/passwd", - "/etc/shadow", - "/etc/master.passwd"] + "/etc/shadow", + "/etc/master.passwd"] self.groupFiles=["/etc/group", - "/etc/gshadow"] + "/etc/gshadow"] self.tempDir="/tmp/makejail_logs" self.psCommand="ps -e" self.psColumns=[1,4] # -e file=trace doesn't catch socket connections - self.straceCommand="strace -f %command >/dev/null 2>>%file" - self.straceCommandPid="strace -f -p %pid >/dev/null 2>>%file" + self.straceCommand="strace -e trace=file,connect -e signal=none -f -ff -o %file %command >/dev/null 2>&1" + self.straceCommandPid="strace -e trace=file,connect -e signal=none -f -ff -o %file -p %pid >/dev/null 2>&1" self.straceCommandStop="killall -9 strace" self.straceCommandView=None self.stracePatterns=['.*\("([^"]*)",.*\) .*= -[0-9]* ENO.*', - '.*\("([^"]*)",.*\) .*= -[0-9]* EACCES.*'] + '.*\("([^"]*)",.*\) .*= -[0-9]* EACCES.*', + 'chdir\("([^"]*)"\) .*= -[0-9]* ENO.*', + 'chdir\("([^"]*)"\) .*= -[0-9]* EACCESS.*'] + self.straceCreatePatterns=['.*\("([^"]*)",.*O_CREAT.*\) .* ENOENT .*', - 'bind\(.* path="([^"]*)".* ENOENT .*'] + 'bind\(.* path="([^"]*)".* ENOENT .*'] self.straceSocketPatterns=['connect\(.* path="([^"]*)".* ENOENT .*'] # Global variables @@ -220,11 +228,24 @@ def dpkgInfoFiles(package): return readFileLines(config.debianDpkgInfoFile % package) -def copyStat(source,target): +def copyStatAndOwner(source,target): + # Keep all attributes + shutil.copystat(source,target) + + # Copy user/group info statInfos=os.stat(source) - os.chmod(target,statInfos[stat.ST_MODE]) os.chown(target,statInfos[stat.ST_UID],statInfos[stat.ST_GID]) +def unmountProc(): + debug("Unmounting %s" % config.procPath) + moveIndent(1) + returnCode=os.system("umount -t proc %s%s" % (config.chroot,config.procPath)) + if returnCode==0: + debug("%s unmounted successfully" % config.procPath) + else: + abort("Unable to unmount %s" % config.procPath) + moveIndent(-1) + def mountProc(): debug("Mounting %s" % config.procPath) moveIndent(1) @@ -332,7 +353,14 @@ moveIndent(1) addFileToJail(checkDir) moveIndent(-1) - fileInChroot="%s%s" % (config.chroot,fileName) + # The directory part of fileName may be a symlink to an + # absolute pathname. For example, fileName is + # "lib64/ld-linux.so.2" where "lib64" is a symlink to "/lib". + # In that case it should be resolved before constructing + # fileInChroot. See http://bugs.debian.org/570695. + fileDir, baseName = os.path.split(fileName) + fileInChroot=os.path.join(config.chroot,os.path.realpath(fileDir)[1:], + baseName) if os.path.exists(fileInChroot): if fileIsNewer(fileName,fileInChroot): debug(" File %s is newer than the %s, overwriting" % (fileName,fileInChroot)) @@ -352,7 +380,9 @@ absoluteLinkTarget="%s/%s" % (fileDir,linkTarget) newFiles=addFileToJail(absoluteLinkTarget) missingFiles=missingFiles+newFiles - newWorkingDir="%s/%s" % (config.chroot,fileDir[1:]) + # newWorkingDir may be a symlink to an absolute + # pathname. See the above comment. + newWorkingDir="%s/%s" % (config.chroot,os.path.realpath(fileDir)[1:]) os.chdir(newWorkingDir) debug(" Creating '%s' as a symlink to '%s' (pwd=%s)" % (fileName[1:],linkTarget,newWorkingDir)) os.symlink(linkTarget,os.path.split(fileName)[1]) @@ -400,9 +430,13 @@ addPasswdFile(fileName,"groups") else: debug(" Copying %s -> %s" % (fileName,fileInChroot)) - shutil.copyfile(fileName,fileInChroot) + # Copy the file + shutil.copy(fileName,fileInChroot) + shutil.copystat(fileName,fileInChroot) missingFiles.append(fileName) - copyStat(fileName,fileInChroot) + + copyStatAndOwner(fileName,fileInChroot) + if os.path.isfile(fileName): checkRequirements(fileName) return missingFiles @@ -440,7 +474,7 @@ chunk=files[i].read() if chunk=="": finished[i]=1 - feedbackQueues[i]+=chunk + feedbackQueues[i]=feedbackQueues[i]+chunk for i in (0,1): while "\n" in feedbackQueues[i]: pos=feedbackQueues[i].find("\n") @@ -501,9 +535,14 @@ for line in ldd_lines: if not(line): continue - if string.find(line,"=>")==-1: + # Not all ldd lines include => they might + # reference the absolute path of the library + if string.find(line,"=>")==-1 and string.find(line,"/")==-1: continue - lib=string.strip(string.split(string.split(line,"=>")[1],"(")[0]) + if string.find(line,"=>")!=-1: + lib=string.strip(string.split(string.split(line,"=>")[1],"(")[0]) + else: + lib=string.strip(string.split(line,"(")[0]) addFileToJail(lib) moveIndent(-1) moveIndent(-1) @@ -615,8 +654,6 @@ def addMissingFilesFromProcess(items,testCommandsOutsideJail=[]): straceTempFileName=tempfile.mktemp("trace") - straceTempFile=open(straceTempFileName,"w") - straceTempFile.close() if not(type(items) in (types.ListType,types.TupleType)): items=[items] @@ -660,6 +697,13 @@ out.append(line) debug(string.join(out," ")) + # Join the generated pid-specific trace files (strace -ff) into one single trace file + # If there are no such files the following lines should do nothing. + debug("Joining pid-specific trace files (if any)...") + command=string.replace("cat %file.* >>%file 2>/dev/null","%file",straceTempFileName) + os.system(command) + os.system("rm -f %s.* >/dev/null 2>/dev/null" % straceTempFileName) + if config.straceCommandView: command=string.replace(config.straceCommandView,"%file",straceTempFileName) lines=execute(command) @@ -804,6 +848,10 @@ global tmpOut debug("Chroot directory is %s" % config.chroot) + if not(os.path.isdir(config.chroot)): + sys.stderr.write("ERROR: The chroot location defined '%s' does not exist. Please create it and run makejail again.\n" % config.chroot) + sys.exit(1) + # In the strace output, the command attempt to access # the directory where this script was started outside @@ -823,6 +871,9 @@ killall(config.processNames) if config.cleanJailFirst: + # We have to umount /proc before we proceed + if os.path.isdir(config.chroot+config.procPath): + unmountProc() cleanJail() # === Add packages @@ -949,8 +1000,8 @@ except: if fp: fp.close() - sys.stderr.write("Cannot load configuration file '%s' as a python module\n" % file) - sys.stderr.write("Executing it with python which should display a syntax error:\n") + sys.stderr.write("ERROR: Cannot load configuration file '%s' as a python module\n" % file) + sys.stderr.write("ERROR: Executing it with python which should display a syntax error:\n") os.system("python %s" % file) sys.exit(1) @@ -984,7 +1035,7 @@ try: configFile=sys.argv[1] except IndexError: - abort("Usage: %s configFile" % sys.argv[0]) + abort("Usage: %s package\n\tpackage is the name of an installed package\n\t(a configuration file must exist in %s)" % (sys.argv[0],config.etcFile)) if os.path.isfile(config.etcFile): loadConfig(config.etcFile) --- makejail-0.0.5.orig/Makefile +++ makejail-0.0.5/Makefile @@ -1,6 +1,7 @@ # Makefile for makejail -prefix = /usr +DESTDIR=/ +prefix = $(DESTDIR)/usr BIN_DIR = $(prefix)/sbin DOC_DIR = $(prefix)/share/doc/makejail MAN_DIR = $(prefix)/share/man/man8 @@ -14,11 +15,11 @@ .PHONY: install distclean -all: +all: docs @echo "Usage: make [install|uninstall|docs|clean_docs]" docs: - ./makedocs + python makedocs docbook-to-man manpage.sgml > $(MAN_PAGE) install: @@ -32,7 +33,7 @@ cp doc/index.html $(HTML_DIR) chmod 644 $(HTML_DIR)/index.html if (test ! -d $(EXAMPLES_DIR)); then mkdir -p $(EXAMPLES_DIR) ; chmod 755 $(EXAMPLES_DIR) ; fi - cp -Rp examples/* $(EXAMPLES_DIR) + cp -a examples/* $(EXAMPLES_DIR) chmod 644 $(EXAMPLES_DIR)/* if (test ! -d $(MAN_DIR)); then mkdir -p $(MAN_DIR) ; chmod 755 $(MAN_DIR) ; fi $(INSTALL) makejail.8 $(MAN_DIR) --- makejail-0.0.5.orig/doc.src +++ makejail-0.0.5/doc.src @@ -18,7 +18,7 @@ - the files which belongs to a package and eventually the packages it requires. When a file is added into the jail: -- the shared librairies it needs (given by ldd) are added too. +- the shared libraries it needs (given by ldd) are added too. - upper directories are created if needed. - if the file is a symbolic link, the target is added too. - all the checks to determine what files a file needs are recursive. @@ -39,7 +39,7 @@ H1:Configuration files The file must be written in a correct python syntax. The good news is that the syntax is simple, and you can eventually write some python code to define the syntax. -Some default directives may be defined in /etc/makejail, the configuration file given on the command line has predecence. +Some default directives may be defined in /etc/makejail/makejail.conf, the configuration file given on the command line has predecence. All paths you use in the configuration file must be absolute. __MANMODE=2__ @@ -61,7 +61,7 @@ The commands used to start the daemon, a good starting point may be the command used in the startup script in /etc/init.d -Format: ["command1","command2"] +Format: ["command1", "command2"] Default: [] @@ -69,7 +69,7 @@ The name of the runnning processes after the daemon has been started. -Format: ["process1","process2"] +Format: ["process1", "process2"] Default: [] @@ -81,7 +81,7 @@ The test commands which should be executed. -Format: ["command1","command2"] +Format: ["command1", "command2"] Default: [] @@ -118,16 +118,16 @@ Do not copy the files matching these patterns according to the rules used by the Unix shell. No tilde expansion is done, but *, ?, and character ranges expressed with [] will be correctly matched. -Format: ["path1","path2"] +Format: ["path1", "path2"] -Default: ["/usr/share/doc","/usr/share/info","/usr/share/man","/etc/fstab","/etc/mtab"] +Default: ["/usr/share/doc", "/usr/share/info", "/usr/share/man", "/etc/fstab", "/etc/mtab", "/proc"] H3:forceCopy When initializing the jail, copy the files matching these patterns according to the rules used by the Unix shell. No tilde expansion is done, but *, ?, and character ranges expressed with [] will be correctly matched. -Format: ["path1","path2"] +Format: ["path1", "path2"] Default: [] @@ -137,14 +137,14 @@ Format: 0 to do nothing or 1 to remove files from the jail. -Default: 1 +Default: 0 H3:preserve Useful only if cleanJailFirst=1, makejail won't remove files or directories if their path begins with one of the strings in this list. When updating a jail, you should for example put the locations of log files here. -Format: ["path1","path2"] +Format: ["path1", "path2"] Default: [] @@ -162,7 +162,7 @@ Makejail will filter the files listed in the directive userFiles and copy only lines matching these users, which means lines starting with "user:" You can use ["*"] to disable filtering and copy the whole file. -Format: ["user1","user2"] +Format: ["user1", "user2"] Default: [] @@ -171,7 +171,7 @@ Makejail will filter the files listed in the directive groupFiles and copy only lines matching these groups, which means lines starting with "group:" You can use ["*"] to disable filtering and copy the whole file. -Format: ["group1","group2"] +Format: ["group1", "group2"] Default: [] @@ -219,7 +219,7 @@ The name of the packages. It will copy the files which belongs to the package according to the file /var/lib/dpkg/info/$package.list. -Format: ["package1","package2"] +Format: ["package1", "package2"] Default: [] @@ -236,7 +236,7 @@ Useful only if useDepends=1, it prevents the installation of these packages even if dpkg says they are required. -Format: ["package1","package2"] +Format: ["package1", "package2"] Default: [] @@ -252,15 +252,15 @@ H3:pathToLdConfig -Path to the executable ldconfig, used to generate the shared librairies cache. ldconfig is executed in the jail to regenerate this cache. +Path to the executable ldconfig, used to generate the shared libraries cache. ldconfig is executed in the jail to regenerate this cache. Format: "/path/to/ldconfig" -Default: "/sbin/ldconfig" +Default: "/sbin/ldconfig" (Debian), "/sbin/ldconfig.real" (Ubuntu) H3:pathToLdSoConf -The path to the configuration files used by ldconfig, which says which directories should be scanned searching for shared librairies. +The path to the configuration files used by ldconfig, which says which directories should be scanned searching for shared libraries. Set this to None if your system doesn't use such a file. Format: "/path/to/ld.so.conf" @@ -269,7 +269,7 @@ H3:pathToLdSoCache -The path to the shared librairies cache generated by ldconfig. +The path to the shared libraries cache generated by ldconfig. Format: "/path/to/ld.so.cache" @@ -287,17 +287,17 @@ List of the files whose contents should be filtered, to keep only the users listed in the directive "users". -Format: ["file1","file2] +Format: ["file1", "file2] -Default: ["/etc/passwd","/etc/shadow"] +Default: ["/etc/passwd", "/etc/shadow"] H3:groupFiles List of the files whose contents should be filtered, to keep only the groups listed in the directive "groups". -Format: ["file1","file2] +Format: ["file1", "file2] -Default:["/etc/group","/etc/gshadow"] +Default:["/etc/group", "/etc/gshadow"] H3:tempDir @@ -337,13 +337,13 @@ Format: "strace_command [options] %command > %file" -Default: "strace -f %command >/dev/null 2>>%file" +Default: "strace -e trace=file,connect -e signal=none -f -ff -o %file %command >/dev/null 2>&1" H3:straceCommandPid String describing the strace command when attaching itself to a running process. "%pid" will be replaced by the id of the process to trace, and "%file" by the path to the temporary trace file. -Format: "strace_command [options] %pid > %file" +Format: "strace -e trace=file,connect -e signal=none -f -ff -o %file -p %pid >/dev/null 2>&1" Default: "strace -f -p %pid >/dev/null 2>>%file" @@ -384,26 +384,26 @@ Regular expressions to detect a failed attempt at accessing a file. If the file exists outside the jail makejail will copy it into the jail. -Format: ["regexp1","regexp2",["regexp3","regexp3 for the next line"]] +Format: ["regexp1", "regexp2", ["regexp3", "regexp3 for the next line"]] -Default: ['.*\("([^"]*)",.*\) .* ENOENT .*'] +Default: ['.*("([^"]*)",.*) .* ENOENT .*'] H3:straceCreatePatterns Regular expressions to detect a failed attempt at creating a file. If the directory where the file should be created exists outside the jail, it will create it inside the jail. -Format: ["regexp1","regexp2",["regexp3","regexp3 for the next line"]] +Format: ["regexp1", "regexp2", ["regexp3", "regexp3 for the next line"]] -Default: ['.*\("([^"]*)",.*O_CREAT.*\) .* ENOENT .*','bind\(.* path="([^"]*)".* ENOENT .*'] +Default: ['.*("([^"]*)",.*O_CREAT.*) .* ENOENT .*','bind(.* path="([^"]*)".* ENOENT .*'] H3:straceSocketPatterns Regular expressions to detect a failed attempt at accessing a socket. makejail can't create the socket, it will just print a warning. -Format: ["regexp1","regexp2",["regexp3","regexp3 for the next line"]] +Format: ["regexp1", "regexp2", ["regexp3", "regexp3 for the next line"]] -Default: ['connect\(.* path="([^"]*)".* ENOENT .*'] +Default: ['connect(.* path="([^"]*)".* ENOENT .*'] __MANMODE=0__ --- makejail-0.0.5.orig/manpage.sgml.template +++ makejail-0.0.5/manpage.sgml.template @@ -94,8 +94,18 @@ REPORTING BUGS - Report bugs to makejail@floc.net - + Makejail is heavily patched for Debian systems. + If you are using this program as part of the Debian + distribution you should report bugs to the Debian Bug Tracking System + using + submit@bugs.debian.org. For this you can use the + reportbug or bug program. + Please, read /usr/share/doc/debian/bug-reporting.txt + (or www.debian.org/Bugs) before doing so. + + If you want to report bugs to the upstream maintainer use + makejail@floc.net +