[logrotate] - fix #688520 - fixed CVE-2011-1154, CVE-2011-1155 and CVE-2011-1098

Jan Kaluža jkaluza at fedoraproject.org
Mon Mar 21 12:43:15 UTC 2011


commit 849f471971418b7fcbec0b331ffd219f83a580c5
Author: Jan Kaluza <hanzz.k at gmail.com>
Date:   Mon Mar 21 13:42:59 2011 +0100

    - fix #688520 - fixed CVE-2011-1154, CVE-2011-1155 and CVE-2011-1098

 logrotate-3.7.9-atomic-create.patch |   70 ++++++++++++++++
 logrotate-3.7.9-shred.patch         |  151 +++++++++++++++++++++++++++++++++++
 logrotate-3.7.9-statefile.patch     |   96 ++++++++++++++++++++++
 3 files changed, 317 insertions(+), 0 deletions(-)
---
diff --git a/logrotate-3.7.9-atomic-create.patch b/logrotate-3.7.9-atomic-create.patch
new file mode 100644
index 0000000..b888dc0
--- /dev/null
+++ b/logrotate-3.7.9-atomic-create.patch
@@ -0,0 +1,70 @@
+diff --git a/logrotate.c b/logrotate.c
+index 3748918..fbe232a 100644
+--- a/logrotate.c
++++ b/logrotate.c
+@@ -194,31 +194,41 @@ static int runScript(char *logfn, char *script)
+ int createOutputFile(char *fileName, int flags, struct stat *sb)
+ {
+     int fd;
++	char template[PATH_MAX + 1];
++	mode_t umask_value;
++	snprintf(template, PATH_MAX, "%s/logrotate_temp.XXXXXX", ourDirName(fileName));
++
++	umask_value = umask(0000);
++	fd = mkstemp(template);
++	umask(umask_value);
++
++	if (fd < 0) {
++		message(MESS_ERROR, "error creating unique temp file: %s\n",
++				strerror(errno));
++		return -1;
++	}
++
++	if (fchown(fd, sb->st_uid, sb->st_gid)) {
++		message(MESS_ERROR, "error setting owner of %s: %s\n",
++				fileName, strerror(errno));
++		close(fd);
++		return -1;
++	}
++
++	if (fchmod(fd, sb->st_mode)) {
++		message(MESS_ERROR, "error setting mode of %s: %s\n",
++				fileName, strerror(errno));
++		close(fd);
++		return -1;
++	}
++
++	if (rename(template, fileName)) {
++		message(MESS_ERROR, "error renaming temp file to %s: %s\n",
++				fileName, strerror(errno));
++		close(fd);
++		return -1;
++	}
+ 
+-    fd = open(fileName, flags, sb->st_mode);
+-    if (fd < 0) {
+-	message(MESS_ERROR, "error creating output file %s: %s\n",
+-		fileName, strerror(errno));
+-	return -1;
+-    }
+-    if (fchmod(fd, (S_IRUSR | S_IWUSR) & sb->st_mode)) {
+-	message(MESS_ERROR, "error setting mode of %s: %s\n",
+-		fileName, strerror(errno));
+-	close(fd);
+-	return -1;
+-    }
+-    if (fchown(fd, sb->st_uid, sb->st_gid)) {
+-	message(MESS_ERROR, "error setting owner of %s: %s\n",
+-		fileName, strerror(errno));
+-	close(fd);
+-	return -1;
+-    }
+-    if (fchmod(fd, sb->st_mode)) {
+-	message(MESS_ERROR, "error setting mode of %s: %s\n",
+-		fileName, strerror(errno));
+-	close(fd);
+-	return -1;
+-    }
+     return fd;
+ }
+ 
diff --git a/logrotate-3.7.9-shred.patch b/logrotate-3.7.9-shred.patch
new file mode 100644
index 0000000..d978000
--- /dev/null
+++ b/logrotate-3.7.9-shred.patch
@@ -0,0 +1,151 @@
+Index: logrotate.c
+===================================================================
+--- logrotate.c	(revision 310)
++++ logrotate.c	(working copy)
+@@ -71,7 +71,7 @@
+ char *mailCommand = DEFAULT_MAIL_COMMAND;
+ time_t nowSecs = 0;
+ 
+-static int shred_file(char *filename, struct logInfo *log);
++static int shred_file(int fd, char *filename, struct logInfo *log);
+ 
+ static int globerr(const char *pathname, int theerr)
+ {
+@@ -231,59 +231,79 @@
+     return fd;
+ }
+ 
+-#define SHRED_CALL "shred -u "
+-#define SHRED_COUNT_FLAG "-n "
+ #define DIGITS 10
++
+ /* unlink, but try to call shred from GNU fileutils */
+-static int shred_file(char *filename, struct logInfo *log)
++static int shred_file(int fd, char *filename, struct logInfo *log)
+ {
+-	int len, ret;
+-	char *cmd;
+ 	char count[DIGITS];    /*  that's a lot of shredding :)  */
++	const char **fullCommand;
++	int id = 0;
++	int status;
+ 
+ 	if (!(log->flags & LOG_FLAG_SHRED)) {
+ 		return unlink(filename);
+ 	}
+ 
+-	len = strlen(filename) + strlen(SHRED_CALL);
+-	len += strlen(SHRED_COUNT_FLAG) + DIGITS;
+-	cmd = malloc(len);
++	message(MESS_DEBUG, "Using shred to remove the file %s\n", filename);
+ 
+-	if (!cmd) {
+-		message(MESS_ERROR, "malloc error while shredding");
+-		return unlink(filename);
++	if (log->shred_cycles != 0) {
++		fullCommand = alloca(sizeof(*fullCommand) * 6);
+ 	}
+-	strcpy(cmd, SHRED_CALL);
++	else {
++		fullCommand = alloca(sizeof(*fullCommand) * 4);
++	}
++	fullCommand[id++] = "shred";
++	fullCommand[id++] = "-u";
++
+ 	if (log->shred_cycles != 0) {
+-		strcat(cmd, SHRED_COUNT_FLAG);
++		fullCommand[id++] = "-n";
+ 		snprintf(count, DIGITS - 1, "%d", log->shred_cycles);
+-		strcat(count, " ");
+-		strcat(cmd, count);
++		fullCommand[id++] = count;
+ 	}
+-	strcat(cmd, filename);
+-	ret = system(cmd);
+-	free(cmd);
+-	if (ret != 0) {
++	fullCommand[id++] = "-";
++	fullCommand[id++] = NULL;
++
++	if (!fork()) {
++		dup2(fd, 1);
++		close(fd);
++
++		execvp(fullCommand[0], (void *) fullCommand);
++		exit(1);
++	}
++	
++	wait(&status);
++
++	if (!WIFEXITED(status) || WEXITSTATUS(status)) {
+ 		message(MESS_ERROR, "Failed to shred %s\n, trying unlink", filename);
+-		if (ret != -1) {
+-			message(MESS_NORMAL, "Shred returned %d\n", ret);
+-		}
+ 		return unlink(filename);
+-	} else {
+-		return ret;
+ 	}
++
++	/* We have to unlink it after shred anyway,
++	 * because it doesn't remove the file itself */
++	return unlink(filename);
+ }
+ 
+ static int removeLogFile(char *name, struct logInfo *log)
+ {
+-    message(MESS_DEBUG, "removing old log %s\n", name);
++	int fd;
++	message(MESS_DEBUG, "removing old log %s\n", name);
+ 
+-    if (!debug && shred_file(name, log)) {
+-	message(MESS_ERROR, "Failed to remove old log %s: %s\n",
+-		name, strerror(errno));
+-	return 1;
+-    }
+-    return 0;
++	if ((fd = open(name, O_RDWR)) < 0) {
++		message(MESS_ERROR, "error opening %s: %s\n",
++			name, strerror(errno));
++		return 1;
++	}
++
++	if (!debug && shred_file(fd, name, log)) {
++		message(MESS_ERROR, "Failed to remove old log %s: %s\n",
++			name, strerror(errno));
++		close(fd);
++		return 1;
++	}
++
++	close(fd);
++	return 0;
+ }
+ 
+ static int compressLogFile(char *name, struct logInfo *log, struct stat *sb)
+@@ -310,7 +330,7 @@
+     compressedName = alloca(strlen(name) + strlen(log->compress_ext) + 2);
+     sprintf(compressedName, "%s%s", name, log->compress_ext);
+ 
+-    if ((inFile = open(name, O_RDONLY)) < 0) {
++    if ((inFile = open(name, O_RDWR)) < 0) {
+ 	message(MESS_ERROR, "unable to open %s for compression\n", name);
+ 	return 1;
+     }
+@@ -357,7 +377,6 @@
+ 	exit(1);
+     }
+ 
+-    close(inFile);
+     close(outFile);
+ 
+     wait(&status);
+@@ -373,7 +392,8 @@
+     /* If we can't change atime/mtime, it's not a disaster.
+        It might possibly fail under SELinux. */
+ 
+-    shred_file(name, log);
++    shred_file(inFile, name, log);
++	close(inFile);
+ 
+     return 0;
+ }
diff --git a/logrotate-3.7.9-statefile.patch b/logrotate-3.7.9-statefile.patch
new file mode 100644
index 0000000..daa0240
--- /dev/null
+++ b/logrotate-3.7.9-statefile.patch
@@ -0,0 +1,96 @@
+Index: logrotate.c
+===================================================================
+--- logrotate.c	(revision 314)
++++ logrotate.c	(working copy)
+@@ -45,6 +45,12 @@
+ #define GLOB_ABORTED GLOB_ABEND
+ #endif
+ 
++#ifdef PATH_MAX
++#define STATEFILE_BUFFER_SIZE 2 * PATH_MAX + 16
++#else
++#define STATEFILE_BUFFER_SIZE 4096
++#endif
++
+ struct logState {
+     char *fn;
+     struct tm lastRotated;	/* only tm.mon, tm_mday, tm_year are good! */
+@@ -82,6 +88,34 @@
+     return 1;
+ }
+ 
++static void unescape(char *arg)
++{
++	char *p = arg;
++	char *next;
++	char escaped;
++	while ((next = strchr(p, '\\')) != NULL) {
++
++		p = next;
++
++		switch (p[1]) {
++		case 'n':
++			escaped = '\n';
++			break;
++		case '\\':
++			escaped = '\\';
++			break;
++		default:
++			++p;
++			continue;
++		}
++
++		/* Overwrite the backslash with the intended character,
++		 * and shift everything down one */
++		*p++ = escaped;
++		memmove(p, p+1, 1 + strlen(p+1));
++	}
++}
++
+ #define HASH_SIZE_MIN 64
+ static int allocateHash(void)
+ {
+@@ -1546,7 +1580,13 @@
+ 			for (chptr = p->fn; *chptr; chptr++) {
+ 				switch (*chptr) {
+ 				case '"':
++				case '\\':
+ 					fputc('\\', f);
++					break;
++				case '\n':
++					fputc('\\', f);
++					fputc('n', f);
++					continue;
+ 				}
+ 
+ 				fputc(*chptr, f);
+@@ -1567,7 +1607,8 @@
+ static int readState(char *stateFilename)
+ {
+     FILE *f;
+-    char buf[1024];
++    char buf[STATEFILE_BUFFER_SIZE];
++	char *filename;
+     const char **argv;
+     int argc;
+     int year, month, day;
+@@ -1678,7 +1719,10 @@
+ 
+ 	year -= 1900, month -= 1;
+ 
+-	if ((st = findState(argv[0])) == NULL)
++	filename = strdup(argv[0]);
++	unescape(filename);
++	
++	if ((st = findState(filename)) == NULL)
+ 		return 1;
+ 
+ 	st->lastRotated.tm_mon = month;
+@@ -1690,6 +1734,7 @@
+ 	st->lastRotated = *localtime(&lr_time);
+ 
+ 	free(argv);
++	free(filename);
+     }
+ 
+     fclose(f);


More information about the scm-commits mailing list