From: Carl Worth Date: Wed, 24 Apr 2013 00:25:13 +0000 (-0700) Subject: Compile both 32-bit and 64-bit versions of the wrapper library. X-Git-Url: https://git.cworth.org/git?p=fips;a=commitdiff_plain;h=b32aa136d3e51a250e58c0fc28162b5e5fd52f67 Compile both 32-bit and 64-bit versions of the wrapper library. This is intended to make it transparent to run fips with either a 32-bit or a 64-bit program. And it does do that once you successfully build both versions of the library. Actually being able to build both versions of the library is a little tricky though. Here are some of the tricks: 1. You will need to have installed both a 32-bit and a 64-bit .so file for each dependent library, (currently libelf and libtalloc). The current configure script doesn't check for both versions, so you don't get a lot of guidance here. And that's because... 2. On Debian, at least, one cannot currently install both libtalloc-dev:amd64 and libtalloc-dev:i386 at the same time. Contrast with libelf-dev:i386 and libelf-dev:amd64 which work just fine when installed simultaneously. One can work around this by just install libtalloc-dev:amd64 and then manually creating the link you need for the i386 package. Namely: sudo ln -s libelf.so.1 /usr/lib/i386-linux-gnu/libelf.so --- diff --git a/.gitignore b/.gitignore index 65bec77..f95e49b 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ Makefile.config config.h fips -libfips.so +libfips-32.so +libfips-64.so *.o *~ diff --git a/Makefile.local b/Makefile.local index 1287f49..3dd7932 100644 --- a/Makefile.local +++ b/Makefile.local @@ -4,15 +4,12 @@ include Makefile.release # Smash together user's values with our extra values FINAL_CFLAGS = -DFIPS_VERSION=$(VERSION) $(CFLAGS) $(WARN_CFLAGS) $(CONFIGURE_CFLAGS) $(extra_cflags) -FINAL_FIPS_LDFLAGS = $(LDFLAGS) $(AS_NEEDED_LDFLAGS) $(TALLOC_LDFLAGS) -FINAL_LIBFIPS_LDFLAGS = $(LDFLAGS) -ldl +FINAL_FIPS_LDFLAGS = $(LDFLAGS) $(AS_NEEDED_LDFLAGS) $(CONFIGURE_LDFLAGS) +FINAL_LIBFIPS_LDFLAGS = $(LDFLAGS) $(CONFIGURE_LDFLAGS) -ldl FINAL_FIPS_LINKER = CC -ifneq ($(LINKER_RESOLVES_LIBRARY_DEPENDENCIES),1) -FINAL_FIPS_LDFLAGS += $(CONFIGURE_LDFLAGS) -endif .PHONY: all -all: fips libfips.so +all: fips libfips-64.so libfips-32.so ifeq ($(MAKECMDGOALS),) ifeq ($(shell cat .first-build-message 2>/dev/null),) @@ -46,6 +43,14 @@ endif # Otherwise, print the full command line. quiet ?= $($(shell echo $1 | sed -e s'/ .*//')) +%-32.o: %.c $(global_deps) + @mkdir -p .deps/$(@D) + $(call quiet,CC $(CFLAGS) -m32) -c $(FINAL_CFLAGS) -m32 $< -o $@ -MD -MP -MF .deps/$*.d + +%-64.o: %.c $(global_deps) + @mkdir -p .deps/$(@D) + $(call quiet,CC $(CFLAGS) -m64) -c $(FINAL_CFLAGS) -m64 $< -o $@ -MD -MP -MF .deps/$*.d + %.o: %.c $(global_deps) @mkdir -p .deps/$(@D) $(call quiet,CC $(CFLAGS)) -c $(FINAL_CFLAGS) $< -o $@ -MD -MP -MF .deps/$*.d @@ -77,17 +82,23 @@ extra_cflags += -I$(srcdir) -fPIC libfips_srcs = \ glxwrap.c -libfips_modules = $(libfips_srcs:.c=.o) +libfips_32_modules = $(libfips_srcs:.c=-32.o) + +libfips_64_modules = $(libfips_srcs:.c=-64.o) + +libfips-32.so: $(libfips_32_modules) libfips.sym + $(call quiet,$(FINAL_FIPS_LINKER) $(CFLAGS) -m32) $(FINAL_CFLAGS) -m32 $(libfips_32_modules) $(FINAL_LIBFIPS_LDFLAGS) $(LIBRARY_LINK_FLAGS) -o $@ -libfips.so: $(libfips_modules) libfips.sym - $(call quiet,$(FINAL_FIPS_LINKER) $(CFLAGS)) $(FINAL_CFLAGS) $(libfips_modules) $(FINAL_LIBFIPS_LDFLAGS) $(LIBRARY_LINK_FLAGS) -o $@ +libfips-64.so: $(libfips_64_modules) libfips.sym + $(call quiet,$(FINAL_FIPS_LINKER) $(CFLAGS) -m64) $(FINAL_CFLAGS) -m64 $(libfips_64_modules) $(FINAL_LIBFIPS_LDFLAGS) $(LIBRARY_LINK_FLAGS) -o $@ .PHONY: install install: all mkdir -p $(DESTDIR)$(bindir) install fips $(DESTDIR)$(bindir)/fips mkdir -p $(DESTDIR)$(libdir)/fips - install -m0644 libfips.so $(DESTDIR)$(libdir)/fips/libfips.so + install -m0644 libfips-32.so $(DESTDIR)$(libdir)/fips/libfips-32.so + install -m0644 libfips-64.so $(DESTDIR)$(libdir)/fips/libfips-64.so ifeq ($(MAKECMDGOALS), install) @echo "" @echo "Fips is now installed to $(DESTDIR)$(prefix)" @@ -95,7 +106,7 @@ ifeq ($(MAKECMDGOALS), install) endif SRCS := $(SRCS) $(fips_srcs) $(libfips_srcs) -CLEAN := $(CLEAN) fips $(fips_modules) $(libfips_modules) +CLEAN := $(CLEAN) fips $(fips_modules) $(libfips_32_modules) $(libfips_64_modules) DISTCLEAN := $(DISTCLEAN) .first-build-message Makefile.config diff --git a/configure b/configure index 6c8b186..f86db97 100755 --- a/configure +++ b/configure @@ -211,36 +211,22 @@ else errors=$((errors + 1)) fi -printf "Checking which platform we are on... " -uname=`uname` -if [ $uname = "Darwin" ] ; then - printf "Mac OS X.\n" - platform=MACOSX - linker_resolves_library_dependencies=0 -elif [ $uname = "SunOS" ] ; then - printf "Solaris.\n" - platform=SOLARIS - linker_resolves_library_dependencies=0 -elif [ $uname = "FreeBSD" ] ; then - printf "FreeBSD.\n" - platform=FREEBSD - linker_resolves_library_dependencies=0 -elif [ $uname = "OpenBSD" ] ; then - printf "OpenBSD.\n" - platform=OPENBSD - linker_resolves_library_dependencies=0 -elif [ $uname = "Linux" ] || [ $uname = "GNU" ] ; then - printf "$uname\n" - platform="$uname" - linker_resolves_library_dependencies=1 +printf "Checking for libelf... " +printf "#include \nint main(void){return elf_version (EV_CURRENT);}\n" > elf-minimal.c +if ${CC} -o elf-minimal elf-minimal.c -lelf > /dev/null 2>&1 +then + printf "Yes.\n" + have_libelf=1 + libelf_cflags= + libelf_ldflags=-lelf else - printf "Unknown.\n" - cat < +#include +#include + #include "execute.h" /* Terminate a string representing a filename at the final '/' to @@ -112,8 +115,70 @@ exists (const char *path) return 1; } -/* Given "library" filename resolve it to an absolute path to an - * existing file as follows: +/* Is the given elf program 32 or 64 bit? + * + * Note: This function aborts the current program if 'program' cannot + * be opened as a valid ELF file. */ +static int +elf_bits (const char *program) +{ + Elf *elf; + GElf_Ehdr ehdr; + int fd, class; + + fd = open (program, O_RDONLY, 0); + if (fd < 0) { + fprintf (stderr, "Failed to open %s: %s\n", program, + strerror (errno)); + exit (1); + } + + if (elf_version (EV_CURRENT ) == EV_NONE) { + fprintf (stderr, "Failed to initialize elf library: %s\n", + elf_errmsg (-1)); + exit (1); + } + + elf = elf_begin (fd, ELF_C_READ, NULL); + if (elf == NULL) { + fprintf (stderr, "Call to elf_begin on %s failed: %s\n", + program, elf_errmsg(-1)); + exit (1); + } + + if (elf_kind (elf) != ELF_K_ELF) { + fprintf (stderr, "Not an ELF object: %s\n", program); + exit (1); + } + + if (gelf_getehdr (elf, &ehdr) == NULL) { + fprintf (stderr, "getehdr on %s failed: %s\n", + program, elf_errmsg (-1)); + exit (1); + } + + class = gelf_getclass (elf); + + if (class == ELFCLASSNONE) { + fprintf (stderr, "getclass on %s failed: %s\n", program, + elf_errmsg (-1)); + exit (1); + } + + if (class == ELFCLASS32) + return 32; + else + return 64; + +} + +/* Find the appropriate path to the libfips wrapper. + * + * This involves, first, examining the elf header of the 'program' + * binary to be executed to know whether we should look for + * libfips-32.so or libfips-64.so. + * + * Next, we find the absolute patch containing the library as follows: * * 1. Look in same directory as current executable image * @@ -134,9 +199,14 @@ exists (const char *path) * Returns: a string talloc'ed to 'ctx' */ static char * -resolve_path (void *ctx, const char *library) +find_libfips_path (void *ctx, const char *program) { - char *bin_path, *lib_path; + char *bin_path, *library, *lib_path; + int bits; + + bits = elf_bits (program); + + library = talloc_asprintf(ctx, "libfips-%d.so", bits); bin_path = get_bin_name (ctx); @@ -163,14 +233,11 @@ resolve_path (void *ctx, const char *library) exit (1); } -/* After forking, set LD_PRELOAD to preload "library" within child - * environment, then exec given arguments. - * - * The "library" argument is the filename (without path) of a shared - * library to load. The complete path will be resolved with - * resolve_library_path above. */ +/* After forking, set LD_PRELOAD to preload libfips-{32,64}.so within + * child environment, then exec given arguments. + */ static int -fork_exec_with_preload_and_wait (char * const argv[], const char *library) +fork_exec_with_fips_preload_and_wait (char * const argv[]) { pid_t pid; int i, status; @@ -182,7 +249,7 @@ fork_exec_with_preload_and_wait (char * const argv[], const char *library) void *ctx = talloc_new (NULL); char *lib_path; - lib_path = resolve_path (ctx, library); + lib_path = find_libfips_path (ctx, argv[0]); setenv ("LD_PRELOAD", lib_path, 1); @@ -210,7 +277,7 @@ fork_exec_with_preload_and_wait (char * const argv[], const char *library) } int -execute_with_preload (int argc, char * const argv[], const char *library) +execute_with_fips_preload (int argc, char * const argv[]) { char **execvp_args; int i; @@ -228,5 +295,5 @@ execute_with_preload (int argc, char * const argv[], const char *library) /* execvp needs final NULL */ execvp_args[i] = NULL; - return fork_exec_with_preload_and_wait (execvp_args, library); + return fork_exec_with_fips_preload_and_wait (execvp_args); } diff --git a/execute.h b/execute.h index 03af777..c1ba3bc 100644 --- a/execute.h +++ b/execute.h @@ -23,10 +23,9 @@ #define EXECUTE_H /* Execute the program with arguments as specified, but with the - * library specified in "library" pre-loaded. The library should be - * specified as the compiled filename (such as libfips.so). + * fips library specified as an LD_PRELOAD. */ int -execute_with_preload (int argc, char * const argv[], const char *library); +execute_with_fips_preload (int argc, char * const argv[]); #endif diff --git a/fips.c b/fips.c index 98cd9ba..370a2ee 100644 --- a/fips.c +++ b/fips.c @@ -74,7 +74,7 @@ main (int argc, char *argv[]) exit (1); } - ret = execute_with_preload (argc - optind, &argv[optind], "libfips.so"); + ret = execute_with_fips_preload (argc - optind, &argv[optind]); return ret; }