From 05fcdf2237fe6100cc31828ca206d42b24e8ae5a Mon Sep 17 00:00:00 2001 From: Stephen Soltesz Date: Wed, 22 Jul 2009 23:02:31 +0000 Subject: [PATCH] svn merge -c 9766 https://svn.planet-lab.org/svn/BootManager/branches/3.2 into trunk --- bootmanager.spec | 1 + source/libc-opendir-hack.c | 157 ++++++++++++++++++++++++++ source/steps/ChainBootNode.py | 10 +- source/steps/CheckForNewDisks.py | 2 +- source/steps/InstallBootstrapFS.py | 3 +- 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, 212 insertions(+), 27 deletions(-) create mode 100644 source/libc-opendir-hack.c diff --git a/bootmanager.spec b/bootmanager.spec index 7973393..f97ef29 100644 --- a/bootmanager.spec +++ b/bootmanager.spec @@ -40,6 +40,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..e7f6953 --- /dev/null +++ b/source/libc-opendir-hack.c @@ -0,0 +1,157 @@ +<<<<<<< .working +#define _GNU_SOURCE 1 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define INIT(x) real_ ## x = dlsym(RTLD_NEXT, #x); \ + if (!real_ ## x) { \ + fprintf(stderr, "Would the real " #x " please stand up? %s\n", dlerror()); \ + exit(1); \ + } + +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); +} + +DIR *__opendir(const char *name) +{ + return opendir(name); +} + +static int (*real_glob)(const char *pattern, int flags, + int (*errfunc) (const char *epath, int eerrno), + glob_t *pglob); + +int glob(const char *pattern, int flags, + int (*errfunc) (const char *epath, int eerrno), + glob_t *pglob) +{ + if (!(flags & GLOB_ALTDIRFUNC)) { + pglob->gl_closedir = closedir; + pglob->gl_readdir = readdir; + pglob->gl_opendir = opendir; + pglob->gl_lstat = lstat; + pglob->gl_stat = stat; + flags |= GLOB_ALTDIRFUNC; + } + if (!real_glob) { + INIT(glob) + } + return real_glob(pattern, flags, errfunc, pglob); +} + +#define PWD_LOCKFILE "/etc/.pwd.lock" + +static int lock_fd = -1; + +/* FIXME: Ignores multi-thread issues. + * Doesn't wait for the file to become lockable + */ +int lckpwdf(void) +{ + struct flock fl = { 0 }; + + /* This process already holds the lock */ + if (lock_fd != -1) + return -1; + + lock_fd = open(PWD_LOCKFILE, O_WRONLY|O_CREAT, 0600); + if (lock_fd == -1) + return -1; + + if (fcntl(lock_fd, F_SETFD, fcntl(lock_fd, F_GETFD, 0) | FD_CLOEXEC) == -1) { + close(lock_fd); + return -1; + } + + fl.l_type = F_WRLCK; + fl.l_whence = SEEK_SET; + return fcntl(lock_fd, F_SETLKW, &fl); +} + +int ulckpwdf(void) +{ + int result; + + if (lock_fd == -1) + return -1; + + result = close(lock_fd); + lock_fd = -1; + return result; +} + +static (*real_open)(const char *name, int flags, ...); +int open(const char *name, int flags, ...) +{ + mode_t mode; + if (flags & O_CREAT) { + va_list va; + va_start(va, flags); + mode = va_arg(va, mode_t); + va_end(va); + } + if (!real_open) { + INIT(open) + } + return real_open(name, flags, mode); +} + +static FILE *(*real_fopen)(const char *name, const char *flags); +FILE *fopen(const char *name, const char *flags) +{ + char *str, *ptr = strchr(flags, 'e'); + FILE *ret; + if (ptr) { + str = strdup(flags); + ptr = (str + (ptr - flags)); + strcpy(ptr, ptr + 1); + } + else + str = flags; + if (!real_fopen) { + INIT(fopen) + } + ret = real_fopen(name, str); + if (ptr) + free(str); + return ret; +} + +static void _init() __attribute__((constructor)); +static void _init() +{ + INIT(glob) + INIT(open) + INIT(fopen) +} +======= +#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); +} +>>>>>>> .merge-right.r9766 diff --git a/source/steps/ChainBootNode.py b/source/steps/ChainBootNode.py index 6d1e39e..f246162 100644 --- a/source/steps/ChainBootNode.py +++ b/source/steps/ChainBootNode.py @@ -110,18 +110,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 ) @@ -155,7 +155,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 44489e8..d53351c 100644 --- a/source/steps/CheckForNewDisks.py +++ b/source/steps/CheckForNewDisks.py @@ -136,7 +136,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 b9862ef..72cfe16 100644 --- a/source/steps/InstallBootstrapFS.py +++ b/source/steps/InstallBootstrapFS.py @@ -229,8 +229,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") # the yum config has changed entirely; # in addition yum installs have more or less never worked - let's forget about this diff --git a/source/steps/InstallInit.py b/source/steps/InstallInit.py index 9eb9900..c609818 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 5f9dd61..ccf1d12 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 e272fdb..29b4e4c 100644 --- a/source/steps/InstallWriteConfig.py +++ b/source/steps/InstallWriteConfig.py @@ -69,11 +69,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) ): @@ -103,14 +103,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 @@ -134,22 +134,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 7fa7178..3abbd73 100644 --- a/source/steps/MakeInitrd.py +++ b/source/steps/MakeInitrd.py @@ -71,12 +71,12 @@ def Run( vars, log ): # hack for CentOS 5.3 bypassRaidIfNeeded(SYSIMG_PATH) if kernelHasMkinitrd() == 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 407216b..ebd5430 100644 --- a/source/utils.py +++ b/source/utils.py @@ -149,6 +149,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.43.0