1 diff -up findutils-4.4.2/configure.ac_old findutils-4.4.2/configure.ac
2 --- findutils-4.4.2/configure.ac_old 2009-07-01 10:24:04.000000000 +0200
3 +++ findutils-4.4.2/configure.ac 2009-07-01 10:24:46.000000000 +0200
4 @@ -114,6 +114,16 @@ AC_CHECK_LIB([m],[fabs],[FINDLIBS="-lm $
5 AC_DEFINE_UNQUOTED(HAVE_FABS_IN_LIBM,1,[fabs is defined in -lm]))
8 +AC_ARG_WITH([selinux],
9 + AS_HELP_STRING([--without-selinux], [disable SELinux support]),
11 +[AC_CHECK_LIB([selinux], [is_selinux_enabled],
12 + [with_selinux=yes], [with_selinux=no])])
13 +if test x$with_selinux != xno; then
14 + AC_DEFINE([WITH_SELINUX], [1], [Define to support SELinux])
15 + AC_SUBST([LIBSELINUX], [-lselinux])
18 dnl Checks for header files.
20 dnl Assume unistd.h is present - coreutils does too.
21 diff -up findutils-4.4.2/doc/find.texi_old findutils-4.4.2/doc/find.texi
22 --- findutils-4.4.2/doc/find.texi_old 2009-07-01 10:25:09.000000000 +0200
23 +++ findutils-4.4.2/doc/find.texi 2009-07-01 10:26:37.000000000 +0200
28 -@include ../locate/dblocation.texi
32 @@ -1242,6 +1241,14 @@ situation.
36 +@deffn Test -context pattern
37 +True if file's SELinux context matches the pattern @var{pattern}.
38 +The pattern uses shell glob matching.
40 +This predicate is supported only on @code{find} versions compiled with
41 +SELinux support and only when SELinux is enabled.
47 @@ -1826,6 +1833,9 @@ value used for BLOCKSIZE is system-depen
48 bytes. If the file size is zero, the value printed is undefined. On
49 systems which lack support for st_blocks, a file's sparseness is
52 +File's SELinux context, or empty string if the file has no SELinux context
53 +or this version of find does not support SELinux.
56 @node Location Directives
57 diff -up findutils-4.4.2/find/defs.h_old findutils-4.4.2/find/defs.h
58 --- findutils-4.4.2/find/defs.h_old 2009-07-01 12:38:32.000000000 +0200
59 +++ findutils-4.4.2/find/defs.h 2009-07-01 12:52:47.000000000 +0200
60 @@ -91,6 +91,9 @@ int get_statinfo PARAMS((const char *pat
61 #define MODE_RWX (S_IXUSR | S_IXGRP | S_IXOTH | MODE_RW)
62 #define MODE_ALL (S_ISUID | S_ISGID | S_ISVTX | MODE_RWX)
65 +#include <selinux/selinux.h>
70 @@ -315,6 +318,9 @@ struct predicate
71 struct samefile_file_id samefileid; /* samefile */
72 mode_t type; /* type */
73 struct format_val printf_vec; /* printf fprintf fprint ls fls print0 fprint0 print */
75 + security_context_t scontext; /* scontext */
79 /* The next predicate in the user input sequence,
80 @@ -459,6 +465,9 @@ PREDICATEFUNCTION pred_used;
81 PREDICATEFUNCTION pred_user;
82 PREDICATEFUNCTION pred_writable;
83 PREDICATEFUNCTION pred_xtype;
85 +PREDICATEFUNCTION pred_context;
90 @@ -601,6 +610,10 @@ struct options
95 + int (*x_getfilecon) ();
98 /* Optimisation level. One is the default.
100 unsigned short optimisation_level;
101 diff -up findutils-4.4.2/find/find.1_old findutils-4.4.2/find/find.1
102 --- findutils-4.4.2/find/find.1_old 2009-07-01 10:30:04.000000000 +0200
103 +++ findutils-4.4.2/find/find.1 2009-07-01 10:30:59.000000000 +0200
104 @@ -933,6 +933,8 @@ if \fIc\fR is `l'. In other words, for
105 checks the type of the file that
108 +.IP "\-context \fIpattern\fR"
109 +(SELinux only) Security context of the file matches glob \fIpattern\fR.
113 @@ -1354,6 +1356,8 @@ File's type (like in
114 U=unknown type (shouldn't happen)
116 File's type (like %y), plus follow symlinks: L=loop, N=nonexistent
118 +(SELinux only) file's security context.
120 A `%' character followed by any other character is discarded, but the
121 other character is printed (don't rely on this, as further format
122 diff -up findutils-4.4.2/find/find.c_old findutils-4.4.2/find/find.c
123 --- findutils-4.4.2/find/find.c_old 2009-07-01 10:26:53.000000000 +0200
124 +++ findutils-4.4.2/find/find.c 2009-07-01 10:29:52.000000000 +0200
125 @@ -120,6 +120,36 @@ int get_current_dirfd(void)
131 +fallback_getfilecon(const char *name, security_context_t *p, int prev_rv)
133 + /* Our original getfilecon() call failed. Perhaps we can't follow a
134 + * symbolic link. If that might be the problem, lgetfilecon() the link.
135 + * Otherwise, admit defeat.
142 + fprintf(stderr, "fallback_getfilecon(): getfilecon(%s) failed; falling back on lgetfilecon()\n", name);
144 + return lgetfilecon(name, p);
151 + case EOVERFLOW: /* EOVERFLOW is not #defined on UNICOS. */
157 +#endif /* WITH_SELINUX */
161 main (int argc, char **argv)
162 @@ -1270,7 +1300,7 @@ process_path (char *pathname, char *name
164 process_dir (char *pathname, char *name, int pathlen, const struct stat *statp, char *parent)
166 - int subdirs_left; /* Number of unexamined subdirs in PATHNAME. */
167 + int subdirs_left = 0; /* Number of unexamined subdirs in PATHNAME. */
168 boolean subdirs_unreliable; /* if true, cannot use dir link count as subdir limif (if false, it may STILL be unreliable) */
169 unsigned int idx; /* Which entry are we on? */
170 struct stat stat_buf;
171 diff -up findutils-4.4.2/find/Makefile.am_old findutils-4.4.2/find/Makefile.am
172 --- findutils-4.4.2/find/Makefile.am_old 2009-07-01 10:35:04.000000000 +0200
173 +++ findutils-4.4.2/find/Makefile.am 2009-07-01 10:35:37.000000000 +0200
174 @@ -26,7 +26,7 @@ endif
176 EXTRA_DIST = defs.h $(man_MANS)
177 INCLUDES = -I../gnulib/lib -I$(top_srcdir)/lib -I$(top_srcdir)/gnulib/lib -I../intl -DLOCALEDIR=\"$(localedir)\"
178 -LDADD = ./libfindtools.a ../lib/libfind.a ../gnulib/lib/libgnulib.a @INTLLIBS@ @LIB_CLOCK_GETTIME@ @FINDLIBS@
179 +LDADD = ./libfindtools.a ../lib/libfind.a ../gnulib/lib/libgnulib.a @INTLLIBS@ @LIB_CLOCK_GETTIME@ @FINDLIBS@ @LIBSELINUX@
181 SUBDIRS = . testsuite
183 diff -up findutils-4.4.2/find/parser.c_old findutils-4.4.2/find/parser.c
184 --- findutils-4.4.2/find/parser.c_old 2009-07-01 10:35:43.000000000 +0200
185 +++ findutils-4.4.2/find/parser.c 2009-07-01 12:38:19.000000000 +0200
188 #include <sys/stat.h>
191 +#include <selinux/selinux.h>
195 # include <libintl.h>
196 # define _(Text) gettext (Text)
197 @@ -155,6 +159,9 @@ static boolean parse_noignore_race PARAM
198 static boolean parse_warn PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
199 static boolean parse_xtype PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
200 static boolean parse_quit PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
202 +static boolean parse_context PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
205 boolean parse_print PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
207 @@ -251,6 +258,9 @@ static struct parser_table const parse_t
208 PARSE_TEST ("cmin", cmin), /* GNU */
209 PARSE_TEST ("cnewer", cnewer), /* GNU */
210 {ARG_TEST, "ctime", parse_time, pred_ctime}, /* POSIX */
212 + PARSE_TEST ("context", context), /* GNU */
214 PARSE_POSOPT ("daystart", daystart), /* GNU */
215 PARSE_ACTION ("delete", delete), /* GNU, Mac OS, FreeBSD */
216 PARSE_OPTION ("d", d), /* Mac OS X, FreeBSD, NetBSD, OpenBSD, but deprecated in favour of -depth */
217 @@ -347,6 +357,89 @@ static struct parser_table const parse_t
218 static const char *first_nonoption_arg = NULL;
219 static const struct parser_table *noop = NULL;
223 +fallback_getfilecon(const char *name, security_context_t *p, int prev_rv)
225 + /* Our original getfilecon() call failed. Perhaps we can't follow a
226 + * symbolic link. If that might be the problem, lgetfilecon() the link.
227 + * Otherwise, admit defeat.
234 + fprintf(stderr, "fallback_getfilecon(): getfilecon(%s) failed; falling back on lgetfilecon()\n", name);
236 + return lgetfilecon(name, p);
243 + case EOVERFLOW: /* EOVERFLOW is not #defined on UNICOS. */
250 +/* optionh_getfilecon() implements the getfilecon operation when the
251 + * -H option is in effect.
253 + * If the item to be examined is a command-line argument, we follow
254 + * symbolic links. If the getfilecon() call fails on the command-line
255 + * item, we fall back on the properties of the symbolic link.
257 + * If the item to be examined is not a command-line argument, we
258 + * examine the link itself.
261 +optionh_getfilecon(const char *name, security_context_t *p)
263 + if (0 == state.curdepth)
265 + /* This file is from the command line; deference the link (if it
268 + int rv = getfilecon(name, p);
270 + return 0; /* success */
272 + return fallback_getfilecon(name, p, rv);
276 + /* Not a file on the command line; do not derefernce the link.
278 + return lgetfilecon(name, p);
281 +/* optionl_getfilecon() implements the getfilecon operation when the
282 + * -L option is in effect. That option makes us examine the thing the
283 + * symbolic link points to, not the symbolic link itself.
286 +optionl_getfilecon(const char *name, security_context_t *p)
288 + int rv = getfilecon(name, p);
290 + return 0; /* normal case. */
292 + return fallback_getfilecon(name, p, rv);
294 +/* optionp_getfilecon() implements the stat operation when the -P
295 + * option is in effect (this is also the default). That option makes
296 + * us examine the symbolic link itself, not the thing it points to.
299 +optionp_getfilecon(const char *name, security_context_t *p)
301 + return lgetfilecon(name, p);
303 +#endif /* WITH_SELINUX */
306 check_option_combinations(const struct predicate *p)
307 @@ -450,11 +543,17 @@ set_follow_state(enum SymlinkOption opt)
309 case SYMLINK_ALWAYS_DEREF: /* -L */
310 options.xstat = optionl_stat;
312 + options.x_getfilecon = optionl_getfilecon;
314 options.no_leaf_check = true;
317 case SYMLINK_NEVER_DEREF: /* -P (default) */
318 options.xstat = optionp_stat;
320 + options.x_getfilecon = optionp_getfilecon;
322 /* Can't turn no_leaf_check off because the user might have specified
325 @@ -462,6 +561,9 @@ set_follow_state(enum SymlinkOption opt)
327 case SYMLINK_DEREF_ARGSONLY: /* -H */
328 options.xstat = optionh_stat;
330 + options.x_getfilecon = optionh_getfilecon;
332 options.no_leaf_check = true;
335 @@ -1127,8 +1229,12 @@ tests (N can be +N or -N or N): -amin N
336 -nouser -nogroup -path PATTERN -perm [+-]MODE -regex PATTERN\n\
337 -readable -writable -executable\n\
338 -wholename PATTERN -size N[bcwkMG] -true -type [bcdpflsD] -uid N\n\
339 - -used N -user NAME -xtype [bcdpfls]\n"));
340 + -used N -user NAME -xtype [bcdpfls]"));
343 + -context CONTEXT\n"));
346 actions: -delete -print0 -printf FORMAT -fprintf FILE FORMAT -print \n\
347 -fprint0 FILE -fprint FILE -ls -fls FILE -prune -quit\n\
348 -exec COMMAND ; -exec COMMAND {} + -ok COMMAND ;\n\
349 @@ -2518,6 +2624,10 @@ parse_version (const struct parser_table
350 printf("LEAF_OPTIMISATION ");
353 +#if defined(WITH_SELINUX)
354 + printf("SELINUX ");
359 if (is_fts_enabled(&flags))
360 @@ -2552,6 +2662,32 @@ parse_version (const struct parser_table
366 +parse_context (const struct parser_table* entry, char **argv, int *arg_ptr)
368 + struct predicate *our_pred;
370 + if ((argv == NULL) || (argv[*arg_ptr] == NULL))
373 + if (is_selinux_enabled() <= 0)
375 + error (1, 0, _("invalid predicate -context: SELinux is not enabled."));
378 + our_pred = insert_primary (entry);
379 + our_pred->need_stat = false;
381 + our_pred->p_name = find_pred_name (pred_context);
383 + our_pred->args.scontext = argv[*arg_ptr];
388 +#endif /* WITH_SELINUX */
391 parse_xdev (const struct parser_table* entry, char **argv, int *arg_ptr)
393 @@ -2803,7 +2939,7 @@ insert_fprintf (struct format_val *vec,
395 for (scan2++; ISDIGIT (*scan2); scan2++)
397 - if (strchr ("abcdDfFgGhHiklmMnpPsStuUyY", *scan2))
398 + if (strchr ("abcdDfFgGhHiklmMnpPsStuUyYZ", *scan2))
400 segmentp = make_segment (segmentp, format, scan2 - format,
401 KIND_FORMAT, *scan2, 0,
402 @@ -2930,6 +3066,7 @@ make_segment (struct segment **segment,
403 case 'h': /* leading directories part of path */
404 case 'p': /* pathname */
405 case 'P': /* pathname with ARGV element stripped */
406 + case 'Z': /* SELinux security context */
410 diff -up findutils-4.4.2/find/pred.c_old findutils-4.4.2/find/pred.c
411 --- findutils-4.4.2/find/pred.c_old 2009-07-01 10:31:11.000000000 +0200
412 +++ findutils-4.4.2/find/pred.c 2009-07-01 10:33:45.000000000 +0200
418 +#include <selinux/selinux.h>
419 +#endif /*WITH_SELINUX*/
422 # include <libintl.h>
423 # define _(Text) gettext (Text)
424 @@ -230,6 +234,9 @@ struct pred_assoc pred_table[] =
425 {pred_user, "user "},
426 {pred_writable, "writable "},
427 {pred_xtype, "xtype "},
429 + {pred_context, "context"},
430 +#endif /*WITH_SELINUX*/
434 @@ -1054,6 +1061,27 @@ do_fprintf(struct format_val *dest,
435 mode_to_filetype(stat_buf->st_mode & S_IFMT));
438 + case 'Z': /* SELinux security context */
441 + security_context_t scontext;
443 + rv = (*options.x_getfilecon) (state.rel_pathname, &scontext);
447 + fprintf (stderr, "getfilecon(%s): %s", pathname,
453 + checked_fprintf (dest, segment->text, scontext);
454 + freecon (scontext);
457 +#endif /* WITH_SELINUX */
460 /* end of KIND_FORMAT case */
462 @@ -1844,6 +1872,32 @@ pred_xtype (const char *pathname, struct
464 return (pred_type (pathname, &sbuf, pred_ptr));
470 +pred_context (const char *pathname, struct stat *stat_buf,
471 + struct predicate *pred_ptr)
474 + security_context_t scontext;
476 + rv = (*options.x_getfilecon) (state.rel_pathname, &scontext);
480 + fprintf (stderr, "getfilecon(%s): %s\n", pathname, strerror(errno));
485 + rv = (fnmatch (pred_ptr->args.scontext, scontext, 0) == 0);
486 + freecon (scontext);
490 +#endif /*WITH_SELINUX*/
493 /* 1) fork to get a child; parent remembers the child pid
494 2) child execs the command requested
495 diff -up findutils-4.4.2/find/tree.c_old findutils-4.4.2/find/tree.c
496 --- findutils-4.4.2/find/tree.c_old 2009-07-01 10:33:57.000000000 +0200
497 +++ findutils-4.4.2/find/tree.c 2009-07-01 10:34:54.000000000 +0200
498 @@ -953,7 +953,8 @@ static struct pred_cost_lookup costlooku
499 { pred_used , NeedsStatInfo },
500 { pred_user , NeedsStatInfo },
501 { pred_writable , NeedsAccessInfo },
502 - { pred_xtype , NeedsType } /* roughly correct unless most files are symlinks */
503 + { pred_xtype , NeedsType }, /* roughly correct unless most files are symlinks */
504 + { pred_context , NeedsNothing } /* remove warning only:) */
506 static int pred_table_sorted = 0;
508 @@ -1434,6 +1435,9 @@ get_new_pred (const struct parser_table
509 last_pred->need_stat = true;
510 last_pred->need_type = true;
511 last_pred->args.str = NULL;
513 + last_pred->args.scontext = NULL;
515 last_pred->pred_next = NULL;
516 last_pred->pred_left = NULL;
517 last_pred->pred_right = NULL;