OBS User unknown 2008-07-11 22:15:45 +00:00 committed by Git OBS Bridge
parent c1e415b095
commit 2750418b95
7 changed files with 143 additions and 710 deletions

View File

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:1a46338bedea261eda948549509f60d1351d8b73440a1fa18e4bfd200702ff26
size 131042

3
acl-2.2.47.src.tar.bz2 Normal file
View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:e7113f1a6447476b8f20ede65eaa4179b287be47829b9b820357754c570db880
size 129813

View File

@ -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

View File

@ -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

57
null-pointer-access.diff Normal file
View File

@ -0,0 +1,57 @@
From: Andreas Gruenbacher <agruen@suse.de>
Subject: Fix NULL pointer access / segmentation fault
When invoked as ``setfacl -- ...'', setfacl segfaults. Reported
by Jiri Moskovcak <jmoskovc@redhat.com> and
Peng Haitao <penght@cn.fujitsu.com>.
This fix is based on their proposed patch.
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Cc: Jiri Moskovcak <jmoskovc@redhat.com>
Cc: Peng Haitao <penght@cn.fujitsu.com>
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) {

View File

@ -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 <dirent.h>
#include <libgen.h>
#include <getopt.h>
-#include <ftw.h>
#include <locale.h>
#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 <sys/stat.h>
#include <dirent.h>
#include <libgen.h>
-#include <ftw.h>
#include <getopt.h>
#include <locale.h>
#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 <a.gruenbacher@computer.org>
+
+ 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 <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <dirent.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#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);
+}

View File

@ -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 <bphilips@suse.de>
---
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;
/*