]> git.cworth.org Git - fips/commitdiff
Compile both 32-bit and 64-bit versions of the wrapper library.
authorCarl Worth <cworth@cworth.org>
Wed, 24 Apr 2013 00:25:13 +0000 (17:25 -0700)
committerCarl Worth <cworth@cworth.org>
Wed, 24 Apr 2013 00:25:13 +0000 (17:25 -0700)
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

.gitignore
Makefile.local
configure
execute.c
execute.h
fips.c

index 65bec7717e07367d8663f656f5507fcafb421ea9..f95e49bb01846a01f26f6cee35814338f7fb62b4 100644 (file)
@@ -3,6 +3,7 @@
 Makefile.config
 config.h
 fips
-libfips.so
+libfips-32.so
+libfips-64.so
 *.o
 *~
index 1287f49ce3b2e252dbe60763b2a0d0f2c0f58922..3dd793271a02ae49775e8181d853ba534f439c46 100644 (file)
@@ -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
 
index 6c8b186d4da8b25b3f48d4d2c4178962d9f90cff..f86db978dd5fec4a87c9f2fa095fb306ff7cacb8 100755 (executable)
--- 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 <gelf.h>\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 <<EOF
-
-*** Warning: Unknown platform. ${PROJECT} might or might not build correctly.
-
-EOF
+    printf "No.\n"
+    have_libelf=0
+    libelf_cflags=
+    libelf_ldflags=
+    errors=$((errors + 1))
 fi
+rm -f elf-minimal elf-minimal.c
 
 if [ $errors -gt 0 ]; then
     cat <<EOF
@@ -255,6 +241,11 @@ EOF
        echo "  http://talloc.samba.org/"
        echo
     fi
+    if [ $have_libelf -eq 0 ]; then
+       echo "  The libelf library (including development files such as headers)"
+       echo "  http://http://sourceforge.net/projects/elftoolchain/"
+       echo
+    fi
     cat <<EOF
 With any luck, you're using a modern, package-based operating system
 that has all of these packages available in the distribution. In that
@@ -262,11 +253,11 @@ case a simple command will install everything you need. For example:
 
 On Debian and similar systems:
 
-       sudo apt-get install libtalloc-dev
+       sudo apt-get install libtalloc-dev libelf-dev
 
 Or on Fedora and similar systems:
 
-       sudo yum install libtalloc-devel
+       sudo yum install libtalloc-devel libelf-devel
 
 On other systems, similar commands can be used, but the details of the
 package names may be different.
@@ -382,24 +373,20 @@ mandir = ${MANDIR:=\$(prefix)/share/man}
 # The directory to which read-only (configuration) files should be installed
 sysconfdir = ${SYSCONFDIR:=\$(prefix)/etc}
 
-# Supported platforms (so far) are: LINUX, MACOSX, SOLARIS, FREEBSD, OPENBSD
-PLATFORM = ${platform}
-
-# Whether the linker will automatically resolve the dependency of one
-# library on another (if not, then linking a binary requires linking
-# directly against both)
-LINKER_RESOLVES_LIBRARY_DEPENDENCIES = ${linker_resolves_library_dependencies}
-
 # Flags needed to compile and link against talloc
 TALLOC_CFLAGS = ${talloc_cflags}
 TALLOC_LDFLAGS = ${talloc_ldflags}
 
+# Flags needed to compile and link against libelf
+LIBELF_CFLAGS = ${libelf_cflags}
+LIBELF_LDFLAGS = ${libelf_ldflags}
+
 # Flags needed to have linker link only to necessary libraries
 AS_NEEDED_LDFLAGS = ${as_needed_ldflags}
 
 # Combined flags for compiling and linking against all of the above
-CONFIGURE_CFLAGS = \$(TALLOC_CFLAGS)
-CONFIGURE_LDFLAGS = \$(TALLOC_LDFLAGS)
+CONFIGURE_CFLAGS = \$(TALLOC_CFLAGS) \$(LIBELF_CFLAGS)
+CONFIGURE_LDFLAGS = \$(TALLOC_LDFLAGS) \$(LIBELF_LDFLAGS)
 EOF
 
 # construct config.h
index b102a4a2b4b4945e8cc20dc1cfeadeb43f90f789..8ce88e52cfa84ffada8525fedc9ee12bed8b2938 100644 (file)
--- a/execute.c
+++ b/execute.c
@@ -36,6 +36,9 @@
 
 #include <linux/limits.h>
 
+#include <fcntl.h>
+#include <gelf.h>
+
 #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);
 }
index 03af7779a229aeb6fae5ec7a84d82572b56e7d42..c1ba3bca1d35932ba26547a0ad321621da7cbecb 100644 (file)
--- a/execute.h
+++ b/execute.h
 #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 98cd9ba2ddf287ff3aeab11066b9f54c2124f723..370a2eefab16d28c25b74eb87b645cee2d3c1a9b 100644 (file)
--- 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;
 }