1
Description: fix arbitrary code execution via shell metacharacters in log filename
2
Origin: upstream, https://fedorahosted.org/logrotate/changeset/311
3
Origin: upstream, https://fedorahosted.org/logrotate/changeset/313
5
Index: logrotate-3.7.8/logrotate.c
6
===================================================================
7
--- logrotate-3.7.8.orig/logrotate.c 2011-06-17 13:30:54.081717762 -0400
8
+++ logrotate-3.7.8/logrotate.c 2011-06-17 13:32:25.321717738 -0400
10
char *mailCommand = DEFAULT_MAIL_COMMAND;
13
-static int shred_file(char *filename, struct logInfo *log);
14
+static int shred_file(int fd, char *filename, struct logInfo *log);
16
static int globerr(const char *pathname, int theerr)
22
-#define SHRED_CALL "shred -u "
23
-#define SHRED_COUNT_FLAG "-n "
26
/* unlink, but try to call shred from GNU fileutils */
27
-static int shred_file(char *filename, struct logInfo *log)
28
+static int shred_file(int fd, char *filename, struct logInfo *log)
32
char count[DIGITS]; /* that's a lot of shredding :) */
33
+ const char **fullCommand;
37
if (!(log->flags & LOG_FLAG_SHRED)) {
38
return unlink(filename);
41
- len = strlen(filename) + strlen(SHRED_CALL);
42
- len += strlen(SHRED_COUNT_FLAG) + DIGITS;
44
+ message(MESS_DEBUG, "Using shred to remove the file %s\n", filename);
47
- message(MESS_ERROR, "malloc error while shredding");
48
- return unlink(filename);
49
+ if (log->shred_cycles != 0) {
50
+ fullCommand = alloca(sizeof(*fullCommand) * 6);
53
+ fullCommand = alloca(sizeof(*fullCommand) * 4);
55
- strcpy(cmd, SHRED_CALL);
56
+ fullCommand[id++] = "shred";
57
+ fullCommand[id++] = "-u";
59
if (log->shred_cycles != 0) {
60
- strcat(cmd, SHRED_COUNT_FLAG);
61
+ fullCommand[id++] = "-n";
62
snprintf(count, DIGITS - 1, "%d", log->shred_cycles);
65
+ fullCommand[id++] = count;
67
+ fullCommand[id++] = "-";
68
+ fullCommand[id++] = NULL;
74
+ execvp(fullCommand[0], (void *) fullCommand);
77
- strcat(cmd, filename);
84
+ if (!WIFEXITED(status) || WEXITSTATUS(status)) {
85
message(MESS_ERROR, "Failed to shred %s\n, trying unlink", filename);
87
- message(MESS_NORMAL, "Shred returned %d\n", ret);
89
return unlink(filename);
94
+ /* We have to unlink it after shred anyway,
95
+ * because it doesn't remove the file itself */
96
+ return unlink(filename);
99
static int removeLogFile(char *name, struct logInfo *log)
101
- message(MESS_DEBUG, "removing old log %s\n", name);
103
+ message(MESS_DEBUG, "removing old log %s\n", name);
105
- if (!debug && shred_file(name, log)) {
106
- message(MESS_ERROR, "Failed to remove old log %s: %s\n",
107
- name, strerror(errno));
111
+ if ((fd = open(name, O_RDWR)) < 0) {
112
+ message(MESS_ERROR, "error opening %s: %s\n",
113
+ name, strerror(errno));
117
+ if (!debug && shred_file(fd, name, log)) {
118
+ message(MESS_ERROR, "Failed to remove old log %s: %s\n",
119
+ name, strerror(errno));
128
static int compressLogFile(char *name, struct logInfo *log, struct stat *sb)
130
compressedName = alloca(strlen(name) + strlen(log->compress_ext) + 2);
131
sprintf(compressedName, "%s%s", name, log->compress_ext);
133
- if ((inFile = open(name, O_RDONLY | O_NOFOLLOW)) < 0) {
134
+ if ((inFile = open(name, O_RDWR | O_NOFOLLOW)) < 0) {
135
message(MESS_ERROR, "unable to open %s for compression\n", name);
147
/* If we can't change atime/mtime, it's not a disaster.
148
It might possibly fail under SELinux. */
150
- shred_file(name, log);
151
+ shred_file(inFile, name, log);