The following commit has been merged in the master branch:
commit b3ffabc01224d0317f774405722f679ee8bf3978
Author: Guillem Jover <[email protected]>
Date: Mon Mar 1 18:54:39 2010 +0100
dpkg: Switch SE Linux support to explicitly set path contexts
The current code sets the default context and does not clean it on
conffile extraction or in case of unpack error, which causes the wrong
context to be applied to files under <admindir>.
Switch the code to explicitly set the path context for newly extracted
and created files so that we don't need to care about unpack error
recovery or conffile extraction to restore the default context.
Refactor the code into a new function and remove an unneeded setting of
the context just before the rename from <node>.dpkg-new to <node>.
Closes: #498438
diff --git a/debian/changelog b/debian/changelog
index 46a9c7b..a32f4e1 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -145,6 +145,9 @@ dpkg (1.15.6) UNRELEASED; urgency=low
- README.api only in development packages, dpkg-dev and libdpkg-dev.
- triggers.txt only in dpkg-dev.
* Move source.lintian-overrides to debian/source/lintian-overrides.
+ * Switch SE Linux support to explicitly set path context. This fixes the
+ mislabeling of files under <admindir> on conffile extraction or on unpack
+ errors, due to improper default context restoration. Closes: #498438
[ Modestas Vainius ]
* Implement symbol patterns (Closes: #563752). From now on, it is possible to
diff --git a/src/archives.c b/src/archives.c
index 365f17e..69110c1 100644
--- a/src/archives.c
+++ b/src/archives.c
@@ -51,8 +51,6 @@
#ifdef WITH_SELINUX
#include <selinux/selinux.h>
-static int selinux_enabled=-1;
-static security_context_t scontext = NULL;
#endif
#include "filesdb.h"
@@ -256,6 +254,41 @@ static void newtarobject_allmodes(const char *path, struct
TarInfo *ti, struct f
newtarobject_utime(path,ti);
}
+static void
+set_selinux_path_context(const char *matchpath, const char *path, mode_t mode)
+{
+#ifdef WITH_SELINUX
+ static int selinux_enabled = -1;
+ security_context_t scontext = NULL;
+ int ret;
+
+ /* Set selinux_enabled if it is not already set (singleton). */
+ if (selinux_enabled < 0)
+ selinux_enabled = (is_selinux_enabled() > 0);
+
+ /* If SE Linux is not enabled just do nothing. */
+ if (!selinux_enabled)
+ return;
+
+ /* XXX: Well, we could use set_matchpathcon_printf() to redirect the
+ * errors from the following bit, but that seems too much effort. */
+
+ /* Do nothing if we can't figure out what the context is, or if it has
+ * no context; in which case the default context shall be applied. */
+ ret = matchpathcon(matchpath, mode & ~S_IFMT, &scontext);
+ if (ret == -1 || (ret == 0 && scontext == NULL))
+ return;
+
+ if (strcmp(scontext, "<<none>>") != 0) {
+ if (lsetfilecon(path, scontext) < 0)
+ /* XXX: This might need to be fatal instead!? */
+ perror("Error setting security context for next file object:");
+ }
+
+ freecon(scontext);
+#endif /* WITH_SELINUX */
+}
+
void setupfnamevbs(const char *filename) {
fnamevb.used= fnameidlu;
varbufaddstr(&fnamevb,filename);
@@ -594,38 +627,6 @@ int tarobject(struct TarInfo *ti) {
* its original filename.
*/
-#ifdef WITH_SELINUX
- /* Set selinux_enabled if it is not already set (singleton) */
- if (selinux_enabled < 0)
- selinux_enabled = (is_selinux_enabled() > 0);
-
- /* Since selinux is enabled, try and set the context */
- if (selinux_enabled > 0) {
- /*
- * well, we could use
- * void set_matchpathcon_printf(void (*f)(const char *fmt, ...));
- * to redirect the errors from the following bit, but that
- * seems too much effort.
- */
-
- /*
- * Do nothing if we can't figure out what the context is,
- * or if it has no context; in which case the default
- * context shall be applied.
- */
- if( ! ((matchpathcon(fnamevb.buf,
- (nifd->namenode->statoverride ?
- nifd->namenode->statoverride->mode : ti->Mode)
- & ~S_IFMT, &scontext) != 0) ||
- (strcmp(scontext, "<<none>>") == 0)))
- {
- if(setfscreatecon(scontext) < 0)
- perror("Error setting security context for file object:");
- }
- }
-#endif /* WITH_SELINUX */
-
-
/* Extract whatever it is as .dpkg-new ... */
switch (ti->Type) {
case NormalFile0: case NormalFile1:
@@ -711,6 +712,11 @@ int tarobject(struct TarInfo *ti) {
default:
internerr("unknown tar type '%d', but already checked", ti->Type);
}
+
+ set_selinux_path_context(fnamevb.buf, fnamenewvb.buf,
+ nifd->namenode->statoverride ?
+ nifd->namenode->statoverride->mode : ti->Mode);
+
/* CLEANUP: Now we have extracted the new object in .dpkg-new (or,
* if the file already exists as a directory and we were trying to extract
* a directory or symlink, we returned earlier, so we don't need
@@ -755,6 +761,7 @@ int tarobject(struct TarInfo *ti) {
ohshite(_("unable to make backup symlink for `%.255s'"),ti->Name);
if (lchown(fnametmpvb.buf,stab.st_uid,stab.st_gid))
ohshite(_("unable to chown backup symlink for `%.255s'"),ti->Name);
+ set_selinux_path_context(fnamevb.buf, fnametmpvb.buf, stab.st_mode);
} else {
debug(dbg_eachfiledetail,"tarobject nondirectory, `link' backup");
if (link(fnamevb.buf,fnametmpvb.buf))
@@ -767,21 +774,6 @@ int tarobject(struct TarInfo *ti) {
* in dpkg-new.
*/
-#ifdef WITH_SELINUX
- /*
- * if selinux is enabled, try and set the default security context
- * for the renamed file
- */
- if (selinux_enabled > 0)
- if(scontext) {
- if(setfscreatecon(scontext) < 0)
- perror("Error setting security context for next file object:");
- freecon(scontext);
- scontext = NULL;
- }
-
-#endif /* WITH_SELINUX */
-
if (rename(fnamenewvb.buf,fnamevb.buf))
ohshite(_("unable to install new version of `%.255s'"),ti->Name);
@@ -792,17 +784,6 @@ int tarobject(struct TarInfo *ti) {
*/
nifd->namenode->flags |= fnnf_placed_on_disk;
-
-#ifdef WITH_SELINUX
- /*
- * if selinux is enabled, restore the default security context
- */
- if (selinux_enabled > 0)
- if(setfscreatecon(NULL) < 0)
- perror("Error restoring default security context:");
-#endif /* WITH_SELINUX */
-
-
nifd->namenode->flags |= fnnf_elide_other_lists;
debug(dbg_eachfiledetail,"tarobject done and installed");
--
dpkg's main repository
--
To UNSUBSCRIBE, email to [email protected]
with a subject of "unsubscribe". Trouble? Contact [email protected]