findutils/findutils-selinux.patch

469 lines
15 KiB
Diff
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

diff -ur --exclude '*.o' --exclude '*~' --exclude '*.selinux' findutils-4.2.27/configure.in findutils/configure.in
--- findutils-4.2.27/configure.in 2005-12-06 07:53:12.000000000 +0100
+++ findutils/configure.in 2006-01-30 21:10:04.000000000 +0100
@@ -95,6 +95,16 @@
AC_CHECK_FUNC(getpwnam, [],
[AC_CHECK_LIB(sun, getpwnam)])
+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 -ur --exclude '*.o' --exclude '*~' --exclude '*.selinux' findutils-4.2.27/doc/find.texi findutils/doc/find.texi
--- findutils-4.2.27/doc/find.texi 2005-12-05 08:35:33.000000000 +0100
+++ findutils/doc/find.texi 2006-01-30 21:20:10.000000000 +0100
@@ -1091,6 +1091,14 @@
@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
@@ -1610,6 +1618,9 @@
file is a sparse file (that is, it has ``holes'').
@item %s
File's size in bytes.
+@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 -ur --exclude '*.o' --exclude '*~' --exclude '*.selinux' findutils-4.2.27/find/defs.h findutils/find/defs.h
--- findutils-4.2.27/find/defs.h 2005-09-04 19:59:34.000000000 +0200
+++ findutils/find/defs.h 2006-01-30 21:15:38.000000000 +0100
@@ -131,6 +131,10 @@
#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 <selinux/selinux.h>
+#endif
+
#if 1
#include <stdbool.h>
typedef bool boolean;
@@ -320,6 +324,9 @@
struct dir_id fileid; /* samefile */
mode_t type; /* type */
FILE *stream; /* ls fls fprint0 */
+#ifdef WITH_SELINUX
+ security_context_t scontext; /* scontext */
+#endif
struct format_val printf_vec; /* printf fprintf fprint */
} args;
@@ -479,6 +486,9 @@
boolean pred_used PARAMS((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
boolean pred_user PARAMS((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
boolean pred_xtype PARAMS((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
+#ifdef WITH_SELINUX
+boolean pred_context PARAMS((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr));
+#endif
@@ -568,6 +578,10 @@
* can be changed with the positional option, -regextype.
*/
int regex_options;
+
+#ifdef WITH_SELINUX
+ int (*x_getfilecon) ();
+#endif
};
extern struct options options;
diff -ur --exclude '*.o' --exclude '*~' --exclude '*.selinux' findutils-4.2.27/find/find.c findutils/find/find.c
--- findutils-4.2.27/find/find.c 2005-11-11 08:41:37.000000000 +0100
+++ findutils/find/find.c 2006-01-30 21:15:21.000000000 +0100
@@ -245,6 +245,93 @@
return lstat(name, p);
}
+#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 */
+
#ifdef DEBUG_STAT
static uintmax_t stat_count = 0u;
@@ -272,11 +359,17 @@
{
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
*/
@@ -284,6 +377,9 @@
case SYMLINK_DEREF_ARGSONLY: /* -H */
options.xstat = optionh_stat;
+#ifdef WITH_SELINUX
+ options.x_getfilecon = optionh_getfilecon;
+#endif
options.no_leaf_check = true;
}
@@ -1807,7 +1903,7 @@
static void
process_dir (char *pathname, char *name, int pathlen, 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) */
int idx; /* Which entry are we on? */
struct stat stat_buf;
diff -ur --exclude '*.o' --exclude '*~' --exclude '*.selinux' findutils-4.2.27/find/find.1 findutils/find/find.1
--- findutils-4.2.27/find/find.1 2005-12-05 18:05:02.000000000 +0100
+++ findutils/find/find.1 2006-01-30 21:46:01.000000000 +0100
@@ -483,6 +483,8 @@
link to a file of type \fIc\fR; if the \-L option has been given, true
if \fIc\fR is `l'. In other words, for symbolic links, \-xtype checks
the type of the file that \-type does not check.
+.IP "\-context \fIpattern\fR"
+(SELinux only) Security context of the file matches glob \fIpattern\fR.
.SS ACTIONS
.IP "\-delete\fR"
@@ -785,6 +787,8 @@
File's type (like in ls \-l), 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).
diff -ur --exclude '*.o' --exclude '*~' --exclude '*.selinux' findutils-4.2.27/find/Makefile.am findutils/find/Makefile.am
--- findutils-4.2.27/find/Makefile.am 2005-07-03 18:07:08.000000000 +0200
+++ findutils/find/Makefile.am 2006-01-30 21:46:39.000000000 +0100
@@ -6,7 +6,7 @@
find_SOURCES = find.c fstype.c parser.c pred.c tree.c util.c version.c
EXTRA_DIST = defs.h $(man_MANS)
INCLUDES = -I../gnulib/lib -I$(top_srcdir)/lib -I$(top_srcdir)/gnulib/lib -I../intl -DLOCALEDIR=\"$(localedir)\"
-LDADD = ../lib/libfind.a ../gnulib/lib/libgnulib.a @INTLLIBS@
+LDADD = ../lib/libfind.a ../gnulib/lib/libgnulib.a @INTLLIBS@ @LIBSELINUX@
man_MANS = find.1
SUBDIRS = testsuite
diff -ur --exclude '*.o' --exclude '*~' --exclude '*.selinux' findutils-4.2.27/find/parser.c findutils/find/parser.c
--- findutils-4.2.27/find/parser.c 2005-12-04 03:07:52.000000000 +0100
+++ findutils/find/parser.c 2006-01-30 21:14:46.000000000 +0100
@@ -47,6 +47,10 @@
/* We need <unistd.h> for isatty(). */
#include <unistd.h>
+#ifdef WITH_SELINUX
+#include <selinux/selinux.h>
+#endif
+
#if ENABLE_NLS
# include <libintl.h>
# define _(Text) gettext (Text)
@@ -147,6 +151,9 @@
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
@@ -217,6 +224,9 @@
PARSE_TEST ("cmin", cmin), /* GNU */
PARSE_TEST ("cnewer", cnewer), /* GNU */
PARSE_TEST ("ctime", ctime),
+#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 */
@@ -802,8 +812,12 @@
puts (_("\
-nouser -nogroup -path PATTERN -perm [+-]MODE -regex PATTERN\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\
@@ -1716,6 +1730,10 @@
printf("LEAF_OPTIMISATION ");
++features;
#endif
+#if defined(WITH_SELINUX)
+ printf("SELINUX ");
+ ++features;
+#endif
if (0 == features)
{
/* For the moment, leave this as English in case someone wants
@@ -1727,6 +1745,32 @@
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)
{
@@ -1964,7 +2008,7 @@
if (*scan2 == '.')
for (scan2++; ISDIGIT (*scan2); scan2++)
/* Do nothing. */ ;
- if (strchr ("abcdDfFgGhHiklmMnpPstuUyY", *scan2))
+ if (strchr ("abcdDfFgGhHiklmMnpPstuUyYZ", *scan2))
{
segmentp = make_segment (segmentp, format, scan2 - format,
(int) *scan2);
@@ -2046,6 +2090,7 @@
case 'H': /* ARGV element file was found under */
case 'p': /* pathname */
case 'P': /* pathname with ARGV element stripped */
+ case 'Z': /* SELinux security context */
*fmt++ = 's';
break;
diff -ur --exclude '*.o' --exclude '*~' --exclude '*.selinux' findutils-4.2.27/find/pred.c findutils/find/pred.c
--- findutils-4.2.27/find/pred.c 2005-11-30 07:17:15.000000000 +0100
+++ findutils/find/pred.c 2006-01-30 21:13:18.000000000 +0100
@@ -38,6 +38,10 @@
#include "buildcmd.h"
#include "yesno.h"
+#ifdef WITH_SELINUX
+#include <selinux/selinux.h>
+#endif /*WITH_SELINUX*/
+
#if ENABLE_NLS
# include <libintl.h>
# define _(Text) gettext (Text)
@@ -215,6 +219,9 @@
{pred_used, "used "},
{pred_user, "user "},
{pred_xtype, "xtype "},
+#ifdef WITH_SELINUX
+ {pred_context, "context"},
+#endif /*WITH_SELINUX*/
{0, "none "}
};
@@ -903,6 +910,27 @@
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
+ {
+ fprintf (fp, segment->text, scontext);
+ freecon (scontext);
+ }
+ }
+#endif /* WITH_SELINUX */
+ break;
}
}
return true;
@@ -1493,6 +1521,33 @@
*/
return (pred_type (pathname, &sbuf, pred_ptr));
}
+
+
+#ifdef WITH_SELINUX
+
+boolean
+pred_context (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 -ur --exclude '*.o' --exclude '*~' --exclude '*.selinux' findutils-4.2.27/find/util.c findutils/find/util.c
--- findutils-4.2.27/find/util.c 2005-07-01 23:45:18.000000000 +0200
+++ findutils/find/util.c 2006-01-27 14:38:43.000000000 +0100
@@ -78,6 +78,9 @@
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;