From 42db2f9640d98557f4156dfbdb380ca917b35e78 Mon Sep 17 00:00:00 2001 From: Daniel Hokka Zakrisson Date: Tue, 1 Jul 2008 16:17:42 +0000 Subject: [PATCH] Add ugly hack to workaround O_CLOEXEC vs. O_ATOMICLOOKUP. --- bootmanager.spec | 1 + source/libc-opendir-hack.c | 16 +++++++++++++++ source/steps/ChainBootNode.py | 10 +++++----- source/steps/CheckForNewDisks.py | 2 +- source/steps/InstallBootstrapFS.py | 5 ++--- source/steps/InstallInit.py | 2 +- source/steps/InstallUninitHardware.py | 2 +- source/steps/InstallWriteConfig.py | 28 +++++++++++++-------------- source/steps/MakeInitrd.py | 6 +++--- source/utils.py | 28 +++++++++++++++++++++++++++ 10 files changed, 72 insertions(+), 28 deletions(-) create mode 100644 source/libc-opendir-hack.c diff --git a/bootmanager.spec b/bootmanager.spec index d77e1da..9ced617 100644 --- a/bootmanager.spec +++ b/bootmanager.spec @@ -36,6 +36,7 @@ nodes. %setup -q %build +gcc -shared -fPIC -Os -o source/libc-opendir-hack.so source/libc-opendir-hack.c %install rm -rf $RPM_BUILD_ROOT diff --git a/source/libc-opendir-hack.c b/source/libc-opendir-hack.c new file mode 100644 index 0000000..95786ef --- /dev/null +++ b/source/libc-opendir-hack.c @@ -0,0 +1,16 @@ +#define _GNU_SOURCE 1 + +#include +#include +#include +#include + +#define NAME "O_CLOEXEC-vs-O_ATOMICLOOKUP" + +DIR *opendir(const char *name) +{ + int fd = open(name, O_RDONLY|O_NDELAY|O_DIRECTORY|O_LARGEFILE); + if (fd == -1) + return NULL; + return fdopendir(fd); +} diff --git a/source/steps/ChainBootNode.py b/source/steps/ChainBootNode.py index 10f068e..6d9d5c6 100644 --- a/source/steps/ChainBootNode.py +++ b/source/steps/ChainBootNode.py @@ -120,18 +120,18 @@ def Run( vars, log ): log.write( "Updating configuration files.\n" ) try: cmd = "/etc/init.d/conf_files start --noscripts" - utils.sysexec( "chroot %s %s" % (SYSIMG_PATH, cmd), log ) + utils.sysexec_chroot( SYSIMG_PATH, cmd, log ) except IOError, e: log.write("conf_files failed with \n %s" % e) # update node packages log.write( "Running node update.\n" ) if os.path.exists( SYSIMG_PATH + "/usr/bin/NodeUpdate.py" ): - cmd = "chroot %s /usr/bin/NodeUpdate.py start noreboot" % SYSIMG_PATH + cmd = "/usr/bin/NodeUpdate.py start noreboot" else: # for backwards compatibility - cmd = "chroot %s /usr/local/planetlab/bin/NodeUpdate.py start noreboot" % SYSIMG_PATH - utils.sysexec( cmd, log ) + cmd = "/usr/local/planetlab/bin/NodeUpdate.py start noreboot" + utils.sysexec_chroot( SYSIMG_PATH, cmd, log ) # the following step should be done by NM UpdateNodeConfiguration.Run( vars, log ) @@ -165,7 +165,7 @@ def Run( vars, log ): try: # backwards compat, though, we should never hit this case post PL 3.2 os.stat("%s/rcfs/taskclass"%SYSIMG_PATH) - utils.sysexec_noerr( "chroot %s umount /rcfs" % SYSIMG_PATH, log ) + utils.sysexec_chroot_noerr( SYSIMG_PATH, "umount /rcfs", log ) except OSError, e: pass diff --git a/source/steps/CheckForNewDisks.py b/source/steps/CheckForNewDisks.py index e90e459..a952b09 100644 --- a/source/steps/CheckForNewDisks.py +++ b/source/steps/CheckForNewDisks.py @@ -138,7 +138,7 @@ def Run( vars, log ): try: # backwards compat, though, we should never hit this case post PL 3.2 os.stat("%s/rcfs/taskclass"%SYSIMG_PATH) - utils.sysexec_noerr( "chroot %s umount /rcfs" % SYSIMG_PATH, log ) + utils.sysexec_chroot_noerr( SYSIMG_PATH, "umount /rcfs", log ) except OSError, e: pass diff --git a/source/steps/InstallBootstrapFS.py b/source/steps/InstallBootstrapFS.py index e04f930..a8f5174 100644 --- a/source/steps/InstallBootstrapFS.py +++ b/source/steps/InstallBootstrapFS.py @@ -200,8 +200,7 @@ def Run( vars, log ): utils.sysexec("gpg --homedir=/root --export --armor" \ " --no-default-keyring --keyring %s/usr/boot/pubring.gpg" \ " >%s/etc/pki/rpm-gpg/RPM-GPG-KEY-planetlab" % (SYSIMG_PATH, SYSIMG_PATH)) - utils.sysexec("chroot %s rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-planetlab" % \ - SYSIMG_PATH) + utils.sysexec_chroot(SYSIMG_PATH, "rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-planetlab") # yum-based extensions: # before we can use yum, yum.conf needs to get installed @@ -229,7 +228,7 @@ def Run( vars, log ): yum_command="yum groupinstall extension%s"%extension utils.breakpoint ("before chroot %s %s"%(SYSIMG_PATH,yum_command)) log.write("Attempting to install extension %s through yum\n"%extension) - utils.sysexec_noerr("chroot %s %s" % (SYSIMG_PATH,yum_command)) + utils.sysexec_chroot_noerr(SYSIMG_PATH, "%s" % (yum_command)) # xxx how to check that this completed correctly ? # let's cleanup utils.sysexec_noerr( "umount %s/proc" % SYSIMG_PATH, log ) diff --git a/source/steps/InstallInit.py b/source/steps/InstallInit.py index 2e6b66b..c0980c1 100644 --- a/source/steps/InstallInit.py +++ b/source/steps/InstallInit.py @@ -60,7 +60,7 @@ def Run( vars, log ): try: # backwards compat, though, we should never hit this case post PL 3.2 os.stat("%s/rcfs/taskclass"%SYSIMG_PATH) - utils.sysexec_noerr( "chroot %s umount /rcfs" % SYSIMG_PATH, log ) + utils.sysexec_chroot_noerr( SYSIMG_PATH, "umount /rcfs", log ) except OSError, e: pass diff --git a/source/steps/InstallUninitHardware.py b/source/steps/InstallUninitHardware.py index df99515..0b01209 100644 --- a/source/steps/InstallUninitHardware.py +++ b/source/steps/InstallUninitHardware.py @@ -66,7 +66,7 @@ def Run( vars, log ): try: # backwards compat, though, we should never hit this case post PL 3.2 os.stat("%s/rcfs/taskclass"%SYSIMG_PATH) - utils.sysexec_noerr( "chroot %s umount /rcfs" % SYSIMG_PATH, log ) + utils.sysexec_chroot_noerr( SYSIMG_PATH, "umount /rcfs", log ) except OSError, e: pass diff --git a/source/steps/InstallWriteConfig.py b/source/steps/InstallWriteConfig.py index 60a53c3..f7afb52 100644 --- a/source/steps/InstallWriteConfig.py +++ b/source/steps/InstallWriteConfig.py @@ -75,11 +75,11 @@ def Run( vars, log ): raise BootManagerException, "Variable in vars, shouldn't be: %s\n" % var log.write( "Setting local time to UTC\n" ) - utils.sysexec( "chroot %s ln -sf /usr/share/zoneinfo/UTC /etc/localtime" % \ - SYSIMG_PATH, log ) + utils.sysexec_chroot( SYSIMG_PATH, + "ln -sf /usr/share/zoneinfo/UTC /etc/localtime", log ) log.write( "Enabling ntp at boot\n" ) - utils.sysexec( "chroot %s chkconfig ntpd on" % SYSIMG_PATH, log ) + utils.sysexec_chroot( SYSIMG_PATH, "chkconfig ntpd on", log ) log.write( "Creating system directory %s\n" % PLCONF_DIR ) if not utils.makedirs( "%s/%s" % (SYSIMG_PATH,PLCONF_DIR) ): @@ -109,14 +109,14 @@ def Run( vars, log ): issue.close() log.write( "Setting up authentication (non-ssh)\n" ) - utils.sysexec( "chroot %s authconfig --nostart --kickstart --enablemd5 " \ - "--enableshadow" % SYSIMG_PATH, log ) + utils.sysexec_chroot( SYSIMG_PATH, "authconfig --nostart --kickstart --enablemd5 " \ + "--enableshadow", log ) utils.sysexec( "sed -e 's/^root\:\:/root\:*\:/g' " \ "%s/etc/shadow > %s/etc/shadow.new" % \ (SYSIMG_PATH,SYSIMG_PATH), log ) - utils.sysexec( "chroot %s mv " \ - "/etc/shadow.new /etc/shadow" % SYSIMG_PATH, log ) - utils.sysexec( "chroot %s chmod 400 /etc/shadow" % SYSIMG_PATH, log ) + utils.sysexec_chroot( SYSIMG_PATH, "mv " \ + "/etc/shadow.new /etc/shadow", log ) + utils.sysexec_chroot( SYSIMG_PATH, "chmod 400 /etc/shadow", log ) # if we are setup with dhcp, copy the current /etc/resolv.conf into # the system image so we can run programs inside that need network access @@ -140,22 +140,22 @@ def Run( vars, log ): log.write( "Generating SSH1 RSA host key:\n" ) key_file= "/etc/ssh/ssh_host_key" - utils.sysexec( "chroot %s %s -q -t rsa1 -f %s -C '' -N ''" % - (SYSIMG_PATH,key_gen_prog,key_file), log ) + utils.sysexec_chroot( SYSIMG_PATH, "%s -q -t rsa1 -f %s -C '' -N ''" % + (key_gen_prog,key_file), log ) utils.sysexec( "chmod 600 %s/%s" % (SYSIMG_PATH,key_file), log ) utils.sysexec( "chmod 644 %s/%s.pub" % (SYSIMG_PATH,key_file), log ) log.write( "Generating SSH2 RSA host key:\n" ) key_file= "/etc/ssh/ssh_host_rsa_key" - utils.sysexec( "chroot %s %s -q -t rsa -f %s -C '' -N ''" % - (SYSIMG_PATH,key_gen_prog,key_file), log ) + utils.sysexec_chroot( SYSIMG_PATH, "%s -q -t rsa -f %s -C '' -N ''" % + (key_gen_prog,key_file), log ) utils.sysexec( "chmod 600 %s/%s" % (SYSIMG_PATH,key_file), log ) utils.sysexec( "chmod 644 %s/%s.pub" % (SYSIMG_PATH,key_file), log ) log.write( "Generating SSH2 DSA host key:\n" ) key_file= "/etc/ssh/ssh_host_dsa_key" - utils.sysexec( "chroot %s %s -q -t dsa -f %s -C '' -N ''" % - (SYSIMG_PATH,key_gen_prog,key_file), log ) + utils.sysexec_chroot( SYSIMG_PATH, "%s -q -t dsa -f %s -C '' -N ''" % + (key_gen_prog,key_file), log ) utils.sysexec( "chmod 600 %s/%s" % (SYSIMG_PATH,key_file), log ) utils.sysexec( "chmod 644 %s/%s.pub" % (SYSIMG_PATH,key_file), log ) diff --git a/source/steps/MakeInitrd.py b/source/steps/MakeInitrd.py index f742859..b5abb2c 100644 --- a/source/steps/MakeInitrd.py +++ b/source/steps/MakeInitrd.py @@ -44,12 +44,12 @@ def Run( vars, log ): initrd, kernel_version= systeminfo.getKernelVersion(vars,log) utils.removefile( "%s/boot/%s" % (SYSIMG_PATH, initrd) ) if checkKern() == True: - utils.sysexec( "chroot %s mkinitrd -v /boot/initrd-%s.img %s" % \ - (SYSIMG_PATH, kernel_version, kernel_version), log ) + utils.sysexec_chroot( SYSIMG_PATH, "mkinitrd -v /boot/initrd-%s.img %s" % \ + (kernel_version, kernel_version), log ) else: shutil.copy("./mkinitrd.sh","%s/tmp/mkinitrd.sh" % SYSIMG_PATH) os.chmod("%s/tmp/mkinitrd.sh" % SYSIMG_PATH, 755) - utils.sysexec( "chroot %s /tmp/mkinitrd.sh %s" % (SYSIMG_PATH, kernel_version)) + utils.sysexec_chroot( SYSIMG_PATH, "/tmp/mkinitrd.sh %s" % (kernel_version)) utils.sysexec_noerr("umount %s/sys" % SYSIMG_PATH) utils.sysexec_noerr("umount %s/dev" % SYSIMG_PATH) diff --git a/source/utils.py b/source/utils.py index 35496ed..5c75606 100644 --- a/source/utils.py +++ b/source/utils.py @@ -93,6 +93,34 @@ def sysexec( cmd, log= None ): return 1 +def sysexec_chroot( path, cmd, log= None ): + """ + same as sysexec, but inside a chroot + """ + preload = "" + release = os.uname()[2] + # 2.6.12 kernels need this + if release[:5] == "2.6.1": + library = "%s/lib/libc-opendir-hack.so" % path + if not os.path.exists(library): + shutil.copy("./libc-opendir-hack.so", library) + preload = "/bin/env LD_PRELOAD=/lib/libc-opendir-hack.so" + sysexec("chroot %s %s %s" % (path, preload, cmd), log) + + +def sysexec_chroot_noerr( path, cmd, log= None ): + """ + same as sysexec_chroot, but capture boot manager exceptions + """ + try: + rc= 0 + rc= syexec_chroot( cmd, log ) + except BootManagerException, e: + pass + + return rc + + def sysexec_noerr( cmd, log= None ): """ same as sysexec, but capture boot manager exceptions -- 2.47.0