From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mp2 ([2001:41d0:2:4a6f::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by ms11 with LMTPS id +BoGN6vBul58JQAA0tVLHw (envelope-from ) for ; Tue, 12 May 2020 15:32:59 +0000 Received: from aspmx1.migadu.com ([2001:41d0:2:4a6f::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by mp2 with LMTPS id gHzdEbrBul6PVgAAB5/wlQ (envelope-from ) for ; Tue, 12 May 2020 15:33:14 +0000 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by aspmx1.migadu.com (Postfix) with ESMTPS id C0E6A9411C5 for ; Tue, 12 May 2020 15:33:11 +0000 (UTC) Received: from localhost ([::1]:57140 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jYWu8-0001dp-Kb for larch@yhetil.org; Tue, 12 May 2020 11:33:12 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:39314) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jYWty-0001cv-Pi for guix-patches@gnu.org; Tue, 12 May 2020 11:33:02 -0400 Received: from debbugs.gnu.org ([209.51.188.43]:44823) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1jYWty-0001wZ-F8 for guix-patches@gnu.org; Tue, 12 May 2020 11:33:02 -0400 Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1jYWty-0005Lw-Cy for guix-patches@gnu.org; Tue, 12 May 2020 11:33:02 -0400 X-Loop: help-debbugs@gnu.org Subject: [bug#41189] [PATCH 0/3] Add Fakechroot engine for 'guix pack -RR' Resent-From: Ludovic =?UTF-8?Q?Court=C3=A8s?= Original-Sender: "Debbugs-submit" Resent-CC: guix-patches@gnu.org Resent-Date: Tue, 12 May 2020 15:33:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 41189 X-GNU-PR-Package: guix-patches X-GNU-PR-Keywords: patch To: Carlos O'Donell Cc: 41189@debbugs.gnu.org Received: via spool by 41189-submit@debbugs.gnu.org id=B41189.158929756320544 (code B ref 41189); Tue, 12 May 2020 15:33:02 +0000 Received: (at 41189) by debbugs.gnu.org; 12 May 2020 15:32:43 +0000 Received: from localhost ([127.0.0.1]:56368 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1jYWtY-0005LA-5q for submit@debbugs.gnu.org; Tue, 12 May 2020 11:32:43 -0400 Received: from mail2-relais-roc.national.inria.fr ([192.134.164.83]:23260) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1jYWtV-0005Kj-HM for 41189@debbugs.gnu.org; Tue, 12 May 2020 11:32:34 -0400 X-IronPort-AV: E=Sophos;i="5.73,384,1583190000"; d="scan'208";a="449355026" Received: from 91-160-117-201.subs.proxad.net (HELO ribbon) ([91.160.117.201]) by mail2-relais-roc.national.inria.fr with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 12 May 2020 17:32:26 +0200 From: Ludovic =?UTF-8?Q?Court=C3=A8s?= References: <20200511170554.22916-1-ludo@gnu.org> <28e3ffa2-b565-3052-e0c7-7208fab25a11@redhat.com> <87r1vpbhce.fsf@gnu.org> X-URL: http://www.fdn.fr/~lcourtes/ X-Revolutionary-Date: 24 =?UTF-8?Q?Flor=C3=A9al?= an 228 de la =?UTF-8?Q?R=C3=A9volution?= X-PGP-Key-ID: 0x090B11993D9AEBB5 X-PGP-Key: http://www.fdn.fr/~lcourtes/ludovic.asc X-PGP-Fingerprint: 3CE4 6455 8A84 FDC6 9DB4 0CFB 090B 1199 3D9A EBB5 X-OS: x86_64-pc-linux-gnu Date: Tue, 12 May 2020 17:32:26 +0200 In-Reply-To: (Carlos O'Donell's message of "Tue, 12 May 2020 08:09:53 -0400") Message-ID: <87tv0l9njp.fsf@inria.fr> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/26.3 (gnu/linux) MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-Spam-Score: -5.0 (-----) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-Spam-Score: -1.0 (-) X-BeenThere: guix-patches@gnu.org List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: guix-patches-bounces+larch=yhetil.org@gnu.org Sender: "Guix-patches" X-Scanner: scn0 X-Spam-Score: -1.01 Authentication-Results: aspmx1.migadu.com; dkim=none; dmarc=none; spf=pass (aspmx1.migadu.com: domain of guix-patches-bounces@gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=guix-patches-bounces@gnu.org X-Scan-Result: default: False [-1.01 / 13.00]; GENERIC_REPUTATION(0.00)[-0.53995588720391]; TO_DN_SOME(0.00)[]; R_SPF_ALLOW(-0.20)[+ip4:209.51.188.0/24:c]; IP_REPUTATION_HAM(0.00)[asn: 22989(0.06), country: US(-0.00), ip: 209.51.188.17(-0.54)]; DWL_DNSWL_FAIL(0.00)[209.51.188.17:server fail]; MX_GOOD(-0.50)[cached: eggs.gnu.org]; RCPT_COUNT_TWO(0.00)[2]; MAILLIST(-0.20)[mailman]; FORGED_RECIPIENTS_MAILLIST(0.00)[]; RCVD_IN_DNSWL_FAIL(0.00)[209.51.188.17:server fail]; R_DKIM_NA(0.00)[]; MIME_TRACE(0.00)[0:+,1:+,2:+]; ASN(0.00)[asn:22989, ipnet:209.51.188.0/24, country:US]; TAGGED_FROM(0.00)[larch=yhetil.org]; FROM_NEQ_ENVFROM(0.00)[ludovic.courtes@inria.fr,guix-patches-bounces@gnu.org]; ARC_NA(0.00)[]; MID_RHS_MATCH_FROM(0.00)[]; FROM_HAS_DN(0.00)[]; URIBL_BLOCKED(0.00)[gnu.org:email,ld.so:url,guile-readline.so:url,libreadline.so:url]; MIME_GOOD(-0.10)[multipart/mixed,text/plain,text/x-patch]; RCVD_TLS_LAST(0.00)[]; DMARC_NA(0.00)[inria.fr]; HAS_LIST_UNSUB(-0.01)[]; RWL_MAILSPIKE_POSSIBLE(0.00)[209.51.188.17:from]; RCVD_COUNT_SEVEN(0.00)[8]; FORGED_SENDER_MAILLIST(0.00)[] X-TUID: HVXyaC91jB2E --=-=-= Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Hi Carlos, Carlos O'Donell skribis: > On 5/12/20 6:03 AM, Ludovic Court=C3=A8s wrote: >> One thing that won=E2=80=99t work is dlopen because our =E2=80=98--libra= ry-path=E2=80=99 >> argument is computed statically based on the RUNPATH of the wrapped >> program. So for instance if you try to load guile-readline.so from >> Guile, it eventually fails because libreadline.so isn=E2=80=99t found >> (libreadline.so is in the RUNPATH of guile-readline.so, but the loader >> uses non-interposable calls here as well.) Probably no simple solution >> to that one. > > There is a simple solution. You need to write a dynamic loader audit modu= le > that handles la_objsearch() and inject your lookup path. See man 7 rtld-a= udit. > The dynamic loader audit modules allow you to alter the loader's core beh= aviour > with a plugin. That=E2=80=99s a great idea, and it works like a charm. Thank you! Concretely, I can do: guix pack -RR -S /bin=3Dbin -S /etc=3Detc guile guile-readline and then, on the target machine: tar xf pack.tar.gz . ./etc/profile export GUIX_EXECUTION_ENGINE=3Dfakechroot ./bin/guile -c '(use-modules (ice-9 readline))' Neat! Ludo=E2=80=99. --=-=-= Content-Type: text/x-patch; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: quoted-printable diff --git a/Makefile.am b/Makefile.am index 6cd6e79cab..f65bf5f900 100644 --- a/Makefile.am +++ b/Makefile.am @@ -338,6 +338,7 @@ AUX_FILES =3D \ 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 =20 # Templates, examples. diff --git a/gnu/packages/aux-files/pack-audit.c b/gnu/packages/aux-files/p= ack-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=C3=A8s + + 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[] =3D "@STORE_DIRECTORY@"; + +/* Like 'malloc', but abort if 'malloc' returns NULL. */ +static void * +xmalloc (size_t size) +{ + void *result =3D malloc (size); + assert (result !=3D NULL); + return result; +} + +unsigned int +la_version (unsigned int v) +{ + if (v !=3D LAV_CURRENT) + error (1, 0, "cannot handle interface version %u", v); + + root_directory =3D getenv ("FAKECHROOT_BASE"); + if (root_directory =3D=3D NULL) + error (1, 0, "'FAKECHROOT_BASE' is not set"); + + store =3D 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) =3D=3D 0) + { + size_t len =3D strlen (name) - sizeof original_store + + strlen (store) + 1; + result =3D xmalloc (len); + strcpy (result, store); + strcat (result, name + sizeof original_store - 1); + } + else + result =3D strdup (name); + + return result; +} diff --git a/gnu/packages/aux-files/run-in-namespace.c b/gnu/packages/aux-f= iles/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 *ar= gv[]) =20 char *loader =3D concat (store, PROGRAM_INTERPRETER + sizeof "@STORE_DIRECTORY@"); - size_t loader_specific_argc =3D 6; + size_t loader_specific_argc =3D 8; size_t loader_argc =3D argc + loader_specific_argc; char *loader_argv[loader_argc + 1]; loader_argv[0] =3D argv[0]; @@ -409,7 +409,10 @@ exec_with_loader (const char *store, int argc, char *a= rgv[]) loader_argv[3] =3D "--preload"; loader_argv[4] =3D concat (store, FAKECHROOT_LIBRARY + sizeof "@STORE_DIRECTORY@"); - loader_argv[5] =3D concat (store, + loader_argv[5] =3D "--audit"; + loader_argv[6] =3D concat (store, + LOADER_AUDIT_MODULE + sizeof "@STORE_DIRECTORY@"); + loader_argv[7] =3D concat (store, "@WRAPPED_PROGRAM@" + sizeof "@STORE_DIRECTORY@"); =20 for (size_t i =3D 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"))) =20 + (define audit-source + (local-file (search-auxiliary-file "pack-audit.c"))) + (define (proot) (specification->package "proot-static")) =20 @@ -691,6 +694,21 @@ last resort for relocation." "/lib/fakechroot/libfakechroot.so") #$output))) =20 + (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=3Dgnu99" + "-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=3D\"" #$(fakechroot-library) "\"= ") =20 + (string-append "-DLOADER_AUDIT_MODULE=3D\= "" + #$(audit-module) "\"") (if gconv (string-append "-DGCONV_DIRECTORY=3D\= "" gconv "\"") --=-=-=--