]> 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
 Makefile.config
 config.h
 fips
-libfips.so
+libfips-32.so
+libfips-64.so
 *.o
 *~
 *.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)
 
 # 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
 FINAL_FIPS_LINKER = CC
-ifneq ($(LINKER_RESOLVES_LIBRARY_DEPENDENCIES),1)
-FINAL_FIPS_LDFLAGS += $(CONFIGURE_LDFLAGS)
-endif
 
 .PHONY: all
 
 .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),)
 
 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'/ .*//'))
 
 # 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
 %.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_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
 
 .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)"
 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)
 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
 
 
 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
 
     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
 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
 fi
+rm -f elf-minimal elf-minimal.c
 
 if [ $errors -gt 0 ]; then
     cat <<EOF
 
 if [ $errors -gt 0 ]; then
     cat <<EOF
@@ -255,6 +241,11 @@ EOF
        echo "  http://talloc.samba.org/"
        echo
     fi
        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
     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:
 
 
 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:
 
 
 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.
 
 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}
 
 # 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 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
 # 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
 EOF
 
 # construct config.h
index b102a4a2b4b4945e8cc20dc1cfeadeb43f90f789..8ce88e52cfa84ffada8525fedc9ee12bed8b2938 100644 (file)
--- a/execute.c
+++ b/execute.c
@@ -36,6 +36,9 @@
 
 #include <linux/limits.h>
 
 
 #include <linux/limits.h>
 
+#include <fcntl.h>
+#include <gelf.h>
+
 #include "execute.h"
 
 /* Terminate a string representing a filename at the final '/' to
 #include "execute.h"
 
 /* Terminate a string representing a filename at the final '/' to
@@ -112,8 +115,70 @@ exists (const char *path)
        return 1;
 }
 
        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
  *
  *
  *   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 *
  * 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);
 
 
        bin_path = get_bin_name (ctx);
 
@@ -163,14 +233,11 @@ resolve_path (void *ctx, const char *library)
        exit (1);
 }
 
        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
 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;
 {
        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;
 
                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);
 
 
                setenv ("LD_PRELOAD", lib_path, 1);
 
@@ -210,7 +277,7 @@ fork_exec_with_preload_and_wait (char * const argv[], const char *library)
 }
 
 int
 }
 
 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;
 {
        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;
 
        /* 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
 #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
  */
 int
-execute_with_preload (int argc, char * const argv[], const char *library);
+execute_with_fips_preload (int argc, char * const argv[]);
 
 #endif
 
 #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);
        }
 
                exit (1);
        }
 
-       ret = execute_with_preload (argc - optind, &argv[optind], "libfips.so");
+       ret = execute_with_fips_preload (argc - optind, &argv[optind]);
 
        return ret;
 }
 
        return ret;
 }