git: c5637b8be8a5 - main - rtld: ignore fstatfs(2) errors when checking MNT_NOEXEC flag

From: Konstantin Belousov <kib_at_FreeBSD.org>
Date: Sat, 06 Nov 2021 04:40:28 UTC
The branch main has been updated by kib:

URL: https://cgit.FreeBSD.org/src/commit/?id=c5637b8be8a5b6aaf663a58b0027f7f924d78b04

commit c5637b8be8a5b6aaf663a58b0027f7f924d78b04
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2021-11-06 03:06:34 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2021-11-06 04:40:17 +0000

    rtld: ignore fstatfs(2) errors when checking MNT_NOEXEC flag
    
    File descriptor we operate on might reference something that is not a
    file, e.g. shmfd.  In this case, we cannot check MNT_NOEXEC in
    principle.
    
    If fstatfs(2) caused some failure on normal filesystem, then typical
    expectation is that read or mmap of this file would also fail.  If not,
    mmap(2) PROT_EXEC on MNT_NOEXEC filesystem returns EACCES.
    
    Reported by:    obiwac@gmail.com
    Sponsored by:   The FreeBSD Foundation
    MFC after:      1 week
---
 libexec/rtld-elf/rtld.c | 16 +++++++---------
 1 file changed, 7 insertions(+), 9 deletions(-)

diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c
index 5a8e4f6bbc96..db89a878c5f9 100644
--- a/libexec/rtld-elf/rtld.c
+++ b/libexec/rtld-elf/rtld.c
@@ -2773,19 +2773,17 @@ do_load_object(int fd, const char *name, char *path, struct stat *sbp,
     struct statfs fs;
 
     /*
-     * but first, make sure that environment variables haven't been
+     * First, make sure that environment variables haven't been
      * used to circumvent the noexec flag on a filesystem.
+     * We ignore fstatfs(2) failures, since fd might reference
+     * not a file, e.g. shmfd.
      */
-    if (dangerous_ld_env) {
-	if (fstatfs(fd, &fs) != 0) {
-	    _rtld_error("Cannot fstatfs \"%s\"", printable_path(path));
-	    return NULL;
-	}
-	if (fs.f_flags & MNT_NOEXEC) {
+    if (dangerous_ld_env && fstatfs(fd, &fs) == 0 &&
+	(fs.f_flags & MNT_NOEXEC) != 0) {
 	    _rtld_error("Cannot execute objects on %s", fs.f_mntonname);
-	    return NULL;
-	}
+	    return (NULL);
     }
+
     dbg("loading \"%s\"", printable_path(path));
     obj = map_object(fd, printable_path(path), sbp);
     if (obj == NULL)