diff --git a/Makefile.am b/Makefile.am index 6cd6e79cab..f65bf5f900 100644 --- a/Makefile.am +++ b/Makefile.am @@ -338,6 +338,7 @@ AUX_FILES = \ gnu/packages/aux-files/linux-libre/4.9-x86_64.conf \ gnu/packages/aux-files/linux-libre/4.4-i686.conf \ gnu/packages/aux-files/linux-libre/4.4-x86_64.conf \ + gnu/packages/aux-files/pack-audit.c \ gnu/packages/aux-files/run-in-namespace.c # Templates, examples. diff --git a/gnu/packages/aux-files/pack-audit.c b/gnu/packages/aux-files/pack-audit.c new file mode 100644 index 0000000000..374787e8b9 --- /dev/null +++ b/gnu/packages/aux-files/pack-audit.c @@ -0,0 +1,85 @@ +/* GNU Guix --- Functional package management for GNU + Copyright (C) 2020 Ludovic Courtès + + This file is part of GNU Guix. + + GNU Guix is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or (at + your option) any later version. + + GNU Guix is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNU Guix. If not, see . */ + +/* This file implements part of the GNU ld.so audit interface. It is used by + the "fakechroot" engine of the 'guix pack -RR' wrappers to make sure the + loader looks for shared objects under the "fake" root directory. */ + +#define _GNU_SOURCE 1 + +#include + +#include +#include +#include +#include + +/* The pseudo root directory and store that we are relocating to. */ +static const char *root_directory; +static char *store; + +/* The original store, "/gnu/store" by default. */ +static const char original_store[] = "@STORE_DIRECTORY@"; + +/* Like 'malloc', but abort if 'malloc' returns NULL. */ +static void * +xmalloc (size_t size) +{ + void *result = malloc (size); + assert (result != NULL); + return result; +} + +unsigned int +la_version (unsigned int v) +{ + if (v != LAV_CURRENT) + error (1, 0, "cannot handle interface version %u", v); + + root_directory = getenv ("FAKECHROOT_BASE"); + if (root_directory == NULL) + error (1, 0, "'FAKECHROOT_BASE' is not set"); + + store = xmalloc (strlen (root_directory) + sizeof original_store); + strcpy (store, root_directory); + strcat (store, original_store); + + return v; +} + +/* Return NAME, a shared object file name, relocated under STORE. This + function is called by the loader whenever it looks for a shared object. */ +char * +la_objsearch (const char *name, uintptr_t *cookie, unsigned int flag) +{ + char *result; + + if (strncmp (name, original_store, + sizeof original_store - 1) == 0) + { + size_t len = strlen (name) - sizeof original_store + + strlen (store) + 1; + result = xmalloc (len); + strcpy (result, store); + strcat (result, name + sizeof original_store - 1); + } + else + result = strdup (name); + + return result; +} diff --git a/gnu/packages/aux-files/run-in-namespace.c b/gnu/packages/aux-files/run-in-namespace.c index c56c35a510..5ed1c6a1bc 100644 --- a/gnu/packages/aux-files/run-in-namespace.c +++ b/gnu/packages/aux-files/run-in-namespace.c @@ -400,7 +400,7 @@ exec_with_loader (const char *store, int argc, char *argv[]) char *loader = concat (store, PROGRAM_INTERPRETER + sizeof "@STORE_DIRECTORY@"); - size_t loader_specific_argc = 6; + size_t loader_specific_argc = 8; size_t loader_argc = argc + loader_specific_argc; char *loader_argv[loader_argc + 1]; loader_argv[0] = argv[0]; @@ -409,7 +409,10 @@ exec_with_loader (const char *store, int argc, char *argv[]) loader_argv[3] = "--preload"; loader_argv[4] = concat (store, FAKECHROOT_LIBRARY + sizeof "@STORE_DIRECTORY@"); - loader_argv[5] = concat (store, + loader_argv[5] = "--audit"; + loader_argv[6] = concat (store, + LOADER_AUDIT_MODULE + sizeof "@STORE_DIRECTORY@"); + loader_argv[7] = concat (store, "@WRAPPED_PROGRAM@" + sizeof "@STORE_DIRECTORY@"); for (size_t i = 0; i < argc; i++) diff --git a/guix/scripts/pack.scm b/guix/scripts/pack.scm index 2b37bf5027..13ede581e9 100644 --- a/guix/scripts/pack.scm +++ b/guix/scripts/pack.scm @@ -681,6 +681,9 @@ last resort for relocation." (define runner (local-file (search-auxiliary-file "run-in-namespace.c"))) + (define audit-source + (local-file (search-auxiliary-file "pack-audit.c"))) + (define (proot) (specification->package "proot-static")) @@ -691,6 +694,21 @@ last resort for relocation." "/lib/fakechroot/libfakechroot.so") #$output))) + (define (audit-module) + (computed-file "pack-audit.so" + (with-imported-modules '((guix build utils)) + #~(begin + (use-modules (guix build utils)) + + (copy-file #$audit-source "audit.c") + (substitute* "audit.c" + (("@STORE_DIRECTORY@") + (%store-directory))) + + (invoke #$compiler "-std=gnu99" + "-shared" "-fPIC" "-Os" "-g0" + "-Wall" "audit.c" "-o" #$output))))) + (define build (with-imported-modules (source-module-closure '((guix build utils) @@ -771,6 +789,8 @@ last resort for relocation." (string-append "-DFAKECHROOT_LIBRARY=\"" #$(fakechroot-library) "\"") + (string-append "-DLOADER_AUDIT_MODULE=\"" + #$(audit-module) "\"") (if gconv (string-append "-DGCONV_DIRECTORY=\"" gconv "\"")