From c5de3e1d34d1230f4d2b575257d01f2a817a7c8c Mon Sep 17 00:00:00 2001 From: Kamil Dudka Date: Thu, 26 Nov 2009 17:50:53 +0000 Subject: [PATCH] - update SELinux patch to the latest upstream (gnulib based) version --- findutils-4.4.0-selinux.patch | 517 ------------ findutils-4.4.2-fts-remount.patch | 2 + findutils-4.4.2-selinux-gnulib.patch | 1143 ++++++++++++++++++++++++++ findutils-4.4.2-selinux.patch | 453 ++++++++++ findutils-4.4.2-xautofs.patch | 56 +- findutils.spec | 20 +- 6 files changed, 1641 insertions(+), 550 deletions(-) delete mode 100644 findutils-4.4.0-selinux.patch create mode 100644 findutils-4.4.2-selinux-gnulib.patch create mode 100644 findutils-4.4.2-selinux.patch diff --git a/findutils-4.4.0-selinux.patch b/findutils-4.4.0-selinux.patch deleted file mode 100644 index cc68c67..0000000 --- a/findutils-4.4.0-selinux.patch +++ /dev/null @@ -1,517 +0,0 @@ -diff -up findutils-4.4.2/configure.ac_old findutils-4.4.2/configure.ac ---- findutils-4.4.2/configure.ac_old 2009-07-01 10:24:04.000000000 +0200 -+++ findutils-4.4.2/configure.ac 2009-07-01 10:24:46.000000000 +0200 -@@ -114,6 +114,16 @@ AC_CHECK_LIB([m],[fabs],[FINDLIBS="-lm $ - AC_DEFINE_UNQUOTED(HAVE_FABS_IN_LIBM,1,[fabs is defined in -lm])) - AC_SUBST([FINDLIBS]) - -+AC_ARG_WITH([selinux], -+ AS_HELP_STRING([--without-selinux], [disable SELinux support]), -+ [:], -+[AC_CHECK_LIB([selinux], [is_selinux_enabled], -+ [with_selinux=yes], [with_selinux=no])]) -+if test x$with_selinux != xno; then -+ AC_DEFINE([WITH_SELINUX], [1], [Define to support SELinux]) -+ AC_SUBST([LIBSELINUX], [-lselinux]) -+fi -+ - dnl Checks for header files. - AC_HEADER_STDC - dnl Assume unistd.h is present - coreutils does too. -diff -up findutils-4.4.2/doc/find.texi_old findutils-4.4.2/doc/find.texi ---- findutils-4.4.2/doc/find.texi_old 2009-07-01 10:25:09.000000000 +0200 -+++ findutils-4.4.2/doc/find.texi 2009-07-01 10:26:37.000000000 +0200 -@@ -7,7 +7,6 @@ - @c %**end of header - - @include version.texi --@include ../locate/dblocation.texi - - @iftex - @finalout -@@ -1242,6 +1241,14 @@ situation. - - @end deffn - -+@deffn Test -context pattern -+True if file's SELinux context matches the pattern @var{pattern}. -+The pattern uses shell glob matching. -+ -+This predicate is supported only on @code{find} versions compiled with -+SELinux support and only when SELinux is enabled. -+@end deffn -+ - @node Contents - @section Contents - -@@ -1826,6 +1833,9 @@ value used for BLOCKSIZE is system-depen - bytes. If the file size is zero, the value printed is undefined. On - systems which lack support for st_blocks, a file's sparseness is - assumed to be 1.0. -+@item %Z -+File's SELinux context, or empty string if the file has no SELinux context -+or this version of find does not support SELinux. - @end table - - @node Location Directives -diff -up findutils-4.4.2/find/defs.h_old findutils-4.4.2/find/defs.h ---- findutils-4.4.2/find/defs.h_old 2009-07-01 12:38:32.000000000 +0200 -+++ findutils-4.4.2/find/defs.h 2009-07-01 12:52:47.000000000 +0200 -@@ -91,6 +91,9 @@ int get_statinfo PARAMS((const char *pat - #define MODE_RWX (S_IXUSR | S_IXGRP | S_IXOTH | MODE_RW) - #define MODE_ALL (S_ISUID | S_ISGID | S_ISVTX | MODE_RWX) - -+#ifdef WITH_SELINUX -+#include -+#endif - - struct predicate; - struct options; -@@ -315,6 +318,9 @@ struct predicate - struct samefile_file_id samefileid; /* samefile */ - mode_t type; /* type */ - struct format_val printf_vec; /* printf fprintf fprint ls fls print0 fprint0 print */ -+#ifdef WITH_SELINUX -+ security_context_t scontext; /* scontext */ -+#endif - } args; - - /* The next predicate in the user input sequence, -@@ -459,6 +465,9 @@ PREDICATEFUNCTION pred_used; - PREDICATEFUNCTION pred_user; - PREDICATEFUNCTION pred_writable; - PREDICATEFUNCTION pred_xtype; -+#ifdef WITH_SELINUX -+PREDICATEFUNCTION pred_context; -+#endif - - - -@@ -601,6 +610,10 @@ struct options - */ - int regex_options; - -+#ifdef WITH_SELINUX -+ int (*x_getfilecon) (); -+#endif -+ - /* Optimisation level. One is the default. - */ - unsigned short optimisation_level; -diff -up findutils-4.4.2/find/find.1_old findutils-4.4.2/find/find.1 ---- findutils-4.4.2/find/find.1_old 2009-07-01 10:30:04.000000000 +0200 -+++ findutils-4.4.2/find/find.1 2009-07-01 10:30:59.000000000 +0200 -@@ -933,6 +933,8 @@ if \fIc\fR is `l'. In other words, for - checks the type of the file that - .B \-type - does not check. -+.IP "\-context \fIpattern\fR" -+(SELinux only) Security context of the file matches glob \fIpattern\fR. - - .SS ACTIONS - .IP "\-delete\fR" -@@ -1354,6 +1356,8 @@ File's type (like in - U=unknown type (shouldn't happen) - .IP %Y - File's type (like %y), plus follow symlinks: L=loop, N=nonexistent -+.IP %Z -+(SELinux only) file's security context. - .PP - A `%' character followed by any other character is discarded, but the - other character is printed (don't rely on this, as further format -diff -up findutils-4.4.2/find/find.c_old findutils-4.4.2/find/find.c ---- findutils-4.4.2/find/find.c_old 2009-07-01 10:26:53.000000000 +0200 -+++ findutils-4.4.2/find/find.c 2009-07-01 10:29:52.000000000 +0200 -@@ -120,6 +120,36 @@ int get_current_dirfd(void) - return AT_FDCWD; - } - -+#ifdef WITH_SELINUX -+static int -+fallback_getfilecon(const char *name, security_context_t *p, int prev_rv) -+{ -+ /* Our original getfilecon() call failed. Perhaps we can't follow a -+ * symbolic link. If that might be the problem, lgetfilecon() the link. -+ * Otherwise, admit defeat. -+ */ -+ switch (errno) -+ { -+ case ENOENT: -+ case ENOTDIR: -+#ifdef DEBUG_STAT -+ fprintf(stderr, "fallback_getfilecon(): getfilecon(%s) failed; falling back on lgetfilecon()\n", name); -+#endif -+ return lgetfilecon(name, p); -+ -+ case EACCES: -+ case EIO: -+ case ELOOP: -+ case ENAMETOOLONG: -+#ifdef EOVERFLOW -+ case EOVERFLOW: /* EOVERFLOW is not #defined on UNICOS. */ -+#endif -+ default: -+ return prev_rv; -+ } -+} -+#endif /* WITH_SELINUX */ -+ - - int - main (int argc, char **argv) -@@ -1270,7 +1300,7 @@ process_path (char *pathname, char *name - static void - process_dir (char *pathname, char *name, int pathlen, const struct stat *statp, char *parent) - { -- int subdirs_left; /* Number of unexamined subdirs in PATHNAME. */ -+ int subdirs_left = 0; /* Number of unexamined subdirs in PATHNAME. */ - boolean subdirs_unreliable; /* if true, cannot use dir link count as subdir limif (if false, it may STILL be unreliable) */ - unsigned int idx; /* Which entry are we on? */ - struct stat stat_buf; -diff -up findutils-4.4.2/find/Makefile.am_old findutils-4.4.2/find/Makefile.am ---- findutils-4.4.2/find/Makefile.am_old 2009-07-01 10:35:04.000000000 +0200 -+++ findutils-4.4.2/find/Makefile.am 2009-07-01 10:35:37.000000000 +0200 -@@ -26,7 +26,7 @@ endif - - EXTRA_DIST = defs.h $(man_MANS) - INCLUDES = -I../gnulib/lib -I$(top_srcdir)/lib -I$(top_srcdir)/gnulib/lib -I../intl -DLOCALEDIR=\"$(localedir)\" --LDADD = ./libfindtools.a ../lib/libfind.a ../gnulib/lib/libgnulib.a @INTLLIBS@ @LIB_CLOCK_GETTIME@ @FINDLIBS@ -+LDADD = ./libfindtools.a ../lib/libfind.a ../gnulib/lib/libgnulib.a @INTLLIBS@ @LIB_CLOCK_GETTIME@ @FINDLIBS@ @LIBSELINUX@ - man_MANS = find.1 - SUBDIRS = . testsuite - -diff -up findutils-4.4.2/find/parser.c_old findutils-4.4.2/find/parser.c ---- findutils-4.4.2/find/parser.c_old 2009-07-01 10:35:43.000000000 +0200 -+++ findutils-4.4.2/find/parser.c 2009-07-01 12:38:19.000000000 +0200 -@@ -53,6 +53,10 @@ - #include - #include - -+#ifdef WITH_SELINUX -+#include -+#endif -+ - #if ENABLE_NLS - # include - # define _(Text) gettext (Text) -@@ -155,6 +159,9 @@ static boolean parse_noignore_race PARAM - static boolean parse_warn PARAMS((const struct parser_table*, char *argv[], int *arg_ptr)); - static boolean parse_xtype PARAMS((const struct parser_table*, char *argv[], int *arg_ptr)); - static boolean parse_quit PARAMS((const struct parser_table*, char *argv[], int *arg_ptr)); -+#ifdef WITH_SELINUX -+static boolean parse_context PARAMS((const struct parser_table*, char *argv[], int *arg_ptr)); -+#endif - - boolean parse_print PARAMS((const struct parser_table*, char *argv[], int *arg_ptr)); - -@@ -251,6 +258,9 @@ static struct parser_table const parse_t - PARSE_TEST ("cmin", cmin), /* GNU */ - PARSE_TEST ("cnewer", cnewer), /* GNU */ - {ARG_TEST, "ctime", parse_time, pred_ctime}, /* POSIX */ -+#ifdef WITH_SELINUX -+ PARSE_TEST ("context", context), /* GNU */ -+#endif - PARSE_POSOPT ("daystart", daystart), /* GNU */ - PARSE_ACTION ("delete", delete), /* GNU, Mac OS, FreeBSD */ - PARSE_OPTION ("d", d), /* Mac OS X, FreeBSD, NetBSD, OpenBSD, but deprecated in favour of -depth */ -@@ -347,6 +357,89 @@ static struct parser_table const parse_t - static const char *first_nonoption_arg = NULL; - static const struct parser_table *noop = NULL; - -+#ifdef WITH_SELINUX -+static int -+fallback_getfilecon(const char *name, security_context_t *p, int prev_rv) -+{ -+ /* Our original getfilecon() call failed. Perhaps we can't follow a -+ * symbolic link. If that might be the problem, lgetfilecon() the link. -+ * Otherwise, admit defeat. -+ */ -+ switch (errno) -+ { -+ case ENOENT: -+ case ENOTDIR: -+#ifdef DEBUG_STAT -+ fprintf(stderr, "fallback_getfilecon(): getfilecon(%s) failed; falling back on lgetfilecon()\n", name); -+#endif -+ return lgetfilecon(name, p); -+ -+ case EACCES: -+ case EIO: -+ case ELOOP: -+ case ENAMETOOLONG: -+#ifdef EOVERFLOW -+ case EOVERFLOW: /* EOVERFLOW is not #defined on UNICOS. */ -+#endif -+ default: -+ return prev_rv; -+ } -+} -+ -+/* optionh_getfilecon() implements the getfilecon operation when the -+ * -H option is in effect. -+ * -+ * If the item to be examined is a command-line argument, we follow -+ * symbolic links. If the getfilecon() call fails on the command-line -+ * item, we fall back on the properties of the symbolic link. -+ * -+ * If the item to be examined is not a command-line argument, we -+ * examine the link itself. -+ */ -+int -+optionh_getfilecon(const char *name, security_context_t *p) -+{ -+ if (0 == state.curdepth) -+ { -+ /* This file is from the command line; deference the link (if it -+ * is a link). -+ */ -+ int rv = getfilecon(name, p); -+ if (0 == rv) -+ return 0; /* success */ -+ else -+ return fallback_getfilecon(name, p, rv); -+ } -+ else -+ { -+ /* Not a file on the command line; do not derefernce the link. -+ */ -+ return lgetfilecon(name, p); -+ } -+} -+/* optionl_getfilecon() implements the getfilecon operation when the -+ * -L option is in effect. That option makes us examine the thing the -+ * symbolic link points to, not the symbolic link itself. -+ */ -+int -+optionl_getfilecon(const char *name, security_context_t *p) -+{ -+ int rv = getfilecon(name, p); -+ if (0 == rv) -+ return 0; /* normal case. */ -+ else -+ return fallback_getfilecon(name, p, rv); -+} -+/* optionp_getfilecon() implements the stat operation when the -P -+ * option is in effect (this is also the default). That option makes -+ * us examine the symbolic link itself, not the thing it points to. -+ */ -+int -+optionp_getfilecon(const char *name, security_context_t *p) -+{ -+ return lgetfilecon(name, p); -+} -+#endif /* WITH_SELINUX */ - - void - check_option_combinations(const struct predicate *p) -@@ -450,11 +543,17 @@ set_follow_state(enum SymlinkOption opt) - { - case SYMLINK_ALWAYS_DEREF: /* -L */ - options.xstat = optionl_stat; -+#ifdef WITH_SELINUX -+ options.x_getfilecon = optionl_getfilecon; -+#endif - options.no_leaf_check = true; - break; - - case SYMLINK_NEVER_DEREF: /* -P (default) */ - options.xstat = optionp_stat; -+#ifdef WITH_SELINUX -+ options.x_getfilecon = optionp_getfilecon; -+#endif - /* Can't turn no_leaf_check off because the user might have specified - * -noleaf anyway - */ -@@ -462,6 +561,9 @@ set_follow_state(enum SymlinkOption opt) - - case SYMLINK_DEREF_ARGSONLY: /* -H */ - options.xstat = optionh_stat; -+#ifdef WITH_SELINUX -+ options.x_getfilecon = optionh_getfilecon; -+#endif - options.no_leaf_check = true; - } - } -@@ -1127,8 +1229,12 @@ tests (N can be +N or -N or N): -amin N - -nouser -nogroup -path PATTERN -perm [+-]MODE -regex PATTERN\n\ - -readable -writable -executable\n\ - -wholename PATTERN -size N[bcwkMG] -true -type [bcdpflsD] -uid N\n\ -- -used N -user NAME -xtype [bcdpfls]\n")); -+ -used N -user NAME -xtype [bcdpfls]")); -+#ifdef WITH_SELINUX - puts (_("\ -+ -context CONTEXT\n")); -+#endif -+ puts (_("\n\ - actions: -delete -print0 -printf FORMAT -fprintf FILE FORMAT -print \n\ - -fprint0 FILE -fprint FILE -ls -fls FILE -prune -quit\n\ - -exec COMMAND ; -exec COMMAND {} + -ok COMMAND ;\n\ -@@ -2518,6 +2624,10 @@ parse_version (const struct parser_table - printf("LEAF_OPTIMISATION "); - ++features; - #endif -+#if defined(WITH_SELINUX) -+ printf("SELINUX "); -+ ++features; -+#endif - - flags = 0; - if (is_fts_enabled(&flags)) -@@ -2552,6 +2662,32 @@ parse_version (const struct parser_table - exit (0); - } - -+#ifdef WITH_SELINUX -+static boolean -+parse_context (const struct parser_table* entry, char **argv, int *arg_ptr) -+{ -+ struct predicate *our_pred; -+ -+ if ((argv == NULL) || (argv[*arg_ptr] == NULL)) -+ return false; -+ -+ if (is_selinux_enabled() <= 0) -+ { -+ error (1, 0, _("invalid predicate -context: SELinux is not enabled.")); -+ return false; -+ } -+ our_pred = insert_primary (entry); -+ our_pred->need_stat = false; -+#ifdef DEBUG -+ our_pred->p_name = find_pred_name (pred_context); -+#endif /*DEBUG*/ -+ our_pred->args.scontext = argv[*arg_ptr]; -+ -+ (*arg_ptr)++; -+ return true; -+} -+#endif /* WITH_SELINUX */ -+ - static boolean - parse_xdev (const struct parser_table* entry, char **argv, int *arg_ptr) - { -@@ -2803,7 +2939,7 @@ insert_fprintf (struct format_val *vec, - if (*scan2 == '.') - for (scan2++; ISDIGIT (*scan2); scan2++) - /* Do nothing. */ ; -- if (strchr ("abcdDfFgGhHiklmMnpPsStuUyY", *scan2)) -+ if (strchr ("abcdDfFgGhHiklmMnpPsStuUyYZ", *scan2)) - { - segmentp = make_segment (segmentp, format, scan2 - format, - KIND_FORMAT, *scan2, 0, -@@ -2930,6 +3066,7 @@ make_segment (struct segment **segment, - case 'h': /* leading directories part of path */ - case 'p': /* pathname */ - case 'P': /* pathname with ARGV element stripped */ -+ case 'Z': /* SELinux security context */ - *fmt++ = 's'; - break; - -diff -up findutils-4.4.2/find/pred.c_old findutils-4.4.2/find/pred.c ---- findutils-4.4.2/find/pred.c_old 2009-07-01 10:31:11.000000000 +0200 -+++ findutils-4.4.2/find/pred.c 2009-07-01 10:33:45.000000000 +0200 -@@ -48,6 +48,10 @@ - #include "error.h" - #include "verify.h" - -+#ifdef WITH_SELINUX -+#include -+#endif /*WITH_SELINUX*/ -+ - #if ENABLE_NLS - # include - # define _(Text) gettext (Text) -@@ -230,6 +234,9 @@ struct pred_assoc pred_table[] = - {pred_user, "user "}, - {pred_writable, "writable "}, - {pred_xtype, "xtype "}, -+#ifdef WITH_SELINUX -+ {pred_context, "context"}, -+#endif /*WITH_SELINUX*/ - {0, "none "} - }; - #endif -@@ -1054,6 +1061,27 @@ do_fprintf(struct format_val *dest, - mode_to_filetype(stat_buf->st_mode & S_IFMT)); - } - break; -+ case 'Z': /* SELinux security context */ -+#ifdef WITH_SELINUX -+ { -+ security_context_t scontext; -+ int rv; -+ rv = (*options.x_getfilecon) (state.rel_pathname, &scontext); -+ -+ if (rv < 0) -+ { -+ fprintf (stderr, "getfilecon(%s): %s", pathname, -+ strerror(errno)); -+ fflush (stderr); -+ } -+ else -+ { -+ checked_fprintf (dest, segment->text, scontext); -+ freecon (scontext); -+ } -+ } -+#endif /* WITH_SELINUX */ -+ break; - } - /* end of KIND_FORMAT case */ - break; -@@ -1844,6 +1872,32 @@ pred_xtype (const char *pathname, struct - */ - return (pred_type (pathname, &sbuf, pred_ptr)); - } -+ -+#ifdef WITH_SELINUX -+ -+boolean -+pred_context (const char *pathname, struct stat *stat_buf, -+ struct predicate *pred_ptr) -+{ -+ int rv; -+ security_context_t scontext; -+ -+ rv = (*options.x_getfilecon) (state.rel_pathname, &scontext); -+ -+ if (rv < 0) -+ { -+ fprintf (stderr, "getfilecon(%s): %s\n", pathname, strerror(errno)); -+ fflush (stderr); -+ return false; -+ } -+ -+ rv = (fnmatch (pred_ptr->args.scontext, scontext, 0) == 0); -+ freecon (scontext); -+ return rv; -+} -+ -+#endif /*WITH_SELINUX*/ -+ - - /* 1) fork to get a child; parent remembers the child pid - 2) child execs the command requested -diff -up findutils-4.4.2/find/tree.c_old findutils-4.4.2/find/tree.c ---- findutils-4.4.2/find/tree.c_old 2009-07-01 10:33:57.000000000 +0200 -+++ findutils-4.4.2/find/tree.c 2009-07-01 10:34:54.000000000 +0200 -@@ -953,7 +953,8 @@ static struct pred_cost_lookup costlooku - { pred_used , NeedsStatInfo }, - { pred_user , NeedsStatInfo }, - { pred_writable , NeedsAccessInfo }, -- { pred_xtype , NeedsType } /* roughly correct unless most files are symlinks */ -+ { pred_xtype , NeedsType }, /* roughly correct unless most files are symlinks */ -+ { pred_context , NeedsNothing } /* remove warning only:) */ - }; - static int pred_table_sorted = 0; - -@@ -1434,6 +1435,9 @@ get_new_pred (const struct parser_table - last_pred->need_stat = true; - last_pred->need_type = true; - last_pred->args.str = NULL; -+#ifdef WITH_SELINUX -+ last_pred->args.scontext = NULL; -+#endif - last_pred->pred_next = NULL; - last_pred->pred_left = NULL; - last_pred->pred_right = NULL; diff --git a/findutils-4.4.2-fts-remount.patch b/findutils-4.4.2-fts-remount.patch index 858177b..eb32922 100644 --- a/findutils-4.4.2-fts-remount.patch +++ b/findutils-4.4.2-fts-remount.patch @@ -1,3 +1,5 @@ +This patch is already applied on gnulib upstream git. + diff --git a/gnulib/lib/fts.c b/gnulib/lib/fts.c index ceb8935..2f1eda4 100644 --- a/gnulib/lib/fts.c diff --git a/findutils-4.4.2-selinux-gnulib.patch b/findutils-4.4.2-selinux-gnulib.patch new file mode 100644 index 0000000..11a8f0d --- /dev/null +++ b/findutils-4.4.2-selinux-gnulib.patch @@ -0,0 +1,1143 @@ +Once the selinux-at module appears on the list within import-gnulib.config this +patch is no longer needed. + +diff --git a/aclocal.m4 b/aclocal.m4 +index 1f97dda..61ad660 100644 +--- a/aclocal.m4 ++++ b/aclocal.m4 +@@ -1039,6 +1039,8 @@ m4_include([gnulib/m4/rpmatch.m4]) + m4_include([gnulib/m4/same.m4]) + m4_include([gnulib/m4/save-cwd.m4]) + m4_include([gnulib/m4/savedir.m4]) ++m4_include([gnulib/m4/selinux-context-h.m4]) ++m4_include([gnulib/m4/selinux-selinux-h.m4]) + m4_include([gnulib/m4/setenv.m4]) + m4_include([gnulib/m4/ssize_t.m4]) + m4_include([gnulib/m4/st_dm_mode.m4]) +diff --git a/gnulib/lib/Makefile.am b/gnulib/lib/Makefile.am +index 59ed5f2..b13e509 100644 +--- a/gnulib/lib/Makefile.am ++++ b/gnulib/lib/Makefile.am +@@ -1007,6 +1007,49 @@ EXTRA_libgnulib_a_SOURCES += savedir.c + + ## end gnulib module savedir + ++## begin gnulib module selinux-at ++ ++ ++EXTRA_DIST += selinux-at.c selinux-at.h ++ ++EXTRA_libgnulib_a_SOURCES += selinux-at.c ++ ++## end gnulib module selinux-at ++ ++## begin gnulib module selinux-h ++ ++libgnulib_a_SOURCES += se-context.in.h se-selinux.in.h ++ ++BUILT_SOURCES += selinux/selinux.h ++selinux/selinux.h: se-selinux.in.h ++ $(AM_V_at)$(MKDIR_P) selinux ++ $(AM_V_GEN)rm -f $@-t $@ && \ ++ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ ++ sed -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ ++ -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ ++ -e 's|@''NEXT_SELINUX_SELINUX_H''@|$(NEXT_SELINUX_SELINUX_H)|g' \ ++ < $(srcdir)/se-selinux.in.h; \ ++ } > $@-t && \ ++ chmod a-x $@-t && \ ++ mv $@-t $@ ++MOSTLYCLEANFILES += selinux/selinux.h selinux/selinux.h-t ++ ++BUILT_SOURCES += $(SELINUX_CONTEXT_H) ++selinux/context.h: se-context.in.h ++ $(AM_V_at)$(MKDIR_P) selinux ++ $(AM_V_GEN)rm -f $@-t $@ && \ ++ cp $(srcdir)/se-context.in.h $@-t && \ ++ chmod a-x $@-t && \ ++ mv $@-t $@ ++MOSTLYCLEANFILES += selinux/context.h selinux/context.h-t ++MOSTLYCLEANDIRS += selinux ++ ++EXTRA_DIST += getfilecon.c ++ ++EXTRA_libgnulib_a_SOURCES += getfilecon.c ++ ++## end gnulib module selinux-h ++ + ## begin gnulib module setenv + + +diff --git a/gnulib/lib/at-func.c b/gnulib/lib/at-func.c +index c7963fe..73be401 100644 +--- a/gnulib/lib/at-func.c ++++ b/gnulib/lib/at-func.c +@@ -1,5 +1,5 @@ + /* Define an at-style functions like fstatat, unlinkat, fchownat, etc. +- Copyright (C) 2006 Free Software Foundation, Inc. ++ Copyright (C) 2006, 2009 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by +@@ -16,62 +16,106 @@ + + /* written by Jim Meyering */ + +-#define CALL_FUNC(F) \ +- (AT_FUNC_USE_F1_COND \ ++#include "dirname.h" /* solely for definition of IS_ABSOLUTE_FILE_NAME */ ++#include "openat.h" ++#include "openat-priv.h" ++#include "save-cwd.h" ++ ++#ifdef AT_FUNC_USE_F1_COND ++# define CALL_FUNC(F) \ ++ (flag == AT_FUNC_USE_F1_COND \ + ? AT_FUNC_F1 (F AT_FUNC_POST_FILE_ARGS) \ + : AT_FUNC_F2 (F AT_FUNC_POST_FILE_ARGS)) ++# define VALIDATE_FLAG(F) \ ++ if (flag & ~AT_FUNC_USE_F1_COND) \ ++ { \ ++ errno = EINVAL; \ ++ return FUNC_FAIL; \ ++ } ++#else ++# define CALL_FUNC(F) (AT_FUNC_F1 (F AT_FUNC_POST_FILE_ARGS)) ++# define VALIDATE_FLAG(F) /* empty */ ++#endif ++ ++#ifdef AT_FUNC_RESULT ++# define FUNC_RESULT AT_FUNC_RESULT ++#else ++# define FUNC_RESULT int ++#endif ++ ++#ifdef AT_FUNC_FAIL ++# define FUNC_FAIL AT_FUNC_FAIL ++#else ++# define FUNC_FAIL -1 ++#endif + +-/* Call AT_FUNC_F1 or AT_FUNC_F2 (testing AT_FUNC_USE_F1_COND to +- determine which) to operate on FILE, which is in the directory +- open on descriptor FD. If possible, do it without changing the ++/* Call AT_FUNC_F1 to operate on FILE, which is in the directory ++ open on descriptor FD. If AT_FUNC_USE_F1_COND is defined to a value, ++ AT_FUNC_POST_FILE_PARAM_DECLS must inlude a parameter named flag; ++ call AT_FUNC_F2 if FLAG is 0 or fail if FLAG contains more bits than ++ AT_FUNC_USE_F1_COND. Return int and fail with -1 unless AT_FUNC_RESULT ++ or AT_FUNC_FAIL are defined. If possible, do it without changing the + working directory. Otherwise, resort to using save_cwd/fchdir, + then AT_FUNC_F?/restore_cwd. If either the save_cwd or the restore_cwd + fails, then give a diagnostic and exit nonzero. */ +-int ++FUNC_RESULT + AT_FUNC_NAME (int fd, char const *file AT_FUNC_POST_FILE_PARAM_DECLS) + { ++ /* Be careful to choose names unlikely to conflict with ++ AT_FUNC_POST_FILE_PARAM_DECLS. */ + struct saved_cwd saved_cwd; + int saved_errno; +- int err; ++ FUNC_RESULT err; ++ ++ VALIDATE_FLAG (flag); + + if (fd == AT_FDCWD || IS_ABSOLUTE_FILE_NAME (file)) + return CALL_FUNC (file); + + { +- char buf[OPENAT_BUFFER_SIZE]; +- char *proc_file = openat_proc_name (buf, fd, file); ++ char proc_buf[OPENAT_BUFFER_SIZE]; ++ char *proc_file = openat_proc_name (proc_buf, fd, file); + if (proc_file) + { +- int proc_result = CALL_FUNC (proc_file); +- int proc_errno = errno; +- if (proc_file != buf) +- free (proc_file); +- /* If the syscall succeeds, or if it fails with an unexpected +- errno value, then return right away. Otherwise, fall through +- and resort to using save_cwd/restore_cwd. */ +- if (0 <= proc_result) +- return proc_result; +- if (! EXPECTED_ERRNO (proc_errno)) +- { +- errno = proc_errno; +- return proc_result; +- } ++ FUNC_RESULT proc_result = CALL_FUNC (proc_file); ++ int proc_errno = errno; ++ if (proc_file != proc_buf) ++ free (proc_file); ++ /* If the syscall succeeds, or if it fails with an unexpected ++ errno value, then return right away. Otherwise, fall through ++ and resort to using save_cwd/restore_cwd. */ ++ if (FUNC_FAIL != proc_result) ++ return proc_result; ++ if (! EXPECTED_ERRNO (proc_errno)) ++ { ++ errno = proc_errno; ++ return proc_result; ++ } + } + } + + if (save_cwd (&saved_cwd) != 0) + openat_save_fail (errno); ++ if (0 <= fd && fd == saved_cwd.desc) ++ { ++ /* If saving the working directory collides with the user's ++ requested fd, then the user's fd must have been closed to ++ begin with. */ ++ free_cwd (&saved_cwd); ++ errno = EBADF; ++ return FUNC_FAIL; ++ } + + if (fchdir (fd) != 0) + { + saved_errno = errno; + free_cwd (&saved_cwd); + errno = saved_errno; +- return -1; ++ return FUNC_FAIL; + } + + err = CALL_FUNC (file); +- saved_errno = (err < 0 ? errno : 0); ++ saved_errno = (err == FUNC_FAIL ? errno : 0); + + if (restore_cwd (&saved_cwd) != 0) + openat_restore_fail (errno); +@@ -83,3 +127,5 @@ AT_FUNC_NAME (int fd, char const *file AT_FUNC_POST_FILE_PARAM_DECLS) + return err; + } + #undef CALL_FUNC ++#undef FUNC_RESULT ++#undef FUNC_FAIL +diff --git a/gnulib/lib/getfilecon.c b/gnulib/lib/getfilecon.c +new file mode 100644 +index 0000000..d712307 +--- /dev/null ++++ b/gnulib/lib/getfilecon.c +@@ -0,0 +1,87 @@ ++/* wrap getfilecon, lgetfilecon, and fgetfilecon ++ Copyright (C) 2009 Free Software Foundation, Inc. ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 3, 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 General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, write to the Free Software Foundation, ++ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ ++ ++/* written by Jim Meyering */ ++ ++#include ++ ++#include ++ ++#include ++#include ++#include ++ ++/* FIXME: remove this once there is an errno-gnu module ++ that guarantees the definition of ENODATA. */ ++#ifndef ENODATA ++# define ENODATA ENOTSUP ++#endif ++ ++#undef getfilecon ++#undef lgetfilecon ++#undef fgetfilecon ++int getfilecon (char const *file, security_context_t *con); ++int lgetfilecon (char const *file, security_context_t *con); ++int fgetfilecon (int fd, security_context_t *con); ++ ++/* getfilecon, lgetfilecon, and fgetfilecon can all misbehave, be it ++ via an old version of libselinux where these would return 0 and set the ++ result context to NULL, or via a modern kernel+lib operating on a file ++ from a disk whose attributes were set by a kernel from around 2006. ++ In that latter case, the functions return a length of 10 for the ++ "unlabeled" context. Map both failures to a return value of -1, and ++ set errno to ENOTSUP in the first case, and ENODATA in the latter. */ ++ ++static inline int ++map_to_failure (int ret, security_context_t *con) ++{ ++ if (ret == 0) ++ { ++ errno = ENOTSUP; ++ return -1; ++ } ++ ++ if (ret == 10 && strcmp (*con, "unlabeled") == 0) ++ { ++ freecon (*con); ++ errno = ENODATA; ++ return -1; ++ } ++ ++ return ret; ++} ++ ++int ++rpl_getfilecon (char const *file, security_context_t *con) ++{ ++ int ret = getfilecon (file, con); ++ return map_to_failure (ret, con); ++} ++ ++int ++rpl_lgetfilecon (char const *file, security_context_t *con) ++{ ++ int ret = lgetfilecon (file, con); ++ return map_to_failure (ret, con); ++} ++ ++int ++rpl_fgetfilecon (int fd, security_context_t *con) ++{ ++ int ret = fgetfilecon (fd, con); ++ return map_to_failure (ret, con); ++} +diff --git a/gnulib/lib/openat.c b/gnulib/lib/openat.c +index 73f24b0..2b15bb5 100644 +--- a/gnulib/lib/openat.c ++++ b/gnulib/lib/openat.c +@@ -1,5 +1,5 @@ + /* provide a replacement openat function +- Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation, Inc. ++ Copyright (C) 2004-2009 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by +@@ -22,13 +22,108 @@ + + #include + #include ++#include ++#include + + #include "dirname.h" /* solely for definition of IS_ABSOLUTE_FILE_NAME */ +-#include "fcntl--.h" +-#include "lstat.h" + #include "openat-priv.h" + #include "save-cwd.h" + ++#if HAVE_OPENAT ++ ++# undef openat ++ ++/* Like openat, but work around Solaris 9 bugs with trailing slash. */ ++int ++rpl_openat (int dfd, char const *filename, int flags, ...) ++{ ++ mode_t mode; ++ int fd; ++ ++ mode = 0; ++ if (flags & O_CREAT) ++ { ++ va_list arg; ++ va_start (arg, flags); ++ ++ /* We have to use PROMOTED_MODE_T instead of mode_t, otherwise GCC 4 ++ creates crashing code when 'mode_t' is smaller than 'int'. */ ++ mode = va_arg (arg, PROMOTED_MODE_T); ++ ++ va_end (arg); ++ } ++ ++#if OPEN_TRAILING_SLASH_BUG ++ /* If the filename ends in a slash and one of O_CREAT, O_WRONLY, O_RDWR ++ is specified, then fail. ++ Rationale: POSIX ++ says that ++ "A pathname that contains at least one non-slash character and that ++ ends with one or more trailing slashes shall be resolved as if a ++ single dot character ( '.' ) were appended to the pathname." ++ and ++ "The special filename dot shall refer to the directory specified by ++ its predecessor." ++ If the named file already exists as a directory, then ++ - if O_CREAT is specified, open() must fail because of the semantics ++ of O_CREAT, ++ - if O_WRONLY or O_RDWR is specified, open() must fail because POSIX ++ says that it ++ fails with errno = EISDIR in this case. ++ If the named file does not exist or does not name a directory, then ++ - if O_CREAT is specified, open() must fail since open() cannot create ++ directories, ++ - if O_WRONLY or O_RDWR is specified, open() must fail because the ++ file does not contain a '.' directory. */ ++ if (flags & (O_CREAT | O_WRONLY | O_RDWR)) ++ { ++ size_t len = strlen (filename); ++ if (len > 0 && filename[len - 1] == '/') ++ { ++ errno = EISDIR; ++ return -1; ++ } ++ } ++#endif ++ ++ fd = openat (dfd, filename, flags, mode); ++ ++#if OPEN_TRAILING_SLASH_BUG ++ /* If the filename ends in a slash and fd does not refer to a directory, ++ then fail. ++ Rationale: POSIX ++ says that ++ "A pathname that contains at least one non-slash character and that ++ ends with one or more trailing slashes shall be resolved as if a ++ single dot character ( '.' ) were appended to the pathname." ++ and ++ "The special filename dot shall refer to the directory specified by ++ its predecessor." ++ If the named file without the slash is not a directory, open() must fail ++ with ENOTDIR. */ ++ if (fd >= 0) ++ { ++ /* We know len is positive, since open did not fail with ENOENT. */ ++ size_t len = strlen (filename); ++ if (filename[len - 1] == '/') ++ { ++ struct stat statbuf; ++ ++ if (fstat (fd, &statbuf) >= 0 && !S_ISDIR (statbuf.st_mode)) ++ { ++ close (fd); ++ errno = ENOTDIR; ++ return -1; ++ } ++ } ++ } ++#endif ++ ++ return fd; ++} ++ ++#else /* !HAVE_OPENAT */ ++ + /* Replacement for Solaris' openat function. + + First, try to simulate it via open ("/proc/self/fd/FD/FILE"). +@@ -47,12 +142,9 @@ openat (int fd, char const *file, int flags, ...) + va_list arg; + va_start (arg, flags); + +- /* If mode_t is narrower than int, use the promoted type (int), +- not mode_t. Use sizeof to guess whether mode_t is narrower; +- we don't know of any practical counterexamples. */ +- mode = (sizeof (mode_t) < sizeof (int) +- ? va_arg (arg, int) +- : va_arg (arg, mode_t)); ++ /* We have to use PROMOTED_MODE_T instead of mode_t, otherwise GCC 4 ++ creates crashing code when 'mode_t' is smaller than 'int'. */ ++ mode = va_arg (arg, PROMOTED_MODE_T); + + va_end (arg); + } +@@ -73,7 +165,7 @@ openat (int fd, char const *file, int flags, ...) + + int + openat_permissive (int fd, char const *file, int flags, mode_t mode, +- int *cwd_errno) ++ int *cwd_errno) + { + struct saved_cwd saved_cwd; + int saved_errno; +@@ -88,18 +180,18 @@ openat_permissive (int fd, char const *file, int flags, mode_t mode, + char *proc_file = openat_proc_name (buf, fd, file); + if (proc_file) + { +- int open_result = open (proc_file, flags, mode); +- int open_errno = errno; +- if (proc_file != buf) +- free (proc_file); +- /* If the syscall succeeds, or if it fails with an unexpected +- errno value, then return right away. Otherwise, fall through +- and resort to using save_cwd/restore_cwd. */ +- if (0 <= open_result || ! EXPECTED_ERRNO (open_errno)) +- { +- errno = open_errno; +- return open_result; +- } ++ int open_result = open (proc_file, flags, mode); ++ int open_errno = errno; ++ if (proc_file != buf) ++ free (proc_file); ++ /* If the syscall succeeds, or if it fails with an unexpected ++ errno value, then return right away. Otherwise, fall through ++ and resort to using save_cwd/restore_cwd. */ ++ if (0 <= open_result || ! EXPECTED_ERRNO (open_errno)) ++ { ++ errno = open_errno; ++ return open_result; ++ } + } + } + +@@ -107,9 +199,18 @@ openat_permissive (int fd, char const *file, int flags, mode_t mode, + if (! save_ok) + { + if (! cwd_errno) +- openat_save_fail (errno); ++ openat_save_fail (errno); + *cwd_errno = errno; + } ++ if (0 <= fd && fd == saved_cwd.desc) ++ { ++ /* If saving the working directory collides with the user's ++ requested fd, then the user's fd must have been closed to ++ begin with. */ ++ free_cwd (&saved_cwd); ++ errno = EBADF; ++ return -1; ++ } + + err = fchdir (fd); + saved_errno = errno; +@@ -119,11 +220,17 @@ openat_permissive (int fd, char const *file, int flags, mode_t mode, + err = open (file, flags, mode); + saved_errno = errno; + if (save_ok && restore_cwd (&saved_cwd) != 0) +- { +- if (! cwd_errno) +- openat_restore_fail (errno); +- *cwd_errno = errno; +- } ++ { ++ if (! cwd_errno) ++ { ++ /* Don't write a message to just-created fd 2. */ ++ saved_errno = errno; ++ if (err == STDERR_FILENO) ++ close (err); ++ openat_restore_fail (saved_errno); ++ } ++ *cwd_errno = errno; ++ } + } + + free_cwd (&saved_cwd); +@@ -144,125 +251,15 @@ openat_needs_fchdir (void) + char buf[OPENAT_BUFFER_SIZE]; + char *proc_file = openat_proc_name (buf, fd, "."); + if (proc_file) +- { +- needs_fchdir = false; +- if (proc_file != buf) +- free (proc_file); +- } ++ { ++ needs_fchdir = false; ++ if (proc_file != buf) ++ free (proc_file); ++ } + close (fd); + } + + return needs_fchdir; + } + +-#if !HAVE_FDOPENDIR +- +-/* Replacement for Solaris' function by the same name. +- +- First, try to simulate it via opendir ("/proc/self/fd/FD"). Failing +- that, simulate it by doing save_cwd/fchdir/opendir(".")/restore_cwd. +- If either the save_cwd or the restore_cwd fails (relatively unlikely), +- then give a diagnostic and exit nonzero. +- Otherwise, this function works just like Solaris' fdopendir. +- +- W A R N I N G: +- Unlike the other fd-related functions here, this one +- effectively consumes its FD parameter. The caller should not +- close or otherwise manipulate FD if this function returns successfully. */ +-DIR * +-fdopendir (int fd) +-{ +- struct saved_cwd saved_cwd; +- int saved_errno; +- DIR *dir; +- +- char buf[OPENAT_BUFFER_SIZE]; +- char *proc_file = openat_proc_name (buf, fd, "."); +- if (proc_file) +- { +- dir = opendir (proc_file); +- saved_errno = errno; +- } +- else +- { +- dir = NULL; +- saved_errno = EOPNOTSUPP; +- } +- +- /* If the syscall fails with an expected errno value, resort to +- save_cwd/restore_cwd. */ +- if (! dir && EXPECTED_ERRNO (saved_errno)) +- { +- if (save_cwd (&saved_cwd) != 0) +- openat_save_fail (errno); +- +- if (fchdir (fd) != 0) +- { +- dir = NULL; +- saved_errno = errno; +- } +- else +- { +- dir = opendir ("."); +- saved_errno = errno; +- +- if (restore_cwd (&saved_cwd) != 0) +- openat_restore_fail (errno); +- } +- +- free_cwd (&saved_cwd); +- } +- +- if (dir) +- close (fd); +- if (proc_file != buf) +- free (proc_file); +- errno = saved_errno; +- return dir; +-} +- +-#endif +- +-/* Replacement for Solaris' function by the same name. +- +- First, try to simulate it via l?stat ("/proc/self/fd/FD/FILE"). +- Failing that, simulate it via save_cwd/fchdir/(stat|lstat)/restore_cwd. +- If either the save_cwd or the restore_cwd fails (relatively unlikely), +- then give a diagnostic and exit nonzero. +- Otherwise, this function works just like Solaris' fstatat. */ +- +-#define AT_FUNC_NAME fstatat +-#define AT_FUNC_F1 lstat +-#define AT_FUNC_F2 stat +-#define AT_FUNC_USE_F1_COND flag == AT_SYMLINK_NOFOLLOW +-#define AT_FUNC_POST_FILE_PARAM_DECLS , struct stat *st, int flag +-#define AT_FUNC_POST_FILE_ARGS , st +-#include "at-func.c" +-#undef AT_FUNC_NAME +-#undef AT_FUNC_F1 +-#undef AT_FUNC_F2 +-#undef AT_FUNC_USE_F1_COND +-#undef AT_FUNC_POST_FILE_PARAM_DECLS +-#undef AT_FUNC_POST_FILE_ARGS +- +-/* Replacement for Solaris' function by the same name. +- +- First, try to simulate it via (unlink|rmdir) ("/proc/self/fd/FD/FILE"). +- Failing that, simulate it via save_cwd/fchdir/(unlink|rmdir)/restore_cwd. +- If either the save_cwd or the restore_cwd fails (relatively unlikely), +- then give a diagnostic and exit nonzero. +- Otherwise, this function works just like Solaris' unlinkat. */ +- +-#define AT_FUNC_NAME unlinkat +-#define AT_FUNC_F1 rmdir +-#define AT_FUNC_F2 unlink +-#define AT_FUNC_USE_F1_COND flag == AT_REMOVEDIR +-#define AT_FUNC_POST_FILE_PARAM_DECLS , int flag +-#define AT_FUNC_POST_FILE_ARGS /* empty */ +-#include "at-func.c" +-#undef AT_FUNC_NAME +-#undef AT_FUNC_F1 +-#undef AT_FUNC_F2 +-#undef AT_FUNC_USE_F1_COND +-#undef AT_FUNC_POST_FILE_PARAM_DECLS +-#undef AT_FUNC_POST_FILE_ARGS ++#endif /* !HAVE_OPENAT */ +diff --git a/gnulib/lib/openat.h b/gnulib/lib/openat.h +index b5e4f11..433b998 100644 +--- a/gnulib/lib/openat.h ++++ b/gnulib/lib/openat.h +@@ -1,5 +1,5 @@ + /* provide a replacement openat function +- Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc. ++ Copyright (C) 2004-2006, 2008-2009 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by +@@ -16,6 +16,9 @@ + + /* written by Jim Meyering */ + ++#ifndef _GL_HEADER_OPENAT ++#define _GL_HEADER_OPENAT ++ + #include + + #include +@@ -25,7 +28,7 @@ + #include + + #ifndef __attribute__ +-# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8) || __STRICT_ANSI__ ++# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8) + # define __attribute__(x) /* empty */ + # endif + #endif +@@ -34,46 +37,10 @@ + # define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__)) + #endif + +-/* Work around a bug in Solaris 9 and 10: AT_FDCWD is positive. Its +- value exceeds INT_MAX, so its use as an int doesn't conform to the +- C standard, and GCC and Sun C complain in some cases. If the bug +- is present, undef AT_FDCWD here, so it can be redefined below. */ +-#if 0 < AT_FDCWD && AT_FDCWD == 0xffd19553 +-# undef AT_FDCWD +-#endif +- +-/* Use the same bit pattern as Solaris 9, but with the proper +- signedness. The bit pattern is important, in case this actually is +- Solaris with the above workaround. */ +-#ifndef AT_FDCWD +-# define AT_FDCWD (-3041965) +-#endif +- +-/* Use the same values as Solaris 9. This shouldn't matter, but +- there's no real reason to differ. */ +-#ifndef AT_SYMLINK_NOFOLLOW +-# define AT_SYMLINK_NOFOLLOW 4096 +-# define AT_REMOVEDIR 1 +-#endif +- +-#ifdef __OPENAT_PREFIX ++#if !HAVE_OPENAT + +-# undef openat +-# define __OPENAT_CONCAT(x, y) x ## y +-# define __OPENAT_XCONCAT(x, y) __OPENAT_CONCAT (x, y) +-# define __OPENAT_ID(y) __OPENAT_XCONCAT (__OPENAT_PREFIX, y) +-# define openat __OPENAT_ID (openat) +-int openat (int fd, char const *file, int flags, /* mode_t mode */ ...); + int openat_permissive (int fd, char const *file, int flags, mode_t mode, + int *cwd_errno); +-# if ! HAVE_FDOPENDIR +-# define fdopendir __OPENAT_ID (fdopendir) +-# endif +-DIR *fdopendir (int fd); +-# define fstatat __OPENAT_ID (fstatat) +-int fstatat (int fd, char const *file, struct stat *st, int flag); +-# define unlinkat __OPENAT_ID (unlinkat) +-int unlinkat (int fd, char const *file, int flag); + bool openat_needs_fchdir (void); + + #else +@@ -84,19 +51,8 @@ bool openat_needs_fchdir (void); + + #endif + +-#if HAVE_OPENAT && ! LSTAT_FOLLOWS_SLASHED_SYMLINK +-int rpl_fstatat (int fd, char const *file, struct stat *st, int flag); +-# if !COMPILING_FSTATAT +-# undef fstatat +-# define fstatat rpl_fstatat +-# endif +-#endif +- +-int mkdirat (int fd, char const *file, mode_t mode); + void openat_restore_fail (int) ATTRIBUTE_NORETURN; + void openat_save_fail (int) ATTRIBUTE_NORETURN; +-int fchmodat (int fd, char const *file, mode_t mode, int flag); +-int fchownat (int fd, char const *file, uid_t owner, gid_t group, int flag); + + /* Using these function names makes application code + slightly more readable than it would be with +@@ -124,3 +80,35 @@ lchmodat (int fd, char const *file, mode_t mode) + { + return fchmodat (fd, file, mode, AT_SYMLINK_NOFOLLOW); + } ++ ++static inline int ++statat (int fd, char const *name, struct stat *st) ++{ ++ return fstatat (fd, name, st, 0); ++} ++ ++static inline int ++lstatat (int fd, char const *name, struct stat *st) ++{ ++ return fstatat (fd, name, st, AT_SYMLINK_NOFOLLOW); ++} ++ ++#if GNULIB_FACCESSAT ++/* For now, there are no wrappers named laccessat or leuidaccessat, ++ since gnulib doesn't support faccessat(,AT_SYMLINK_NOFOLLOW) and ++ since access rights on symlinks are of limited utility. */ ++ ++static inline int ++accessat (int fd, char const *file, int mode) ++{ ++ return faccessat (fd, file, mode, 0); ++} ++ ++static inline int ++euidaccessat (int fd, char const *file, int mode) ++{ ++ return faccessat (fd, file, mode, AT_EACCESS); ++} ++#endif ++ ++#endif /* _GL_HEADER_OPENAT */ +diff --git a/gnulib/lib/se-selinux.in.h b/gnulib/lib/se-selinux.in.h +new file mode 100644 +index 0000000..3f30a3c +--- /dev/null ++++ b/gnulib/lib/se-selinux.in.h +@@ -0,0 +1,73 @@ ++#ifndef _GL_SELINUX_SELINUX_H ++# define _GL_SELINUX_SELINUX_H ++ ++# if __GNUC__ >= 3 ++#pragma GCC system_header ++# endif ++ ++# if HAVE_SELINUX_SELINUX_H ++ ++#@INCLUDE_NEXT@ @NEXT_SELINUX_SELINUX_H@ ++ ++# else ++ ++# include ++# include ++ ++typedef unsigned short security_class_t; ++# define security_context_t char* ++# define is_selinux_enabled() 0 ++ ++static inline int getcon (security_context_t *con _UNUSED_PARAMETER_) ++ { errno = ENOTSUP; return -1; } ++static inline void freecon (security_context_t con _UNUSED_PARAMETER_) {} ++ ++ ++static inline int getfscreatecon (security_context_t *con _UNUSED_PARAMETER_) ++ { errno = ENOTSUP; return -1; } ++static inline int setfscreatecon (security_context_t con _UNUSED_PARAMETER_) ++ { errno = ENOTSUP; return -1; } ++static inline int matchpathcon (char const *file _UNUSED_PARAMETER_, ++ mode_t m _UNUSED_PARAMETER_, ++ security_context_t *con _UNUSED_PARAMETER_) ++ { errno = ENOTSUP; return -1; } ++static inline int getfilecon (char const *file _UNUSED_PARAMETER_, ++ security_context_t *con _UNUSED_PARAMETER_) ++ { errno = ENOTSUP; return -1; } ++static inline int lgetfilecon (char const *file _UNUSED_PARAMETER_, ++ security_context_t *con _UNUSED_PARAMETER_) ++ { errno = ENOTSUP; return -1; } ++static inline int fgetfilecon (int fd, ++ security_context_t *con _UNUSED_PARAMETER_) ++ { errno = ENOTSUP; return -1; } ++static inline int setfilecon (char const *file _UNUSED_PARAMETER_, ++ security_context_t con _UNUSED_PARAMETER_) ++ { errno = ENOTSUP; return -1; } ++static inline int lsetfilecon (char const *file _UNUSED_PARAMETER_, ++ security_context_t con _UNUSED_PARAMETER_) ++ { errno = ENOTSUP; return -1; } ++static inline int fsetfilecon (int fd _UNUSED_PARAMETER_, ++ security_context_t con _UNUSED_PARAMETER_) ++ { errno = ENOTSUP; return -1; } ++ ++static inline int security_check_context ++ (security_context_t con _UNUSED_PARAMETER_) ++ { errno = ENOTSUP; return -1; } ++static inline int security_check_context_raw ++ (security_context_t con _UNUSED_PARAMETER_) ++ { errno = ENOTSUP; return -1; } ++static inline int setexeccon (security_context_t con _UNUSED_PARAMETER_) ++ { errno = ENOTSUP; return -1; } ++static inline int security_compute_create ++ (security_context_t scon _UNUSED_PARAMETER_, ++ security_context_t tcon _UNUSED_PARAMETER_, ++ security_class_t tclass _UNUSED_PARAMETER_, ++ security_context_t *newcon _UNUSED_PARAMETER_) ++ { errno = ENOTSUP; return -1; } ++static inline int matchpathcon_init_prefix ++ (char const *path _UNUSED_PARAMETER_, ++ char const *prefix _UNUSED_PARAMETER_) ++ { errno = ENOTSUP; return -1; } ++ ++# endif ++#endif /* _GL_SELINUX_SELINUX_H */ +diff --git a/gnulib/lib/selinux-at.c b/gnulib/lib/selinux-at.c +new file mode 100644 +index 0000000..65f938b +--- /dev/null ++++ b/gnulib/lib/selinux-at.c +@@ -0,0 +1,72 @@ ++/* openat-style fd-relative functions for SE Linux ++ Copyright (C) 2007, 2009 Free Software Foundation, Inc. ++ ++ This program is free software: you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation, either version 3 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 General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program. If not, see . */ ++ ++/* written by Jim Meyering */ ++ ++#include ++ ++#include "selinux-at.h" ++#include "openat.h" ++ ++#include ++#include ++#include ++#include ++ ++#include "dirname.h" /* solely for definition of IS_ABSOLUTE_FILE_NAME */ ++#include "save-cwd.h" ++ ++#include "openat-priv.h" ++ ++#define AT_FUNC_NAME getfileconat ++#define AT_FUNC_F1 getfilecon ++#define AT_FUNC_POST_FILE_PARAM_DECLS , security_context_t *con ++#define AT_FUNC_POST_FILE_ARGS , con ++#include "at-func.c" ++#undef AT_FUNC_NAME ++#undef AT_FUNC_F1 ++#undef AT_FUNC_POST_FILE_PARAM_DECLS ++#undef AT_FUNC_POST_FILE_ARGS ++ ++#define AT_FUNC_NAME lgetfileconat ++#define AT_FUNC_F1 lgetfilecon ++#define AT_FUNC_POST_FILE_PARAM_DECLS , security_context_t *con ++#define AT_FUNC_POST_FILE_ARGS , con ++#include "at-func.c" ++#undef AT_FUNC_NAME ++#undef AT_FUNC_F1 ++#undef AT_FUNC_POST_FILE_PARAM_DECLS ++#undef AT_FUNC_POST_FILE_ARGS ++ ++#define AT_FUNC_NAME setfileconat ++#define AT_FUNC_F1 setfilecon ++#define AT_FUNC_POST_FILE_PARAM_DECLS , security_context_t con ++#define AT_FUNC_POST_FILE_ARGS , con ++#include "at-func.c" ++#undef AT_FUNC_NAME ++#undef AT_FUNC_F1 ++#undef AT_FUNC_POST_FILE_PARAM_DECLS ++#undef AT_FUNC_POST_FILE_ARGS ++ ++#define AT_FUNC_NAME lsetfileconat ++#define AT_FUNC_F1 lsetfilecon ++#define AT_FUNC_POST_FILE_PARAM_DECLS , security_context_t con ++#define AT_FUNC_POST_FILE_ARGS , con ++#include "at-func.c" ++#undef AT_FUNC_NAME ++#undef AT_FUNC_F1 ++#undef AT_FUNC_POST_FILE_PARAM_DECLS ++#undef AT_FUNC_POST_FILE_ARGS +diff --git a/gnulib/lib/selinux-at.h b/gnulib/lib/selinux-at.h +new file mode 100644 +index 0000000..1d84c19 +--- /dev/null ++++ b/gnulib/lib/selinux-at.h +@@ -0,0 +1,52 @@ ++/* Prototypes for openat-style fd-relative SELinux functions ++ Copyright (C) 2007, 2009 Free Software Foundation, Inc. ++ ++ This program is free software: you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation, either version 3 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 General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program. If not, see . */ ++ ++#include ++#include ++ ++/* These are the dir-fd-relative variants of the functions without the ++ "at" suffix. For example, getfileconat (AT_FDCWD, file, &c) is usually ++ equivalent to getfilecon (file, &c). The emulation is accomplished ++ by first attempting getfilecon ("/proc/self/fd/DIR_FD/FILE", &c). ++ Failing that, simulate it via save_cwd/fchdir/getfilecon/restore_cwd. ++ If either the save_cwd or the restore_cwd fails (relatively unlikely), ++ then give a diagnostic and exit nonzero. */ ++ ++/* dir-fd-relative getfilecon. Set *CON to the SELinux security context ++ of the file specified by DIR_FD and FILE and return the length of *CON. ++ DIR_FD and FILE are interpreted as for fstatat[*]. A non-NULL *CON ++ must be freed with freecon. Upon error, set *CON to NULL, set errno ++ and return -1. ++ [*] with flags=0 here, with flags=AT_SYMLINK_NOFOLLOW for lgetfileconat */ ++int getfileconat (int dir_fd, char const *file, security_context_t *con); ++ ++/* dir-fd-relative lgetfilecon. This function is just like getfileconat, ++ except when DIR_FD and FILE specify a symlink: lgetfileconat operates on ++ the symlink, while getfileconat operates on the referent of the symlink. */ ++int lgetfileconat (int dir_fd, char const *file, security_context_t *con); ++ ++/* dir-fd-relative setfilecon. Set the SELinux security context of ++ the file specified by DIR_FD and FILE to CON. DIR_FD and FILE are ++ interpreted as for fstatat[*]. Upon success, return 0. ++ Otherwise, return -1 and set errno. */ ++int setfileconat (int dir_fd, char const *file, security_context_t con); ++ ++/* dir-fd-relative lsetfilecon. This function is just like setfileconat, ++ except that rather than dereferencing a symlink, this function affects it. */ ++/* dir-fd-relative lsetfilecon. This function is just like setfileconat, ++ except when DIR_FD and FILE specify a symlink: lsetfileconat operates on ++ the symlink, while setfileconat operates on the referent of the symlink. */ ++int lsetfileconat (int dir_fd, char const *file, security_context_t con); +diff --git a/gnulib/m4/gnulib-comp.m4 b/gnulib/m4/gnulib-comp.m4 +index 1efe223..87f11dd 100644 +--- a/gnulib/m4/gnulib-comp.m4 ++++ b/gnulib/m4/gnulib-comp.m4 +@@ -165,6 +165,11 @@ AC_DEFUN([gl_INIT], + gl_SAME + gl_SAVE_CWD + gl_SAVEDIR ++ AC_CHECK_HEADERS([selinux/flask.h]) ++ AC_LIBOBJ([selinux-at]) ++ gl_HEADERS_SELINUX_SELINUX_H ++ gl_HEADERS_SELINUX_CONTEXT_H ++ AC_REQUIRE([AC_C_INLINE]) + gl_FUNC_SETENV + gl_FUNC_UNSETENV + gt_TYPE_SSIZE_T +@@ -425,6 +430,7 @@ AC_DEFUN([gl_FILE_LIST], [ + lib/getdate.h + lib/getdate.y + lib/getdelim.c ++ lib/getfilecon.c + lib/getline.c + lib/getopt.c + lib/getopt.in.h +@@ -506,6 +512,10 @@ AC_DEFUN([gl_FILE_LIST], [ + lib/save-cwd.h + lib/savedir.c + lib/savedir.h ++ lib/se-context.in.h ++ lib/se-selinux.in.h ++ lib/selinux-at.c ++ lib/selinux-at.h + lib/setenv.c + lib/setenv.h + lib/stat-macros.h +@@ -688,6 +698,8 @@ AC_DEFUN([gl_FILE_LIST], [ + m4/same.m4 + m4/save-cwd.m4 + m4/savedir.m4 ++ m4/selinux-context-h.m4 ++ m4/selinux-selinux-h.m4 + m4/setenv.m4 + m4/size_max.m4 + m4/ssize_t.m4 +diff --git a/gnulib/m4/selinux-context-h.m4 b/gnulib/m4/selinux-context-h.m4 +new file mode 100644 +index 0000000..6b0bed1 +--- /dev/null ++++ b/gnulib/m4/selinux-context-h.m4 +@@ -0,0 +1,16 @@ ++# serial 1 -*- Autoconf -*- ++# Copyright (C) 2006, 2007 Free Software Foundation, Inc. ++# This file is free software; the Free Software Foundation ++# gives unlimited permission to copy and/or distribute it, ++# with or without modifications, as long as this notice is preserved. ++ ++# From Jim Meyering ++# Provide , if necessary. ++ ++AC_DEFUN([gl_HEADERS_SELINUX_CONTEXT_H], ++[ ++ AC_CHECK_HEADERS([selinux/context.h], ++ [SELINUX_CONTEXT_H=], ++ [SELINUX_CONTEXT_H=selinux/context.h]) ++ AC_SUBST([SELINUX_CONTEXT_H]) ++]) +diff --git a/gnulib/m4/selinux-selinux-h.m4 b/gnulib/m4/selinux-selinux-h.m4 +new file mode 100644 +index 0000000..767c4f7 +--- /dev/null ++++ b/gnulib/m4/selinux-selinux-h.m4 +@@ -0,0 +1,57 @@ ++# serial 3 -*- Autoconf -*- ++# Copyright (C) 2006, 2007, 2009 Free Software Foundation, Inc. ++# This file is free software; the Free Software Foundation ++# gives unlimited permission to copy and/or distribute it, ++# with or without modifications, as long as this notice is preserved. ++ ++# From Jim Meyering ++# Provide , if necessary. ++# If it is already present, provide wrapper functions to guard against ++# misbehavior from getfilecon, lgetfilecon, and fgetfilecon. ++ ++AC_DEFUN([gl_HEADERS_SELINUX_SELINUX_H], ++[ ++ AC_REQUIRE([gl_LIBSELINUX]) ++ AC_CHECK_HEADERS([selinux/selinux.h]) ++ ++ if test "$ac_cv_header_selinux_selinux_h" = yes; then ++ # We do have , so do compile getfilecon.c ++ # and arrange to use its wrappers. ++ AC_LIBOBJ([getfilecon]) ++ gl_CHECK_NEXT_HEADERS([selinux/selinux.h]) ++ AC_DEFINE([getfilecon], [rpl_getfilecon], ++ [Always use our getfilecon wrapper.]) ++ AC_DEFINE([lgetfilecon], [rpl_lgetfilecon], ++ [Always use our lgetfilecon wrapper.]) ++ AC_DEFINE([fgetfilecon], [rpl_fgetfilecon], ++ [Always use our fgetfilecon wrapper.]) ++ fi ++ ++ case "$ac_cv_search_setfilecon:$ac_cv_header_selinux_selinux_h" in ++ no:*) # already warned ++ ;; ++ *:no) ++ AC_MSG_WARN([libselinux was found but selinux/selinux.h is missing.]) ++ AC_MSG_WARN([AC_PACKAGE_NAME will be compiled without SELinux support.]) ++ esac ++]) ++ ++AC_DEFUN([gl_LIBSELINUX], ++[ ++ AC_REQUIRE([AC_CANONICAL_HOST]) ++ AC_REQUIRE([AC_CANONICAL_BUILD]) ++ LIB_SELINUX= ++ gl_save_LIBS=$LIBS ++ AC_SEARCH_LIBS([setfilecon], [selinux], ++ [test "$ac_cv_search_setfilecon" = "none required" || ++ LIB_SELINUX=$ac_cv_search_setfilecon]) ++ AC_SUBST([LIB_SELINUX]) ++ LIBS=$gl_save_LIBS ++ ++ # Warn if SELinux is found but libselinux is absent; ++ if test "$ac_cv_search_setfilecon" = no && ++ test "$host" = "$build" && test -d /selinux; then ++ AC_MSG_WARN([This system supports SELinux but libselinux is missing.]) ++ AC_MSG_WARN([AC_PACKAGE_NAME will be compiled without SELinux support.]) ++ fi ++]) diff --git a/findutils-4.4.2-selinux.patch b/findutils-4.4.2-selinux.patch new file mode 100644 index 0000000..8537105 --- /dev/null +++ b/findutils-4.4.2-selinux.patch @@ -0,0 +1,453 @@ +diff --git a/NEWS b/NEWS +index d00862f..6b8b725 100644 +--- a/NEWS ++++ b/NEWS +@@ -1,5 +1,11 @@ + GNU findutils NEWS - User visible changes. -*- outline -*- (allout) + ++* Major changes in release 4.4.2, 2009-11-26 ++ ++** Functional Enhancements to find ++ ++patch #4848: Patch - Support for SELinux ++ + * Major changes in release 4.4.2, 2009-05-16 + + ** Bug Fixes +diff --git a/doc/find.texi b/doc/find.texi +index 8944096..4d71066 100644 +--- a/doc/find.texi ++++ b/doc/find.texi +@@ -7,7 +7,6 @@ + @c %**end of header + + @include version.texi +-@include ../locate/dblocation.texi + + @iftex + @finalout +@@ -1242,6 +1241,14 @@ situation. + + @end deffn + ++@deffn Test -context pattern ++True if file's SELinux context matches the pattern @var{pattern}. ++The pattern uses shell glob matching. ++ ++This predicate is supported only on @code{find} versions compiled with ++SELinux support and only when SELinux is enabled. ++@end deffn ++ + @node Contents + @section Contents + +@@ -1737,6 +1744,7 @@ from the novel you are reading. + * Size Directives:: + * Location Directives:: + * Time Directives:: ++* Other Directives:: + * Formatting Flags:: + @end menu + +@@ -1894,6 +1902,14 @@ File's last modification time in the format specified by @var{k} + (@pxref{Time Formats}). + @end table + ++@node Other Directives ++@subsubsection Other Directives ++ ++@table @code ++@item %Z ++File's SELinux context, or empty string if the file has no SELinux context. ++@end table ++ + @node Time Formats + @subsection Time Formats + +diff --git a/find/Makefile.am b/find/Makefile.am +index b001509..6fc7df3 100644 +--- a/find/Makefile.am ++++ b/find/Makefile.am +@@ -26,7 +26,7 @@ endif + + EXTRA_DIST = defs.h $(man_MANS) + INCLUDES = -I../gnulib/lib -I$(top_srcdir)/lib -I$(top_srcdir)/gnulib/lib -I../intl -DLOCALEDIR=\"$(localedir)\" +-LDADD = ./libfindtools.a ../lib/libfind.a ../gnulib/lib/libgnulib.a @INTLLIBS@ @LIB_CLOCK_GETTIME@ @FINDLIBS@ ++LDADD = ./libfindtools.a ../lib/libfind.a ../gnulib/lib/libgnulib.a @INTLLIBS@ @LIB_CLOCK_GETTIME@ @FINDLIBS@ @LIB_SELINUX@ + man_MANS = find.1 + SUBDIRS = . testsuite + +diff --git a/find/defs.h b/find/defs.h +index a0e7059..36d428d 100644 +--- a/find/defs.h ++++ b/find/defs.h +@@ -48,6 +48,7 @@ Please stop compiling the program now + #include /* for bool/boolean */ + #include /* for uintmax_t */ + #include /* S_ISUID etc. */ ++#include + + + +@@ -315,6 +316,7 @@ struct predicate + struct samefile_file_id samefileid; /* samefile */ + mode_t type; /* type */ + struct format_val printf_vec; /* printf fprintf fprint ls fls print0 fprint0 print */ ++ security_context_t scontext; /* security context */ + } args; + + /* The next predicate in the user input sequence, +@@ -459,6 +461,7 @@ PREDICATEFUNCTION pred_used; + PREDICATEFUNCTION pred_user; + PREDICATEFUNCTION pred_writable; + PREDICATEFUNCTION pred_xtype; ++PREDICATEFUNCTION pred_context; + + + +@@ -604,6 +607,9 @@ struct options + */ + int regex_options; + ++ /* function used to get file context */ ++ int (*x_getfilecon) (int, const char *, security_context_t *); ++ + /* Optimisation level. One is the default. + */ + unsigned short optimisation_level; +diff --git a/find/find.1 b/find/find.1 +index f9c61a3..27ad1da 100644 +--- a/find/find.1 ++++ b/find/find.1 +@@ -936,6 +936,8 @@ if \fIc\fR is `l'. In other words, for symbolic links, + checks the type of the file that + .B \-type + does not check. ++.IP "\-context \fIpattern\fR" ++(SELinux only) Security context of the file matches glob \fIpattern\fR. + + .SS ACTIONS + .IP "\-delete\fR" +@@ -1357,6 +1359,8 @@ File's type (like in + U=unknown type (shouldn't happen) + .IP %Y + File's type (like %y), plus follow symlinks: L=loop, N=nonexistent ++.IP %Z ++(SELinux only) file's security context. + .PP + A `%' character followed by any other character is discarded, but the + other character is printed (don't rely on this, as further format +diff --git a/find/parser.c b/find/parser.c +index 036ddb8..6b09eee 100644 +--- a/find/parser.c ++++ b/find/parser.c +@@ -53,6 +53,8 @@ + #include + #include + ++#include "selinux-at.h" ++ + #if ENABLE_NLS + # include + # define _(Text) gettext (Text) +@@ -156,6 +158,7 @@ static boolean parse_noignore_race PARAMS((const struct parser_table*, char *arg + static boolean parse_warn PARAMS((const struct parser_table*, char *argv[], int *arg_ptr)); + static boolean parse_xtype PARAMS((const struct parser_table*, char *argv[], int *arg_ptr)); + static boolean parse_quit PARAMS((const struct parser_table*, char *argv[], int *arg_ptr)); ++static boolean parse_context PARAMS((const struct parser_table*, char *argv[], int *arg_ptr)); + + boolean parse_print PARAMS((const struct parser_table*, char *argv[], int *arg_ptr)); + +@@ -252,6 +255,7 @@ static struct parser_table const parse_table[] = + PARSE_TEST ("cmin", cmin), /* GNU */ + PARSE_TEST ("cnewer", cnewer), /* GNU */ + {ARG_TEST, "ctime", parse_time, pred_ctime}, /* POSIX */ ++ PARSE_TEST ("context", context), /* GNU */ + PARSE_POSOPT ("daystart", daystart), /* GNU */ + PARSE_ACTION ("delete", delete), /* GNU, Mac OS, FreeBSD */ + PARSE_OPTION ("d", d), /* Mac OS X, FreeBSD, NetBSD, OpenBSD, but deprecated in favour of -depth */ +@@ -349,6 +353,86 @@ static struct parser_table const parse_table[] = + static const char *first_nonoption_arg = NULL; + static const struct parser_table *noop = NULL; + ++static int ++fallback_getfilecon (int fd, const char *name, security_context_t *p, ++ int prev_rv) ++{ ++ /* Our original getfilecon () call failed. Perhaps we can't follow a ++ * symbolic link. If that might be the problem, lgetfilecon () the link. ++ * Otherwise, admit defeat. */ ++ switch (errno) ++ { ++ case ENOENT: ++ case ENOTDIR: ++#ifdef DEBUG_STAT ++ fprintf (stderr, "fallback_getfilecon(): getfilecon(%s) failed; falling " ++ "back on lgetfilecon()\n", name); ++#endif ++ return lgetfileconat (fd, name, p); ++ ++ case EACCES: ++ case EIO: ++ case ELOOP: ++ case ENAMETOOLONG: ++#ifdef EOVERFLOW ++ case EOVERFLOW: /* EOVERFLOW is not #defined on UNICOS. */ ++#endif ++ default: ++ return prev_rv; ++ } ++} ++ ++/* optionh_getfilecon () implements the getfilecon operation when the ++ * -H option is in effect. ++ * ++ * If the item to be examined is a command-line argument, we follow ++ * symbolic links. If the getfilecon () call fails on the command-line ++ * item, we fall back on the properties of the symbolic link. ++ * ++ * If the item to be examined is not a command-line argument, we ++ * examine the link itself. */ ++int ++optionh_getfilecon (int fd, const char *name, security_context_t *p) ++{ ++ int rv; ++ if (0 == state.curdepth) ++ { ++ /* This file is from the command line; dereference the link (if it is ++ a link). */ ++ rv = getfileconat (fd, name, p); ++ if (0 == rv) ++ return 0; /* success */ ++ else ++ return fallback_getfilecon (fd, name, p, rv); ++ } ++ else ++ { ++ /* Not a file on the command line; do not dereference the link. */ ++ return lgetfileconat (fd, name, p); ++ } ++} ++ ++/* optionl_getfilecon () implements the getfilecon operation when the ++ * -L option is in effect. That option makes us examine the thing the ++ * symbolic link points to, not the symbolic link itself. */ ++int ++optionl_getfilecon (int fd, const char *name, security_context_t *p) ++{ ++ int rv = getfileconat (fd, name, p); ++ if (0 == rv) ++ return 0; /* normal case. */ ++ else ++ return fallback_getfilecon (fd, name, p, rv); ++} ++ ++/* optionp_getfilecon () implements the stat operation when the -P ++ * option is in effect (this is also the default). That option makes ++ * us examine the symbolic link itself, not the thing it points to. */ ++int ++optionp_getfilecon (int fd, const char *name, security_context_t *p) ++{ ++ return lgetfileconat (fd, name, p); ++} + + void + check_option_combinations(const struct predicate *p) +@@ -452,11 +536,13 @@ set_follow_state(enum SymlinkOption opt) + { + case SYMLINK_ALWAYS_DEREF: /* -L */ + options.xstat = optionl_stat; ++ options.x_getfilecon = optionl_getfilecon; + options.no_leaf_check = true; + break; + + case SYMLINK_NEVER_DEREF: /* -P (default) */ + options.xstat = optionp_stat; ++ options.x_getfilecon = optionp_getfilecon; + /* Can't turn no_leaf_check off because the user might have specified + * -noleaf anyway + */ +@@ -464,6 +550,7 @@ set_follow_state(enum SymlinkOption opt) + + case SYMLINK_DEREF_ARGSONLY: /* -H */ + options.xstat = optionh_stat; ++ options.x_getfilecon = optionh_getfilecon; + options.no_leaf_check = true; + } + } +@@ -1129,8 +1216,10 @@ tests (N can be +N or -N or N): -amin N -anewer FILE -atime N -cmin N\n\ + -nouser -nogroup -path PATTERN -perm [+-]MODE -regex PATTERN\n\ + -readable -writable -executable\n\ + -wholename PATTERN -size N[bcwkMG] -true -type [bcdpflsD] -uid N\n\ +- -used N -user NAME -xtype [bcdpfls]\n")); ++ -used N -user NAME -xtype [bcdpfls]")); + puts (_("\ ++ -context CONTEXT\n")); ++ puts (_("\n\ + actions: -delete -print0 -printf FORMAT -fprintf FILE FORMAT -print \n\ + -fprint0 FILE -fprint FILE -ls -fls FILE -prune -quit\n\ + -exec COMMAND ; -exec COMMAND {} + -ok COMMAND ;\n\ +@@ -2520,6 +2609,11 @@ parse_version (const struct parser_table* entry, char **argv, int *arg_ptr) + printf("LEAF_OPTIMISATION "); + ++features; + #endif ++ if (0 < is_selinux_enabled ()) ++ { ++ printf ("SELINUX "); ++ ++features; ++ } + + flags = 0; + if (is_fts_enabled(&flags)) +@@ -2555,6 +2649,31 @@ parse_version (const struct parser_table* entry, char **argv, int *arg_ptr) + } + + static boolean ++parse_context (const struct parser_table* entry, char **argv, int *arg_ptr) ++{ ++ struct predicate *our_pred; ++ ++ if ((argv == NULL) || (argv[*arg_ptr] == NULL)) ++ return false; ++ ++ if (is_selinux_enabled () <= 0) ++ { ++ error (1, 0, _("invalid predicate -context: SELinux is not enabled.")); ++ return false; ++ } ++ our_pred = insert_primary (entry); ++ our_pred->est_success_rate = 0.01f; ++ our_pred->need_stat = false; ++#ifdef DEBUG ++ our_pred->p_name = find_pred_name (pred_context); ++#endif /*DEBUG*/ ++ our_pred->args.scontext = argv[*arg_ptr]; ++ ++ (*arg_ptr)++; ++ return true; ++} ++ ++static boolean + parse_xdev (const struct parser_table* entry, char **argv, int *arg_ptr) + { + options.stay_on_filesystem = true; +@@ -2815,7 +2934,7 @@ insert_fprintf (struct format_val *vec, + if (*scan2 == '.') + for (scan2++; ISDIGIT (*scan2); scan2++) + /* Do nothing. */ ; +- if (strchr ("abcdDfFgGhHiklmMnpPsStuUyY", *scan2)) ++ if (strchr ("abcdDfFgGhHiklmMnpPsStuUyYZ", *scan2)) + { + segmentp = make_segment (segmentp, format, scan2 - format, + KIND_FORMAT, *scan2, 0, +@@ -2945,6 +3064,11 @@ make_segment (struct segment **segment, + *fmt++ = 's'; + break; + ++ case 'Z': /* SELinux security context */ ++ mycost = NeedsAccessInfo; ++ *fmt++ = 's'; ++ break; ++ + case 'H': /* ARGV element file was found under */ + *fmt++ = 's'; + break; +diff --git a/find/pred.c b/find/pred.c +index b1f48a0..7c34119 100644 +--- a/find/pred.c ++++ b/find/pred.c +@@ -48,6 +48,8 @@ + #include "error.h" + #include "verify.h" + ++#include ++ + #if ENABLE_NLS + # include + # define _(Text) gettext (Text) +@@ -230,6 +232,7 @@ struct pred_assoc pred_table[] = + {pred_user, "user "}, + {pred_writable, "writable "}, + {pred_xtype, "xtype "}, ++ {pred_context, "context"}, + {0, "none "} + }; + #endif +@@ -1054,6 +1057,30 @@ do_fprintf(struct format_val *dest, + mode_to_filetype(stat_buf->st_mode & S_IFMT)); + } + break; ++ ++ case 'Z': /* SELinux security context */ ++ { ++ security_context_t scontext; ++ int rv = (*options.x_getfilecon) (state.cwd_dir_fd, state.rel_pathname, ++ &scontext); ++ if (rv < 0) ++ { ++ /* If getfilecon fails, there will in the general case ++ still be some text to print. We just make %Z expand ++ to an empty string. */ ++ checked_fprintf (dest, segment->text, ""); ++ ++ error (0, errno, "getfilecon: %s", ++ safely_quote_err_filename (0, pathname)); ++ state.exit_status = 1; ++ } ++ else ++ { ++ checked_fprintf (dest, segment->text, scontext); ++ freecon (scontext); ++ } ++ } ++ break; + } + /* end of KIND_FORMAT case */ + break; +@@ -1844,6 +1871,26 @@ pred_xtype (const char *pathname, struct stat *stat_buf, struct predicate *pred_ + */ + return (pred_type (pathname, &sbuf, pred_ptr)); + } ++ ++ ++boolean ++pred_context (const char *pathname, struct stat *stat_buf, ++ struct predicate *pred_ptr) ++{ ++ security_context_t scontext; ++ int rv = (*options.x_getfilecon) (state.cwd_dir_fd, state.rel_pathname, ++ &scontext); ++ if (rv < 0) ++ { ++ error (0, errno, "getfilecon: %s", safely_quote_err_filename (0, pathname)); ++ return false; ++ } ++ ++ rv = (fnmatch (pred_ptr->args.scontext, scontext, 0) == 0); ++ freecon (scontext); ++ return rv; ++} ++ + + /* 1) fork to get a child; parent remembers the child pid + 2) child execs the command requested +diff --git a/find/tree.c b/find/tree.c +index 7420c60..ecdd4c9 100644 +--- a/find/tree.c ++++ b/find/tree.c +@@ -904,6 +904,7 @@ static struct pred_cost_lookup costlookup[] = + { pred_cmin , NeedsStatInfo, }, + { pred_cnewer , NeedsStatInfo, }, + { pred_comma , NeedsNothing, }, ++ { pred_context , NeedsAccessInfo }, + { pred_ctime , NeedsStatInfo, }, + { pred_delete , NeedsSyncDiskHit }, + { pred_empty , NeedsStatInfo }, +@@ -1434,6 +1435,7 @@ get_new_pred (const struct parser_table *entry) + last_pred->need_stat = true; + last_pred->need_type = true; + last_pred->args.str = NULL; ++ last_pred->args.scontext = NULL; + last_pred->pred_next = NULL; + last_pred->pred_left = NULL; + last_pred->pred_right = NULL; diff --git a/findutils-4.4.2-xautofs.patch b/findutils-4.4.2-xautofs.patch index c9dcb65..d37ae06 100644 --- a/findutils-4.4.2-xautofs.patch +++ b/findutils-4.4.2-xautofs.patch @@ -1,7 +1,8 @@ -diff -rup findutils-4.4.2.orig/doc/find.texi findutils-4.4.2/doc/find.texi ---- findutils-4.4.2.orig/doc/find.texi 2009-10-20 14:31:43.902741386 +0200 -+++ findutils-4.4.2/doc/find.texi 2009-10-20 14:30:55.680178944 +0200 -@@ -1420,6 +1420,10 @@ them. +diff --git a/doc/find.texi b/doc/find.texi +index 2e5958d..8944096 100644 +--- a/doc/find.texi ++++ b/doc/find.texi +@@ -1413,6 +1413,10 @@ them. There are two ways to avoid searching certain filesystems. One way is to tell @code{find} to only search one filesystem: @@ -12,23 +13,25 @@ diff -rup findutils-4.4.2.orig/doc/find.texi findutils-4.4.2/doc/find.texi @deffn Option -xdev @deffnx Option -mount Don't descend directories on other filesystems. These options are -diff -rup findutils-4.4.2.orig/find/defs.h findutils-4.4.2/find/defs.h ---- findutils-4.4.2.orig/find/defs.h 2009-10-20 14:31:43.902741386 +0200 -+++ findutils-4.4.2/find/defs.h 2009-10-20 14:30:55.680906690 +0200 -@@ -559,6 +559,9 @@ struct options +diff --git a/find/defs.h b/find/defs.h +index 1708d83..a0e7059 100644 +--- a/find/defs.h ++++ b/find/defs.h +@@ -550,6 +550,9 @@ struct options /* If true, don't cross filesystem boundaries. */ boolean stay_on_filesystem; + /* If true, don't descend directories on autofs filesystems. */ + boolean bypass_autofs; -+ ++ /* If true, we ignore the problem where we find that a directory entry * no longer exists by the time we get around to processing it. */ -diff -rup findutils-4.4.2.orig/find/find.1 findutils-4.4.2/find/find.1 ---- findutils-4.4.2.orig/find/find.1 2009-10-20 14:31:43.903741308 +0200 -+++ findutils-4.4.2/find/find.1 2009-10-20 14:30:55.680906690 +0200 -@@ -451,6 +451,9 @@ if standard input is a tty, and to +diff --git a/find/find.1 b/find/find.1 +index 8b67ae3..f9c61a3 100644 +--- a/find/find.1 ++++ b/find/find.1 +@@ -451,6 +451,9 @@ if standard input is a tty, and to .B \-nowarn otherwise. @@ -38,9 +41,10 @@ diff -rup findutils-4.4.2.orig/find/find.1 findutils-4.4.2/find/find.1 .IP \-xdev Don't descend directories on other filesystems. -diff -rup findutils-4.4.2.orig/find/ftsfind.c findutils-4.4.2/find/ftsfind.c ---- findutils-4.4.2.orig/find/ftsfind.c 2009-05-16 17:17:01.000000000 +0200 -+++ findutils-4.4.2/find/ftsfind.c 2009-10-20 14:31:04.745866565 +0200 +diff --git a/find/ftsfind.c b/find/ftsfind.c +index b59d896..838b81f 100644 +--- a/find/ftsfind.c ++++ b/find/ftsfind.c @@ -525,6 +525,12 @@ consider_visiting(FTS *p, FTSENT *ent) } } @@ -54,10 +58,11 @@ diff -rup findutils-4.4.2.orig/find/ftsfind.c findutils-4.4.2/find/ftsfind.c if ( (ent->fts_info == FTS_D) && !options.do_dir_first ) { /* this is the preorder visit, but user said -depth */ -diff -rup findutils-4.4.2.orig/find/parser.c findutils-4.4.2/find/parser.c ---- findutils-4.4.2.orig/find/parser.c 2009-10-20 14:31:43.906741469 +0200 -+++ findutils-4.4.2/find/parser.c 2009-10-20 14:30:55.683024396 +0200 -@@ -154,6 +154,7 @@ static boolean parse_user PARAM +diff --git a/find/parser.c b/find/parser.c +index 534b670..036ddb8 100644 +--- a/find/parser.c ++++ b/find/parser.c +@@ -150,6 +150,7 @@ static boolean parse_user PARAMS((const struct parser_table*, char *arg static boolean parse_version PARAMS((const struct parser_table*, char *argv[], int *arg_ptr)); static boolean parse_wholename PARAMS((const struct parser_table*, char *argv[], int *arg_ptr)); static boolean parse_xdev PARAMS((const struct parser_table*, char *argv[], int *arg_ptr)); @@ -65,7 +70,7 @@ diff -rup findutils-4.4.2.orig/find/parser.c findutils-4.4.2/find/parser.c static boolean parse_ignore_race PARAMS((const struct parser_table*, char *argv[], int *arg_ptr)); static boolean parse_noignore_race PARAMS((const struct parser_table*, char *argv[], int *arg_ptr)); static boolean parse_warn PARAMS((const struct parser_table*, char *argv[], int *arg_ptr)); -@@ -330,6 +331,7 @@ static struct parser_table const parse_t +@@ -320,6 +321,7 @@ static struct parser_table const parse_table[] = PARSE_TEST_NP ("wholename", wholename), /* GNU, replaced -path, but anyway -path will soon be in POSIX */ {ARG_TEST, "writable", parse_accesscheck, pred_writable}, /* GNU, 4.3.0+ */ PARSE_OPTION ("xdev", xdev), /* POSIX */ @@ -73,7 +78,7 @@ diff -rup findutils-4.4.2.orig/find/parser.c findutils-4.4.2/find/parser.c PARSE_TEST ("xtype", xtype), /* GNU */ #ifdef UNIMPLEMENTED_UNIX /* It's pretty ugly for find to know about archive formats. -@@ -2696,6 +2698,16 @@ parse_xdev (const struct parser_table* e +@@ -2560,6 +2562,16 @@ parse_xdev (const struct parser_table* entry, char **argv, int *arg_ptr) } static boolean @@ -90,9 +95,10 @@ diff -rup findutils-4.4.2.orig/find/parser.c findutils-4.4.2/find/parser.c parse_ignore_race (const struct parser_table* entry, char **argv, int *arg_ptr) { options.ignore_readdir_race = true; -diff -rup findutils-4.4.2.orig/find/util.c findutils-4.4.2/find/util.c ---- findutils-4.4.2.orig/find/util.c 2009-05-16 17:17:01.000000000 +0200 -+++ findutils-4.4.2/find/util.c 2009-10-20 14:30:55.684180119 +0200 +diff --git a/find/util.c b/find/util.c +index a06eada..d3cb467 100644 +--- a/find/util.c ++++ b/find/util.c @@ -933,6 +933,7 @@ set_option_defaults(struct options *p) p->full_days = false; diff --git a/findutils.spec b/findutils.spec index 9754219..c8d4e6f 100644 --- a/findutils.spec +++ b/findutils.spec @@ -1,7 +1,7 @@ Summary: The GNU versions of find utilities (find and xargs) Name: findutils Version: 4.4.2 -Release: 5%{?dist} +Release: 6%{?dist} Epoch: 1 License: GPLv3+ Group: Applications/File @@ -9,10 +9,11 @@ URL: http://www.gnu.org/software/findutils/ Source0: ftp://ftp.gnu.org/gnu/findutils/%{name}-%{version}.tar.gz Source1: ftp://ftp.gnu.org/gnu/findutils/%{name}-%{version}.tar.gz.sig Patch1: findutils-4.4.0-no-locate.patch -Patch2: findutils-4.4.0-selinux.patch -Patch3: findutils-4.4.2-autofs.patch -Patch4: findutils-4.4.2-xautofs.patch -Patch5: findutils-4.4.2-fts-remount.patch +Patch2: findutils-4.4.2-autofs.patch +Patch3: findutils-4.4.2-xautofs.patch +Patch4: findutils-4.4.2-fts-remount.patch +Patch5: findutils-4.4.2-selinux.patch +Patch6: findutils-4.4.2-selinux-gnulib.patch Requires(post): /sbin/install-info Requires(preun): /sbin/install-info Buildroot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) @@ -24,7 +25,7 @@ BuildRequires: libselinux-devel The findutils package contains programs which will help you locate files on your system. The find utility searches through a hierarchy of directories looking for files which match a certain set of criteria -(such as a filename pattern). The xargs utility builds and executes +(such as a file name pattern). The xargs utility builds and executes command lines from standard input arguments (usually lists of file names generated by the find command). @@ -38,7 +39,7 @@ useful for finding things on your system. %patch3 -p1 %patch4 -p1 %patch5 -p1 - +%patch6 -p1 autoreconf %build @@ -83,7 +84,7 @@ fi rm -rf $RPM_BUILD_ROOT %files -f %{name}.lang -%defattr(-,root,root) +%defattr(-,root,root,-) %doc AUTHORS COPYING NEWS README THANKS TODO /bin/find %{_bindir}/find @@ -95,6 +96,9 @@ rm -rf $RPM_BUILD_ROOT %{_infodir}/find-maint.info.gz %changelog +* Wed Nov 26 2009 Kamil Dudka - 1:4.4.2-6 +- update SELinux patch to the latest upstream (gnulib based) version + * Wed Nov 18 2009 Kamil Dudka - 1:4.4.2-5 - do not fail silently on a remount during traverse (#501848)