Lukáš Zaoral ec87f8
From 915004f403cb25fadb207ddfdbe6a2f43bd44fac Mon Sep 17 00:00:00 2001
Lukáš Zaoral ec87f8
From: =?UTF-8?q?P=C3=A1draig=20Brady?= <P@draigBrady.com>
Lukáš Zaoral ec87f8
Date: Fri, 17 Jan 2025 17:29:34 +0000
Lukáš Zaoral ec87f8
Subject: [PATCH] ls: fix crash with --context
Lukáš Zaoral ec87f8
Lukáš Zaoral ec87f8
* src/ls.c (main): Flag that we need to stat()
Lukáš Zaoral ec87f8
if we're going to get security context (call file_has_aclinfo_cache).
Lukáš Zaoral ec87f8
(file_has_aclinfo_cache): Be defensive and only lookup the device
Lukáš Zaoral ec87f8
for the file if the stat has been performed.
Lukáš Zaoral ec87f8
(has_capability_cache): Likewise.
Lukáš Zaoral ec87f8
* tests/ls/selinux-segfault.sh: Add a test case.
Lukáš Zaoral ec87f8
Reported by Bruno Haible.
Lukáš Zaoral ec87f8
---
Lukáš Zaoral ec87f8
 src/ls.c                     | 10 +++++-----
Lukáš Zaoral ec87f8
 tests/ls/selinux-segfault.sh |  3 +++
Lukáš Zaoral ec87f8
 2 files changed, 8 insertions(+), 5 deletions(-)
Lukáš Zaoral ec87f8
Lukáš Zaoral ec87f8
diff --git a/src/ls.c b/src/ls.c
Lukáš Zaoral ec87f8
index 3215360216..f67167f160 100644
Lukáš Zaoral ec87f8
--- a/src/ls.c
Lukáš Zaoral ec87f8
+++ b/src/ls.c
Lukáš Zaoral ec87f8
@@ -1768,7 +1768,7 @@ main (int argc, char **argv)
Lukáš Zaoral ec87f8
 
Lukáš Zaoral ec87f8
   format_needs_stat = ((sort_type == sort_time) | (sort_type == sort_size)
Lukáš Zaoral ec87f8
                        | (format == long_format)
Lukáš Zaoral ec87f8
-                       | print_block_size | print_hyperlink);
Lukáš Zaoral ec87f8
+                       | print_block_size | print_hyperlink | print_scontext);
Lukáš Zaoral ec87f8
   format_needs_type = ((! format_needs_stat)
Lukáš Zaoral ec87f8
                        & (recursive | print_with_color | print_scontext
Lukáš Zaoral ec87f8
                           | directories_first
Lukáš Zaoral ec87f8
@@ -3309,7 +3309,7 @@ file_has_aclinfo_cache (char const *file, struct fileinfo *f,
Lukáš Zaoral ec87f8
   static int unsupported_scontext_err;
Lukáš Zaoral ec87f8
   static dev_t unsupported_device;
Lukáš Zaoral ec87f8
 
Lukáš Zaoral ec87f8
-  if (f->stat.st_dev == unsupported_device)
Lukáš Zaoral ec87f8
+  if (f->stat_ok && f->stat.st_dev == unsupported_device)
Lukáš Zaoral ec87f8
     {
Lukáš Zaoral ec87f8
       ai->buf = ai->u.__gl_acl_ch;
Lukáš Zaoral ec87f8
       ai->size = 0;
Lukáš Zaoral ec87f8
@@ -3322,7 +3322,7 @@ file_has_aclinfo_cache (char const *file, struct fileinfo *f,
Lukáš Zaoral ec87f8
   errno = 0;
Lukáš Zaoral ec87f8
   int n = file_has_aclinfo (file, ai, flags);
Lukáš Zaoral ec87f8
   int err = errno;
Lukáš Zaoral ec87f8
-  if (n <= 0 && !acl_errno_valid (err))
Lukáš Zaoral ec87f8
+  if (f->stat_ok && n <= 0 && !acl_errno_valid (err))
Lukáš Zaoral ec87f8
     {
Lukáš Zaoral ec87f8
       unsupported_return = n;
Lukáš Zaoral ec87f8
       unsupported_scontext = ai->scontext;
Lukáš Zaoral ec87f8
@@ -3342,14 +3342,14 @@ has_capability_cache (char const *file, struct fileinfo *f)
Lukáš Zaoral ec87f8
      found that has_capability fails indicating lack of support.  */
Lukáš Zaoral ec87f8
   static dev_t unsupported_device;
Lukáš Zaoral ec87f8
 
Lukáš Zaoral ec87f8
-  if (f->stat.st_dev == unsupported_device)
Lukáš Zaoral ec87f8
+  if (f->stat_ok && f->stat.st_dev == unsupported_device)
Lukáš Zaoral ec87f8
     {
Lukáš Zaoral ec87f8
       errno = ENOTSUP;
Lukáš Zaoral ec87f8
       return 0;
Lukáš Zaoral ec87f8
     }
Lukáš Zaoral ec87f8
 
Lukáš Zaoral ec87f8
   bool b = has_capability (file);
Lukáš Zaoral ec87f8
-  if ( !b && !acl_errno_valid (errno))
Lukáš Zaoral ec87f8
+  if (f->stat_ok && !b && !acl_errno_valid (errno))
Lukáš Zaoral ec87f8
     unsupported_device = f->stat.st_dev;
Lukáš Zaoral ec87f8
   return b;
Lukáš Zaoral ec87f8
 }
Lukáš Zaoral ec87f8
diff --git a/tests/ls/selinux-segfault.sh b/tests/ls/selinux-segfault.sh
Lukáš Zaoral ec87f8
index 11623acb3f..1cac2b5fc0 100755
Lukáš Zaoral ec87f8
--- a/tests/ls/selinux-segfault.sh
Lukáš Zaoral ec87f8
+++ b/tests/ls/selinux-segfault.sh
Lukáš Zaoral ec87f8
@@ -30,4 +30,7 @@ mkdir sedir || framework_failure_
Lukáš Zaoral ec87f8
 ln -sf missing sedir/broken || framework_failure_
Lukáš Zaoral ec87f8
 returns_ 1 ls -L -R -Z -m sedir > out || fail=1
Lukáš Zaoral ec87f8
 
Lukáš Zaoral ec87f8
+# ls 9.6 would segfault with the following
Lukáš Zaoral ec87f8
+ls -Z . > out || fail=1
Lukáš Zaoral ec87f8
+
Lukáš Zaoral ec87f8
 Exit $fail