selinux-h: always use getfilecon wrappers
authorJim Meyering <meyering@redhat.com>
Wed, 7 Oct 2009 17:00:42 +0000 (19:00 +0200)
committerJim Meyering <meyering@redhat.com>
Fri, 9 Oct 2009 08:07:11 +0000 (10:07 +0200)
* lib/getfilecon.c: New file.
* lib/se-selinux.in.h: Use a better inclusion guard symbol name.
[HAVE_SELINUX_SELINUX_H]: Include-next <selinux/selinux.h>.
[!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 <selinux/selinux.h> 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
MODULES.html.sh
doc/glibc-functions/fgetfilecon.texi [new file with mode: 0644]
doc/glibc-functions/getfilecon-desc.texi [new file with mode: 0644]
doc/glibc-functions/getfilecon.texi [new file with mode: 0644]
doc/glibc-functions/lgetfilecon.texi [new file with mode: 0644]
doc/gnulib.texi
lib/getfilecon.c [new file with mode: 0644]
lib/se-selinux.in.h
m4/selinux-selinux-h.m4
modules/selinux-h

index f374647..7ad1a66 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,26 @@
+2009-10-09  Jim Meyering  <meyering@redhat.com>
+
+       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 <selinux/selinux.h>.
+       [!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 <selinux/selinux.h> 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  <meyering@redhat.com>
 
        unistd: fix comment typo
index 0d2c3cb..53b0b5d 100755 (executable)
@@ -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 (file)
index 0000000..b2cf7e8
--- /dev/null
@@ -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 (file)
index 0000000..fb661a7
--- /dev/null
@@ -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 (file)
index 0000000..d7afcb9
--- /dev/null
@@ -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 (file)
index 0000000..7de1bb2
--- /dev/null
@@ -0,0 +1,5 @@
+@node lgetfilecon
+@subsection @code{lgetfilecon}
+@findex lgetfilecon
+
+@getfileconDesc{lgetfilecon}
index 37cec41..b3085d4 100644 (file)
@@ -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{<selinux/selinux.h>}
+
+@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{<semaphore.h>}
 
diff --git a/lib/getfilecon.c b/lib/getfilecon.c
new file mode 100644 (file)
index 0000000..d712307
--- /dev/null
@@ -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 <config.h>
+
+#include <selinux/selinux.h>
+
+#include <sys/types.h>
+#include <errno.h>
+#include <string.h>
+
+/* 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);
+}
index 25cbaae..c09aebd 100644 (file)
@@ -1,12 +1,22 @@
-#ifndef SELINUX_SELINUX_H
-# define SELINUX_SELINUX_H
+#ifndef _GL_SELINUX_SELINUX_H
+# define _GL_SELINUX_SELINUX_H
 
-# include <sys/types.h>
-# include <errno.h>
+# if __GNUC__ >= 3
+@PRAGMA_SYSTEM_HEADER@
+# endif
+
+# if HAVE_SELINUX_SELINUX_H
+
+#@INCLUDE_NEXT@ @NEXT_SELINUX_SELINUX_H@
+
+# else
+
+#  include <sys/types.h>
+#  include <errno.h>
 
 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 */
index 20dc77c..767c4f7 100644 (file)
@@ -6,14 +6,26 @@
 
 # From Jim Meyering
 # Provide <selinux/selinux.h>, 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 <selinux/selinux.h>, 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
index c9a5a04..fd01241 100644 (file)
@@ -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