Skip to content

ls fails to dereference path for ACL output (showing the referenced path's ACL) #13234

Description

@j5awry

on Ubuntu 26.04 and 26.10, with

ls --version
ls (uutils coreutils) 0.8.0

ls -dl <link> returns the ACL bit ( + ) from the referenced inode rather than the link itself. This is reproducible with the following

# ensure acl is installed
sudo apt update && sudo apt install acl
umask 022
mkdir d
setfacl -m d:u:bin:rwx d
ln -s d l
ls -dl l

> lrwxrwxrwx+ 1 root root 1 Jun 30 11:17 l -> d

This mimics the behaviour of passing in -L , which appropriately dereferences. Compare to a system running gnu-coreutils (such as debian/unstable)

ls --version
> ls (GNU coreutils) 9.10
> Packaged by Debian (9.10-1)

sudo apt update && sudo apt install acl
umask 022
mkdir d
setfacl -m d:u:bin:rwx d
ln -s d l
ls -dl l
lrwxrwxrwx 1 root root 1 Jun 30 11:16 l -> d

root cause and call chain

From entry to calls :

uumain(args) 
 |-> ls.rs:119 -- ls entrypoint
        |-> ls.rs:122 -- sets config. Correctly sets config for -dl to Dereference::None and Format::Long
        |-> ls.rs:128  -- list(locs, &config) with correct config
               |-> ls.rs:1470-1471 -- TextOuput created and  list_with_output called with correct config
                      |-> ls.rs:1180 -- for each location, call PathData::new with correct config. the PathData sets must_dereference=false
                             |-> ls.rs:821-914 -- PathData implementation. fn metadata 
                                    |-> ls.rs: 923 -- get_metadata_with_deref_opt correctly gets symlink metadata at ls.rs:1547
                                     # so at this point, we've collected the correct metadata from  [std::fs.symlink_metadata](https://doc.rust-lang.org/std/fs 
                                     # fn.symlink_metadata.html).  onto long-format
                      |-> ls.rs:1217 -- not in stream mode, will call output.write_entries
                             |-> ls.rs:1071 -- calls display_items with all entries and passes config (same config with Dereference::None)
                                    |-> display.rs:377 -- config.format matches, drops into calculate_padding_collection
                                            |-> display.rs:1342 -- for each item, a call to `has_acl(item.path()`
                                                     |-> uucore/src/lib/fsxattr.rs:164 -- has_acl only takes a path. Always calls xattr::list_deref(file)
                                                     # BUG HIT ONE
                                    |->  display.rs:389 -- then each item calls display_long_item with item and config
                                            |-> display.rs:937 -- in display_item_long another call to has_acl
                                             # BUG HIT TWO                                                  

at this point we've made a couple calls to has_acl, a function that doesn't accept configuration for deferencing. So a couple possible bugs

  • padding may be set incorrectly due to incorrect acl assumption
  • long display will show an acl that is not present in the item metadata

My gut is that there is a bigger root here -- it looks like in display.rs has other calls that are similar. It seems like there's duplication in calls, where instead of referencing the metadata there are calls to get the information again. The simple fix is for has_acl to have a switch but that does not feel like the correct approach. it's a quick fix, but getting into the broader architectural issue of a) either not using metadata that's present or; b) not having all the metadata and therefore querying for it in display.rs.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions