From f4dc80620e25623a69aa852bec5a52e150cedd4a Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Wed, 7 Oct 2009 19:00:42 +0200 Subject: [PATCH] selinux-h: always use getfilecon wrappers * lib/getfilecon.c: New file. * lib/se-selinux.in.h: Use a better inclusion guard symbol name. [HAVE_SELINUX_SELINUX_H]: Include-next . [!HAVE_SELINUX_SELINUX_H]: Use better parameter names. (fgetfilecon): Provide a stub. * m4/selinux-selinux-h.m4 (gl_HEADERS_SELINUX_SELINUX_H): Don't AC_SUBST SELINUX_SELINUX_H, since now we're generating that file unconditionally. When is found, arrange to use wrappers. * modules/selinux-h (Files): Add getfilecon.c. (Makefile.am): Substitute include-next-related bits into the now-always-generated selinux/selinux.h file. * doc/glibc-functions/getfilecon.texi: New file. * doc/glibc-functions/lgetfilecon.texi: New file. * doc/glibc-functions/fgetfilecon.texi: New file. * doc/glibc-functions/getfilecon-desc.texi: New file. * doc/gnulib.texi (Glibc selinux/selinux.h): New section, by which to pull in the new files. * MODULES.html.sh (Misc): Add selinux-h. --- ChangeLog | 23 +++++++++ MODULES.html.sh | 1 + doc/glibc-functions/fgetfilecon.texi | 5 ++ doc/glibc-functions/getfilecon-desc.texi | 27 ++++++++++ doc/glibc-functions/getfilecon.texi | 5 ++ doc/glibc-functions/lgetfilecon.texi | 5 ++ doc/gnulib.texi | 15 ++++++ lib/getfilecon.c | 87 ++++++++++++++++++++++++++++++++ lib/se-selinux.in.h | 39 +++++++++----- m4/selinux-selinux-h.m4 | 20 ++++++-- modules/selinux-h | 10 +++- 11 files changed, 219 insertions(+), 18 deletions(-) create mode 100644 doc/glibc-functions/fgetfilecon.texi create mode 100644 doc/glibc-functions/getfilecon-desc.texi create mode 100644 doc/glibc-functions/getfilecon.texi create mode 100644 doc/glibc-functions/lgetfilecon.texi create mode 100644 lib/getfilecon.c diff --git a/ChangeLog b/ChangeLog index f3746471a..7ad1a661c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,26 @@ +2009-10-09 Jim Meyering + + selinux-h: always use getfilecon wrappers + * lib/getfilecon.c: New file. + * lib/se-selinux.in.h: Use a better inclusion guard symbol name. + [HAVE_SELINUX_SELINUX_H]: Include-next . + [!HAVE_SELINUX_SELINUX_H]: Use better parameter names. + (fgetfilecon): Provide a stub. + * m4/selinux-selinux-h.m4 (gl_HEADERS_SELINUX_SELINUX_H): Don't + AC_SUBST SELINUX_SELINUX_H, since now we're generating that + file unconditionally. + When is found, arrange to use wrappers. + * modules/selinux-h (Files): Add getfilecon.c. + (Makefile.am): Substitute include-next-related bits + into the now-always-generated selinux/selinux.h file. + * doc/glibc-functions/lgetfilecon.texi: New file. + * doc/glibc-functions/fgetfilecon.texi: New file. + * doc/glibc-functions/getfilecon.texi: New file. + * doc/glibc-functions/getfilecon-desc.texi: New file. + * doc/gnulib.texi (Glibc selinux/selinux.h): New section, by + which to pull in the new files. + * MODULES.html.sh (Misc): Add selinux-h. + 2009-10-08 Jim Meyering unistd: fix comment typo diff --git a/MODULES.html.sh b/MODULES.html.sh index 0d2c3cb29..53b0b5dac 100755 --- a/MODULES.html.sh +++ b/MODULES.html.sh @@ -3142,6 +3142,7 @@ func_all_modules () func_module quote func_module readutmp func_module random_r + func_module selinux-h func_module selinux-at func_module sysexits func_module u64 diff --git a/doc/glibc-functions/fgetfilecon.texi b/doc/glibc-functions/fgetfilecon.texi new file mode 100644 index 000000000..b2cf7e89b --- /dev/null +++ b/doc/glibc-functions/fgetfilecon.texi @@ -0,0 +1,5 @@ +@node fgetfilecon +@subsection @code{fgetfilecon} +@findex fgetfilecon + +@getfileconDesc{fgetfilecon} diff --git a/doc/glibc-functions/getfilecon-desc.texi b/doc/glibc-functions/getfilecon-desc.texi new file mode 100644 index 000000000..fb661a7f4 --- /dev/null +++ b/doc/glibc-functions/getfilecon-desc.texi @@ -0,0 +1,27 @@ +@macro getfileconDesc{fn} +Gnulib module: selinux-h + +Portability problems fixed by Gnulib: +@itemize +@item +This function is missing on some platforms: +MacOS X 10.3, OpenBSD 3.8, AIX 5.1, HP-UX 11, IRIX 6.5, OSF/1 5.1, Solaris 10, mingw, Interix 3.5, BeOS. +On those platforms, this module provides a stub that always sets +@code{errno} to @code{ENOTSUP} and returns @samp{-1}. +@item +On systems with SELinux support, this module provides a wrapper for the +@code{\fn\} function that insulates the caller from API-nonconforming behavior. +Without this wrapper, @code{\fn\} can return @samp{0} and set +the @code{context} pointer to NULL, and in another scenario can return +@samp{10} and set the @code{context} pointer to @samp{unlabeled}. +This wrapper returns @samp{-1} in each case and sets @code{errno} to +@code{ENOTSUP} and @code{ENODATA} respectively. +While the conditions that can provoke such behavior are rare, the +average caller does not handle them because the possibility of such +behavior is not documented. +@end itemize + +Portability problems not fixed by Gnulib: +@itemize +@end itemize +@end macro diff --git a/doc/glibc-functions/getfilecon.texi b/doc/glibc-functions/getfilecon.texi new file mode 100644 index 000000000..d7afcb90a --- /dev/null +++ b/doc/glibc-functions/getfilecon.texi @@ -0,0 +1,5 @@ +@node getfilecon +@subsection @code{getfilecon} +@findex getfilecon + +@getfileconDesc{getfilecon} diff --git a/doc/glibc-functions/lgetfilecon.texi b/doc/glibc-functions/lgetfilecon.texi new file mode 100644 index 000000000..7de1bb284 --- /dev/null +++ b/doc/glibc-functions/lgetfilecon.texi @@ -0,0 +1,5 @@ +@node lgetfilecon +@subsection @code{lgetfilecon} +@findex lgetfilecon + +@getfileconDesc{lgetfilecon} diff --git a/doc/gnulib.texi b/doc/gnulib.texi index 37cec417e..b3085d4ad 100644 --- a/doc/gnulib.texi +++ b/doc/gnulib.texi @@ -3290,6 +3290,7 @@ This list of functions is sorted according to the header that declares them. * Glibc rpcsvc/ypupd.h:: * Glibc sched.h:: * Glibc search.h:: +* Glibc selinux/selinux.h:: * Glibc shadow.h:: * Glibc signal.h:: * Glibc stdio.h:: @@ -4906,6 +4907,20 @@ This list of functions is sorted according to the header that declares them. @include glibc-functions/hsearch_r.texi @include glibc-functions/tdestroy.texi +@node Glibc selinux/selinux.h +@section Glibc Extensions to @code{} + +@menu +* fgetfilecon:: +* getfilecon:: +* lgetfilecon:: +@end menu + +@include glibc-functions/getfilecon-desc.texi +@include glibc-functions/fgetfilecon.texi +@include glibc-functions/getfilecon.texi +@include glibc-functions/lgetfilecon.texi + @c @node Glibc semaphore.h @c @section Glibc Extensions to @code{} diff --git a/lib/getfilecon.c b/lib/getfilecon.c new file mode 100644 index 000000000..d712307fd --- /dev/null +++ b/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/lib/se-selinux.in.h b/lib/se-selinux.in.h index 25cbaaef7..c09aebd95 100644 --- a/lib/se-selinux.in.h +++ b/lib/se-selinux.in.h @@ -1,12 +1,22 @@ -#ifndef SELINUX_SELINUX_H -# define SELINUX_SELINUX_H +#ifndef _GL_SELINUX_SELINUX_H +# define _GL_SELINUX_SELINUX_H -# include -# include +# if __GNUC__ >= 3 +@PRAGMA_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 +# define security_context_t char* +# define is_selinux_enabled() 0 static inline int getcon (security_context_t *con _UNUSED_PARAMETER_) { errno = ENOTSUP; return -1; } @@ -17,20 +27,23 @@ 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 *s _UNUSED_PARAMETER_, +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 *s _UNUSED_PARAMETER_, +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 *s _UNUSED_PARAMETER_, +static inline int lgetfilecon (char const *file _UNUSED_PARAMETER_, security_context_t *con _UNUSED_PARAMETER_) { errno = ENOTSUP; return -1; } -static inline int setfilecon (char const *s _UNUSED_PARAMETER_, +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 *s _UNUSED_PARAMETER_, +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_, @@ -55,4 +68,6 @@ static inline int matchpathcon_init_prefix (char const *path _UNUSED_PARAMETER_, char const *prefix _UNUSED_PARAMETER_) { errno = ENOTSUP; return -1; } -#endif + +# endif +#endif /* _GL_SELINUX_SELINUX_H */ diff --git a/m4/selinux-selinux-h.m4 b/m4/selinux-selinux-h.m4 index 20dc77c43..767c4f7f1 100644 --- a/m4/selinux-selinux-h.m4 +++ b/m4/selinux-selinux-h.m4 @@ -6,14 +6,26 @@ # 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], - [SELINUX_SELINUX_H=], - [SELINUX_SELINUX_H=selinux/selinux.h]) - AC_SUBST([SELINUX_SELINUX_H]) + 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 diff --git a/modules/selinux-h b/modules/selinux-h index c9a5a046a..fd01241c7 100644 --- a/modules/selinux-h +++ b/modules/selinux-h @@ -2,6 +2,7 @@ Description: SELinux-related headers for systems that lack them. Files: +lib/getfilecon.c lib/se-context.in.h lib/se-selinux.in.h m4/selinux-context-h.m4 @@ -18,11 +19,16 @@ AC_REQUIRE([AC_C_INLINE]) Makefile.am: lib_SOURCES += se-context.in.h se-selinux.in.h -BUILT_SOURCES += $(SELINUX_SELINUX_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 $@ && \ - cp $(srcdir)/se-selinux.in.h $@-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 -- 2.11.0