From aef5531fa3051cfadbda0083db19e62823b8b1fc Mon Sep 17 00:00:00 2001 From: Xin Ouyang Date: Tue, 26 Jun 2012 14:29:22 +0800 Subject: findutils: 4.4.2, support selinux Signed-off-by: Xin Ouyang --- .../findutils-4.4.2/findutils-selinux-gnulib.patch | 1174 ++++++++++++++++++++ .../findutils-4.4.2/findutils-selinux.patch | 524 +++++++++ .../findutils/findutils_4.4.2.bbappend | 10 + 3 files changed, 1708 insertions(+) create mode 100644 recipes-extended/findutils/findutils-4.4.2/findutils-selinux-gnulib.patch create mode 100644 recipes-extended/findutils/findutils-4.4.2/findutils-selinux.patch create mode 100644 recipes-extended/findutils/findutils_4.4.2.bbappend 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 @@ +From: Xin Ouyang +Date: Tue, 26 Jun 2012 13:56:52 +0800 +Subject: [PATCH 2/2] findutils: support selinux and gnulib + +Upstream-Status: Inappropriate [configuration] + +This is a F13 SRPM patch. + +Once the selinux-at module appears on the list within import-gnulib.config, +this patch is no longer needed. +--- + aclocal.m4 | 2 + + gnulib/lib/Makefile.am | 43 ++++++ + gnulib/lib/at-func.c | 98 ++++++++++---- + gnulib/lib/getfilecon.c | 87 ++++++++++++ + gnulib/lib/openat.c | 285 ++++++++++++++++++++-------------------- + gnulib/lib/openat.h | 88 ++++++------- + gnulib/lib/se-selinux.in.h | 73 ++++++++++ + gnulib/lib/selinux-at.c | 72 ++++++++++ + gnulib/lib/selinux-at.h | 52 ++++++++ + gnulib/m4/gnulib-comp.m4 | 12 ++ + gnulib/m4/selinux-context-h.m4 | 16 +++ + gnulib/m4/selinux-selinux-h.m4 | 57 ++++++++ + 12 files changed, 665 insertions(+), 220 deletions(-) + create mode 100644 gnulib/lib/getfilecon.c + create mode 100644 gnulib/lib/se-selinux.in.h + create mode 100644 gnulib/lib/selinux-at.c + create mode 100644 gnulib/lib/selinux-at.h + create mode 100644 gnulib/m4/selinux-context-h.m4 + create mode 100644 gnulib/m4/selinux-selinux-h.m4 + +diff --git a/aclocal.m4 b/aclocal.m4 +index 95ff111..0034170 100644 +--- a/aclocal.m4 ++++ b/aclocal.m4 +@@ -115,6 +115,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 ++]) +-- +1.7.5.4 + 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 @@ +From: Xin Ouyang +Date: Tue, 26 Jun 2012 13:48:44 +0800 +Subject: [PATCH 1/2] findutils: support selinux + +Upstream-Status: Backport + +This is modified from a F13'sx SRPM patch. + +================================================================================ + + Author: James Youngman + Date: Sat Jul 11 19:55:27 2009 +0100 + + Fix Savannah bug #27017: find -D opt / -fstype ext3 -print , -quit coredump. + + Fix Savannah bug #27017: find -D opt / -fstype ext3 -print , -quit + coredumps. + * find/tree.c (set_new_parent): Initialise struct + predicate->arg_text to NULL (instead of leaving it uninitialised). + (get_new_pred_noarg): Likewise. + (get_new_pred): Initialise predicate->arg_text to + "ThisShouldBeSetToSomethingElse" to make it easier to notice + bugs. + (get_new_pred_chk_op): Use get_new_pred_noarg. + (print_predicate): Use an if statement instead of + two ternary operators. + * find/util.c (insert_primary_withpred): Accept new argument, arg, + being the argument (if any) of this predicate. Pass it to + get_new_pred_chk_op. + (insert_primary): Likewise (pass arg to insert_primary_withpred). + (insert_primary_noarg): New function; calls insert_primary with + arg=NULL. + * find/parser.c (collect_arg_stat_info): Add an output parameter; + the filename from which we collected the stat information. + (parse_closeparen, parse_delete, parse_and, parse_or, + parse_comma): Use get_new_pred_noarg. + (parse_cnewer, parse_newer, parse_anewer): Use new + collect_arg_stat_info and insert_primary interface. + (parse_print, parse_prune, parse_nouser, parse_empty): Use + insert_primary_noarg. + (parse_accesscheck, parse_false): Use insert_primary_noarg. + (parse_used, parse_iname, parse_fprint, insert_fprint, + parse_fstype, parse_ilname): Use new collect_arg and + insert_primary interfaces. + (parse_ipath, parse_lname, do_parse_xmin, parse_name, parse_path, + parse_perm, parse_size, parse_user, parse_time): Use new + collect_arg and insert_primary_withpred interface. + (parse_negate, parse_openparen): Use new get_new_pred_chk_op interface. + (parse_newerXY, parse_nogroup): Use new insert_primary interface. + (insert_regex, parse_samefile): Use new insert_primary_withpred + interface. + (insert_type, insert_fprintf, new_insert_exec_ok, insert_num): Use + new insert_primary_withpred interface. + * find/defs.h (struct predicate.arg_text): make const. + Add declarations for new function get_new_pred_noarg and + insert_primary_noarg. Add 'arg' parameter to get_new_pred_chk_op + and insert_primary_withpred. +--- + NEWS | 6 +++ + doc/find.texi | 18 +++++++- + find/Makefile.am | 2 +- + find/defs.h | 6 +++ + find/find.1 | 4 ++ + find/parser.c | 128 +++++++++++++++++++++++++++++++++++++++++++++++++++++- + find/pred.c | 47 ++++++++++++++++++++ + find/tree.c | 2 + + 8 files changed, 209 insertions(+), 4 deletions(-) + +diff --git a/NEWS b/NEWS +index 342a3d3..df0681c 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 391ffa0..f599bbc 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 + +@@ -1733,6 +1740,7 @@ from the novel you are reading. + * Size Directives:: + * Location Directives:: + * Time Directives:: ++* Other Directives:: + * Formatting Flags:: + @end menu + +@@ -1890,6 +1898,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 4539fd9..e7e3a69 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 8b67ae3..1d23b17 100644 +--- a/find/find.1 ++++ b/find/find.1 +@@ -933,6 +933,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" +@@ -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 --git a/find/parser.c b/find/parser.c +index 08758ee..d7fc9ce 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) +@@ -155,6 +157,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)); + +@@ -251,6 +254,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 */ +@@ -347,6 +351,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) +@@ -450,11 +534,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 + */ +@@ -462,6 +548,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; + } + } +@@ -1146,8 +1233,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\ +@@ -2574,6 +2663,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)) +@@ -2609,6 +2703,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, NULL); ++ 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; +@@ -2861,7 +2980,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, +@@ -2991,6 +3110,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 60a0601..63100fb 100644 +--- a/find/tree.c ++++ b/find/tree.c +@@ -909,6 +909,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 }, +@@ -1453,6 +1454,7 @@ get_new_pred (const struct parser_table *entry) + last_pred->p_cost = NeedsUnknown; + last_pred->arg_text = "ThisShouldBeSetToSomethingElse"; + 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; +-- +1.7.5.4 + 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 @@ +PR .= ".1" + +FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}-${PV}:" + +SRC_URI += "file://findutils-selinux.patch" +SRC_URI += "file://findutils-selinux-gnulib.patch" + +DEPENDS += "${@base_contains('DISTRO_FEATURES', 'selinux', 'libselinux', '', d)}" + +EXTRA_OECONF += "${@base_contains('DISTRO_FEATURES', 'selinux', '--with-selinux', '--without-selinux', d)}" -- cgit v1.2.3-54-g00ecf