diff --git a/acl-2.2.45.src.tar.bz2 b/acl-2.2.45.src.tar.bz2 deleted file mode 100644 index 5a6eda3..0000000 --- a/acl-2.2.45.src.tar.bz2 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:1a46338bedea261eda948549509f60d1351d8b73440a1fa18e4bfd200702ff26 -size 131042 diff --git a/acl-2.2.47.src.tar.bz2 b/acl-2.2.47.src.tar.bz2 new file mode 100644 index 0000000..663792f --- /dev/null +++ b/acl-2.2.47.src.tar.bz2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e7113f1a6447476b8f20ede65eaa4179b287be47829b9b820357754c570db880 +size 129813 diff --git a/acl.changes b/acl.changes index 5880edd..3a41ef1 100644 --- a/acl.changes +++ b/acl.changes @@ -1,3 +1,9 @@ +------------------------------------------------------------------- +Fri Jul 11 22:25:17 CEST 2008 - bphilips@suse.de + +- Failure to recursively set/get ACLs on directories (bnc#404075) +- When invoked as ``setfacl -- ...'', setfacl segfaults (bnc#369425). + ------------------------------------------------------------------- Thu Apr 10 12:54:45 CEST 2008 - ro@suse.de diff --git a/acl.spec b/acl.spec index 6321b2a..40f9492 100644 --- a/acl.spec +++ b/acl.spec @@ -1,5 +1,5 @@ # -# spec file for package acl (Version 2.2.45) +# spec file for package acl (Version 2.2.47) # # Copyright (c) 2008 SUSE LINUX Products GmbH, Nuernberg, Germany. # This file and all modifications and additions to the pristine @@ -16,11 +16,12 @@ BuildRequires: libattr-devel Group: System/Filesystems AutoReqProv: on Summary: Commands for Manipulating POSIX Access Control Lists -Version: 2.2.45 -Release: 31 +Version: 2.2.47 +Release: 1 Source: %name-%version.src.tar.bz2 Patch0: builddefs.in.diff -Patch1: walk-acl.diff +Patch1: walk-tree-fix-for-deref.patch +Patch2: null-pointer-access.diff Url: ftp://oss.sgi.com/projects/xfs/cmd_tars License: GPL v2 or later BuildRoot: %{_tmppath}/%{name}-%{version}-build @@ -76,6 +77,7 @@ Authors: %setup -n acl-%version %patch0 -p1 %patch1 -p1 +%patch2 -p1 %build export OPTIMIZER="$RPM_OPT_FLAGS -fPIC" @@ -183,6 +185,9 @@ rm -f $RPM_BUILD_ROOT/%{_lib}/libacl.{a,la,so} /%{_lib}/libacl.so.1* %changelog +* Sat Jul 12 2008 bphilips@suse.de +- Failure to recursively set/get ACLs on directories (bnc#404075) +- When invoked as ``setfacl -- ...'', setfacl segfaults (bnc#369425). * Thu Apr 10 2008 ro@suse.de - added baselibs.conf file to build xxbit packages for multilib support diff --git a/null-pointer-access.diff b/null-pointer-access.diff new file mode 100644 index 0000000..a3cb09a --- /dev/null +++ b/null-pointer-access.diff @@ -0,0 +1,57 @@ +From: Andreas Gruenbacher +Subject: Fix NULL pointer access / segmentation fault + +When invoked as ``setfacl -- ...'', setfacl segfaults. Reported +by Jiri Moskovcak and +Peng Haitao . + +This fix is based on their proposed patch. + +Signed-off-by: Andreas Gruenbacher +Cc: Jiri Moskovcak +Cc: Peng Haitao + +Index: acl-2.2.45/setfacl/setfacl.c +=================================================================== +--- acl-2.2.45.orig/setfacl/setfacl.c ++++ acl-2.2.45/setfacl/setfacl.c +@@ -301,7 +301,7 @@ int main(int argc, char *argv[]) + int which; + int lineno; + int error; +- seq_t seq = NULL; ++ seq_t seq; + int seq_cmd, parse_mode; + + progname = basename(argv[0]); +@@ -326,6 +326,10 @@ int main(int argc, char *argv[]) + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + ++ seq = seq_init(); ++ if (!seq) ++ ERRNO_ERROR(1); ++ + while ((opt = getopt_long(argc, argv, cmd_line_options, + long_options, NULL)) != -1) { + /* we remember the two REMOVE_ACL commands of the set +@@ -334,15 +338,12 @@ int main(int argc, char *argv[]) + cmd_t seq_remove_acl_cmd = NULL; + + if (opt != '\1' && saw_files) { +- if (seq) { ++ if (seq) + seq_free(seq); +- seq = NULL; +- } +- saw_files = 0; +- } +- if (seq == NULL) { +- if (!(seq = seq_init())) ++ seq = seq_init(); ++ if (!seq) + ERRNO_ERROR(1); ++ saw_files = 0; + } + + switch (opt) { diff --git a/walk-acl.diff b/walk-acl.diff deleted file mode 100644 index 9474fa4..0000000 --- a/walk-acl.diff +++ /dev/null @@ -1,703 +0,0 @@ -Index: acl-2.2.45/doc/CHANGES -=================================================================== ---- acl-2.2.45.orig/doc/CHANGES -+++ acl-2.2.45/doc/CHANGES -@@ -2,6 +2,12 @@ - * Update acl.5 man page to clarify the relationship between - the file permissions and the *OBJ ACL entries thanks - to Andreas Gruenbacher. -+* In some cases, gcc does not link in functions from libmisc.a -+ unless libmisc is specifief before the dynamic libraries on -+ the command line. -+* Rip out nftw tree walking, it is broken and hopeless to fix. -+ The replacement walk_tree() function does exactly what we -+ want, and is much simpler to use. - - 2.2.45 (11 September 2007) - * Fix symlink handling with getfacl and setfacl, thanks to Utako Usaka. -Index: acl-2.2.45/getfacl/Makefile -=================================================================== ---- acl-2.2.45.orig/getfacl/Makefile -+++ acl-2.2.45/getfacl/Makefile -@@ -9,8 +9,8 @@ LTCOMMAND = getfacl - CFILES = getfacl.c user_group.c - HFILES = user_group.h - --LLDLIBS = $(LIBACL) $(LIBATTR) $(LIBMISC) --LTDEPENDENCIES = $(LIBACL) $(LIBMISC) -+LLDLIBS = $(LIBMISC) $(LIBACL) $(LIBATTR) -+LTDEPENDENCIES = $(LIBMISC) $(LIBACL) - - default: $(LTCOMMAND) - -Index: acl-2.2.45/getfacl/getfacl.c -=================================================================== ---- acl-2.2.45.orig/getfacl/getfacl.c -+++ acl-2.2.45/getfacl/getfacl.c -@@ -34,10 +34,10 @@ - #include - #include - #include --#include - #include - #include "config.h" - #include "user_group.h" -+#include "walk_tree.h" - #include "misc.h" - - #define POSIXLY_CORRECT_STR "POSIXLY_CORRECT" -@@ -70,24 +70,22 @@ struct option long_options[] = { - const char *progname; - const char *cmd_line_options; - --int opt_recursive; /* recurse into sub-directories? */ --int opt_walk_logical; /* always follow symbolic links */ --int opt_walk_physical; /* never follow symbolic links */ --int opt_print_acl = 0; --int opt_print_default_acl = 0; -+int walk_flags = WALK_TREE_DEREFERENCE; -+int opt_print_acl; -+int opt_print_default_acl; - int opt_strip_leading_slash = 1; - int opt_comments = 1; /* include comments */ --int opt_skip_base = 0; /* skip files that only have the base entries */ --int opt_tabular = 0; /* tabular output format (alias `showacl') */ -+int opt_skip_base; /* skip files that only have the base entries */ -+int opt_tabular; /* tabular output format (alias `showacl') */ - #if POSIXLY_CORRECT - const int posixly_correct = 1; /* Posix compatible behavior! */ - #else --int posixly_correct = 0; /* Posix compatible behavior? */ -+int posixly_correct; /* Posix compatible behavior? */ - #endif --int had_errors = 0; --int absolute_warning = 0; /* Absolute path warning was issued */ -+int had_errors; -+int absolute_warning; /* Absolute path warning was issued */ - int print_options = TEXT_SOME_EFFECTIVE; --int opt_numeric = 0; /* don't convert id's to symbolic names */ -+int opt_numeric; /* don't convert id's to symbolic names */ - - - static const char *xquote(const char *str) -@@ -425,12 +423,23 @@ acl_get_file_mode(const char *path_p) - return acl_from_mode(st.st_mode); - } - --int do_print(const char *path_p, const struct stat *st) -+int do_print(const char *path_p, const struct stat *st, int walk_flags, void *unused) - { - const char *default_prefix = NULL; - acl_t acl = NULL, default_acl = NULL; - int error = 0; - -+ if (walk_flags & WALK_TREE_FAILED) { -+ fprintf(stderr, "%s: %s: %s\n", progname, xquote(path_p), -+ strerror(errno)); -+ return 1; -+ } -+ -+ if ((walk_flags & WALK_TREE_SYMLINK) && -+ ((walk_flags & WALK_TREE_PHYSICAL) || -+ !(walk_flags & (WALK_TREE_TOPLEVEL | WALK_TREE_LOGICAL)))) -+ return 0; -+ - if (opt_print_acl) { - acl = acl_get_file(path_p, ACL_TYPE_ACCESS); - if (acl == NULL && (errno == ENOSYS || errno == ENOTSUP)) -@@ -549,7 +558,7 @@ void help(void) - " --skip-base skip files that only have the base entries\n" - " -R, --recursive recurse into subdirectories\n" - " -L, --logical logical walk, follow symbolic links\n" --" -P --physical physical walk, do not follow symbolic links\n" -+" -P, --physical physical walk, do not follow symbolic links\n" - " --tabular use tabular output format\n" - " --numeric print numeric user/group identifiers\n" - " --absolute-names don't strip leading '/' in pathnames\n")); -@@ -560,75 +569,6 @@ void help(void) - " --help this help text\n")); - } - -- --static int __errors; --int __do_print(const char *file, const struct stat *stat, -- int flag, struct FTW *ftw) --{ -- int saved_errno = errno; -- -- /* Process the target of a symbolic link, and traverse the link, -- only if doing a logical walk, or if the symbolic link was -- specified on the command line. Always skip symbolic links if -- doing a physical walk. */ -- -- if (S_ISLNK(stat->st_mode) && -- (opt_walk_physical || (ftw->level > 0 && !opt_walk_logical))) -- return 0; -- -- if (do_print(file, stat)) -- __errors++; -- -- if (flag == FTW_DNR && opt_recursive) { -- /* Item is a directory which can't be read. */ -- fprintf(stderr, "%s: %s: %s\n", -- progname, file, strerror(saved_errno)); -- return 0; -- } -- -- /* We also get here in non-recursive mode. In that case, -- return something != 0 to abort nftw. */ -- -- if (!opt_recursive) -- return 1; -- -- return 0; --} -- --char *resolve_symlinks(const char *file) --{ -- static char buffer[4096]; -- struct stat stat; -- char *path = NULL; -- -- if (lstat(file, &stat) == -1) -- return path; -- -- if (S_ISLNK(stat.st_mode) && !opt_walk_physical) -- path = realpath(file, buffer); -- else -- path = (char *)file; /* not a symlink, use given path */ -- -- return path; --} -- --int walk_tree(const char *file) --{ -- const char *p; -- -- __errors = 0; -- if ((p = resolve_symlinks(file)) == NULL) { -- fprintf(stderr, "%s: %s: %s\n", progname, -- xquote(file), strerror(errno)); -- __errors++; -- } else if (nftw(p, __do_print, 0, opt_walk_logical? 0 : FTW_PHYS) < 0) { -- fprintf(stderr, "%s: %s: %s\n", progname, xquote(file), -- strerror(errno)); -- __errors++; -- } -- return __errors; --} -- - int main(int argc, char *argv[]) - { - int opt; -@@ -691,21 +631,21 @@ int main(int argc, char *argv[]) - case 'R': /* recursive */ - if (posixly_correct) - goto synopsis; -- opt_recursive = 1; -+ walk_flags |= WALK_TREE_RECURSIVE; - break; - - case 'L': /* follow all symlinks */ - if (posixly_correct) - goto synopsis; -- opt_walk_logical = 1; -- opt_walk_physical = 0; -+ walk_flags |= WALK_TREE_LOGICAL; -+ walk_flags &= ~WALK_TREE_PHYSICAL; - break; - - case 'P': /* skip all symlinks */ - if (posixly_correct) - goto synopsis; -- opt_walk_logical = 0; -- opt_walk_physical = 1; -+ walk_flags |= WALK_TREE_PHYSICAL; -+ walk_flags &= ~WALK_TREE_LOGICAL; - break; - - case 's': /* skip files with only base entries */ -@@ -762,7 +702,8 @@ int main(int argc, char *argv[]) - if (*line == '\0') - continue; - -- had_errors += walk_tree(line); -+ had_errors += walk_tree(line, walk_flags, 0, -+ do_print, NULL); - } - if (!feof(stdin)) { - fprintf(stderr, _("%s: Standard input: %s\n"), -@@ -770,7 +711,8 @@ int main(int argc, char *argv[]) - had_errors++; - } - } else -- had_errors += walk_tree(argv[optind]); -+ had_errors += walk_tree(argv[optind], walk_flags, 0, -+ do_print, NULL); - optind++; - } while (optind < argc); - -Index: acl-2.2.45/libmisc/Makefile -=================================================================== ---- acl-2.2.45.orig/libmisc/Makefile -+++ acl-2.2.45/libmisc/Makefile -@@ -8,7 +8,7 @@ include $(TOPDIR)/include/builddefs - LTLIBRARY = libmisc.la - LTLDFLAGS = - --CFILES = quote.c unquote.c high_water_alloc.c next_line.c -+CFILES = quote.c unquote.c high_water_alloc.c next_line.c walk_tree.c - - default: $(LTLIBRARY) - install install-dev install-lib: -Index: acl-2.2.45/setfacl/Makefile -=================================================================== ---- acl-2.2.45.orig/setfacl/Makefile -+++ acl-2.2.45/setfacl/Makefile -@@ -9,8 +9,8 @@ LTCOMMAND = setfacl - CFILES = setfacl.c do_set.c sequence.c parse.c - HFILES = sequence.h parse.h - --LLDLIBS = $(LIBACL) $(LIBATTR) $(LIBMISC) --LTDEPENDENCIES = $(LIBACL) $(LIBMISC) -+LLDLIBS = $(LIBMISC) $(LIBACL) $(LIBATTR) -+LTDEPENDENCIES = $(LIBMISC) $(LIBACL) - - default: $(LTCOMMAND) - -Index: acl-2.2.45/setfacl/do_set.c -=================================================================== ---- acl-2.2.45.orig/setfacl/do_set.c -+++ acl-2.2.45/setfacl/do_set.c -@@ -36,10 +36,10 @@ - #include "sequence.h" - #include "parse.h" - #include "config.h" -+#include "walk_tree.h" - - - extern const char *progname; --extern int opt_recursive; - extern int opt_recalculate; - extern int opt_test; - extern int print_options; -@@ -259,8 +259,10 @@ int - do_set( - const char *path_p, - const struct stat *st, -- const seq_t seq) -+ int walk_flags, -+ void *arg) - { -+ const seq_t seq = (const seq_t)arg; - acl_t old_acl = NULL, old_default_acl = NULL; - acl_t acl = NULL, default_acl = NULL; - acl_t *xacl, *old_xacl; -@@ -272,6 +274,16 @@ do_set( - int acl_modified = 0, default_acl_modified = 0; - int acl_mask_provided = 0, default_acl_mask_provided = 0; - -+ if (walk_flags & WALK_TREE_FAILED) { -+ fprintf(stderr, "%s: %s: %s\n", progname, path_p, strerror(errno)); -+ return 1; -+ } -+ -+ if ((walk_flags & WALK_TREE_SYMLINK) && -+ ((walk_flags & WALK_TREE_PHYSICAL) || -+ !(walk_flags & (WALK_TREE_TOPLEVEL | WALK_TREE_LOGICAL)))) -+ return 0; -+ - /* Execute the commands in seq (read ACLs on demand) */ - error = seq_get_cmd(seq, SEQ_FIRST_CMD, &cmd); - if (error == 0) -@@ -426,7 +438,7 @@ do_set( - } - - /* Only directores can have default ACLs */ -- if (default_acl && !S_ISDIR(st->st_mode) && opt_recursive) { -+ if (default_acl && !S_ISDIR(st->st_mode) && (walk_flags & WALK_TREE_RECURSIVE)) { - /* In recursive mode, ignore default ACLs for files */ - acl_free(default_acl); - default_acl = NULL; -Index: acl-2.2.45/setfacl/setfacl.c -=================================================================== ---- acl-2.2.45.orig/setfacl/setfacl.c -+++ acl-2.2.45/setfacl/setfacl.c -@@ -28,20 +28,15 @@ - #include - #include - #include --#include - #include - #include - #include "config.h" - #include "sequence.h" - #include "parse.h" -+#include "walk_tree.h" - #include "misc.h" - --extern int --do_set( -- const char *path_p, -- const struct stat *stat_p, -- const seq_t seq); -- -+extern int do_set(const char *path_p, const struct stat *stat_p, int flags, void *arg); - - #define POSIXLY_CORRECT_STR "POSIXLY_CORRECT" - -@@ -82,9 +77,7 @@ struct option long_options[] = { - const char *progname; - const char *cmd_line_options, *cmd_line_spec; - --int opt_recursive; /* recurse into sub-directories? */ --int opt_walk_logical; /* always follow symbolic links */ --int opt_walk_physical; /* never follow symbolic links */ -+int walk_flags = WALK_TREE_DEREFERENCE; - int opt_recalculate; /* recalculate mask entry (0=default, 1=yes, -1=no) */ - int opt_promote; /* promote access ACL to default ACL */ - int opt_test; /* do not write to the file system. -@@ -188,7 +181,7 @@ restore( - stat.st_uid = uid; - stat.st_gid = gid; - -- error = do_set(path_p, &stat, seq); -+ error = do_set(path_p, &stat, 0, seq); - if (error != 0) { - status = 1; - goto resume; -@@ -275,77 +268,6 @@ void help(void) - } - - --static int __errors; --static seq_t __seq; -- --int __do_set(const char *file, const struct stat *stat, -- int flag, struct FTW *ftw) --{ -- int saved_errno = errno; -- -- /* Process the target of a symbolic link, and traverse the link, -- only if doing a logical walk, or if the symbolic link was -- specified on the command line. Always skip symbolic links if -- doing a physical walk. */ -- -- if (S_ISLNK(stat->st_mode) && -- (opt_walk_physical || (ftw->level > 0 && !opt_walk_logical))) -- return 0; -- -- if (do_set(file, stat, __seq)) -- __errors++; -- -- if (flag == FTW_DNR && opt_recursive) { -- /* Item is a directory which can't be read. */ -- fprintf(stderr, "%s: %s: %s\n", -- progname, file, strerror(saved_errno)); -- return 0; -- } -- -- /* We also get here in non-recursive mode. In that case, -- return something != 0 to abort nftw. */ -- -- if (!opt_recursive) -- return 1; -- -- return 0; --} -- --char *resolve_symlinks(const char *file) --{ -- static char buffer[4096]; -- struct stat stat; -- char *path = NULL; -- -- if (lstat(file, &stat) == -1) -- return path; -- -- if (S_ISLNK(stat.st_mode) && !opt_walk_physical) -- path = realpath(file, buffer); -- else -- path = (char *)file; /* not a symlink, use given path */ -- -- return path; --} -- --int walk_tree(const char *file, seq_t seq) --{ -- const char *p; -- -- __errors = 0; -- __seq = seq; -- if ((p = resolve_symlinks(file)) == NULL) { -- fprintf(stderr, "%s: %s: %s\n", progname, -- xquote(file), strerror(errno)); -- __errors++; -- } else if (nftw(p, __do_set, 0, opt_walk_logical ? 0 : FTW_PHYS) < 0) { -- fprintf(stderr, "%s: %s: %s\n", progname, -- xquote(file), strerror(errno)); -- __errors++; -- } -- return __errors; --} -- - int next_file(const char *arg, seq_t seq) - { - char *line; -@@ -353,14 +275,14 @@ int next_file(const char *arg, seq_t seq - - if (strcmp(arg, "-") == 0) { - while ((line = next_line(stdin))) -- errors = walk_tree(line, seq); -+ errors = walk_tree(line, walk_flags, 0, do_set, seq); - if (!feof(stdin)) { - fprintf(stderr, _("%s: Standard input: %s\n"), - progname, strerror(errno)); - errors = 1; - } - } else { -- errors = walk_tree(arg, seq); -+ errors = walk_tree(arg, walk_flags, 0, do_set, seq); - } - return errors ? 1 : 0; - } -@@ -627,17 +549,17 @@ int main(int argc, char *argv[]) - break; - - case 'R': /* recursive */ -- opt_recursive = 1; -+ walk_flags |= WALK_TREE_RECURSIVE; - break; - - case 'L': /* follow symlinks */ -- opt_walk_logical = 1; -- opt_walk_physical = 0; -+ walk_flags |= WALK_TREE_LOGICAL; -+ walk_flags &= ~WALK_TREE_PHYSICAL; - break; - - case 'P': /* do not follow symlinks */ -- opt_walk_logical = 0; -- opt_walk_physical = 1; -+ walk_flags |= WALK_TREE_PHYSICAL; -+ walk_flags &= ~WALK_TREE_LOGICAL; - break; - - case 't': /* test mode */ -Index: acl-2.2.45/include/walk_tree.h -=================================================================== ---- /dev/null -+++ acl-2.2.45/include/walk_tree.h -@@ -0,0 +1,19 @@ -+#ifndef __WALK_TREE_H -+#define __WALK_TREE_H -+ -+#define WALK_TREE_RECURSIVE 0x1 -+#define WALK_TREE_PHYSICAL 0x2 -+#define WALK_TREE_LOGICAL 0x4 -+#define WALK_TREE_DEREFERENCE 0x8 -+ -+#define WALK_TREE_TOPLEVEL 0x100 -+#define WALK_TREE_SYMLINK 0x200 -+#define WALK_TREE_FAILED 0x400 -+ -+struct stat; -+ -+extern int walk_tree(const char *path, int walk_flags, unsigned int num, -+ int (*func)(const char *, const struct stat *, int, -+ void *), void *arg); -+ -+#endif -Index: acl-2.2.45/libmisc/walk_tree.c -=================================================================== ---- /dev/null -+++ acl-2.2.45/libmisc/walk_tree.c -@@ -0,0 +1,188 @@ -+/* -+ File: walk_tree.c -+ -+ Copyright (C) 2007 Andreas Gruenbacher -+ -+ This program is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Library General Public -+ License as published by the Free Software Foundation; either -+ version 2 of the License, or (at your option) any later version. -+ -+ This program is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Library General Public License for more details. -+ -+ You should have received a copy of the GNU Library General Public -+ License along with this library; if not, write to the Free Software -+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -+*/ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "walk_tree.h" -+ -+struct entry_handle { -+ struct entry_handle *prev, *next; -+ struct stat st; -+ DIR *stream; -+ off_t pos; -+}; -+ -+struct entry_handle head = { -+ .next = &head, -+ .prev = &head, -+ /* The other fields are unused. */ -+}; -+struct entry_handle *closed = &head; -+unsigned int num_dir_handles; -+ -+static int walk_tree_rec(const char *path, int walk_flags, -+ int (*func)(const char *, const struct stat *, int, -+ void *), void *arg, int depth) -+{ -+ int (*xstat)(const char *, struct stat *) = lstat; -+ int flags = walk_flags, err; -+ struct entry_handle dir; -+ -+ /* -+ * If (walk_flags & WALK_TREE_PHYSICAL), do not traverse symlinks. -+ * If (walk_flags & WALK_TREE_LOGICAL), traverse all symlinks. -+ * Otherwise, traverse only top-level symlinks. -+ */ -+ if (depth == 0) -+ flags |= WALK_TREE_TOPLEVEL; -+ -+follow_symlink: -+ if (xstat(path, &dir.st) != 0) -+ return func(path, NULL, flags | WALK_TREE_FAILED, arg); -+ if (S_ISLNK(dir.st.st_mode)) { -+ flags |= WALK_TREE_SYMLINK; -+ if (flags & WALK_TREE_DEREFERENCE) { -+ xstat = stat; -+ goto follow_symlink; -+ } -+ } -+ err = func(path, &dir.st, flags, arg); -+ if ((flags & WALK_TREE_RECURSIVE) && -+ (S_ISDIR(dir.st.st_mode) || (S_ISLNK(dir.st.st_mode))) && -+ (!(flags & WALK_TREE_PHYSICAL) || !(flags & WALK_TREE_SYMLINK)) && -+ (flags & (WALK_TREE_LOGICAL | WALK_TREE_TOPLEVEL))) { -+ struct entry_handle *i; -+ struct dirent *entry; -+ -+ /* Check if we have already visited this directory. */ -+ for (i = head.next; i != &head; i = i->next) -+ if (i->st.st_dev == dir.st.st_dev && -+ i->st.st_ino == dir.st.st_ino) -+ return err; -+ -+ if (num_dir_handles == 0 && closed->prev != &head) { -+close_another_dir: -+ /* Close the topmost directory handle still open. */ -+ closed = closed->prev; -+ closed->pos = telldir(closed->stream); -+ closedir(closed->stream); -+ closed->stream = NULL; -+ num_dir_handles++; -+ } -+ -+ dir.stream = opendir(path); -+ if (!dir.stream) { -+ if (errno == ENFILE && closed->prev != &head) { -+ /* Ran out of file descriptors. */ -+ num_dir_handles = 0; -+ goto close_another_dir; -+ } -+ -+ /* -+ * PATH may be a symlink to a regular file, or a dead -+ * symlink which we didn't follow above. -+ */ -+ if (errno != ENOTDIR && errno != ENOENT) -+ err += func(path, &dir.st, -+ flags | WALK_TREE_FAILED, arg); -+ return err; -+ } -+ -+ /* Insert into the list of handles. */ -+ dir.next = head.next; -+ dir.prev = &head; -+ dir.prev->next = &dir; -+ dir.next->prev = &dir; -+ num_dir_handles--; -+ -+ while ((entry = readdir(dir.stream)) != NULL) { -+ char *path_end; -+ -+ if (!strcmp(entry->d_name, ".") || -+ !strcmp(entry->d_name, "..")) -+ continue; -+ path_end = strchr(path, 0); -+ if ((path_end - path) + strlen(entry->d_name) + 1 >= -+ FILENAME_MAX) { -+ errno = ENAMETOOLONG; -+ err += func(path, NULL, -+ flags | WALK_TREE_FAILED, arg); -+ continue; -+ } -+ *path_end++ = '/'; -+ strcpy(path_end, entry->d_name); -+ err += walk_tree_rec(path, walk_flags, func, arg, -+ depth + 1); -+ *--path_end = 0; -+ if (!dir.stream) { -+ /* Reopen the directory handle. */ -+ dir.stream = opendir(path); -+ if (!dir.stream) -+ return err + func(path, &dir.st, flags | -+ WALK_TREE_FAILED, arg); -+ seekdir(dir.stream, dir.pos); -+ -+ closed = closed->next; -+ num_dir_handles--; -+ } -+ } -+ -+ if (closedir(dir.stream) != 0) -+ err += func(path, &dir.st, flags | WALK_TREE_FAILED, -+ arg); -+ -+ /* Remove from the list of handles. */ -+ dir.prev->next = dir.next; -+ dir.next->prev = dir.prev; -+ num_dir_handles++; -+ } -+ return err; -+} -+ -+int walk_tree(const char *path, int walk_flags, unsigned int num, -+ int (*func)(const char *, const struct stat *, int, void *), -+ void *arg) -+{ -+ char path_copy[FILENAME_MAX]; -+ -+ num_dir_handles = num; -+ if (num_dir_handles < 1) { -+ struct rlimit rlimit; -+ -+ num_dir_handles = 1; -+ if (getrlimit(RLIMIT_NOFILE, &rlimit) == 0 && -+ rlimit.rlim_cur >= 2) -+ num_dir_handles = rlimit.rlim_cur / 2; -+ } -+ if (strlen(path) >= FILENAME_MAX) { -+ errno = ENAMETOOLONG; -+ return func(path, NULL, WALK_TREE_FAILED, arg); -+ } -+ strcpy(path_copy, path); -+ return walk_tree_rec(path_copy, walk_flags, func, arg, 0); -+} diff --git a/walk-tree-fix-for-deref.patch b/walk-tree-fix-for-deref.patch new file mode 100644 index 0000000..455fe7d --- /dev/null +++ b/walk-tree-fix-for-deref.patch @@ -0,0 +1,68 @@ +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; + + /*