[Rpm-maint] [PATCH 18/19] Use selabel interfaces instead of matchpathcon

Steve Lawrence slawrence at tresys.com
Tue Feb 2 20:25:21 UTC 2010


Rather than using the old matchpathcon for relabeling files, use the new
selinux interfaces and store an selabel handle in the rpmts.

With this change, also comes an added distinction between --nocontexts being
specified and a failure to read the file_contexts file. Previously, there
was no distinction, and both cases used the RPMTRANS_FLAG_NOCONTEXTS flag.
However, With the policy changes made in previous patches, it is necessary
to make such a distinction. This is because matchpathcon_init (now selabel
interfaces) can fail at one point, but succeed at another. Because of this,
we may need to enable/disable RPMTRANS_FLAG_NOCONTEXTS multiple times. However,
because this flag could also mean --nocontexts, we cannot do that. By storing
the selabel handle in the rpmts, we can easy keep track if the handle has
been successfully created, rather than overloading RPMTRANS_FLAG_NOCONTEXTS
with two meanings.
---
 configure.ac         |   13 +++++++++++++
 lib/fsm.c            |    8 ++++----
 lib/rpmpol.c         |    3 +--
 lib/rpmts.c          |   44 ++++++++++++++++++++++++++++++++++++++++++++
 lib/rpmts.h          |   21 +++++++++++++++++++++
 lib/rpmts_internal.h |    1 +
 lib/transaction.c    |    8 +++-----
 system.h             |    4 ++++
 8 files changed, 91 insertions(+), 11 deletions(-)

diff --git a/configure.ac b/configure.ac
index d58cfcb..07446d0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -600,6 +600,19 @@ AS_IF([test "$with_selinux" = yes],[
     AC_MSG_ERROR([--with-selinux given, but selinux/selinux.h not found])
   ])
 
+  AC_CHECK_HEADER([selinux/label.h],[
+    save_LIBS="$LIBS"
+    AC_CHECK_LIB([selinux],[selabel_close],[],[
+      AC_MSG_ERROR([--with-selinux given, but selabel_close not found in libselinux])])
+    AC_CHECK_LIB([selinux],[selabel_lookup_raw],[],[
+      AC_MSG_ERROR([--with-selinux given, but selabel_lookup_raw not found in libselinux])])
+    AC_CHECK_LIB([selinux],[selabel_open],[],[
+      AC_MSG_ERROR([--with-selinux given, but selabel_open not found in libselinux])])
+    LIBS="$save_LIBS"
+  ],[
+    AC_MSG_ERROR([--with-selinux given, but selinux/label.h not found])
+  ])
+
   AC_CHECK_HEADER([semanage/semanage.h],[
     save_LIBS="$LIBS"
     AC_CHECK_LIB([semanage],[semanage_begin_transaction],[],[
diff --git a/lib/fsm.c b/lib/fsm.c
index a0efef4..466c9c6 100644
--- a/lib/fsm.c
+++ b/lib/fsm.c
@@ -585,10 +585,10 @@ static int fsmMapFContext(FSM_t fsm)
      * Find file security context (if not disabled).
      */
     fsm->fcontext = NULL;
-    if (ts != NULL && !(rpmtsFlags(ts) & RPMTRANS_FLAG_NOCONTEXTS)) {
+    if (ts != NULL && !(rpmtsFlags(ts) & RPMTRANS_FLAG_NOCONTEXTS) && rpmtsSELabelHandle(ts)) {
 	security_context_t scon = NULL;
 
-	if (matchpathcon(fsm->path, st->st_mode, &scon) == 0 && scon != NULL) {
+	if (selabel_lookup_raw(rpmtsSELabelHandle(ts), &scon, fsm->path, st->st_mode) == 0 && scon != NULL) {
 	    fsm->fcontext = scon;
 	}
     }
@@ -1214,8 +1214,8 @@ static int fsmMkdirs(FSM_t fsm)
 		if (!rc) {
 		    /* XXX FIXME? only new dir will have context set. */
 		    /* Get file security context from patterns. */
-		    if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOCONTEXTS)) {
-			if (matchpathcon(fsm->path, st->st_mode, &scon) == 0 &&
+		    if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOCONTEXTS) && rpmtsSELabelHandle(ts)) {
+			if (selabel_lookup_raw(rpmtsSELabelHandle(ts), &scon, fsm->path, st->st_mode) == 0 &&
 			    scon != NULL) {
             		    fsm->fcontext = scon;
 			    rc = fsmNext(fsm, FSM_LSETFCON);
diff --git a/lib/rpmpol.c b/lib/rpmpol.c
index 3fb397a..460353d 100644
--- a/lib/rpmpol.c
+++ b/lib/rpmpol.c
@@ -1329,8 +1329,7 @@ rpmRC rpmpolsInstall(rpmpols ps, rpmts ts)
 	}
 
 	if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOCONTEXTS)) {
-		matchpathcon_fini();
-		if (matchpathcon_init(selinux_file_context_path()) == -1) {
+		if (rpmtsSELabelInit(ts, selinux_file_context_path()) != RPMRC_OK) {
 			rpmlog(RPMLOG_WARNING, _("Failed to read new file contexts. New files may be mislabeled.\n"));
 		}
 	}
diff --git a/lib/rpmts.c b/lib/rpmts.c
index 9314740..14eac6d 100644
--- a/lib/rpmts.c
+++ b/lib/rpmts.c
@@ -696,6 +696,49 @@ void rpmtsSetPostponePolicy(rpmts ts, int postpone)
 	}
 }
 
+struct selabel_handle * rpmtsSELabelHandle(rpmts ts)
+{
+#if WITH_SELINUX
+	if (ts != NULL) {
+		return ts->selabelHandle;
+	}
+#endif
+	return NULL;
+}
+
+rpmRC rpmtsSELabelInit(rpmts ts, const char * path)
+{
+#if WITH_SELINUX
+	if (ts == NULL || path == NULL) {
+		return RPMRC_FAIL;
+	}
+
+	struct selinux_opt opts[] = {
+		{SELABEL_OPT_PATH, path}
+	};
+
+	if (ts->selabelHandle) {
+		rpmtsSELabelFini(ts);
+	}
+	ts->selabelHandle = selabel_open(SELABEL_CTX_FILE, opts, 1);
+
+	if (!ts->selabelHandle) {
+		return RPMRC_FAIL;
+	}
+#endif
+	return RPMRC_OK;
+}
+
+void rpmtsSELabelFini(rpmts ts)
+{
+#if WITH_SELINUX
+	if (ts && ts->selabelHandle) {
+		selabel_close(ts->selabelHandle);
+		ts->selabelHandle = NULL;
+	}
+#endif
+}
+
 int rpmtsChrootDone(rpmts ts)
 {
     return (ts != NULL ? ts->chrootDone : 0);
@@ -919,6 +962,7 @@ rpmts rpmtsCreate(void)
 
     ts->selinuxEnabled = is_selinux_enabled();
     ts->postponePolicy = 0;
+    ts->selabelHandle = NULL;
 
     ts->numAddedPackages = 0;
     ts->addedPackages = NULL;
diff --git a/lib/rpmts.h b/lib/rpmts.h
index a7214c8..c8be71b 100644
--- a/lib/rpmts.h
+++ b/lib/rpmts.h
@@ -437,6 +437,27 @@ int rpmtsPostponePolicy(rpmts ts);
 void rpmtsSetPostponePolicy(rpmts ts, int postpone);
 
 /** \ingroup rpmts
+ * Get the selabel handle from the transaction set
+ * @param ts		transaction set
+ * @return		selabel handle, or NULL if it hasn't been initialized yet
+ */
+struct selabel_handle * rpmtsSELabelHandle(rpmts ts);
+
+/** \ingroup rpmts
+ * Initialize selabel
+ * @param ts		transaction set
+ * @param path		path to contexts file
+ * @return		RPMRC_OK on success, RPMRC_FAIL otherwise
+ */
+rpmRC rpmtsSELabelInit(rpmts ts, const char * path);
+
+/** \ingroup rpmts
+ * Clean up selabel
+ * @param ts		transaction set
+ */
+void rpmtsSELabelFini(rpmts ts);
+
+/** \ingroup rpmts
  * Get chrootDone flag, i.e. has chroot(2) been performed?
  * @param ts		transaction set
  * @return		chrootDone flag
diff --git a/lib/rpmts_internal.h b/lib/rpmts_internal.h
index 1d490a4..f21ebd4 100644
--- a/lib/rpmts_internal.h
+++ b/lib/rpmts_internal.h
@@ -46,6 +46,7 @@ struct rpmts_s {
 
     int selinuxEnabled;		/*!< Is SE linux enabled? */
     int postponePolicy;		/*!< Should policy be postponed? */
+    struct selabel_handle * selabelHandle;		/*!< Handle to selabel */
 
     int chrootDone;		/*!< Has chroot(2) been been done? */
     char * rootDir;		/*!< Path to top of install tree. */
diff --git a/lib/transaction.c b/lib/transaction.c
index 7dbaae3..0788393 100644
--- a/lib/transaction.c
+++ b/lib/transaction.c
@@ -1414,11 +1414,9 @@ static rpmRC rpmtsInitSELinux(rpmts ts)
 	existingbase = (semanage_is_managed(sh) == 1);
 	semanage_handle_destroy(sh);
 
-	/* initialize matchpathcon */
+	/* initialize selabel */
 	if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOCONTEXTS)) {
-		if (matchpathcon_init(selinux_file_context_path()) == -1) {
-			rpmtsSetFlags(ts, (rpmtsFlags(ts) | RPMTRANS_FLAG_NOCONTEXTS));
-		}
+		rpmtsSELabelInit(ts, selinux_file_context_path());
 	}
 
 	/* exit chroot */
@@ -1537,7 +1535,7 @@ static int rpmtsSetup(rpmts ts, rpmprobFilterFlags ignoreSet)
 static int rpmtsFinish(rpmts ts)
 {
     if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOCONTEXTS)) {
-	matchpathcon_fini();
+	rpmtsSELabelFini(ts);
     }
     return 0;
 }
diff --git a/system.h b/system.h
index ac18e16..5a3766d 100644
--- a/system.h
+++ b/system.h
@@ -78,8 +78,10 @@ char * stpncpy(char * dest, const char * src, size_t n);
 
 #if WITH_SELINUX
 #include <selinux/selinux.h>
+#include <selinux/label.h>
 #else
 typedef	char * security_context_t;
+typedef	void * selabel_handle;
 
 #define	freecon(_c)
 
@@ -92,6 +94,8 @@ typedef	char * security_context_t;
 #define matchpathcon_fini()			(0)
 #define matchpathcon(_fn, _fm, _c)		(-1)
 
+#define selabel_lookup_raw(_hnd, _scon, _key,_type)	(-1)
+
 #define rpm_execcon(_v, _fn, _av, _envp)	(0)
 #endif
 
-- 
1.6.2.5



More information about the Rpm-maint mailing list