d06a0e
From e90a98395a8c4bc265067519c450360481dff1f3 Mon Sep 17 00:00:00 2001
d06a0e
From: Kamil Dudka <kdudka@redhat.com>
d06a0e
Date: Tue, 11 Oct 2016 18:41:56 +0200
d06a0e
Subject: [PATCH 1/2] copyTruncate: factor out handling of SELinux context
d06a0e
d06a0e
... to separate functions
d06a0e
d06a0e
Closes #72
d06a0e
d06a0e
Upstream-commit: c5bff8adcece162746c68834fa1526dd45ca7bd0
d06a0e
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
d06a0e
---
d06a0e
 logrotate.c | 117 ++++++++++++++++++++++++++++++++++++++----------------------
d06a0e
 1 file changed, 74 insertions(+), 43 deletions(-)
d06a0e
d06a0e
diff --git a/logrotate.c b/logrotate.c
d06a0e
index 2abac3d..6270995 100644
d06a0e
--- a/logrotate.c
d06a0e
+++ b/logrotate.c
d06a0e
@@ -251,6 +251,72 @@ static unsigned hashIndex(const char *fn)
d06a0e
 	return hash % hashSize;
d06a0e
 }
d06a0e
 
d06a0e
+static int setSecCtx(int fdSrc, const char *src, void **pPrevCtx)
d06a0e
+{
d06a0e
+#ifdef WITH_SELINUX
d06a0e
+    security_context_t srcCtx;
d06a0e
+    *pPrevCtx = NULL;
d06a0e
+
d06a0e
+    if (!selinux_enabled)
d06a0e
+	/* pretend success */
d06a0e
+	return 0;
d06a0e
+
d06a0e
+    /* read security context of fdSrc */
d06a0e
+    if (fgetfilecon_raw(fdSrc, &srcCtx) < 0) {
d06a0e
+	if (errno == ENOTSUP)
d06a0e
+	    /* pretend success */
d06a0e
+	    return 0;
d06a0e
+
d06a0e
+	message(MESS_ERROR, "getting file context %s: %s\n", src,
d06a0e
+		strerror(errno));
d06a0e
+	return selinux_enforce;
d06a0e
+    }
d06a0e
+
d06a0e
+    /* save default security context for restoreSecCtx() */
d06a0e
+    if (getfscreatecon_raw((security_context_t *)pPrevCtx) < 0) {
d06a0e
+	message(MESS_ERROR, "getting default context: %s\n", strerror(errno));
d06a0e
+	return selinux_enforce;
d06a0e
+    }
d06a0e
+
d06a0e
+    /* set default security context to match fdSrc */
d06a0e
+    if (setfscreatecon_raw(srcCtx) < 0) {
d06a0e
+	message(MESS_ERROR, "setting default context to %s: %s\n", srcCtx,
d06a0e
+		strerror(errno));
d06a0e
+	freecon(srcCtx);
d06a0e
+	return selinux_enforce;
d06a0e
+    }
d06a0e
+
d06a0e
+    message(MESS_DEBUG, "set default create context to %s\n", srcCtx);
d06a0e
+    freecon(srcCtx);
d06a0e
+#else
d06a0e
+    (void) fdSrc;
d06a0e
+    (void) src;
d06a0e
+    (void) pPrevCtx;
d06a0e
+#endif
d06a0e
+    return 0;
d06a0e
+}
d06a0e
+
d06a0e
+static void restoreSecCtx(void **pPrevCtx)
d06a0e
+{
d06a0e
+#ifdef WITH_SELINUX
d06a0e
+    const security_context_t prevCtx = (security_context_t) *pPrevCtx;
d06a0e
+    if (!prevCtx)
d06a0e
+	/* no security context saved for restoration */
d06a0e
+	return;
d06a0e
+
d06a0e
+    /* set default security context to the previously stored one */
d06a0e
+    if (selinux_enabled && setfscreatecon_raw(prevCtx) < 0)
d06a0e
+	message(MESS_ERROR, "setting default context to %s: %s\n", prevCtx,
d06a0e
+		strerror(errno));
d06a0e
+
d06a0e
+    /* free the memory allocated to save the security context */
d06a0e
+    freecon(prevCtx);
d06a0e
+    *pPrevCtx = NULL;
d06a0e
+#else
d06a0e
+    (void) pPrevCtx;
d06a0e
+#endif
d06a0e
+}
d06a0e
+
d06a0e
 static struct logState *newState(const char *fn)
d06a0e
 {
d06a0e
 	struct tm now = *localtime(&nowSecs);
d06a0e
@@ -679,6 +745,7 @@ static int copyTruncate(char *currLog, char *saveLog, struct stat *sb,
d06a0e
 {
d06a0e
     char buf[BUFSIZ];
d06a0e
     int fdcurr = -1, fdsave = -1;
d06a0e
+    void *prevCtx;
d06a0e
     ssize_t cnt;
d06a0e
 
d06a0e
     message(MESS_DEBUG, "copying %s to %s\n", currLog, saveLog);
d06a0e
@@ -689,48 +756,18 @@ static int copyTruncate(char *currLog, char *saveLog, struct stat *sb,
d06a0e
 		    strerror(errno));
d06a0e
 	    return 1;
d06a0e
 	}
d06a0e
-#ifdef WITH_SELINUX
d06a0e
-	if (selinux_enabled) {
d06a0e
-	    security_context_t oldContext;
d06a0e
-	    if (fgetfilecon_raw(fdcurr, &oldContext) >= 0) {
d06a0e
-		if (getfscreatecon_raw(&prev_context) < 0) {
d06a0e
-		    message(MESS_ERROR,
d06a0e
-			    "getting default context: %s\n",
d06a0e
-			    strerror(errno));
d06a0e
-		    if (selinux_enforce) {
d06a0e
-				freecon(oldContext);
d06a0e
-				close(fdcurr);
d06a0e
-				return 1;
d06a0e
-		    }
d06a0e
-		}
d06a0e
-		if (setfscreatecon_raw(oldContext) < 0) {
d06a0e
-		    message(MESS_ERROR,
d06a0e
-			    "setting file context %s to %s: %s\n",
d06a0e
-			    saveLog, oldContext, strerror(errno));
d06a0e
-			if (selinux_enforce) {
d06a0e
-				freecon(oldContext);
d06a0e
-				close(fdcurr);
d06a0e
-				return 1;
d06a0e
-		    }
d06a0e
-		}
d06a0e
-		message(MESS_DEBUG, "set default create context\n");
d06a0e
-		freecon(oldContext);
d06a0e
-	    } else {
d06a0e
-		    if (errno != ENOTSUP) {
d06a0e
-			    message(MESS_ERROR, "getting file context %s: %s\n",
d06a0e
-				    currLog, strerror(errno));
d06a0e
-			    if (selinux_enforce) {
d06a0e
-				    return 1;
d06a0e
-			    }
d06a0e
-		    }
d06a0e
-	    }
d06a0e
+
d06a0e
+	if (setSecCtx(fdcurr, currLog, &prevCtx) != 0) {
d06a0e
+	    /* error msg already printed */
d06a0e
+	    close(fdcurr);
d06a0e
+	    return 1;
d06a0e
 	}
d06a0e
-#endif
d06a0e
 #ifdef WITH_ACL
d06a0e
 	if ((prev_acl = acl_get_fd(fdcurr)) == NULL) {
d06a0e
 		if (!ACL_NOT_WELL_SUPPORTED(errno)) {
d06a0e
 			message(MESS_ERROR, "getting file ACL %s: %s\n",
d06a0e
 				currLog, strerror(errno));
d06a0e
+			restoreSecCtx(&prevCtx);
d06a0e
 			close(fdcurr);
d06a0e
 			return 1;
d06a0e
 		}
d06a0e
@@ -738,13 +775,7 @@ static int copyTruncate(char *currLog, char *saveLog, struct stat *sb,
d06a0e
 #endif /* WITH_ACL */
d06a0e
 	fdsave =
d06a0e
 	    createOutputFile(saveLog, O_WRONLY | O_CREAT, sb, prev_acl, 0);
d06a0e
-#ifdef WITH_SELINUX
d06a0e
-	if (selinux_enabled) {
d06a0e
-	    setfscreatecon_raw(prev_context);
d06a0e
-		freecon(prev_context);
d06a0e
-		prev_context = NULL;
d06a0e
-	}
d06a0e
-#endif
d06a0e
+	restoreSecCtx(&prevCtx);
d06a0e
 #ifdef WITH_ACL
d06a0e
 	if (prev_acl) {
d06a0e
 		acl_free(prev_acl);
d06a0e
-- 
d06a0e
2.7.4
d06a0e
d06a0e
d06a0e
From 0ed7a45533a3d9d2237c742a2de03faba1b2e35f Mon Sep 17 00:00:00 2001
d06a0e
From: Kamil Dudka <kdudka@redhat.com>
d06a0e
Date: Tue, 11 Oct 2016 18:53:18 +0200
d06a0e
Subject: [PATCH 2/2] compressLogFile: explicitly preserve SELinux context
d06a0e
d06a0e
If we use options 'compress' and 'sharedscripts' together, the rotated
d06a0e
(and compressed) log files may end up with a wrong security context in
d06a0e
case multiple files with different security contexts are rotated in a
d06a0e
row.
d06a0e
d06a0e
Closes #72
d06a0e
d06a0e
Upstream-commit: 57458d5424eebf0c7912eefe955e4d7b0f49fd15
d06a0e
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
d06a0e
---
d06a0e
 logrotate.c | 9 +++++++++
d06a0e
 1 file changed, 9 insertions(+)
d06a0e
d06a0e
diff --git a/logrotate.c b/logrotate.c
d06a0e
index 6270995..20f6ea5 100644
d06a0e
--- a/logrotate.c
d06a0e
+++ b/logrotate.c
d06a0e
@@ -558,6 +558,7 @@ static int compressLogFile(char *name, struct logInfo *log, struct stat *sb)
d06a0e
     int outFile;
d06a0e
     int i;
d06a0e
     int status;
d06a0e
+    void *prevCtx;
d06a0e
 
d06a0e
     message(MESS_DEBUG, "compressing log with: %s\n", log->compress_prog);
d06a0e
     if (debug)
d06a0e
@@ -578,11 +579,18 @@ static int compressLogFile(char *name, struct logInfo *log, struct stat *sb)
d06a0e
 	return 1;
d06a0e
     }
d06a0e
 
d06a0e
+    if (setSecCtx(inFile, name, &prevCtx) != 0) {
d06a0e
+	/* error msg already printed */
d06a0e
+	close(inFile);
d06a0e
+	return 1;
d06a0e
+    }
d06a0e
+
d06a0e
 #ifdef WITH_ACL
d06a0e
 	if ((prev_acl = acl_get_fd(inFile)) == NULL) {
d06a0e
 		if (!ACL_NOT_WELL_SUPPORTED(errno)) {
d06a0e
 			message(MESS_ERROR, "getting file ACL %s: %s\n",
d06a0e
 				name, strerror(errno));
d06a0e
+			restoreSecCtx(&prevCtx);
d06a0e
 			close(inFile);
d06a0e
 			return 1;
d06a0e
 		}
d06a0e
@@ -591,6 +599,7 @@ static int compressLogFile(char *name, struct logInfo *log, struct stat *sb)
d06a0e
 
d06a0e
     outFile =
d06a0e
 	createOutputFile(compressedName, O_RDWR | O_CREAT, sb, prev_acl, 0);
d06a0e
+    restoreSecCtx(&prevCtx);
d06a0e
 #ifdef WITH_ACL
d06a0e
 	if (prev_acl) {
d06a0e
 		acl_free(prev_acl);
d06a0e
-- 
d06a0e
2.7.4
d06a0e