Once the selinux-at module appears on the list within import-gnulib.config this patch is no longer needed. diff --git a/aclocal.m4 b/aclocal.m4 index 1f97dda..61ad660 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -1039,6 +1039,8 @@ m4_include([gnulib/m4/rpmatch.m4]) m4_include([gnulib/m4/same.m4]) m4_include([gnulib/m4/save-cwd.m4]) m4_include([gnulib/m4/savedir.m4]) +m4_include([gnulib/m4/selinux-context-h.m4]) +m4_include([gnulib/m4/selinux-selinux-h.m4]) m4_include([gnulib/m4/setenv.m4]) m4_include([gnulib/m4/ssize_t.m4]) m4_include([gnulib/m4/st_dm_mode.m4]) diff --git a/gnulib/lib/Makefile.am b/gnulib/lib/Makefile.am index 59ed5f2..b13e509 100644 --- a/gnulib/lib/Makefile.am +++ b/gnulib/lib/Makefile.am @@ -1007,6 +1007,49 @@ EXTRA_libgnulib_a_SOURCES += savedir.c ## end gnulib module savedir +## begin gnulib module selinux-at + + +EXTRA_DIST += selinux-at.c selinux-at.h + +EXTRA_libgnulib_a_SOURCES += selinux-at.c + +## end gnulib module selinux-at + +## begin gnulib module selinux-h + +libgnulib_a_SOURCES += se-context.in.h se-selinux.in.h + +BUILT_SOURCES += selinux/selinux.h +selinux/selinux.h: se-selinux.in.h + $(AM_V_at)$(MKDIR_P) selinux + $(AM_V_GEN)rm -f $@-t $@ && \ + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ + sed -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''NEXT_SELINUX_SELINUX_H''@|$(NEXT_SELINUX_SELINUX_H)|g' \ + < $(srcdir)/se-selinux.in.h; \ + } > $@-t && \ + chmod a-x $@-t && \ + mv $@-t $@ +MOSTLYCLEANFILES += selinux/selinux.h selinux/selinux.h-t + +BUILT_SOURCES += $(SELINUX_CONTEXT_H) +selinux/context.h: se-context.in.h + $(AM_V_at)$(MKDIR_P) selinux + $(AM_V_GEN)rm -f $@-t $@ && \ + cp $(srcdir)/se-context.in.h $@-t && \ + chmod a-x $@-t && \ + mv $@-t $@ +MOSTLYCLEANFILES += selinux/context.h selinux/context.h-t +MOSTLYCLEANDIRS += selinux + +EXTRA_DIST += getfilecon.c + +EXTRA_libgnulib_a_SOURCES += getfilecon.c + +## end gnulib module selinux-h + ## begin gnulib module setenv diff --git a/gnulib/lib/at-func.c b/gnulib/lib/at-func.c index c7963fe..73be401 100644 --- a/gnulib/lib/at-func.c +++ b/gnulib/lib/at-func.c @@ -1,5 +1,5 @@ /* Define an at-style functions like fstatat, unlinkat, fchownat, etc. - Copyright (C) 2006 Free Software Foundation, Inc. + Copyright (C) 2006, 2009 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -16,62 +16,106 @@ /* written by Jim Meyering */ -#define CALL_FUNC(F) \ - (AT_FUNC_USE_F1_COND \ +#include "dirname.h" /* solely for definition of IS_ABSOLUTE_FILE_NAME */ +#include "openat.h" +#include "openat-priv.h" +#include "save-cwd.h" + +#ifdef AT_FUNC_USE_F1_COND +# define CALL_FUNC(F) \ + (flag == AT_FUNC_USE_F1_COND \ ? AT_FUNC_F1 (F AT_FUNC_POST_FILE_ARGS) \ : AT_FUNC_F2 (F AT_FUNC_POST_FILE_ARGS)) +# define VALIDATE_FLAG(F) \ + if (flag & ~AT_FUNC_USE_F1_COND) \ + { \ + errno = EINVAL; \ + return FUNC_FAIL; \ + } +#else +# define CALL_FUNC(F) (AT_FUNC_F1 (F AT_FUNC_POST_FILE_ARGS)) +# define VALIDATE_FLAG(F) /* empty */ +#endif + +#ifdef AT_FUNC_RESULT +# define FUNC_RESULT AT_FUNC_RESULT +#else +# define FUNC_RESULT int +#endif + +#ifdef AT_FUNC_FAIL +# define FUNC_FAIL AT_FUNC_FAIL +#else +# define FUNC_FAIL -1 +#endif -/* Call AT_FUNC_F1 or AT_FUNC_F2 (testing AT_FUNC_USE_F1_COND to - determine which) to operate on FILE, which is in the directory - open on descriptor FD. If possible, do it without changing the +/* Call AT_FUNC_F1 to operate on FILE, which is in the directory + open on descriptor FD. If AT_FUNC_USE_F1_COND is defined to a value, + AT_FUNC_POST_FILE_PARAM_DECLS must inlude a parameter named flag; + call AT_FUNC_F2 if FLAG is 0 or fail if FLAG contains more bits than + AT_FUNC_USE_F1_COND. Return int and fail with -1 unless AT_FUNC_RESULT + or AT_FUNC_FAIL are defined. If possible, do it without changing the working directory. Otherwise, resort to using save_cwd/fchdir, then AT_FUNC_F?/restore_cwd. If either the save_cwd or the restore_cwd fails, then give a diagnostic and exit nonzero. */ -int +FUNC_RESULT AT_FUNC_NAME (int fd, char const *file AT_FUNC_POST_FILE_PARAM_DECLS) { + /* Be careful to choose names unlikely to conflict with + AT_FUNC_POST_FILE_PARAM_DECLS. */ struct saved_cwd saved_cwd; int saved_errno; - int err; + FUNC_RESULT err; + + VALIDATE_FLAG (flag); if (fd == AT_FDCWD || IS_ABSOLUTE_FILE_NAME (file)) return CALL_FUNC (file); { - char buf[OPENAT_BUFFER_SIZE]; - char *proc_file = openat_proc_name (buf, fd, file); + char proc_buf[OPENAT_BUFFER_SIZE]; + char *proc_file = openat_proc_name (proc_buf, fd, file); if (proc_file) { - int proc_result = CALL_FUNC (proc_file); - int proc_errno = errno; - if (proc_file != buf) - free (proc_file); - /* If the syscall succeeds, or if it fails with an unexpected - errno value, then return right away. Otherwise, fall through - and resort to using save_cwd/restore_cwd. */ - if (0 <= proc_result) - return proc_result; - if (! EXPECTED_ERRNO (proc_errno)) - { - errno = proc_errno; - return proc_result; - } + FUNC_RESULT proc_result = CALL_FUNC (proc_file); + int proc_errno = errno; + if (proc_file != proc_buf) + free (proc_file); + /* If the syscall succeeds, or if it fails with an unexpected + errno value, then return right away. Otherwise, fall through + and resort to using save_cwd/restore_cwd. */ + if (FUNC_FAIL != proc_result) + return proc_result; + if (! EXPECTED_ERRNO (proc_errno)) + { + errno = proc_errno; + return proc_result; + } } } if (save_cwd (&saved_cwd) != 0) openat_save_fail (errno); + if (0 <= fd && fd == saved_cwd.desc) + { + /* If saving the working directory collides with the user's + requested fd, then the user's fd must have been closed to + begin with. */ + free_cwd (&saved_cwd); + errno = EBADF; + return FUNC_FAIL; + } if (fchdir (fd) != 0) { saved_errno = errno; free_cwd (&saved_cwd); errno = saved_errno; - return -1; + return FUNC_FAIL; } err = CALL_FUNC (file); - saved_errno = (err < 0 ? errno : 0); + saved_errno = (err == FUNC_FAIL ? errno : 0); if (restore_cwd (&saved_cwd) != 0) openat_restore_fail (errno); @@ -83,3 +127,5 @@ AT_FUNC_NAME (int fd, char const *file AT_FUNC_POST_FILE_PARAM_DECLS) return err; } #undef CALL_FUNC +#undef FUNC_RESULT +#undef FUNC_FAIL diff --git a/gnulib/lib/getfilecon.c b/gnulib/lib/getfilecon.c new file mode 100644 index 0000000..d712307 --- /dev/null +++ b/gnulib/lib/getfilecon.c @@ -0,0 +1,87 @@ +/* wrap getfilecon, lgetfilecon, and fgetfilecon + Copyright (C) 2009 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +/* written by Jim Meyering */ + +#include + +#include + +#include +#include +#include + +/* FIXME: remove this once there is an errno-gnu module + that guarantees the definition of ENODATA. */ +#ifndef ENODATA +# define ENODATA ENOTSUP +#endif + +#undef getfilecon +#undef lgetfilecon +#undef fgetfilecon +int getfilecon (char const *file, security_context_t *con); +int lgetfilecon (char const *file, security_context_t *con); +int fgetfilecon (int fd, security_context_t *con); + +/* getfilecon, lgetfilecon, and fgetfilecon can all misbehave, be it + via an old version of libselinux where these would return 0 and set the + result context to NULL, or via a modern kernel+lib operating on a file + from a disk whose attributes were set by a kernel from around 2006. + In that latter case, the functions return a length of 10 for the + "unlabeled" context. Map both failures to a return value of -1, and + set errno to ENOTSUP in the first case, and ENODATA in the latter. */ + +static inline int +map_to_failure (int ret, security_context_t *con) +{ + if (ret == 0) + { + errno = ENOTSUP; + return -1; + } + + if (ret == 10 && strcmp (*con, "unlabeled") == 0) + { + freecon (*con); + errno = ENODATA; + return -1; + } + + return ret; +} + +int +rpl_getfilecon (char const *file, security_context_t *con) +{ + int ret = getfilecon (file, con); + return map_to_failure (ret, con); +} + +int +rpl_lgetfilecon (char const *file, security_context_t *con) +{ + int ret = lgetfilecon (file, con); + return map_to_failure (ret, con); +} + +int +rpl_fgetfilecon (int fd, security_context_t *con) +{ + int ret = fgetfilecon (fd, con); + return map_to_failure (ret, con); +} diff --git a/gnulib/lib/openat.c b/gnulib/lib/openat.c index 73f24b0..2b15bb5 100644 --- a/gnulib/lib/openat.c +++ b/gnulib/lib/openat.c @@ -1,5 +1,5 @@ /* provide a replacement openat function - Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation, Inc. + Copyright (C) 2004-2009 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -22,13 +22,108 @@ #include #include +#include +#include #include "dirname.h" /* solely for definition of IS_ABSOLUTE_FILE_NAME */ -#include "fcntl--.h" -#include "lstat.h" #include "openat-priv.h" #include "save-cwd.h" +#if HAVE_OPENAT + +# undef openat + +/* Like openat, but work around Solaris 9 bugs with trailing slash. */ +int +rpl_openat (int dfd, char const *filename, int flags, ...) +{ + mode_t mode; + int fd; + + mode = 0; + if (flags & O_CREAT) + { + va_list arg; + va_start (arg, flags); + + /* We have to use PROMOTED_MODE_T instead of mode_t, otherwise GCC 4 + creates crashing code when 'mode_t' is smaller than 'int'. */ + mode = va_arg (arg, PROMOTED_MODE_T); + + va_end (arg); + } + +#if OPEN_TRAILING_SLASH_BUG + /* If the filename ends in a slash and one of O_CREAT, O_WRONLY, O_RDWR + is specified, then fail. + Rationale: POSIX + says that + "A pathname that contains at least one non-slash character and that + ends with one or more trailing slashes shall be resolved as if a + single dot character ( '.' ) were appended to the pathname." + and + "The special filename dot shall refer to the directory specified by + its predecessor." + If the named file already exists as a directory, then + - if O_CREAT is specified, open() must fail because of the semantics + of O_CREAT, + - if O_WRONLY or O_RDWR is specified, open() must fail because POSIX + says that it + fails with errno = EISDIR in this case. + If the named file does not exist or does not name a directory, then + - if O_CREAT is specified, open() must fail since open() cannot create + directories, + - if O_WRONLY or O_RDWR is specified, open() must fail because the + file does not contain a '.' directory. */ + if (flags & (O_CREAT | O_WRONLY | O_RDWR)) + { + size_t len = strlen (filename); + if (len > 0 && filename[len - 1] == '/') + { + errno = EISDIR; + return -1; + } + } +#endif + + fd = openat (dfd, filename, flags, mode); + +#if OPEN_TRAILING_SLASH_BUG + /* If the filename ends in a slash and fd does not refer to a directory, + then fail. + Rationale: POSIX + says that + "A pathname that contains at least one non-slash character and that + ends with one or more trailing slashes shall be resolved as if a + single dot character ( '.' ) were appended to the pathname." + and + "The special filename dot shall refer to the directory specified by + its predecessor." + If the named file without the slash is not a directory, open() must fail + with ENOTDIR. */ + if (fd >= 0) + { + /* We know len is positive, since open did not fail with ENOENT. */ + size_t len = strlen (filename); + if (filename[len - 1] == '/') + { + struct stat statbuf; + + if (fstat (fd, &statbuf) >= 0 && !S_ISDIR (statbuf.st_mode)) + { + close (fd); + errno = ENOTDIR; + return -1; + } + } + } +#endif + + return fd; +} + +#else /* !HAVE_OPENAT */ + /* Replacement for Solaris' openat function. First, try to simulate it via open ("/proc/self/fd/FD/FILE"). @@ -47,12 +142,9 @@ openat (int fd, char const *file, int flags, ...) va_list arg; va_start (arg, flags); - /* If mode_t is narrower than int, use the promoted type (int), - not mode_t. Use sizeof to guess whether mode_t is narrower; - we don't know of any practical counterexamples. */ - mode = (sizeof (mode_t) < sizeof (int) - ? va_arg (arg, int) - : va_arg (arg, mode_t)); + /* We have to use PROMOTED_MODE_T instead of mode_t, otherwise GCC 4 + creates crashing code when 'mode_t' is smaller than 'int'. */ + mode = va_arg (arg, PROMOTED_MODE_T); va_end (arg); } @@ -73,7 +165,7 @@ openat (int fd, char const *file, int flags, ...) int openat_permissive (int fd, char const *file, int flags, mode_t mode, - int *cwd_errno) + int *cwd_errno) { struct saved_cwd saved_cwd; int saved_errno; @@ -88,18 +180,18 @@ openat_permissive (int fd, char const *file, int flags, mode_t mode, char *proc_file = openat_proc_name (buf, fd, file); if (proc_file) { - int open_result = open (proc_file, flags, mode); - int open_errno = errno; - if (proc_file != buf) - free (proc_file); - /* If the syscall succeeds, or if it fails with an unexpected - errno value, then return right away. Otherwise, fall through - and resort to using save_cwd/restore_cwd. */ - if (0 <= open_result || ! EXPECTED_ERRNO (open_errno)) - { - errno = open_errno; - return open_result; - } + int open_result = open (proc_file, flags, mode); + int open_errno = errno; + if (proc_file != buf) + free (proc_file); + /* If the syscall succeeds, or if it fails with an unexpected + errno value, then return right away. Otherwise, fall through + and resort to using save_cwd/restore_cwd. */ + if (0 <= open_result || ! EXPECTED_ERRNO (open_errno)) + { + errno = open_errno; + return open_result; + } } } @@ -107,9 +199,18 @@ openat_permissive (int fd, char const *file, int flags, mode_t mode, if (! save_ok) { if (! cwd_errno) - openat_save_fail (errno); + openat_save_fail (errno); *cwd_errno = errno; } + if (0 <= fd && fd == saved_cwd.desc) + { + /* If saving the working directory collides with the user's + requested fd, then the user's fd must have been closed to + begin with. */ + free_cwd (&saved_cwd); + errno = EBADF; + return -1; + } err = fchdir (fd); saved_errno = errno; @@ -119,11 +220,17 @@ openat_permissive (int fd, char const *file, int flags, mode_t mode, err = open (file, flags, mode); saved_errno = errno; if (save_ok && restore_cwd (&saved_cwd) != 0) - { - if (! cwd_errno) - openat_restore_fail (errno); - *cwd_errno = errno; - } + { + if (! cwd_errno) + { + /* Don't write a message to just-created fd 2. */ + saved_errno = errno; + if (err == STDERR_FILENO) + close (err); + openat_restore_fail (saved_errno); + } + *cwd_errno = errno; + } } free_cwd (&saved_cwd); @@ -144,125 +251,15 @@ openat_needs_fchdir (void) char buf[OPENAT_BUFFER_SIZE]; char *proc_file = openat_proc_name (buf, fd, "."); if (proc_file) - { - needs_fchdir = false; - if (proc_file != buf) - free (proc_file); - } + { + needs_fchdir = false; + if (proc_file != buf) + free (proc_file); + } close (fd); } return needs_fchdir; } -#if !HAVE_FDOPENDIR - -/* Replacement for Solaris' function by the same name. - - First, try to simulate it via opendir ("/proc/self/fd/FD"). Failing - that, simulate it by doing save_cwd/fchdir/opendir(".")/restore_cwd. - If either the save_cwd or the restore_cwd fails (relatively unlikely), - then give a diagnostic and exit nonzero. - Otherwise, this function works just like Solaris' fdopendir. - - W A R N I N G: - Unlike the other fd-related functions here, this one - effectively consumes its FD parameter. The caller should not - close or otherwise manipulate FD if this function returns successfully. */ -DIR * -fdopendir (int fd) -{ - struct saved_cwd saved_cwd; - int saved_errno; - DIR *dir; - - char buf[OPENAT_BUFFER_SIZE]; - char *proc_file = openat_proc_name (buf, fd, "."); - if (proc_file) - { - dir = opendir (proc_file); - saved_errno = errno; - } - else - { - dir = NULL; - saved_errno = EOPNOTSUPP; - } - - /* If the syscall fails with an expected errno value, resort to - save_cwd/restore_cwd. */ - if (! dir && EXPECTED_ERRNO (saved_errno)) - { - if (save_cwd (&saved_cwd) != 0) - openat_save_fail (errno); - - if (fchdir (fd) != 0) - { - dir = NULL; - saved_errno = errno; - } - else - { - dir = opendir ("."); - saved_errno = errno; - - if (restore_cwd (&saved_cwd) != 0) - openat_restore_fail (errno); - } - - free_cwd (&saved_cwd); - } - - if (dir) - close (fd); - if (proc_file != buf) - free (proc_file); - errno = saved_errno; - return dir; -} - -#endif - -/* Replacement for Solaris' function by the same name. - - First, try to simulate it via l?stat ("/proc/self/fd/FD/FILE"). - Failing that, simulate it via save_cwd/fchdir/(stat|lstat)/restore_cwd. - If either the save_cwd or the restore_cwd fails (relatively unlikely), - then give a diagnostic and exit nonzero. - Otherwise, this function works just like Solaris' fstatat. */ - -#define AT_FUNC_NAME fstatat -#define AT_FUNC_F1 lstat -#define AT_FUNC_F2 stat -#define AT_FUNC_USE_F1_COND flag == AT_SYMLINK_NOFOLLOW -#define AT_FUNC_POST_FILE_PARAM_DECLS , struct stat *st, int flag -#define AT_FUNC_POST_FILE_ARGS , st -#include "at-func.c" -#undef AT_FUNC_NAME -#undef AT_FUNC_F1 -#undef AT_FUNC_F2 -#undef AT_FUNC_USE_F1_COND -#undef AT_FUNC_POST_FILE_PARAM_DECLS -#undef AT_FUNC_POST_FILE_ARGS - -/* Replacement for Solaris' function by the same name. - - First, try to simulate it via (unlink|rmdir) ("/proc/self/fd/FD/FILE"). - Failing that, simulate it via save_cwd/fchdir/(unlink|rmdir)/restore_cwd. - If either the save_cwd or the restore_cwd fails (relatively unlikely), - then give a diagnostic and exit nonzero. - Otherwise, this function works just like Solaris' unlinkat. */ - -#define AT_FUNC_NAME unlinkat -#define AT_FUNC_F1 rmdir -#define AT_FUNC_F2 unlink -#define AT_FUNC_USE_F1_COND flag == AT_REMOVEDIR -#define AT_FUNC_POST_FILE_PARAM_DECLS , int flag -#define AT_FUNC_POST_FILE_ARGS /* empty */ -#include "at-func.c" -#undef AT_FUNC_NAME -#undef AT_FUNC_F1 -#undef AT_FUNC_F2 -#undef AT_FUNC_USE_F1_COND -#undef AT_FUNC_POST_FILE_PARAM_DECLS -#undef AT_FUNC_POST_FILE_ARGS +#endif /* !HAVE_OPENAT */ diff --git a/gnulib/lib/openat.h b/gnulib/lib/openat.h index b5e4f11..433b998 100644 --- a/gnulib/lib/openat.h +++ b/gnulib/lib/openat.h @@ -1,5 +1,5 @@ /* provide a replacement openat function - Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc. + Copyright (C) 2004-2006, 2008-2009 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -16,6 +16,9 @@ /* written by Jim Meyering */ +#ifndef _GL_HEADER_OPENAT +#define _GL_HEADER_OPENAT + #include #include @@ -25,7 +28,7 @@ #include #ifndef __attribute__ -# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8) || __STRICT_ANSI__ +# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8) # define __attribute__(x) /* empty */ # endif #endif @@ -34,46 +37,10 @@ # define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__)) #endif -/* Work around a bug in Solaris 9 and 10: AT_FDCWD is positive. Its - value exceeds INT_MAX, so its use as an int doesn't conform to the - C standard, and GCC and Sun C complain in some cases. If the bug - is present, undef AT_FDCWD here, so it can be redefined below. */ -#if 0 < AT_FDCWD && AT_FDCWD == 0xffd19553 -# undef AT_FDCWD -#endif - -/* Use the same bit pattern as Solaris 9, but with the proper - signedness. The bit pattern is important, in case this actually is - Solaris with the above workaround. */ -#ifndef AT_FDCWD -# define AT_FDCWD (-3041965) -#endif - -/* Use the same values as Solaris 9. This shouldn't matter, but - there's no real reason to differ. */ -#ifndef AT_SYMLINK_NOFOLLOW -# define AT_SYMLINK_NOFOLLOW 4096 -# define AT_REMOVEDIR 1 -#endif - -#ifdef __OPENAT_PREFIX +#if !HAVE_OPENAT -# undef openat -# define __OPENAT_CONCAT(x, y) x ## y -# define __OPENAT_XCONCAT(x, y) __OPENAT_CONCAT (x, y) -# define __OPENAT_ID(y) __OPENAT_XCONCAT (__OPENAT_PREFIX, y) -# define openat __OPENAT_ID (openat) -int openat (int fd, char const *file, int flags, /* mode_t mode */ ...); int openat_permissive (int fd, char const *file, int flags, mode_t mode, int *cwd_errno); -# if ! HAVE_FDOPENDIR -# define fdopendir __OPENAT_ID (fdopendir) -# endif -DIR *fdopendir (int fd); -# define fstatat __OPENAT_ID (fstatat) -int fstatat (int fd, char const *file, struct stat *st, int flag); -# define unlinkat __OPENAT_ID (unlinkat) -int unlinkat (int fd, char const *file, int flag); bool openat_needs_fchdir (void); #else @@ -84,19 +51,8 @@ bool openat_needs_fchdir (void); #endif -#if HAVE_OPENAT && ! LSTAT_FOLLOWS_SLASHED_SYMLINK -int rpl_fstatat (int fd, char const *file, struct stat *st, int flag); -# if !COMPILING_FSTATAT -# undef fstatat -# define fstatat rpl_fstatat -# endif -#endif - -int mkdirat (int fd, char const *file, mode_t mode); void openat_restore_fail (int) ATTRIBUTE_NORETURN; void openat_save_fail (int) ATTRIBUTE_NORETURN; -int fchmodat (int fd, char const *file, mode_t mode, int flag); -int fchownat (int fd, char const *file, uid_t owner, gid_t group, int flag); /* Using these function names makes application code slightly more readable than it would be with @@ -124,3 +80,35 @@ lchmodat (int fd, char const *file, mode_t mode) { return fchmodat (fd, file, mode, AT_SYMLINK_NOFOLLOW); } + +static inline int +statat (int fd, char const *name, struct stat *st) +{ + return fstatat (fd, name, st, 0); +} + +static inline int +lstatat (int fd, char const *name, struct stat *st) +{ + return fstatat (fd, name, st, AT_SYMLINK_NOFOLLOW); +} + +#if GNULIB_FACCESSAT +/* For now, there are no wrappers named laccessat or leuidaccessat, + since gnulib doesn't support faccessat(,AT_SYMLINK_NOFOLLOW) and + since access rights on symlinks are of limited utility. */ + +static inline int +accessat (int fd, char const *file, int mode) +{ + return faccessat (fd, file, mode, 0); +} + +static inline int +euidaccessat (int fd, char const *file, int mode) +{ + return faccessat (fd, file, mode, AT_EACCESS); +} +#endif + +#endif /* _GL_HEADER_OPENAT */ diff --git a/gnulib/lib/se-selinux.in.h b/gnulib/lib/se-selinux.in.h new file mode 100644 index 0000000..3f30a3c --- /dev/null +++ b/gnulib/lib/se-selinux.in.h @@ -0,0 +1,73 @@ +#ifndef _GL_SELINUX_SELINUX_H +# define _GL_SELINUX_SELINUX_H + +# if __GNUC__ >= 3 +#pragma GCC system_header +# endif + +# if HAVE_SELINUX_SELINUX_H + +#@INCLUDE_NEXT@ @NEXT_SELINUX_SELINUX_H@ + +# else + +# include +# include + +typedef unsigned short security_class_t; +# define security_context_t char* +# define is_selinux_enabled() 0 + +static inline int getcon (security_context_t *con _UNUSED_PARAMETER_) + { errno = ENOTSUP; return -1; } +static inline void freecon (security_context_t con _UNUSED_PARAMETER_) {} + + +static inline int getfscreatecon (security_context_t *con _UNUSED_PARAMETER_) + { errno = ENOTSUP; return -1; } +static inline int setfscreatecon (security_context_t con _UNUSED_PARAMETER_) + { errno = ENOTSUP; return -1; } +static inline int matchpathcon (char const *file _UNUSED_PARAMETER_, + mode_t m _UNUSED_PARAMETER_, + security_context_t *con _UNUSED_PARAMETER_) + { errno = ENOTSUP; return -1; } +static inline int getfilecon (char const *file _UNUSED_PARAMETER_, + security_context_t *con _UNUSED_PARAMETER_) + { errno = ENOTSUP; return -1; } +static inline int lgetfilecon (char const *file _UNUSED_PARAMETER_, + security_context_t *con _UNUSED_PARAMETER_) + { errno = ENOTSUP; return -1; } +static inline int fgetfilecon (int fd, + security_context_t *con _UNUSED_PARAMETER_) + { errno = ENOTSUP; return -1; } +static inline int setfilecon (char const *file _UNUSED_PARAMETER_, + security_context_t con _UNUSED_PARAMETER_) + { errno = ENOTSUP; return -1; } +static inline int lsetfilecon (char const *file _UNUSED_PARAMETER_, + security_context_t con _UNUSED_PARAMETER_) + { errno = ENOTSUP; return -1; } +static inline int fsetfilecon (int fd _UNUSED_PARAMETER_, + security_context_t con _UNUSED_PARAMETER_) + { errno = ENOTSUP; return -1; } + +static inline int security_check_context + (security_context_t con _UNUSED_PARAMETER_) + { errno = ENOTSUP; return -1; } +static inline int security_check_context_raw + (security_context_t con _UNUSED_PARAMETER_) + { errno = ENOTSUP; return -1; } +static inline int setexeccon (security_context_t con _UNUSED_PARAMETER_) + { errno = ENOTSUP; return -1; } +static inline int security_compute_create + (security_context_t scon _UNUSED_PARAMETER_, + security_context_t tcon _UNUSED_PARAMETER_, + security_class_t tclass _UNUSED_PARAMETER_, + security_context_t *newcon _UNUSED_PARAMETER_) + { errno = ENOTSUP; return -1; } +static inline int matchpathcon_init_prefix + (char const *path _UNUSED_PARAMETER_, + char const *prefix _UNUSED_PARAMETER_) + { errno = ENOTSUP; return -1; } + +# endif +#endif /* _GL_SELINUX_SELINUX_H */ diff --git a/gnulib/lib/selinux-at.c b/gnulib/lib/selinux-at.c new file mode 100644 index 0000000..65f938b --- /dev/null +++ b/gnulib/lib/selinux-at.c @@ -0,0 +1,72 @@ +/* openat-style fd-relative functions for SE Linux + Copyright (C) 2007, 2009 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* written by Jim Meyering */ + +#include + +#include "selinux-at.h" +#include "openat.h" + +#include +#include +#include +#include + +#include "dirname.h" /* solely for definition of IS_ABSOLUTE_FILE_NAME */ +#include "save-cwd.h" + +#include "openat-priv.h" + +#define AT_FUNC_NAME getfileconat +#define AT_FUNC_F1 getfilecon +#define AT_FUNC_POST_FILE_PARAM_DECLS , security_context_t *con +#define AT_FUNC_POST_FILE_ARGS , con +#include "at-func.c" +#undef AT_FUNC_NAME +#undef AT_FUNC_F1 +#undef AT_FUNC_POST_FILE_PARAM_DECLS +#undef AT_FUNC_POST_FILE_ARGS + +#define AT_FUNC_NAME lgetfileconat +#define AT_FUNC_F1 lgetfilecon +#define AT_FUNC_POST_FILE_PARAM_DECLS , security_context_t *con +#define AT_FUNC_POST_FILE_ARGS , con +#include "at-func.c" +#undef AT_FUNC_NAME +#undef AT_FUNC_F1 +#undef AT_FUNC_POST_FILE_PARAM_DECLS +#undef AT_FUNC_POST_FILE_ARGS + +#define AT_FUNC_NAME setfileconat +#define AT_FUNC_F1 setfilecon +#define AT_FUNC_POST_FILE_PARAM_DECLS , security_context_t con +#define AT_FUNC_POST_FILE_ARGS , con +#include "at-func.c" +#undef AT_FUNC_NAME +#undef AT_FUNC_F1 +#undef AT_FUNC_POST_FILE_PARAM_DECLS +#undef AT_FUNC_POST_FILE_ARGS + +#define AT_FUNC_NAME lsetfileconat +#define AT_FUNC_F1 lsetfilecon +#define AT_FUNC_POST_FILE_PARAM_DECLS , security_context_t con +#define AT_FUNC_POST_FILE_ARGS , con +#include "at-func.c" +#undef AT_FUNC_NAME +#undef AT_FUNC_F1 +#undef AT_FUNC_POST_FILE_PARAM_DECLS +#undef AT_FUNC_POST_FILE_ARGS diff --git a/gnulib/lib/selinux-at.h b/gnulib/lib/selinux-at.h new file mode 100644 index 0000000..1d84c19 --- /dev/null +++ b/gnulib/lib/selinux-at.h @@ -0,0 +1,52 @@ +/* Prototypes for openat-style fd-relative SELinux functions + Copyright (C) 2007, 2009 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include +#include + +/* These are the dir-fd-relative variants of the functions without the + "at" suffix. For example, getfileconat (AT_FDCWD, file, &c) is usually + equivalent to getfilecon (file, &c). The emulation is accomplished + by first attempting getfilecon ("/proc/self/fd/DIR_FD/FILE", &c). + Failing that, simulate it via save_cwd/fchdir/getfilecon/restore_cwd. + If either the save_cwd or the restore_cwd fails (relatively unlikely), + then give a diagnostic and exit nonzero. */ + +/* dir-fd-relative getfilecon. Set *CON to the SELinux security context + of the file specified by DIR_FD and FILE and return the length of *CON. + DIR_FD and FILE are interpreted as for fstatat[*]. A non-NULL *CON + must be freed with freecon. Upon error, set *CON to NULL, set errno + and return -1. + [*] with flags=0 here, with flags=AT_SYMLINK_NOFOLLOW for lgetfileconat */ +int getfileconat (int dir_fd, char const *file, security_context_t *con); + +/* dir-fd-relative lgetfilecon. This function is just like getfileconat, + except when DIR_FD and FILE specify a symlink: lgetfileconat operates on + the symlink, while getfileconat operates on the referent of the symlink. */ +int lgetfileconat (int dir_fd, char const *file, security_context_t *con); + +/* dir-fd-relative setfilecon. Set the SELinux security context of + the file specified by DIR_FD and FILE to CON. DIR_FD and FILE are + interpreted as for fstatat[*]. Upon success, return 0. + Otherwise, return -1 and set errno. */ +int setfileconat (int dir_fd, char const *file, security_context_t con); + +/* dir-fd-relative lsetfilecon. This function is just like setfileconat, + except that rather than dereferencing a symlink, this function affects it. */ +/* dir-fd-relative lsetfilecon. This function is just like setfileconat, + except when DIR_FD and FILE specify a symlink: lsetfileconat operates on + the symlink, while setfileconat operates on the referent of the symlink. */ +int lsetfileconat (int dir_fd, char const *file, security_context_t con); diff --git a/gnulib/m4/gnulib-comp.m4 b/gnulib/m4/gnulib-comp.m4 index 1efe223..87f11dd 100644 --- a/gnulib/m4/gnulib-comp.m4 +++ b/gnulib/m4/gnulib-comp.m4 @@ -165,6 +165,11 @@ AC_DEFUN([gl_INIT], gl_SAME gl_SAVE_CWD gl_SAVEDIR + AC_CHECK_HEADERS([selinux/flask.h]) + AC_LIBOBJ([selinux-at]) + gl_HEADERS_SELINUX_SELINUX_H + gl_HEADERS_SELINUX_CONTEXT_H + AC_REQUIRE([AC_C_INLINE]) gl_FUNC_SETENV gl_FUNC_UNSETENV gt_TYPE_SSIZE_T @@ -425,6 +430,7 @@ AC_DEFUN([gl_FILE_LIST], [ lib/getdate.h lib/getdate.y lib/getdelim.c + lib/getfilecon.c lib/getline.c lib/getopt.c lib/getopt.in.h @@ -506,6 +512,10 @@ AC_DEFUN([gl_FILE_LIST], [ lib/save-cwd.h lib/savedir.c lib/savedir.h + lib/se-context.in.h + lib/se-selinux.in.h + lib/selinux-at.c + lib/selinux-at.h lib/setenv.c lib/setenv.h lib/stat-macros.h @@ -688,6 +698,8 @@ AC_DEFUN([gl_FILE_LIST], [ m4/same.m4 m4/save-cwd.m4 m4/savedir.m4 + m4/selinux-context-h.m4 + m4/selinux-selinux-h.m4 m4/setenv.m4 m4/size_max.m4 m4/ssize_t.m4 diff --git a/gnulib/m4/selinux-context-h.m4 b/gnulib/m4/selinux-context-h.m4 new file mode 100644 index 0000000..6b0bed1 --- /dev/null +++ b/gnulib/m4/selinux-context-h.m4 @@ -0,0 +1,16 @@ +# serial 1 -*- Autoconf -*- +# Copyright (C) 2006, 2007 Free Software Foundation, Inc. +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# From Jim Meyering +# Provide , if necessary. + +AC_DEFUN([gl_HEADERS_SELINUX_CONTEXT_H], +[ + AC_CHECK_HEADERS([selinux/context.h], + [SELINUX_CONTEXT_H=], + [SELINUX_CONTEXT_H=selinux/context.h]) + AC_SUBST([SELINUX_CONTEXT_H]) +]) diff --git a/gnulib/m4/selinux-selinux-h.m4 b/gnulib/m4/selinux-selinux-h.m4 new file mode 100644 index 0000000..767c4f7 --- /dev/null +++ b/gnulib/m4/selinux-selinux-h.m4 @@ -0,0 +1,57 @@ +# serial 3 -*- Autoconf -*- +# Copyright (C) 2006, 2007, 2009 Free Software Foundation, Inc. +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# From Jim Meyering +# Provide , if necessary. +# If it is already present, provide wrapper functions to guard against +# misbehavior from getfilecon, lgetfilecon, and fgetfilecon. + +AC_DEFUN([gl_HEADERS_SELINUX_SELINUX_H], +[ + AC_REQUIRE([gl_LIBSELINUX]) + AC_CHECK_HEADERS([selinux/selinux.h]) + + if test "$ac_cv_header_selinux_selinux_h" = yes; then + # We do have , so do compile getfilecon.c + # and arrange to use its wrappers. + AC_LIBOBJ([getfilecon]) + gl_CHECK_NEXT_HEADERS([selinux/selinux.h]) + AC_DEFINE([getfilecon], [rpl_getfilecon], + [Always use our getfilecon wrapper.]) + AC_DEFINE([lgetfilecon], [rpl_lgetfilecon], + [Always use our lgetfilecon wrapper.]) + AC_DEFINE([fgetfilecon], [rpl_fgetfilecon], + [Always use our fgetfilecon wrapper.]) + fi + + case "$ac_cv_search_setfilecon:$ac_cv_header_selinux_selinux_h" in + no:*) # already warned + ;; + *:no) + AC_MSG_WARN([libselinux was found but selinux/selinux.h is missing.]) + AC_MSG_WARN([AC_PACKAGE_NAME will be compiled without SELinux support.]) + esac +]) + +AC_DEFUN([gl_LIBSELINUX], +[ + AC_REQUIRE([AC_CANONICAL_HOST]) + AC_REQUIRE([AC_CANONICAL_BUILD]) + LIB_SELINUX= + gl_save_LIBS=$LIBS + AC_SEARCH_LIBS([setfilecon], [selinux], + [test "$ac_cv_search_setfilecon" = "none required" || + LIB_SELINUX=$ac_cv_search_setfilecon]) + AC_SUBST([LIB_SELINUX]) + LIBS=$gl_save_LIBS + + # Warn if SELinux is found but libselinux is absent; + if test "$ac_cv_search_setfilecon" = no && + test "$host" = "$build" && test -d /selinux; then + AC_MSG_WARN([This system supports SELinux but libselinux is missing.]) + AC_MSG_WARN([AC_PACKAGE_NAME will be compiled without SELinux support.]) + fi +])