summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorXin Ouyang <Xin.Ouyang@windriver.com>2012-06-26 14:29:22 +0800
committerXin Ouyang <Xin.Ouyang@windriver.com>2012-06-28 10:42:22 +0800
commitaef5531fa3051cfadbda0083db19e62823b8b1fc (patch)
treec177363fc63f49e226969d9b707a960c2c6280b7
parent02bcec2d7053aa42d0ae71bb8e3fccd228ff166f (diff)
downloadmeta-selinux-aef5531fa3051cfadbda0083db19e62823b8b1fc.tar.gz
findutils: 4.4.2, support selinux
Signed-off-by: Xin Ouyang <Xin.Ouyang@windriver.com>
-rw-r--r--recipes-extended/findutils/findutils-4.4.2/findutils-selinux-gnulib.patch1174
-rw-r--r--recipes-extended/findutils/findutils-4.4.2/findutils-selinux.patch524
-rw-r--r--recipes-extended/findutils/findutils_4.4.2.bbappend10
3 files changed, 1708 insertions, 0 deletions
diff --git a/recipes-extended/findutils/findutils-4.4.2/findutils-selinux-gnulib.patch b/recipes-extended/findutils/findutils-4.4.2/findutils-selinux-gnulib.patch
new file mode 100644
index 0000000..85a1c3a
--- /dev/null
+++ b/recipes-extended/findutils/findutils-4.4.2/findutils-selinux-gnulib.patch
@@ -0,0 +1,1174 @@
1From: Xin Ouyang <Xin.Ouyang@windriver.com>
2Date: Tue, 26 Jun 2012 13:56:52 +0800
3Subject: [PATCH 2/2] findutils: support selinux and gnulib
4
5Upstream-Status: Inappropriate [configuration]
6
7This is a F13 SRPM patch.
8
9Once the selinux-at module appears on the list within import-gnulib.config,
10this patch is no longer needed.
11---
12 aclocal.m4 | 2 +
13 gnulib/lib/Makefile.am | 43 ++++++
14 gnulib/lib/at-func.c | 98 ++++++++++----
15 gnulib/lib/getfilecon.c | 87 ++++++++++++
16 gnulib/lib/openat.c | 285 ++++++++++++++++++++--------------------
17 gnulib/lib/openat.h | 88 ++++++-------
18 gnulib/lib/se-selinux.in.h | 73 ++++++++++
19 gnulib/lib/selinux-at.c | 72 ++++++++++
20 gnulib/lib/selinux-at.h | 52 ++++++++
21 gnulib/m4/gnulib-comp.m4 | 12 ++
22 gnulib/m4/selinux-context-h.m4 | 16 +++
23 gnulib/m4/selinux-selinux-h.m4 | 57 ++++++++
24 12 files changed, 665 insertions(+), 220 deletions(-)
25 create mode 100644 gnulib/lib/getfilecon.c
26 create mode 100644 gnulib/lib/se-selinux.in.h
27 create mode 100644 gnulib/lib/selinux-at.c
28 create mode 100644 gnulib/lib/selinux-at.h
29 create mode 100644 gnulib/m4/selinux-context-h.m4
30 create mode 100644 gnulib/m4/selinux-selinux-h.m4
31
32diff --git a/aclocal.m4 b/aclocal.m4
33index 95ff111..0034170 100644
34--- a/aclocal.m4
35+++ b/aclocal.m4
36@@ -115,6 +115,8 @@ m4_include([gnulib/m4/rpmatch.m4])
37 m4_include([gnulib/m4/same.m4])
38 m4_include([gnulib/m4/save-cwd.m4])
39 m4_include([gnulib/m4/savedir.m4])
40+m4_include([gnulib/m4/selinux-context-h.m4])
41+m4_include([gnulib/m4/selinux-selinux-h.m4])
42 m4_include([gnulib/m4/setenv.m4])
43 m4_include([gnulib/m4/ssize_t.m4])
44 m4_include([gnulib/m4/st_dm_mode.m4])
45diff --git a/gnulib/lib/Makefile.am b/gnulib/lib/Makefile.am
46index 59ed5f2..b13e509 100644
47--- a/gnulib/lib/Makefile.am
48+++ b/gnulib/lib/Makefile.am
49@@ -1007,6 +1007,49 @@ EXTRA_libgnulib_a_SOURCES += savedir.c
50
51 ## end gnulib module savedir
52
53+## begin gnulib module selinux-at
54+
55+
56+EXTRA_DIST += selinux-at.c selinux-at.h
57+
58+EXTRA_libgnulib_a_SOURCES += selinux-at.c
59+
60+## end gnulib module selinux-at
61+
62+## begin gnulib module selinux-h
63+
64+libgnulib_a_SOURCES += se-context.in.h se-selinux.in.h
65+
66+BUILT_SOURCES += selinux/selinux.h
67+selinux/selinux.h: se-selinux.in.h
68+ $(AM_V_at)$(MKDIR_P) selinux
69+ $(AM_V_GEN)rm -f $@-t $@ && \
70+ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \
71+ sed -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \
72+ -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
73+ -e 's|@''NEXT_SELINUX_SELINUX_H''@|$(NEXT_SELINUX_SELINUX_H)|g' \
74+ < $(srcdir)/se-selinux.in.h; \
75+ } > $@-t && \
76+ chmod a-x $@-t && \
77+ mv $@-t $@
78+MOSTLYCLEANFILES += selinux/selinux.h selinux/selinux.h-t
79+
80+BUILT_SOURCES += $(SELINUX_CONTEXT_H)
81+selinux/context.h: se-context.in.h
82+ $(AM_V_at)$(MKDIR_P) selinux
83+ $(AM_V_GEN)rm -f $@-t $@ && \
84+ cp $(srcdir)/se-context.in.h $@-t && \
85+ chmod a-x $@-t && \
86+ mv $@-t $@
87+MOSTLYCLEANFILES += selinux/context.h selinux/context.h-t
88+MOSTLYCLEANDIRS += selinux
89+
90+EXTRA_DIST += getfilecon.c
91+
92+EXTRA_libgnulib_a_SOURCES += getfilecon.c
93+
94+## end gnulib module selinux-h
95+
96 ## begin gnulib module setenv
97
98
99diff --git a/gnulib/lib/at-func.c b/gnulib/lib/at-func.c
100index c7963fe..73be401 100644
101--- a/gnulib/lib/at-func.c
102+++ b/gnulib/lib/at-func.c
103@@ -1,5 +1,5 @@
104 /* Define an at-style functions like fstatat, unlinkat, fchownat, etc.
105- Copyright (C) 2006 Free Software Foundation, Inc.
106+ Copyright (C) 2006, 2009 Free Software Foundation, Inc.
107
108 This program is free software: you can redistribute it and/or modify
109 it under the terms of the GNU General Public License as published by
110@@ -16,62 +16,106 @@
111
112 /* written by Jim Meyering */
113
114-#define CALL_FUNC(F) \
115- (AT_FUNC_USE_F1_COND \
116+#include "dirname.h" /* solely for definition of IS_ABSOLUTE_FILE_NAME */
117+#include "openat.h"
118+#include "openat-priv.h"
119+#include "save-cwd.h"
120+
121+#ifdef AT_FUNC_USE_F1_COND
122+# define CALL_FUNC(F) \
123+ (flag == AT_FUNC_USE_F1_COND \
124 ? AT_FUNC_F1 (F AT_FUNC_POST_FILE_ARGS) \
125 : AT_FUNC_F2 (F AT_FUNC_POST_FILE_ARGS))
126+# define VALIDATE_FLAG(F) \
127+ if (flag & ~AT_FUNC_USE_F1_COND) \
128+ { \
129+ errno = EINVAL; \
130+ return FUNC_FAIL; \
131+ }
132+#else
133+# define CALL_FUNC(F) (AT_FUNC_F1 (F AT_FUNC_POST_FILE_ARGS))
134+# define VALIDATE_FLAG(F) /* empty */
135+#endif
136+
137+#ifdef AT_FUNC_RESULT
138+# define FUNC_RESULT AT_FUNC_RESULT
139+#else
140+# define FUNC_RESULT int
141+#endif
142+
143+#ifdef AT_FUNC_FAIL
144+# define FUNC_FAIL AT_FUNC_FAIL
145+#else
146+# define FUNC_FAIL -1
147+#endif
148
149-/* Call AT_FUNC_F1 or AT_FUNC_F2 (testing AT_FUNC_USE_F1_COND to
150- determine which) to operate on FILE, which is in the directory
151- open on descriptor FD. If possible, do it without changing the
152+/* Call AT_FUNC_F1 to operate on FILE, which is in the directory
153+ open on descriptor FD. If AT_FUNC_USE_F1_COND is defined to a value,
154+ AT_FUNC_POST_FILE_PARAM_DECLS must inlude a parameter named flag;
155+ call AT_FUNC_F2 if FLAG is 0 or fail if FLAG contains more bits than
156+ AT_FUNC_USE_F1_COND. Return int and fail with -1 unless AT_FUNC_RESULT
157+ or AT_FUNC_FAIL are defined. If possible, do it without changing the
158 working directory. Otherwise, resort to using save_cwd/fchdir,
159 then AT_FUNC_F?/restore_cwd. If either the save_cwd or the restore_cwd
160 fails, then give a diagnostic and exit nonzero. */
161-int
162+FUNC_RESULT
163 AT_FUNC_NAME (int fd, char const *file AT_FUNC_POST_FILE_PARAM_DECLS)
164 {
165+ /* Be careful to choose names unlikely to conflict with
166+ AT_FUNC_POST_FILE_PARAM_DECLS. */
167 struct saved_cwd saved_cwd;
168 int saved_errno;
169- int err;
170+ FUNC_RESULT err;
171+
172+ VALIDATE_FLAG (flag);
173
174 if (fd == AT_FDCWD || IS_ABSOLUTE_FILE_NAME (file))
175 return CALL_FUNC (file);
176
177 {
178- char buf[OPENAT_BUFFER_SIZE];
179- char *proc_file = openat_proc_name (buf, fd, file);
180+ char proc_buf[OPENAT_BUFFER_SIZE];
181+ char *proc_file = openat_proc_name (proc_buf, fd, file);
182 if (proc_file)
183 {
184- int proc_result = CALL_FUNC (proc_file);
185- int proc_errno = errno;
186- if (proc_file != buf)
187- free (proc_file);
188- /* If the syscall succeeds, or if it fails with an unexpected
189- errno value, then return right away. Otherwise, fall through
190- and resort to using save_cwd/restore_cwd. */
191- if (0 <= proc_result)
192- return proc_result;
193- if (! EXPECTED_ERRNO (proc_errno))
194- {
195- errno = proc_errno;
196- return proc_result;
197- }
198+ FUNC_RESULT proc_result = CALL_FUNC (proc_file);
199+ int proc_errno = errno;
200+ if (proc_file != proc_buf)
201+ free (proc_file);
202+ /* If the syscall succeeds, or if it fails with an unexpected
203+ errno value, then return right away. Otherwise, fall through
204+ and resort to using save_cwd/restore_cwd. */
205+ if (FUNC_FAIL != proc_result)
206+ return proc_result;
207+ if (! EXPECTED_ERRNO (proc_errno))
208+ {
209+ errno = proc_errno;
210+ return proc_result;
211+ }
212 }
213 }
214
215 if (save_cwd (&saved_cwd) != 0)
216 openat_save_fail (errno);
217+ if (0 <= fd && fd == saved_cwd.desc)
218+ {
219+ /* If saving the working directory collides with the user's
220+ requested fd, then the user's fd must have been closed to
221+ begin with. */
222+ free_cwd (&saved_cwd);
223+ errno = EBADF;
224+ return FUNC_FAIL;
225+ }
226
227 if (fchdir (fd) != 0)
228 {
229 saved_errno = errno;
230 free_cwd (&saved_cwd);
231 errno = saved_errno;
232- return -1;
233+ return FUNC_FAIL;
234 }
235
236 err = CALL_FUNC (file);
237- saved_errno = (err < 0 ? errno : 0);
238+ saved_errno = (err == FUNC_FAIL ? errno : 0);
239
240 if (restore_cwd (&saved_cwd) != 0)
241 openat_restore_fail (errno);
242@@ -83,3 +127,5 @@ AT_FUNC_NAME (int fd, char const *file AT_FUNC_POST_FILE_PARAM_DECLS)
243 return err;
244 }
245 #undef CALL_FUNC
246+#undef FUNC_RESULT
247+#undef FUNC_FAIL
248diff --git a/gnulib/lib/getfilecon.c b/gnulib/lib/getfilecon.c
249new file mode 100644
250index 0000000..d712307
251--- /dev/null
252+++ b/gnulib/lib/getfilecon.c
253@@ -0,0 +1,87 @@
254+/* wrap getfilecon, lgetfilecon, and fgetfilecon
255+ Copyright (C) 2009 Free Software Foundation, Inc.
256+
257+ This program is free software; you can redistribute it and/or modify
258+ it under the terms of the GNU General Public License as published by
259+ the Free Software Foundation; either version 3, or (at your option)
260+ any later version.
261+
262+ This program is distributed in the hope that it will be useful,
263+ but WITHOUT ANY WARRANTY; without even the implied warranty of
264+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
265+ GNU General Public License for more details.
266+
267+ You should have received a copy of the GNU General Public License
268+ along with this program; if not, write to the Free Software Foundation,
269+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
270+
271+/* written by Jim Meyering */
272+
273+#include <config.h>
274+
275+#include <selinux/selinux.h>
276+
277+#include <sys/types.h>
278+#include <errno.h>
279+#include <string.h>
280+
281+/* FIXME: remove this once there is an errno-gnu module
282+ that guarantees the definition of ENODATA. */
283+#ifndef ENODATA
284+# define ENODATA ENOTSUP
285+#endif
286+
287+#undef getfilecon
288+#undef lgetfilecon
289+#undef fgetfilecon
290+int getfilecon (char const *file, security_context_t *con);
291+int lgetfilecon (char const *file, security_context_t *con);
292+int fgetfilecon (int fd, security_context_t *con);
293+
294+/* getfilecon, lgetfilecon, and fgetfilecon can all misbehave, be it
295+ via an old version of libselinux where these would return 0 and set the
296+ result context to NULL, or via a modern kernel+lib operating on a file
297+ from a disk whose attributes were set by a kernel from around 2006.
298+ In that latter case, the functions return a length of 10 for the
299+ "unlabeled" context. Map both failures to a return value of -1, and
300+ set errno to ENOTSUP in the first case, and ENODATA in the latter. */
301+
302+static inline int
303+map_to_failure (int ret, security_context_t *con)
304+{
305+ if (ret == 0)
306+ {
307+ errno = ENOTSUP;
308+ return -1;
309+ }
310+
311+ if (ret == 10 && strcmp (*con, "unlabeled") == 0)
312+ {
313+ freecon (*con);
314+ errno = ENODATA;
315+ return -1;
316+ }
317+
318+ return ret;
319+}
320+
321+int
322+rpl_getfilecon (char const *file, security_context_t *con)
323+{
324+ int ret = getfilecon (file, con);
325+ return map_to_failure (ret, con);
326+}
327+
328+int
329+rpl_lgetfilecon (char const *file, security_context_t *con)
330+{
331+ int ret = lgetfilecon (file, con);
332+ return map_to_failure (ret, con);
333+}
334+
335+int
336+rpl_fgetfilecon (int fd, security_context_t *con)
337+{
338+ int ret = fgetfilecon (fd, con);
339+ return map_to_failure (ret, con);
340+}
341diff --git a/gnulib/lib/openat.c b/gnulib/lib/openat.c
342index 73f24b0..2b15bb5 100644
343--- a/gnulib/lib/openat.c
344+++ b/gnulib/lib/openat.c
345@@ -1,5 +1,5 @@
346 /* provide a replacement openat function
347- Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
348+ Copyright (C) 2004-2009 Free Software Foundation, Inc.
349
350 This program is free software: you can redistribute it and/or modify
351 it under the terms of the GNU General Public License as published by
352@@ -22,13 +22,108 @@
353
354 #include <stdarg.h>
355 #include <stddef.h>
356+#include <string.h>
357+#include <sys/stat.h>
358
359 #include "dirname.h" /* solely for definition of IS_ABSOLUTE_FILE_NAME */
360-#include "fcntl--.h"
361-#include "lstat.h"
362 #include "openat-priv.h"
363 #include "save-cwd.h"
364
365+#if HAVE_OPENAT
366+
367+# undef openat
368+
369+/* Like openat, but work around Solaris 9 bugs with trailing slash. */
370+int
371+rpl_openat (int dfd, char const *filename, int flags, ...)
372+{
373+ mode_t mode;
374+ int fd;
375+
376+ mode = 0;
377+ if (flags & O_CREAT)
378+ {
379+ va_list arg;
380+ va_start (arg, flags);
381+
382+ /* We have to use PROMOTED_MODE_T instead of mode_t, otherwise GCC 4
383+ creates crashing code when 'mode_t' is smaller than 'int'. */
384+ mode = va_arg (arg, PROMOTED_MODE_T);
385+
386+ va_end (arg);
387+ }
388+
389+#if OPEN_TRAILING_SLASH_BUG
390+ /* If the filename ends in a slash and one of O_CREAT, O_WRONLY, O_RDWR
391+ is specified, then fail.
392+ Rationale: POSIX <http://www.opengroup.org/susv3/basedefs/xbd_chap04.html>
393+ says that
394+ "A pathname that contains at least one non-slash character and that
395+ ends with one or more trailing slashes shall be resolved as if a
396+ single dot character ( '.' ) were appended to the pathname."
397+ and
398+ "The special filename dot shall refer to the directory specified by
399+ its predecessor."
400+ If the named file already exists as a directory, then
401+ - if O_CREAT is specified, open() must fail because of the semantics
402+ of O_CREAT,
403+ - if O_WRONLY or O_RDWR is specified, open() must fail because POSIX
404+ <http://www.opengroup.org/susv3/functions/open.html> says that it
405+ fails with errno = EISDIR in this case.
406+ If the named file does not exist or does not name a directory, then
407+ - if O_CREAT is specified, open() must fail since open() cannot create
408+ directories,
409+ - if O_WRONLY or O_RDWR is specified, open() must fail because the
410+ file does not contain a '.' directory. */
411+ if (flags & (O_CREAT | O_WRONLY | O_RDWR))
412+ {
413+ size_t len = strlen (filename);
414+ if (len > 0 && filename[len - 1] == '/')
415+ {
416+ errno = EISDIR;
417+ return -1;
418+ }
419+ }
420+#endif
421+
422+ fd = openat (dfd, filename, flags, mode);
423+
424+#if OPEN_TRAILING_SLASH_BUG
425+ /* If the filename ends in a slash and fd does not refer to a directory,
426+ then fail.
427+ Rationale: POSIX <http://www.opengroup.org/susv3/basedefs/xbd_chap04.html>
428+ says that
429+ "A pathname that contains at least one non-slash character and that
430+ ends with one or more trailing slashes shall be resolved as if a
431+ single dot character ( '.' ) were appended to the pathname."
432+ and
433+ "The special filename dot shall refer to the directory specified by
434+ its predecessor."
435+ If the named file without the slash is not a directory, open() must fail
436+ with ENOTDIR. */
437+ if (fd >= 0)
438+ {
439+ /* We know len is positive, since open did not fail with ENOENT. */
440+ size_t len = strlen (filename);
441+ if (filename[len - 1] == '/')
442+ {
443+ struct stat statbuf;
444+
445+ if (fstat (fd, &statbuf) >= 0 && !S_ISDIR (statbuf.st_mode))
446+ {
447+ close (fd);
448+ errno = ENOTDIR;
449+ return -1;
450+ }
451+ }
452+ }
453+#endif
454+
455+ return fd;
456+}
457+
458+#else /* !HAVE_OPENAT */
459+
460 /* Replacement for Solaris' openat function.
461 <http://www.google.com/search?q=openat+site:docs.sun.com>
462 First, try to simulate it via open ("/proc/self/fd/FD/FILE").
463@@ -47,12 +142,9 @@ openat (int fd, char const *file, int flags, ...)
464 va_list arg;
465 va_start (arg, flags);
466
467- /* If mode_t is narrower than int, use the promoted type (int),
468- not mode_t. Use sizeof to guess whether mode_t is narrower;
469- we don't know of any practical counterexamples. */
470- mode = (sizeof (mode_t) < sizeof (int)
471- ? va_arg (arg, int)
472- : va_arg (arg, mode_t));
473+ /* We have to use PROMOTED_MODE_T instead of mode_t, otherwise GCC 4
474+ creates crashing code when 'mode_t' is smaller than 'int'. */
475+ mode = va_arg (arg, PROMOTED_MODE_T);
476
477 va_end (arg);
478 }
479@@ -73,7 +165,7 @@ openat (int fd, char const *file, int flags, ...)
480
481 int
482 openat_permissive (int fd, char const *file, int flags, mode_t mode,
483- int *cwd_errno)
484+ int *cwd_errno)
485 {
486 struct saved_cwd saved_cwd;
487 int saved_errno;
488@@ -88,18 +180,18 @@ openat_permissive (int fd, char const *file, int flags, mode_t mode,
489 char *proc_file = openat_proc_name (buf, fd, file);
490 if (proc_file)
491 {
492- int open_result = open (proc_file, flags, mode);
493- int open_errno = errno;
494- if (proc_file != buf)
495- free (proc_file);
496- /* If the syscall succeeds, or if it fails with an unexpected
497- errno value, then return right away. Otherwise, fall through
498- and resort to using save_cwd/restore_cwd. */
499- if (0 <= open_result || ! EXPECTED_ERRNO (open_errno))
500- {
501- errno = open_errno;
502- return open_result;
503- }
504+ int open_result = open (proc_file, flags, mode);
505+ int open_errno = errno;
506+ if (proc_file != buf)
507+ free (proc_file);
508+ /* If the syscall succeeds, or if it fails with an unexpected
509+ errno value, then return right away. Otherwise, fall through
510+ and resort to using save_cwd/restore_cwd. */
511+ if (0 <= open_result || ! EXPECTED_ERRNO (open_errno))
512+ {
513+ errno = open_errno;
514+ return open_result;
515+ }
516 }
517 }
518
519@@ -107,9 +199,18 @@ openat_permissive (int fd, char const *file, int flags, mode_t mode,
520 if (! save_ok)
521 {
522 if (! cwd_errno)
523- openat_save_fail (errno);
524+ openat_save_fail (errno);
525 *cwd_errno = errno;
526 }
527+ if (0 <= fd && fd == saved_cwd.desc)
528+ {
529+ /* If saving the working directory collides with the user's
530+ requested fd, then the user's fd must have been closed to
531+ begin with. */
532+ free_cwd (&saved_cwd);
533+ errno = EBADF;
534+ return -1;
535+ }
536
537 err = fchdir (fd);
538 saved_errno = errno;
539@@ -119,11 +220,17 @@ openat_permissive (int fd, char const *file, int flags, mode_t mode,
540 err = open (file, flags, mode);
541 saved_errno = errno;
542 if (save_ok && restore_cwd (&saved_cwd) != 0)
543- {
544- if (! cwd_errno)
545- openat_restore_fail (errno);
546- *cwd_errno = errno;
547- }
548+ {
549+ if (! cwd_errno)
550+ {
551+ /* Don't write a message to just-created fd 2. */
552+ saved_errno = errno;
553+ if (err == STDERR_FILENO)
554+ close (err);
555+ openat_restore_fail (saved_errno);
556+ }
557+ *cwd_errno = errno;
558+ }
559 }
560
561 free_cwd (&saved_cwd);
562@@ -144,125 +251,15 @@ openat_needs_fchdir (void)
563 char buf[OPENAT_BUFFER_SIZE];
564 char *proc_file = openat_proc_name (buf, fd, ".");
565 if (proc_file)
566- {
567- needs_fchdir = false;
568- if (proc_file != buf)
569- free (proc_file);
570- }
571+ {
572+ needs_fchdir = false;
573+ if (proc_file != buf)
574+ free (proc_file);
575+ }
576 close (fd);
577 }
578
579 return needs_fchdir;
580 }
581
582-#if !HAVE_FDOPENDIR
583-
584-/* Replacement for Solaris' function by the same name.
585- <http://www.google.com/search?q=fdopendir+site:docs.sun.com>
586- First, try to simulate it via opendir ("/proc/self/fd/FD"). Failing
587- that, simulate it by doing save_cwd/fchdir/opendir(".")/restore_cwd.
588- If either the save_cwd or the restore_cwd fails (relatively unlikely),
589- then give a diagnostic and exit nonzero.
590- Otherwise, this function works just like Solaris' fdopendir.
591-
592- W A R N I N G:
593- Unlike the other fd-related functions here, this one
594- effectively consumes its FD parameter. The caller should not
595- close or otherwise manipulate FD if this function returns successfully. */
596-DIR *
597-fdopendir (int fd)
598-{
599- struct saved_cwd saved_cwd;
600- int saved_errno;
601- DIR *dir;
602-
603- char buf[OPENAT_BUFFER_SIZE];
604- char *proc_file = openat_proc_name (buf, fd, ".");
605- if (proc_file)
606- {
607- dir = opendir (proc_file);
608- saved_errno = errno;
609- }
610- else
611- {
612- dir = NULL;
613- saved_errno = EOPNOTSUPP;
614- }
615-
616- /* If the syscall fails with an expected errno value, resort to
617- save_cwd/restore_cwd. */
618- if (! dir && EXPECTED_ERRNO (saved_errno))
619- {
620- if (save_cwd (&saved_cwd) != 0)
621- openat_save_fail (errno);
622-
623- if (fchdir (fd) != 0)
624- {
625- dir = NULL;
626- saved_errno = errno;
627- }
628- else
629- {
630- dir = opendir (".");
631- saved_errno = errno;
632-
633- if (restore_cwd (&saved_cwd) != 0)
634- openat_restore_fail (errno);
635- }
636-
637- free_cwd (&saved_cwd);
638- }
639-
640- if (dir)
641- close (fd);
642- if (proc_file != buf)
643- free (proc_file);
644- errno = saved_errno;
645- return dir;
646-}
647-
648-#endif
649-
650-/* Replacement for Solaris' function by the same name.
651- <http://www.google.com/search?q=fstatat+site:docs.sun.com>
652- First, try to simulate it via l?stat ("/proc/self/fd/FD/FILE").
653- Failing that, simulate it via save_cwd/fchdir/(stat|lstat)/restore_cwd.
654- If either the save_cwd or the restore_cwd fails (relatively unlikely),
655- then give a diagnostic and exit nonzero.
656- Otherwise, this function works just like Solaris' fstatat. */
657-
658-#define AT_FUNC_NAME fstatat
659-#define AT_FUNC_F1 lstat
660-#define AT_FUNC_F2 stat
661-#define AT_FUNC_USE_F1_COND flag == AT_SYMLINK_NOFOLLOW
662-#define AT_FUNC_POST_FILE_PARAM_DECLS , struct stat *st, int flag
663-#define AT_FUNC_POST_FILE_ARGS , st
664-#include "at-func.c"
665-#undef AT_FUNC_NAME
666-#undef AT_FUNC_F1
667-#undef AT_FUNC_F2
668-#undef AT_FUNC_USE_F1_COND
669-#undef AT_FUNC_POST_FILE_PARAM_DECLS
670-#undef AT_FUNC_POST_FILE_ARGS
671-
672-/* Replacement for Solaris' function by the same name.
673- <http://www.google.com/search?q=unlinkat+site:docs.sun.com>
674- First, try to simulate it via (unlink|rmdir) ("/proc/self/fd/FD/FILE").
675- Failing that, simulate it via save_cwd/fchdir/(unlink|rmdir)/restore_cwd.
676- If either the save_cwd or the restore_cwd fails (relatively unlikely),
677- then give a diagnostic and exit nonzero.
678- Otherwise, this function works just like Solaris' unlinkat. */
679-
680-#define AT_FUNC_NAME unlinkat
681-#define AT_FUNC_F1 rmdir
682-#define AT_FUNC_F2 unlink
683-#define AT_FUNC_USE_F1_COND flag == AT_REMOVEDIR
684-#define AT_FUNC_POST_FILE_PARAM_DECLS , int flag
685-#define AT_FUNC_POST_FILE_ARGS /* empty */
686-#include "at-func.c"
687-#undef AT_FUNC_NAME
688-#undef AT_FUNC_F1
689-#undef AT_FUNC_F2
690-#undef AT_FUNC_USE_F1_COND
691-#undef AT_FUNC_POST_FILE_PARAM_DECLS
692-#undef AT_FUNC_POST_FILE_ARGS
693+#endif /* !HAVE_OPENAT */
694diff --git a/gnulib/lib/openat.h b/gnulib/lib/openat.h
695index b5e4f11..433b998 100644
696--- a/gnulib/lib/openat.h
697+++ b/gnulib/lib/openat.h
698@@ -1,5 +1,5 @@
699 /* provide a replacement openat function
700- Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
701+ Copyright (C) 2004-2006, 2008-2009 Free Software Foundation, Inc.
702
703 This program is free software: you can redistribute it and/or modify
704 it under the terms of the GNU General Public License as published by
705@@ -16,6 +16,9 @@
706
707 /* written by Jim Meyering */
708
709+#ifndef _GL_HEADER_OPENAT
710+#define _GL_HEADER_OPENAT
711+
712 #include <fcntl.h>
713
714 #include <sys/types.h>
715@@ -25,7 +28,7 @@
716 #include <stdbool.h>
717
718 #ifndef __attribute__
719-# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8) || __STRICT_ANSI__
720+# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8)
721 # define __attribute__(x) /* empty */
722 # endif
723 #endif
724@@ -34,46 +37,10 @@
725 # define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__))
726 #endif
727
728-/* Work around a bug in Solaris 9 and 10: AT_FDCWD is positive. Its
729- value exceeds INT_MAX, so its use as an int doesn't conform to the
730- C standard, and GCC and Sun C complain in some cases. If the bug
731- is present, undef AT_FDCWD here, so it can be redefined below. */
732-#if 0 < AT_FDCWD && AT_FDCWD == 0xffd19553
733-# undef AT_FDCWD
734-#endif
735-
736-/* Use the same bit pattern as Solaris 9, but with the proper
737- signedness. The bit pattern is important, in case this actually is
738- Solaris with the above workaround. */
739-#ifndef AT_FDCWD
740-# define AT_FDCWD (-3041965)
741-#endif
742-
743-/* Use the same values as Solaris 9. This shouldn't matter, but
744- there's no real reason to differ. */
745-#ifndef AT_SYMLINK_NOFOLLOW
746-# define AT_SYMLINK_NOFOLLOW 4096
747-# define AT_REMOVEDIR 1
748-#endif
749-
750-#ifdef __OPENAT_PREFIX
751+#if !HAVE_OPENAT
752
753-# undef openat
754-# define __OPENAT_CONCAT(x, y) x ## y
755-# define __OPENAT_XCONCAT(x, y) __OPENAT_CONCAT (x, y)
756-# define __OPENAT_ID(y) __OPENAT_XCONCAT (__OPENAT_PREFIX, y)
757-# define openat __OPENAT_ID (openat)
758-int openat (int fd, char const *file, int flags, /* mode_t mode */ ...);
759 int openat_permissive (int fd, char const *file, int flags, mode_t mode,
760 int *cwd_errno);
761-# if ! HAVE_FDOPENDIR
762-# define fdopendir __OPENAT_ID (fdopendir)
763-# endif
764-DIR *fdopendir (int fd);
765-# define fstatat __OPENAT_ID (fstatat)
766-int fstatat (int fd, char const *file, struct stat *st, int flag);
767-# define unlinkat __OPENAT_ID (unlinkat)
768-int unlinkat (int fd, char const *file, int flag);
769 bool openat_needs_fchdir (void);
770
771 #else
772@@ -84,19 +51,8 @@ bool openat_needs_fchdir (void);
773
774 #endif
775
776-#if HAVE_OPENAT && ! LSTAT_FOLLOWS_SLASHED_SYMLINK
777-int rpl_fstatat (int fd, char const *file, struct stat *st, int flag);
778-# if !COMPILING_FSTATAT
779-# undef fstatat
780-# define fstatat rpl_fstatat
781-# endif
782-#endif
783-
784-int mkdirat (int fd, char const *file, mode_t mode);
785 void openat_restore_fail (int) ATTRIBUTE_NORETURN;
786 void openat_save_fail (int) ATTRIBUTE_NORETURN;
787-int fchmodat (int fd, char const *file, mode_t mode, int flag);
788-int fchownat (int fd, char const *file, uid_t owner, gid_t group, int flag);
789
790 /* Using these function names makes application code
791 slightly more readable than it would be with
792@@ -124,3 +80,35 @@ lchmodat (int fd, char const *file, mode_t mode)
793 {
794 return fchmodat (fd, file, mode, AT_SYMLINK_NOFOLLOW);
795 }
796+
797+static inline int
798+statat (int fd, char const *name, struct stat *st)
799+{
800+ return fstatat (fd, name, st, 0);
801+}
802+
803+static inline int
804+lstatat (int fd, char const *name, struct stat *st)
805+{
806+ return fstatat (fd, name, st, AT_SYMLINK_NOFOLLOW);
807+}
808+
809+#if GNULIB_FACCESSAT
810+/* For now, there are no wrappers named laccessat or leuidaccessat,
811+ since gnulib doesn't support faccessat(,AT_SYMLINK_NOFOLLOW) and
812+ since access rights on symlinks are of limited utility. */
813+
814+static inline int
815+accessat (int fd, char const *file, int mode)
816+{
817+ return faccessat (fd, file, mode, 0);
818+}
819+
820+static inline int
821+euidaccessat (int fd, char const *file, int mode)
822+{
823+ return faccessat (fd, file, mode, AT_EACCESS);
824+}
825+#endif
826+
827+#endif /* _GL_HEADER_OPENAT */
828diff --git a/gnulib/lib/se-selinux.in.h b/gnulib/lib/se-selinux.in.h
829new file mode 100644
830index 0000000..3f30a3c
831--- /dev/null
832+++ b/gnulib/lib/se-selinux.in.h
833@@ -0,0 +1,73 @@
834+#ifndef _GL_SELINUX_SELINUX_H
835+# define _GL_SELINUX_SELINUX_H
836+
837+# if __GNUC__ >= 3
838+#pragma GCC system_header
839+# endif
840+
841+# if HAVE_SELINUX_SELINUX_H
842+
843+#@INCLUDE_NEXT@ @NEXT_SELINUX_SELINUX_H@
844+
845+# else
846+
847+# include <sys/types.h>
848+# include <errno.h>
849+
850+typedef unsigned short security_class_t;
851+# define security_context_t char*
852+# define is_selinux_enabled() 0
853+
854+static inline int getcon (security_context_t *con _UNUSED_PARAMETER_)
855+ { errno = ENOTSUP; return -1; }
856+static inline void freecon (security_context_t con _UNUSED_PARAMETER_) {}
857+
858+
859+static inline int getfscreatecon (security_context_t *con _UNUSED_PARAMETER_)
860+ { errno = ENOTSUP; return -1; }
861+static inline int setfscreatecon (security_context_t con _UNUSED_PARAMETER_)
862+ { errno = ENOTSUP; return -1; }
863+static inline int matchpathcon (char const *file _UNUSED_PARAMETER_,
864+ mode_t m _UNUSED_PARAMETER_,
865+ security_context_t *con _UNUSED_PARAMETER_)
866+ { errno = ENOTSUP; return -1; }
867+static inline int getfilecon (char const *file _UNUSED_PARAMETER_,
868+ security_context_t *con _UNUSED_PARAMETER_)
869+ { errno = ENOTSUP; return -1; }
870+static inline int lgetfilecon (char const *file _UNUSED_PARAMETER_,
871+ security_context_t *con _UNUSED_PARAMETER_)
872+ { errno = ENOTSUP; return -1; }
873+static inline int fgetfilecon (int fd,
874+ security_context_t *con _UNUSED_PARAMETER_)
875+ { errno = ENOTSUP; return -1; }
876+static inline int setfilecon (char const *file _UNUSED_PARAMETER_,
877+ security_context_t con _UNUSED_PARAMETER_)
878+ { errno = ENOTSUP; return -1; }
879+static inline int lsetfilecon (char const *file _UNUSED_PARAMETER_,
880+ security_context_t con _UNUSED_PARAMETER_)
881+ { errno = ENOTSUP; return -1; }
882+static inline int fsetfilecon (int fd _UNUSED_PARAMETER_,
883+ security_context_t con _UNUSED_PARAMETER_)
884+ { errno = ENOTSUP; return -1; }
885+
886+static inline int security_check_context
887+ (security_context_t con _UNUSED_PARAMETER_)
888+ { errno = ENOTSUP; return -1; }
889+static inline int security_check_context_raw
890+ (security_context_t con _UNUSED_PARAMETER_)
891+ { errno = ENOTSUP; return -1; }
892+static inline int setexeccon (security_context_t con _UNUSED_PARAMETER_)
893+ { errno = ENOTSUP; return -1; }
894+static inline int security_compute_create
895+ (security_context_t scon _UNUSED_PARAMETER_,
896+ security_context_t tcon _UNUSED_PARAMETER_,
897+ security_class_t tclass _UNUSED_PARAMETER_,
898+ security_context_t *newcon _UNUSED_PARAMETER_)
899+ { errno = ENOTSUP; return -1; }
900+static inline int matchpathcon_init_prefix
901+ (char const *path _UNUSED_PARAMETER_,
902+ char const *prefix _UNUSED_PARAMETER_)
903+ { errno = ENOTSUP; return -1; }
904+
905+# endif
906+#endif /* _GL_SELINUX_SELINUX_H */
907diff --git a/gnulib/lib/selinux-at.c b/gnulib/lib/selinux-at.c
908new file mode 100644
909index 0000000..65f938b
910--- /dev/null
911+++ b/gnulib/lib/selinux-at.c
912@@ -0,0 +1,72 @@
913+/* openat-style fd-relative functions for SE Linux
914+ Copyright (C) 2007, 2009 Free Software Foundation, Inc.
915+
916+ This program is free software: you can redistribute it and/or modify
917+ it under the terms of the GNU General Public License as published by
918+ the Free Software Foundation, either version 3 of the License, or
919+ (at your option) any later version.
920+
921+ This program is distributed in the hope that it will be useful,
922+ but WITHOUT ANY WARRANTY; without even the implied warranty of
923+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
924+ GNU General Public License for more details.
925+
926+ You should have received a copy of the GNU General Public License
927+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
928+
929+/* written by Jim Meyering */
930+
931+#include <config.h>
932+
933+#include "selinux-at.h"
934+#include "openat.h"
935+
936+#include <stdlib.h>
937+#include <unistd.h>
938+#include <errno.h>
939+#include <fcntl.h>
940+
941+#include "dirname.h" /* solely for definition of IS_ABSOLUTE_FILE_NAME */
942+#include "save-cwd.h"
943+
944+#include "openat-priv.h"
945+
946+#define AT_FUNC_NAME getfileconat
947+#define AT_FUNC_F1 getfilecon
948+#define AT_FUNC_POST_FILE_PARAM_DECLS , security_context_t *con
949+#define AT_FUNC_POST_FILE_ARGS , con
950+#include "at-func.c"
951+#undef AT_FUNC_NAME
952+#undef AT_FUNC_F1
953+#undef AT_FUNC_POST_FILE_PARAM_DECLS
954+#undef AT_FUNC_POST_FILE_ARGS
955+
956+#define AT_FUNC_NAME lgetfileconat
957+#define AT_FUNC_F1 lgetfilecon
958+#define AT_FUNC_POST_FILE_PARAM_DECLS , security_context_t *con
959+#define AT_FUNC_POST_FILE_ARGS , con
960+#include "at-func.c"
961+#undef AT_FUNC_NAME
962+#undef AT_FUNC_F1
963+#undef AT_FUNC_POST_FILE_PARAM_DECLS
964+#undef AT_FUNC_POST_FILE_ARGS
965+
966+#define AT_FUNC_NAME setfileconat
967+#define AT_FUNC_F1 setfilecon
968+#define AT_FUNC_POST_FILE_PARAM_DECLS , security_context_t con
969+#define AT_FUNC_POST_FILE_ARGS , con
970+#include "at-func.c"
971+#undef AT_FUNC_NAME
972+#undef AT_FUNC_F1
973+#undef AT_FUNC_POST_FILE_PARAM_DECLS
974+#undef AT_FUNC_POST_FILE_ARGS
975+
976+#define AT_FUNC_NAME lsetfileconat
977+#define AT_FUNC_F1 lsetfilecon
978+#define AT_FUNC_POST_FILE_PARAM_DECLS , security_context_t con
979+#define AT_FUNC_POST_FILE_ARGS , con
980+#include "at-func.c"
981+#undef AT_FUNC_NAME
982+#undef AT_FUNC_F1
983+#undef AT_FUNC_POST_FILE_PARAM_DECLS
984+#undef AT_FUNC_POST_FILE_ARGS
985diff --git a/gnulib/lib/selinux-at.h b/gnulib/lib/selinux-at.h
986new file mode 100644
987index 0000000..1d84c19
988--- /dev/null
989+++ b/gnulib/lib/selinux-at.h
990@@ -0,0 +1,52 @@
991+/* Prototypes for openat-style fd-relative SELinux functions
992+ Copyright (C) 2007, 2009 Free Software Foundation, Inc.
993+
994+ This program is free software: you can redistribute it and/or modify
995+ it under the terms of the GNU General Public License as published by
996+ the Free Software Foundation, either version 3 of the License, or
997+ (at your option) any later version.
998+
999+ This program is distributed in the hope that it will be useful,
1000+ but WITHOUT ANY WARRANTY; without even the implied warranty of
1001+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1002+ GNU General Public License for more details.
1003+
1004+ You should have received a copy of the GNU General Public License
1005+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
1006+
1007+#include <selinux/selinux.h>
1008+#include <selinux/context.h>
1009+
1010+/* These are the dir-fd-relative variants of the functions without the
1011+ "at" suffix. For example, getfileconat (AT_FDCWD, file, &c) is usually
1012+ equivalent to getfilecon (file, &c). The emulation is accomplished
1013+ by first attempting getfilecon ("/proc/self/fd/DIR_FD/FILE", &c).
1014+ Failing that, simulate it via save_cwd/fchdir/getfilecon/restore_cwd.
1015+ If either the save_cwd or the restore_cwd fails (relatively unlikely),
1016+ then give a diagnostic and exit nonzero. */
1017+
1018+/* dir-fd-relative getfilecon. Set *CON to the SELinux security context
1019+ of the file specified by DIR_FD and FILE and return the length of *CON.
1020+ DIR_FD and FILE are interpreted as for fstatat[*]. A non-NULL *CON
1021+ must be freed with freecon. Upon error, set *CON to NULL, set errno
1022+ and return -1.
1023+ [*] with flags=0 here, with flags=AT_SYMLINK_NOFOLLOW for lgetfileconat */
1024+int getfileconat (int dir_fd, char const *file, security_context_t *con);
1025+
1026+/* dir-fd-relative lgetfilecon. This function is just like getfileconat,
1027+ except when DIR_FD and FILE specify a symlink: lgetfileconat operates on
1028+ the symlink, while getfileconat operates on the referent of the symlink. */
1029+int lgetfileconat (int dir_fd, char const *file, security_context_t *con);
1030+
1031+/* dir-fd-relative setfilecon. Set the SELinux security context of
1032+ the file specified by DIR_FD and FILE to CON. DIR_FD and FILE are
1033+ interpreted as for fstatat[*]. Upon success, return 0.
1034+ Otherwise, return -1 and set errno. */
1035+int setfileconat (int dir_fd, char const *file, security_context_t con);
1036+
1037+/* dir-fd-relative lsetfilecon. This function is just like setfileconat,
1038+ except that rather than dereferencing a symlink, this function affects it. */
1039+/* dir-fd-relative lsetfilecon. This function is just like setfileconat,
1040+ except when DIR_FD and FILE specify a symlink: lsetfileconat operates on
1041+ the symlink, while setfileconat operates on the referent of the symlink. */
1042+int lsetfileconat (int dir_fd, char const *file, security_context_t con);
1043diff --git a/gnulib/m4/gnulib-comp.m4 b/gnulib/m4/gnulib-comp.m4
1044index 1efe223..87f11dd 100644
1045--- a/gnulib/m4/gnulib-comp.m4
1046+++ b/gnulib/m4/gnulib-comp.m4
1047@@ -165,6 +165,11 @@ AC_DEFUN([gl_INIT],
1048 gl_SAME
1049 gl_SAVE_CWD
1050 gl_SAVEDIR
1051+ AC_CHECK_HEADERS([selinux/flask.h])
1052+ AC_LIBOBJ([selinux-at])
1053+ gl_HEADERS_SELINUX_SELINUX_H
1054+ gl_HEADERS_SELINUX_CONTEXT_H
1055+ AC_REQUIRE([AC_C_INLINE])
1056 gl_FUNC_SETENV
1057 gl_FUNC_UNSETENV
1058 gt_TYPE_SSIZE_T
1059@@ -425,6 +430,7 @@ AC_DEFUN([gl_FILE_LIST], [
1060 lib/getdate.h
1061 lib/getdate.y
1062 lib/getdelim.c
1063+ lib/getfilecon.c
1064 lib/getline.c
1065 lib/getopt.c
1066 lib/getopt.in.h
1067@@ -506,6 +512,10 @@ AC_DEFUN([gl_FILE_LIST], [
1068 lib/save-cwd.h
1069 lib/savedir.c
1070 lib/savedir.h
1071+ lib/se-context.in.h
1072+ lib/se-selinux.in.h
1073+ lib/selinux-at.c
1074+ lib/selinux-at.h
1075 lib/setenv.c
1076 lib/setenv.h
1077 lib/stat-macros.h
1078@@ -688,6 +698,8 @@ AC_DEFUN([gl_FILE_LIST], [
1079 m4/same.m4
1080 m4/save-cwd.m4
1081 m4/savedir.m4
1082+ m4/selinux-context-h.m4
1083+ m4/selinux-selinux-h.m4
1084 m4/setenv.m4
1085 m4/size_max.m4
1086 m4/ssize_t.m4
1087diff --git a/gnulib/m4/selinux-context-h.m4 b/gnulib/m4/selinux-context-h.m4
1088new file mode 100644
1089index 0000000..6b0bed1
1090--- /dev/null
1091+++ b/gnulib/m4/selinux-context-h.m4
1092@@ -0,0 +1,16 @@
1093+# serial 1 -*- Autoconf -*-
1094+# Copyright (C) 2006, 2007 Free Software Foundation, Inc.
1095+# This file is free software; the Free Software Foundation
1096+# gives unlimited permission to copy and/or distribute it,
1097+# with or without modifications, as long as this notice is preserved.
1098+
1099+# From Jim Meyering
1100+# Provide <selinux/context.h>, if necessary.
1101+
1102+AC_DEFUN([gl_HEADERS_SELINUX_CONTEXT_H],
1103+[
1104+ AC_CHECK_HEADERS([selinux/context.h],
1105+ [SELINUX_CONTEXT_H=],
1106+ [SELINUX_CONTEXT_H=selinux/context.h])
1107+ AC_SUBST([SELINUX_CONTEXT_H])
1108+])
1109diff --git a/gnulib/m4/selinux-selinux-h.m4 b/gnulib/m4/selinux-selinux-h.m4
1110new file mode 100644
1111index 0000000..767c4f7
1112--- /dev/null
1113+++ b/gnulib/m4/selinux-selinux-h.m4
1114@@ -0,0 +1,57 @@
1115+# serial 3 -*- Autoconf -*-
1116+# Copyright (C) 2006, 2007, 2009 Free Software Foundation, Inc.
1117+# This file is free software; the Free Software Foundation
1118+# gives unlimited permission to copy and/or distribute it,
1119+# with or without modifications, as long as this notice is preserved.
1120+
1121+# From Jim Meyering
1122+# Provide <selinux/selinux.h>, if necessary.
1123+# If it is already present, provide wrapper functions to guard against
1124+# misbehavior from getfilecon, lgetfilecon, and fgetfilecon.
1125+
1126+AC_DEFUN([gl_HEADERS_SELINUX_SELINUX_H],
1127+[
1128+ AC_REQUIRE([gl_LIBSELINUX])
1129+ AC_CHECK_HEADERS([selinux/selinux.h])
1130+
1131+ if test "$ac_cv_header_selinux_selinux_h" = yes; then
1132+ # We do have <selinux/selinux.h>, so do compile getfilecon.c
1133+ # and arrange to use its wrappers.
1134+ AC_LIBOBJ([getfilecon])
1135+ gl_CHECK_NEXT_HEADERS([selinux/selinux.h])
1136+ AC_DEFINE([getfilecon], [rpl_getfilecon],
1137+ [Always use our getfilecon wrapper.])
1138+ AC_DEFINE([lgetfilecon], [rpl_lgetfilecon],
1139+ [Always use our lgetfilecon wrapper.])
1140+ AC_DEFINE([fgetfilecon], [rpl_fgetfilecon],
1141+ [Always use our fgetfilecon wrapper.])
1142+ fi
1143+
1144+ case "$ac_cv_search_setfilecon:$ac_cv_header_selinux_selinux_h" in
1145+ no:*) # already warned
1146+ ;;
1147+ *:no)
1148+ AC_MSG_WARN([libselinux was found but selinux/selinux.h is missing.])
1149+ AC_MSG_WARN([AC_PACKAGE_NAME will be compiled without SELinux support.])
1150+ esac
1151+])
1152+
1153+AC_DEFUN([gl_LIBSELINUX],
1154+[
1155+ AC_REQUIRE([AC_CANONICAL_HOST])
1156+ AC_REQUIRE([AC_CANONICAL_BUILD])
1157+ LIB_SELINUX=
1158+ gl_save_LIBS=$LIBS
1159+ AC_SEARCH_LIBS([setfilecon], [selinux],
1160+ [test "$ac_cv_search_setfilecon" = "none required" ||
1161+ LIB_SELINUX=$ac_cv_search_setfilecon])
1162+ AC_SUBST([LIB_SELINUX])
1163+ LIBS=$gl_save_LIBS
1164+
1165+ # Warn if SELinux is found but libselinux is absent;
1166+ if test "$ac_cv_search_setfilecon" = no &&
1167+ test "$host" = "$build" && test -d /selinux; then
1168+ AC_MSG_WARN([This system supports SELinux but libselinux is missing.])
1169+ AC_MSG_WARN([AC_PACKAGE_NAME will be compiled without SELinux support.])
1170+ fi
1171+])
1172--
11731.7.5.4
1174
diff --git a/recipes-extended/findutils/findutils-4.4.2/findutils-selinux.patch b/recipes-extended/findutils/findutils-4.4.2/findutils-selinux.patch
new file mode 100644
index 0000000..db0ab89
--- /dev/null
+++ b/recipes-extended/findutils/findutils-4.4.2/findutils-selinux.patch
@@ -0,0 +1,524 @@
1From: Xin Ouyang <Xin.Ouyang@windriver.com>
2Date: Tue, 26 Jun 2012 13:48:44 +0800
3Subject: [PATCH 1/2] findutils: support selinux
4
5Upstream-Status: Backport
6
7This is modified from a F13'sx SRPM patch.
8
9================================================================================
10
11 Author: James Youngman <jay@gnu.org>
12 Date: Sat Jul 11 19:55:27 2009 +0100
13
14 Fix Savannah bug #27017: find -D opt / -fstype ext3 -print , -quit coredump.
15
16 Fix Savannah bug #27017: find -D opt / -fstype ext3 -print , -quit
17 coredumps.
18 * find/tree.c (set_new_parent): Initialise struct
19 predicate->arg_text to NULL (instead of leaving it uninitialised).
20 (get_new_pred_noarg): Likewise.
21 (get_new_pred): Initialise predicate->arg_text to
22 "ThisShouldBeSetToSomethingElse" to make it easier to notice
23 bugs.
24 (get_new_pred_chk_op): Use get_new_pred_noarg.
25 (print_predicate): Use an if statement instead of
26 two ternary operators.
27 * find/util.c (insert_primary_withpred): Accept new argument, arg,
28 being the argument (if any) of this predicate. Pass it to
29 get_new_pred_chk_op.
30 (insert_primary): Likewise (pass arg to insert_primary_withpred).
31 (insert_primary_noarg): New function; calls insert_primary with
32 arg=NULL.
33 * find/parser.c (collect_arg_stat_info): Add an output parameter;
34 the filename from which we collected the stat information.
35 (parse_closeparen, parse_delete, parse_and, parse_or,
36 parse_comma): Use get_new_pred_noarg.
37 (parse_cnewer, parse_newer, parse_anewer): Use new
38 collect_arg_stat_info and insert_primary interface.
39 (parse_print, parse_prune, parse_nouser, parse_empty): Use
40 insert_primary_noarg.
41 (parse_accesscheck, parse_false): Use insert_primary_noarg.
42 (parse_used, parse_iname, parse_fprint, insert_fprint,
43 parse_fstype, parse_ilname): Use new collect_arg and
44 insert_primary interfaces.
45 (parse_ipath, parse_lname, do_parse_xmin, parse_name, parse_path,
46 parse_perm, parse_size, parse_user, parse_time): Use new
47 collect_arg and insert_primary_withpred interface.
48 (parse_negate, parse_openparen): Use new get_new_pred_chk_op interface.
49 (parse_newerXY, parse_nogroup): Use new insert_primary interface.
50 (insert_regex, parse_samefile): Use new insert_primary_withpred
51 interface.
52 (insert_type, insert_fprintf, new_insert_exec_ok, insert_num): Use
53 new insert_primary_withpred interface.
54 * find/defs.h (struct predicate.arg_text): make const.
55 Add declarations for new function get_new_pred_noarg and
56 insert_primary_noarg. Add 'arg' parameter to get_new_pred_chk_op
57 and insert_primary_withpred.
58---
59 NEWS | 6 +++
60 doc/find.texi | 18 +++++++-
61 find/Makefile.am | 2 +-
62 find/defs.h | 6 +++
63 find/find.1 | 4 ++
64 find/parser.c | 128 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
65 find/pred.c | 47 ++++++++++++++++++++
66 find/tree.c | 2 +
67 8 files changed, 209 insertions(+), 4 deletions(-)
68
69diff --git a/NEWS b/NEWS
70index 342a3d3..df0681c 100644
71--- a/NEWS
72+++ b/NEWS
73@@ -1,5 +1,11 @@
74 GNU findutils NEWS - User visible changes. -*- outline -*- (allout)
75
76+* Major changes in release 4.4.2, 2009-11-26
77+
78+** Functional Enhancements to find
79+
80+patch #4848: Patch - Support for SELinux
81+
82 * Major changes in release 4.4.2, 2009-05-16
83
84 ** Bug Fixes
85diff --git a/doc/find.texi b/doc/find.texi
86index 391ffa0..f599bbc 100644
87--- a/doc/find.texi
88+++ b/doc/find.texi
89@@ -7,7 +7,6 @@
90 @c %**end of header
91
92 @include version.texi
93-@include ../locate/dblocation.texi
94
95 @iftex
96 @finalout
97@@ -1242,6 +1241,14 @@ situation.
98
99 @end deffn
100
101+@deffn Test -context pattern
102+True if file's SELinux context matches the pattern @var{pattern}.
103+The pattern uses shell glob matching.
104+
105+This predicate is supported only on @code{find} versions compiled with
106+SELinux support and only when SELinux is enabled.
107+@end deffn
108+
109 @node Contents
110 @section Contents
111
112@@ -1733,6 +1740,7 @@ from the novel you are reading.
113 * Size Directives::
114 * Location Directives::
115 * Time Directives::
116+* Other Directives::
117 * Formatting Flags::
118 @end menu
119
120@@ -1890,6 +1898,14 @@ File's last modification time in the format specified by @var{k}
121 (@pxref{Time Formats}).
122 @end table
123
124+@node Other Directives
125+@subsubsection Other Directives
126+
127+@table @code
128+@item %Z
129+File's SELinux context, or empty string if the file has no SELinux context.
130+@end table
131+
132 @node Time Formats
133 @subsection Time Formats
134
135diff --git a/find/Makefile.am b/find/Makefile.am
136index b001509..6fc7df3 100644
137--- a/find/Makefile.am
138+++ b/find/Makefile.am
139@@ -26,7 +26,7 @@ endif
140
141 EXTRA_DIST = defs.h $(man_MANS)
142 INCLUDES = -I../gnulib/lib -I$(top_srcdir)/lib -I$(top_srcdir)/gnulib/lib -I../intl -DLOCALEDIR=\"$(localedir)\"
143-LDADD = ./libfindtools.a ../lib/libfind.a ../gnulib/lib/libgnulib.a @INTLLIBS@ @LIB_CLOCK_GETTIME@ @FINDLIBS@
144+LDADD = ./libfindtools.a ../lib/libfind.a ../gnulib/lib/libgnulib.a @INTLLIBS@ @LIB_CLOCK_GETTIME@ @FINDLIBS@ @LIB_SELINUX@
145 man_MANS = find.1
146 SUBDIRS = . testsuite
147
148diff --git a/find/defs.h b/find/defs.h
149index 4539fd9..e7e3a69 100644
150--- a/find/defs.h
151+++ b/find/defs.h
152@@ -48,6 +48,7 @@ Please stop compiling the program now
153 #include <stdbool.h> /* for bool/boolean */
154 #include <stdint.h> /* for uintmax_t */
155 #include <sys/stat.h> /* S_ISUID etc. */
156+#include <selinux/selinux.h>
157
158
159
160@@ -315,6 +316,7 @@ struct predicate
161 struct samefile_file_id samefileid; /* samefile */
162 mode_t type; /* type */
163 struct format_val printf_vec; /* printf fprintf fprint ls fls print0 fprint0 print */
164+ security_context_t scontext; /* security context */
165 } args;
166
167 /* The next predicate in the user input sequence,
168@@ -459,6 +461,7 @@ PREDICATEFUNCTION pred_used;
169 PREDICATEFUNCTION pred_user;
170 PREDICATEFUNCTION pred_writable;
171 PREDICATEFUNCTION pred_xtype;
172+PREDICATEFUNCTION pred_context;
173
174
175
176@@ -604,6 +607,9 @@ struct options
177 */
178 int regex_options;
179
180+ /* function used to get file context */
181+ int (*x_getfilecon) (int, const char *, security_context_t *);
182+
183 /* Optimisation level. One is the default.
184 */
185 unsigned short optimisation_level;
186diff --git a/find/find.1 b/find/find.1
187index 8b67ae3..1d23b17 100644
188--- a/find/find.1
189+++ b/find/find.1
190@@ -933,6 +933,8 @@ if \fIc\fR is `l'. In other words, for symbolic links,
191 checks the type of the file that
192 .B \-type
193 does not check.
194+.IP "\-context \fIpattern\fR"
195+(SELinux only) Security context of the file matches glob \fIpattern\fR.
196
197 .SS ACTIONS
198 .IP "\-delete\fR"
199@@ -1354,6 +1356,8 @@ File's type (like in
200 U=unknown type (shouldn't happen)
201 .IP %Y
202 File's type (like %y), plus follow symlinks: L=loop, N=nonexistent
203+.IP %Z
204+(SELinux only) file's security context.
205 .PP
206 A `%' character followed by any other character is discarded, but the
207 other character is printed (don't rely on this, as further format
208diff --git a/find/parser.c b/find/parser.c
209index 08758ee..d7fc9ce 100644
210--- a/find/parser.c
211+++ b/find/parser.c
212@@ -53,6 +53,8 @@
213 #include <unistd.h>
214 #include <sys/stat.h>
215
216+#include "selinux-at.h"
217+
218 #if ENABLE_NLS
219 # include <libintl.h>
220 # define _(Text) gettext (Text)
221@@ -155,6 +157,7 @@ static boolean parse_noignore_race PARAMS((const struct parser_table*, char *arg
222 static boolean parse_warn PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
223 static boolean parse_xtype PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
224 static boolean parse_quit PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
225+static boolean parse_context PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
226
227 boolean parse_print PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
228
229@@ -251,6 +254,7 @@ static struct parser_table const parse_table[] =
230 PARSE_TEST ("cmin", cmin), /* GNU */
231 PARSE_TEST ("cnewer", cnewer), /* GNU */
232 {ARG_TEST, "ctime", parse_time, pred_ctime}, /* POSIX */
233+ PARSE_TEST ("context", context), /* GNU */
234 PARSE_POSOPT ("daystart", daystart), /* GNU */
235 PARSE_ACTION ("delete", delete), /* GNU, Mac OS, FreeBSD */
236 PARSE_OPTION ("d", d), /* Mac OS X, FreeBSD, NetBSD, OpenBSD, but deprecated in favour of -depth */
237@@ -347,6 +351,86 @@ static struct parser_table const parse_table[] =
238 static const char *first_nonoption_arg = NULL;
239 static const struct parser_table *noop = NULL;
240
241+static int
242+fallback_getfilecon (int fd, const char *name, security_context_t *p,
243+ int prev_rv)
244+{
245+ /* Our original getfilecon () call failed. Perhaps we can't follow a
246+ * symbolic link. If that might be the problem, lgetfilecon () the link.
247+ * Otherwise, admit defeat. */
248+ switch (errno)
249+ {
250+ case ENOENT:
251+ case ENOTDIR:
252+#ifdef DEBUG_STAT
253+ fprintf (stderr, "fallback_getfilecon(): getfilecon(%s) failed; falling "
254+ "back on lgetfilecon()\n", name);
255+#endif
256+ return lgetfileconat (fd, name, p);
257+
258+ case EACCES:
259+ case EIO:
260+ case ELOOP:
261+ case ENAMETOOLONG:
262+#ifdef EOVERFLOW
263+ case EOVERFLOW: /* EOVERFLOW is not #defined on UNICOS. */
264+#endif
265+ default:
266+ return prev_rv;
267+ }
268+}
269+
270+/* optionh_getfilecon () implements the getfilecon operation when the
271+ * -H option is in effect.
272+ *
273+ * If the item to be examined is a command-line argument, we follow
274+ * symbolic links. If the getfilecon () call fails on the command-line
275+ * item, we fall back on the properties of the symbolic link.
276+ *
277+ * If the item to be examined is not a command-line argument, we
278+ * examine the link itself. */
279+int
280+optionh_getfilecon (int fd, const char *name, security_context_t *p)
281+{
282+ int rv;
283+ if (0 == state.curdepth)
284+ {
285+ /* This file is from the command line; dereference the link (if it is
286+ a link). */
287+ rv = getfileconat (fd, name, p);
288+ if (0 == rv)
289+ return 0; /* success */
290+ else
291+ return fallback_getfilecon (fd, name, p, rv);
292+ }
293+ else
294+ {
295+ /* Not a file on the command line; do not dereference the link. */
296+ return lgetfileconat (fd, name, p);
297+ }
298+}
299+
300+/* optionl_getfilecon () implements the getfilecon operation when the
301+ * -L option is in effect. That option makes us examine the thing the
302+ * symbolic link points to, not the symbolic link itself. */
303+int
304+optionl_getfilecon (int fd, const char *name, security_context_t *p)
305+{
306+ int rv = getfileconat (fd, name, p);
307+ if (0 == rv)
308+ return 0; /* normal case. */
309+ else
310+ return fallback_getfilecon (fd, name, p, rv);
311+}
312+
313+/* optionp_getfilecon () implements the stat operation when the -P
314+ * option is in effect (this is also the default). That option makes
315+ * us examine the symbolic link itself, not the thing it points to. */
316+int
317+optionp_getfilecon (int fd, const char *name, security_context_t *p)
318+{
319+ return lgetfileconat (fd, name, p);
320+}
321
322 void
323 check_option_combinations(const struct predicate *p)
324@@ -450,11 +534,13 @@ set_follow_state(enum SymlinkOption opt)
325 {
326 case SYMLINK_ALWAYS_DEREF: /* -L */
327 options.xstat = optionl_stat;
328+ options.x_getfilecon = optionl_getfilecon;
329 options.no_leaf_check = true;
330 break;
331
332 case SYMLINK_NEVER_DEREF: /* -P (default) */
333 options.xstat = optionp_stat;
334+ options.x_getfilecon = optionp_getfilecon;
335 /* Can't turn no_leaf_check off because the user might have specified
336 * -noleaf anyway
337 */
338@@ -462,6 +548,7 @@ set_follow_state(enum SymlinkOption opt)
339
340 case SYMLINK_DEREF_ARGSONLY: /* -H */
341 options.xstat = optionh_stat;
342+ options.x_getfilecon = optionh_getfilecon;
343 options.no_leaf_check = true;
344 }
345 }
346@@ -1146,8 +1233,10 @@ tests (N can be +N or -N or N): -amin N -anewer FILE -atime N -cmin N\n\
347 -nouser -nogroup -path PATTERN -perm [+-]MODE -regex PATTERN\n\
348 -readable -writable -executable\n\
349 -wholename PATTERN -size N[bcwkMG] -true -type [bcdpflsD] -uid N\n\
350- -used N -user NAME -xtype [bcdpfls]\n"));
351+ -used N -user NAME -xtype [bcdpfls]"));
352 puts (_("\
353+ -context CONTEXT\n"));
354+ puts (_("\n\
355 actions: -delete -print0 -printf FORMAT -fprintf FILE FORMAT -print \n\
356 -fprint0 FILE -fprint FILE -ls -fls FILE -prune -quit\n\
357 -exec COMMAND ; -exec COMMAND {} + -ok COMMAND ;\n\
358@@ -2574,6 +2663,11 @@ parse_version (const struct parser_table* entry, char **argv, int *arg_ptr)
359 printf("LEAF_OPTIMISATION ");
360 ++features;
361 #endif
362+ if (0 < is_selinux_enabled ())
363+ {
364+ printf ("SELINUX ");
365+ ++features;
366+ }
367
368 flags = 0;
369 if (is_fts_enabled(&flags))
370@@ -2609,6 +2703,31 @@ parse_version (const struct parser_table* entry, char **argv, int *arg_ptr)
371 }
372
373 static boolean
374+parse_context (const struct parser_table* entry, char **argv, int *arg_ptr)
375+{
376+ struct predicate *our_pred;
377+
378+ if ((argv == NULL) || (argv[*arg_ptr] == NULL))
379+ return false;
380+
381+ if (is_selinux_enabled () <= 0)
382+ {
383+ error (1, 0, _("invalid predicate -context: SELinux is not enabled."));
384+ return false;
385+ }
386+ our_pred = insert_primary (entry, NULL);
387+ our_pred->est_success_rate = 0.01f;
388+ our_pred->need_stat = false;
389+#ifdef DEBUG
390+ our_pred->p_name = find_pred_name (pred_context);
391+#endif /*DEBUG*/
392+ our_pred->args.scontext = argv[*arg_ptr];
393+
394+ (*arg_ptr)++;
395+ return true;
396+}
397+
398+static boolean
399 parse_xdev (const struct parser_table* entry, char **argv, int *arg_ptr)
400 {
401 options.stay_on_filesystem = true;
402@@ -2861,7 +2980,7 @@ insert_fprintf (struct format_val *vec,
403 if (*scan2 == '.')
404 for (scan2++; ISDIGIT (*scan2); scan2++)
405 /* Do nothing. */ ;
406- if (strchr ("abcdDfFgGhHiklmMnpPsStuUyY", *scan2))
407+ if (strchr ("abcdDfFgGhHiklmMnpPsStuUyYZ", *scan2))
408 {
409 segmentp = make_segment (segmentp, format, scan2 - format,
410 KIND_FORMAT, *scan2, 0,
411@@ -2991,6 +3110,11 @@ make_segment (struct segment **segment,
412 *fmt++ = 's';
413 break;
414
415+ case 'Z': /* SELinux security context */
416+ mycost = NeedsAccessInfo;
417+ *fmt++ = 's';
418+ break;
419+
420 case 'H': /* ARGV element file was found under */
421 *fmt++ = 's';
422 break;
423diff --git a/find/pred.c b/find/pred.c
424index b1f48a0..7c34119 100644
425--- a/find/pred.c
426+++ b/find/pred.c
427@@ -48,6 +48,8 @@
428 #include "error.h"
429 #include "verify.h"
430
431+#include <selinux/selinux.h>
432+
433 #if ENABLE_NLS
434 # include <libintl.h>
435 # define _(Text) gettext (Text)
436@@ -230,6 +232,7 @@ struct pred_assoc pred_table[] =
437 {pred_user, "user "},
438 {pred_writable, "writable "},
439 {pred_xtype, "xtype "},
440+ {pred_context, "context"},
441 {0, "none "}
442 };
443 #endif
444@@ -1054,6 +1057,30 @@ do_fprintf(struct format_val *dest,
445 mode_to_filetype(stat_buf->st_mode & S_IFMT));
446 }
447 break;
448+
449+ case 'Z': /* SELinux security context */
450+ {
451+ security_context_t scontext;
452+ int rv = (*options.x_getfilecon) (state.cwd_dir_fd, state.rel_pathname,
453+ &scontext);
454+ if (rv < 0)
455+ {
456+ /* If getfilecon fails, there will in the general case
457+ still be some text to print. We just make %Z expand
458+ to an empty string. */
459+ checked_fprintf (dest, segment->text, "");
460+
461+ error (0, errno, "getfilecon: %s",
462+ safely_quote_err_filename (0, pathname));
463+ state.exit_status = 1;
464+ }
465+ else
466+ {
467+ checked_fprintf (dest, segment->text, scontext);
468+ freecon (scontext);
469+ }
470+ }
471+ break;
472 }
473 /* end of KIND_FORMAT case */
474 break;
475@@ -1844,6 +1871,26 @@ pred_xtype (const char *pathname, struct stat *stat_buf, struct predicate *pred_
476 */
477 return (pred_type (pathname, &sbuf, pred_ptr));
478 }
479+
480+
481+boolean
482+pred_context (const char *pathname, struct stat *stat_buf,
483+ struct predicate *pred_ptr)
484+{
485+ security_context_t scontext;
486+ int rv = (*options.x_getfilecon) (state.cwd_dir_fd, state.rel_pathname,
487+ &scontext);
488+ if (rv < 0)
489+ {
490+ error (0, errno, "getfilecon: %s", safely_quote_err_filename (0, pathname));
491+ return false;
492+ }
493+
494+ rv = (fnmatch (pred_ptr->args.scontext, scontext, 0) == 0);
495+ freecon (scontext);
496+ return rv;
497+}
498+
499
500 /* 1) fork to get a child; parent remembers the child pid
501 2) child execs the command requested
502diff --git a/find/tree.c b/find/tree.c
503index 60a0601..63100fb 100644
504--- a/find/tree.c
505+++ b/find/tree.c
506@@ -909,6 +909,7 @@ static struct pred_cost_lookup costlookup[] =
507 { pred_cmin , NeedsStatInfo, },
508 { pred_cnewer , NeedsStatInfo, },
509 { pred_comma , NeedsNothing, },
510+ { pred_context , NeedsAccessInfo },
511 { pred_ctime , NeedsStatInfo, },
512 { pred_delete , NeedsSyncDiskHit },
513 { pred_empty , NeedsStatInfo },
514@@ -1453,6 +1454,7 @@ get_new_pred (const struct parser_table *entry)
515 last_pred->p_cost = NeedsUnknown;
516 last_pred->arg_text = "ThisShouldBeSetToSomethingElse";
517 last_pred->args.str = NULL;
518+ last_pred->args.scontext = NULL;
519 last_pred->pred_next = NULL;
520 last_pred->pred_left = NULL;
521 last_pred->pred_right = NULL;
522--
5231.7.5.4
524
diff --git a/recipes-extended/findutils/findutils_4.4.2.bbappend b/recipes-extended/findutils/findutils_4.4.2.bbappend
new file mode 100644
index 0000000..a3922d8
--- /dev/null
+++ b/recipes-extended/findutils/findutils_4.4.2.bbappend
@@ -0,0 +1,10 @@
1PR .= ".1"
2
3FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}-${PV}:"
4
5SRC_URI += "file://findutils-selinux.patch"
6SRC_URI += "file://findutils-selinux-gnulib.patch"
7
8DEPENDS += "${@base_contains('DISTRO_FEATURES', 'selinux', 'libselinux', '', d)}"
9
10EXTRA_OECONF += "${@base_contains('DISTRO_FEATURES', 'selinux', '--with-selinux', '--without-selinux', d)}"