From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-ot1-x32b.google.com (mail-ot1-x32b.google.com [IPv6:2607:f8b0:4864:20::32b]) by sourceware.org (Postfix) with ESMTPS id 3A7053858C78 for ; Tue, 1 Feb 2022 17:49:10 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 3A7053858C78 Received: by mail-ot1-x32b.google.com with SMTP id o9-20020a9d7189000000b0059ee49b4f0fso16971134otj.2 for ; Tue, 01 Feb 2022 09:49:10 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:message-id:date:mime-version:user-agent:subject :content-language:to:cc:references:from:in-reply-to :content-transfer-encoding; bh=J5ZdtxNC2a2edMZuurYo0tRQ3SYjJljxunAuJzH0r6U=; b=nWXblSYCV2z2JkeR83PRJuVLX7NqAdNpEi7yBBTWN7Xh+q/I1ye7chBaOYOIkcEc+W Z9Aqyb9FWV7Y9ZPlm6tjlxLf5UeZavQcLuoHiAbxC08BXGmBSYD4jwAmZMnVbh8uLgNB /j/4NnG8IF4/xJgjqDHZ421Z1uxaXdsqzj4mRKTJ4jSRDr8pvUwOX45rajOkUgExXzJJ peWhnQVRqaF/Xb5fy3nT0TqvR5QJmTKeHrRq9M1gOplR3yT+a/FILoBZoI6Cb4vI6MN9 ErWmNKr6CBHuSpTOmWI5EDi7zCKDYZDTWgS00F+5abN/eXbcdcu3Pg0BWSbGmWr2RThX 9G7g== X-Gm-Message-State: AOAM531Ifl65YlwTMIh/BVFuq5JiPPskaZTT51j5Tc1P869uQzuh87uz O7B1FWc6ISxagtgT+hdhjyG9cv42PCAB0g== X-Google-Smtp-Source: ABdhPJxKebYPv5/gzCp4zwBn+Um8mMmHj8Cm8ai3NTtw5T9ERaGCoMiDeeLzkSu2BVDEnrMZkHUfiw== X-Received: by 2002:a05:6830:120b:: with SMTP id r11mr14877792otp.182.1643737748125; Tue, 01 Feb 2022 09:49:08 -0800 (PST) Received: from ?IPV6:2804:431:c7ca:709a:f3cb:a92a:e1ce:d27d? ([2804:431:c7ca:709a:f3cb:a92a:e1ce:d27d]) by smtp.gmail.com with ESMTPSA id x16sm103612ooa.6.2022.02.01.09.49.07 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Tue, 01 Feb 2022 09:49:07 -0800 (PST) Message-ID: Date: Tue, 1 Feb 2022 14:49:05 -0300 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Thunderbird/91.5.1 Subject: Re: How can I wrap ld-linux or execve into it? Content-Language: en-US To: Farid Zakaria Cc: Libc-help References: From: Adhemerval Zanella In-Reply-To: Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit X-Spam-Status: No, score=-5.6 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, NICE_REPLY_A, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE, URIBL_BLACK autolearn=no autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: libc-help@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-help mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 01 Feb 2022 17:49:11 -0000 On 01/02/2022 14:14, Farid Zakaria wrote: > Thank you -- I need to parse your solution more in depth. > I will also take a look more at rtld -- however I was hoping to be > compatible with musl as well. > > I was told by a colleague that execve solution may work if the static > binary has "no relocations". > How can I control that through the compilation of a program beyond > limiting myself to a single object-file? Different than musl that packs everything in libc.so, glibc still has a contract between ld.so and libc.so, where the loader will setup multiple global resources where some will be shared between ld.so and libc.so. One of the is the thread pointer (TP), required and defined by ABI (for all supported architectures). So it should be possible to chain execution using this loader like program, this loader-like program will need to setup the expect machine state for the loader's entrypoint (ElfW(Ehdr).e_entry): argc, argv, env, and auxv (you might also check if some ABI also requires some other state I am forgetting here). It also means that it would *very* trick to call back the loader as glibc libc.so does for ld.so on, on for instance, symbol resolution (since TP and other global states can no be shared). It really depends of what you want to perform before dynamic linker. The "no relocations" I take it means no dynamic relocations, but this is not suffice (as indicate by the global resource setup required by libc, such as TP). I think it would be easier to use a a minimal Linux support without any libc or standard libraries (similar to a bare-metal target). I think you might accomplish it with newlib, but I am not sure. > > On Tue, Feb 1, 2022 at 4:43 AM Adhemerval Zanella > wrote: >> >> >> >> On 31/01/2022 17:10, Farid Zakaria via Libc-help wrote: >>> Hi, >>> >>> I am looking to perform some functionality before the dynamic linker >>> (linux-ld/ld.so) is invoked. >>> >>> My naive assessment was that I would be able to set in the PT_INTERP >>> section of a binary, my *static binary*, which will then execve into >>> the dynamic linker after doing some precanned actions. >>> >>> Unfortunately, trying this has resulted in some SIGSEGV... >>> >>> I came across https://github.com/Mic92/nix-ld which seems to do >>> something similar, but I was curious why it has to do a lot more to >>> achieve the same effect with a jump. >>> >>> I have also been pointed to LD_AUDIT however I am also interested in >>> having it agnostic to libc (glibc vs. musl) >>> >>> Thank you for any tips, guidance or links you can provide. >>> FZ >> >> The issue is for static linking _dl_aux_init will setup the _dl_phdr >> to the loaded binary (since it was done by the kernel) passed on auxiliary >> vectors: >> >> elf/dl-support.c: >> >> 246 void >> 247 _dl_aux_init (ElfW(auxv_t) *av) >> 248 { >> [...] >> 269 case AT_PHDR: >> 270 GL(dl_phdr) = (const void *) av->a_un.a_val; >> 271 break; >> [...] >> >> And this is later used to setup the TCB: >> >> csu/libc-tls.c >> >> 104 void >> 105 __libc_setup_tls (void) >> 106 { >> [...] >> 120 /* Look through the TLS segment if there is any. */ >> 121 if (_dl_phdr != NULL) >> 122 for (phdr = _dl_phdr; phdr < &_dl_phdr[_dl_phnum]; ++phdr) >> 123 if (phdr->p_type == PT_TLS) >> 124 { >> 125 /* Remember the values we need. */ >> 126 memsz = phdr->p_memsz; >> 127 filesz = phdr->p_filesz; >> 128 initimage = (void *) phdr->p_vaddr + main_map->l_addr; >> 129 align = phdr->p_align; >> 130 if (phdr->p_align > max_align) >> 131 max_align = phdr->p_align; >> 132 break; >> 133 } >> >> The problem is seice _dl_phdr is not pointing to the static programs acting >> as loader, the PT_TLS is not considered and thus not initialized correctly. >> That's why once __ctype_init tries to access TLS variables it triggers an >> invalid memory reference: >> >> (gdb) c >> Continuing. >> >> Program received signal SIGSEGV, Segmentation fault. >> 0x000000000045f464 in __ctype_init () at ctype-info.c:31 >> 31 *bp = (const uint16_t *) _NL_CURRENT (LC_CTYPE, _NL_CTYPE_CLASS) + 128; >> >> >> And I don't think this would be easy to support without changing a *lot* >> on static linking organization. If you check the loader code, it avoids >> to use TLS exactly to avoid this initialization issue. >> >> I think the best option to work by checking elt/rtld.c and see if you can >> hack a way link you code after its initialization.