From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on inbox.vuxu.org X-Spam-Level: X-Spam-Status: No, score=-2.8 required=5.0 tests=DKIM_INVALID,DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED, RCVD_IN_MSPIKE_H4,RCVD_IN_MSPIKE_WL autolearn=ham autolearn_force=no version=3.4.4 Received: from second.openwall.net (second.openwall.net [193.110.157.125]) by inbox.vuxu.org (Postfix) with SMTP id C911229153 for ; Fri, 5 Jul 2024 23:13:27 +0200 (CEST) Received: (qmail 32664 invoked by uid 550); 5 Jul 2024 21:13:20 -0000 Mailing-List: contact musl-help@lists.openwall.com; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-ID: Reply-To: musl@lists.openwall.com Received: (qmail 32609 invoked from network); 5 Jul 2024 21:13:20 -0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; t=1720213992; x=1720818792; darn=lists.openwall.com; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=ZBb1TOO821Ei5/hopkr7t3PiUmXbImMTCl2VTUFcPLY=; b=ftZiQ0LWs3rrH0Xc3pXrxhyCjM61MrN9/8fb7yUk40L/1fkBaoas4JLK+OJuAGC3J4 d0R18WXnpbowbmftQ8yd/nq8NkTcgkbp4AFr5dR4sB8k2eB9pnGqh9EwgUZ4cVoP+PTR rAVPB5MmUGyMZlIGv2FrYn3zbkeO/HaYuO9WM= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1720213992; x=1720818792; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=ZBb1TOO821Ei5/hopkr7t3PiUmXbImMTCl2VTUFcPLY=; b=EBkqITTn0UwV+ncav8Mb7Anmq3KjCPHRtJVIvC2wKAmIPewnI5XTtKk2ksAyaXxNLq KxYVou6L/XrokFz5uoivhEYzPnd7m+rhmAcaXvQ8m45T0d/QZp2RqW/isi58Azrumcci hbsdquWLyeT4Lh1WA4wk/MVI9hc/jE3ZZ/WszdWsVH/R8OIIt/MwsTEt7PTVBHFo7H5x VcCAxqSsqYpqsgsAW4wrAuowkX8mCKv0NOk+oXwJ7M0yl+E23hzL+EWyQh0Kcb1FJnp8 4U5z1vwVS5JhXqj2GuGznAjAFB75neckulS9cUXW+DWyw4bVAQ66dHBGBgyIn2ankKVH za3g== X-Gm-Message-State: AOJu0YxnHQtQ/CfH8CSblVfEaUN1jwsThHlpny1JcB9TMfGKw0pGOaXf w+PtAf//B6K6n626zNhWNBCLj5omvfPZtaEJLwMKjDN0hQT2d9EcNvpw2tY5bQ== X-Google-Smtp-Source: AGHT+IHGO6frCwrxntvHpIlRKzpo16/TBYKifpmTBE1xmeCxAa2hLZzwUT9sH9swH93ebES++xgnNQ== X-Received: by 2002:a05:6359:411e:b0:1a5:2dd1:8884 with SMTP id e5c5f4694b2df-1aa989ea885mr651280355d.0.1720213991712; Fri, 05 Jul 2024 14:13:11 -0700 (PDT) From: Markus Mayer To: Musl Mailing List Cc: Colin Cross , Colin Cross , Markus Mayer Date: Fri, 5 Jul 2024 14:12:28 -0700 Message-ID: <20240705211232.2718532-2-mmayer@broadcom.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240705211232.2718532-1-mmayer@broadcom.com> References: <20240705211232.2718532-1-mmayer@broadcom.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Subject: [musl] [PATCH 1/1] Ignore incorrect elf architecture libraries From: Colin Cross In multilib systems LD_LIBRARY_PATH is sometimes set to a list that contains both the lib32 and lib64 directories, for example when running code that may execute 32-bit or 64-bit subprocesses or both. Musl's dynamic loader aborts searching a path list when it finds any library that is not loadable, preventing searching the other multilib directory. Modify the loader to continue searching when a file is found that is a valid elf file but for the an elf machine or class that differs from that of the loader itself. --- ldso/dynlink.c | 77 +++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 61 insertions(+), 16 deletions(-) diff --git a/ldso/dynlink.c b/ldso/dynlink.c index 324aa85919f0..2f1ac7e9d089 100644 --- a/ldso/dynlink.c +++ b/ldso/dynlink.c @@ -68,6 +68,8 @@ struct dso { size_t *dynv; struct dso *next, *prev; + int elfmachine; + int elfclass; Phdr *phdr; int phnum; size_t phentsize; @@ -684,6 +686,19 @@ static void unmap_library(struct dso *dso) } } +static int verify_elf_magic(const Ehdr* eh) { + return eh->e_ident[0] == ELFMAG0 && + eh->e_ident[1] == ELFMAG1 && + eh->e_ident[2] == ELFMAG2 && + eh->e_ident[3] == ELFMAG3; +} + +/* Verifies that an elf header's machine and class match the loader */ +static int verify_elf_arch(const Ehdr* eh) { + return eh->e_machine == ldso.elfmachine && + eh->e_ident[EI_CLASS] == ldso.elfclass; +} + static void *map_library(int fd, struct dso *dso) { Ehdr buf[(896+sizeof(Ehdr))/sizeof(Ehdr)]; @@ -706,6 +721,10 @@ static void *map_library(int fd, struct dso *dso) if (l<0) return 0; if (le_type != ET_DYN && eh->e_type != ET_EXEC)) goto noexec; + if (!verify_elf_magic(eh)) goto noexec; + if (!verify_elf_arch(eh)) goto noexec; + dso->elfmachine = eh->e_machine; + dso->elfclass = eh->e_ident[EI_CLASS]; phsize = eh->e_phentsize * eh->e_phnum; if (phsize > sizeof buf - sizeof *eh) { allocated_buf = malloc(phsize); @@ -870,29 +889,53 @@ error: return 0; } -static int path_open(const char *name, const char *s, char *buf, size_t buf_size) +static int path_open_library(const char *name, const char *s, char *buf, size_t buf_size) { size_t l; int fd; + const char *p; for (;;) { s += strspn(s, ":\n"); + p = s; l = strcspn(s, ":\n"); if (l-1 >= INT_MAX) return -1; - if (snprintf(buf, buf_size, "%.*s/%s", (int)l, s, name) < buf_size) { - if ((fd = open(buf, O_RDONLY|O_CLOEXEC))>=0) return fd; - switch (errno) { - case ENOENT: - case ENOTDIR: - case EACCES: - case ENAMETOOLONG: - break; - default: - /* Any negative value but -1 will inhibit - * futher path search. */ + s += l; + if (snprintf(buf, buf_size, "%.*s/%s", (int)l, p, name) < buf_size) { + fd = open(buf, O_RDONLY|O_CLOEXEC); + if (fd < 0) { + switch (errno) { + case ENOENT: + case ENOTDIR: + case EACCES: + case ENAMETOOLONG: + /* Keep searching in path list. */ + continue; + default: + /* Any negative value but -1 will + * inhibit further path search in + * load_library. */ + return -2; + } + } + Ehdr eh; + ssize_t n = pread(fd, &eh, sizeof(eh), 0); + /* If the elf file is invalid return -2 to inhibit + * further path search in load_library. */ + if (n < 0 || + n != sizeof eh || + !verify_elf_magic(&eh)) { + close(fd); return -2; } + /* If the elf file has a valid header but is for the + * wrong architecture ignore it and keep searching the + * path list. */ + if (!verify_elf_arch(&eh)) { + close(fd); + continue; + } + return fd; } - s += l; } } @@ -1116,12 +1159,12 @@ static struct dso *load_library(const char *name, struct dso *needed_by) } if (strlen(name) > NAME_MAX) return 0; fd = -1; - if (env_path) fd = path_open(name, env_path, buf, sizeof buf); + if (env_path) fd = path_open_library(name, env_path, buf, sizeof buf); for (p=needed_by; fd == -1 && p; p=p->needed_by) { if (fixup_rpath(p, buf, sizeof buf) < 0) fd = -2; /* Inhibit further search. */ if (p->rpath) - fd = path_open(name, p->rpath, buf, sizeof buf); + fd = path_open_library(name, p->rpath, buf, sizeof buf); } if (fd == -1) { if (!sys_path) { @@ -1160,7 +1203,7 @@ static struct dso *load_library(const char *name, struct dso *needed_by) } } if (!sys_path) sys_path = "/lib:/usr/local/lib:/usr/lib"; - fd = path_open(name, sys_path, buf, sizeof buf); + fd = path_open_library(name, sys_path, buf, sizeof buf); } pathname = buf; } @@ -1732,6 +1775,8 @@ hidden void __dls2(unsigned char *base, size_t *sp) ldso.phnum = ehdr->e_phnum; ldso.phdr = laddr(&ldso, ehdr->e_phoff); ldso.phentsize = ehdr->e_phentsize; + ldso.elfmachine = ehdr->e_machine; + ldso.elfclass = ehdr->e_ident[EI_CLASS]; search_vec(auxv, &ldso_page_size, AT_PAGESZ); kernel_mapped_dso(&ldso); decode_dyn(&ldso); -- 2.45.2