From: Andi Kleen <ak@linux.intel.com>
To: Andrii Nakryiko <andrii@kernel.org>
Cc: linux-fsdevel@vger.kernel.org, brauner@kernel.org,
viro@zeniv.linux.org.uk, akpm@linux-foundation.org,
linux-kernel@vger.kernel.org, bpf@vger.kernel.org,
gregkh@linuxfoundation.org, linux-mm@kvack.org,
liam.howlett@oracle.com, surenb@google.com, rppt@kernel.org,
adobriyan@gmail.com
Subject: Re: [PATCH v6 3/6] fs/procfs: add build ID fetching to PROCMAP_QUERY API
Date: Thu, 27 Jun 2024 16:00:41 -0700 [thread overview]
Message-ID: <878qyqyorq.fsf@linux.intel.com> (raw)
In-Reply-To: <20240627170900.1672542-4-andrii@kernel.org> (Andrii Nakryiko's message of "Thu, 27 Jun 2024 10:08:55 -0700")
Andrii Nakryiko <andrii@kernel.org> writes:
> The need to get ELF build ID reliably is an important aspect when
> dealing with profiling and stack trace symbolization, and
> /proc/<pid>/maps textual representation doesn't help with this.
>
> To get backing file's ELF build ID, application has to first resolve
> VMA, then use it's start/end address range to follow a special
> /proc/<pid>/map_files/<start>-<end> symlink to open the ELF file (this
> is necessary because backing file might have been removed from the disk
> or was already replaced with another binary in the same file path.
>
> Such approach, beyond just adding complexity of having to do a bunch of
> extra work, has extra security implications. Because application opens
> underlying ELF file and needs read access to its entire contents (as far
> as kernel is concerned), kernel puts additional capable() checks on
> following /proc/<pid>/map_files/<start>-<end> symlink. And that makes
> sense in general.
I was curious about this statement. It has still certainly potential
for side channels e.g. for files that are execute only, or with
some other special protection.
But actually just looking at the parsing code it seems to fail basic
TOCTTOU rules, and since you don't check if the VMA mapping is executable
(I think), so there's no EBUSY checking for writes, it likely is exploitable.
/* only supports phdr that fits in one page */
if (ehdr->e_phnum >
(PAGE_SIZE - sizeof(Elf64_Ehdr)) / sizeof(Elf64_Phdr))
<---------- check in memory
return -EINVAL;
phdr = (Elf64_Phdr *)(page_addr + sizeof(Elf64_Ehdr));
<---- but page is shared in the page cache. So if anybody manages to map
it for write
for (i = 0; i < ehdr->e_phnum; ++i) { <----- this loop can go
off into the next page.
if (phdr[i].p_type == PT_NOTE &&
!parse_build_id(page_addr, build_id, size,
page_addr + phdr[i].p_offset,
phdr[i].p_filesz))
return 0;
Here's an untested patch
diff --git a/lib/buildid.c b/lib/buildid.c
index 7954dd92e36c..6c022fcd03ec 100644
--- a/lib/buildid.c
+++ b/lib/buildid.c
@@ -72,19 +72,20 @@ static int get_build_id_32(const void *page_addr, unsigned char *build_id,
Elf32_Ehdr *ehdr = (Elf32_Ehdr *)page_addr;
Elf32_Phdr *phdr;
int i;
+ unsigned phnum = READ_ONCE(ehdr->e_phnum);
/* only supports phdr that fits in one page */
- if (ehdr->e_phnum >
+ if (phnum >
(PAGE_SIZE - sizeof(Elf32_Ehdr)) / sizeof(Elf32_Phdr))
return -EINVAL;
phdr = (Elf32_Phdr *)(page_addr + sizeof(Elf32_Ehdr));
- for (i = 0; i < ehdr->e_phnum; ++i) {
+ for (i = 0; i < phnum; ++i) {
if (phdr[i].p_type == PT_NOTE &&
!parse_build_id(page_addr, build_id, size,
page_addr + phdr[i].p_offset,
- phdr[i].p_filesz))
+ READ_ONCE(phdr[i].p_filesz)))
return 0;
}
return -EINVAL;
@@ -97,15 +98,16 @@ static int get_build_id_64(const void *page_addr, unsigned char *build_id,
Elf64_Ehdr *ehdr = (Elf64_Ehdr *)page_addr;
Elf64_Phdr *phdr;
int i;
+ unsigned phnum = READ_ONCE(ehdr->e_phnum);
/* only supports phdr that fits in one page */
- if (ehdr->e_phnum >
+ if (phnum >
(PAGE_SIZE - sizeof(Elf64_Ehdr)) / sizeof(Elf64_Phdr))
return -EINVAL;
phdr = (Elf64_Phdr *)(page_addr + sizeof(Elf64_Ehdr));
- for (i = 0; i < ehdr->e_phnum; ++i) {
+ for (i = 0; i < phnum; ++i) {
if (phdr[i].p_type == PT_NOTE &&
!parse_build_id(page_addr, build_id, size,
page_addr + phdr[i].p_offset,
next prev parent reply other threads:[~2024-06-27 23:00 UTC|newest]
Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-06-27 17:08 [PATCH v6 0/6] ioctl()-based API to query VMAs from /proc/<pid>/maps Andrii Nakryiko
2024-06-27 17:08 ` [PATCH v6 1/6] fs/procfs: extract logic for getting VMA name constituents Andrii Nakryiko
2024-06-27 17:08 ` [PATCH v6 2/6] fs/procfs: implement efficient VMA querying API for /proc/<pid>/maps Andrii Nakryiko
2024-06-27 17:08 ` [PATCH v6 3/6] fs/procfs: add build ID fetching to PROCMAP_QUERY API Andrii Nakryiko
2024-06-27 23:00 ` Andi Kleen [this message]
2024-06-28 16:36 ` Andrii Nakryiko
2024-06-28 22:33 ` Andi Kleen
2024-06-28 23:03 ` Andrii Nakryiko
2024-07-02 14:49 ` Andi Kleen
2024-07-02 23:08 ` Andrii Nakryiko
2024-07-08 23:43 ` Andrii Nakryiko
2024-07-09 1:27 ` Andi Kleen
2024-07-09 3:14 ` Andrii Nakryiko
2024-07-29 15:47 ` Jann Horn
2024-07-29 16:52 ` Andrii Nakryiko
2024-06-27 17:08 ` [PATCH v6 4/6] docs/procfs: call out ioctl()-based PROCMAP_QUERY command existence Andrii Nakryiko
2024-06-27 17:08 ` [PATCH v6 5/6] tools: sync uapi/linux/fs.h header into tools subdir Andrii Nakryiko
2024-06-27 17:08 ` [PATCH v6 6/6] selftests/proc: add PROCMAP_QUERY ioctl tests Andrii Nakryiko
2024-06-27 19:59 ` [PATCH v6 0/6] ioctl()-based API to query VMAs from /proc/<pid>/maps Andrew Morton
2024-06-27 20:50 ` Andrii Nakryiko
2024-06-27 21:11 ` Andrew Morton
2024-06-28 16:42 ` Andrii Nakryiko
2024-07-10 18:32 ` Andrew Morton
2024-07-10 18:41 ` Andrii Nakryiko
2024-07-11 18:07 ` Liam R. Howlett
2024-07-24 16:32 ` Alexey Dobriyan
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=878qyqyorq.fsf@linux.intel.com \
--to=ak@linux.intel.com \
--cc=adobriyan@gmail.com \
--cc=akpm@linux-foundation.org \
--cc=andrii@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=brauner@kernel.org \
--cc=gregkh@linuxfoundation.org \
--cc=liam.howlett@oracle.com \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=rppt@kernel.org \
--cc=surenb@google.com \
--cc=viro@zeniv.linux.org.uk \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).