Subject: acl: Fix WALK_TREE_RECURSIVE for the WALK_TREE_DEREFERENCE case getfacl.c calls walk_tree() with WALK_TREE_DEREFERENCE. This causes a stat() of symlinks which in turn causes S_ISDIR(st.st_mode) to be true on symlinks. This causes getfacl -P to return the contents of symlinks... e.g. $ mkdir -p test/sub $ mkdir test/link $ touch test/link/file $ ln -s `pwd`/test/link test/sub/link $ getfacl -P -R test/sub # file: test/sub # owner: philips # group: users user::rwx group::r-x other::r-x # file: test/sub/link/file # owner: philips # group: users user::rw- group::r-- other::r-- After the fix: $ getfacl -R -P test/sub/ # file: test/sub/ # owner: philips # group: users user::rwx group::r-x other::r-x Signed-off-by: Brandon Philips --- libmisc/walk_tree.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) Index: acl-2.2.47/libmisc/walk_tree.c =================================================================== --- acl-2.2.47.orig/libmisc/walk_tree.c +++ acl-2.2.47/libmisc/walk_tree.c @@ -93,8 +93,15 @@ static int walk_tree_rec(const char *pat have_dir_stat = 1; } err = func(path, &st, flags, arg); + + /* + * Recurse if WALK_TREE_RECURSIVE and the path is: + * a dir not from a symlink + * a link and follow_symlinks + */ if ((flags & WALK_TREE_RECURSIVE) && - (S_ISDIR(st.st_mode) || (S_ISLNK(st.st_mode) && follow_symlinks))) { + (!(flags & WALK_TREE_SYMLINK) && S_ISDIR(st.st_mode)) || + ((flags & WALK_TREE_SYMLINK) && follow_symlinks)) { struct dirent *entry; /*