61e7eae690161b1f7e986c7c531383c67c919fb6
1 Description: extreme backport of upstream log format fixes (CVE-2012-2118).
2 Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/xorg-server/+bug/996250
3 Origin: http://patchwork.freedesktop.org/patch/10001/
5 Index: xorg-server-1.11.4/os/log.c
6 ===================================================================
7 --- xorg-server-1.11.4.orig/os/log.c 2012-05-06 11:03:17.621808123 -0700
8 +++ xorg-server-1.11.4/os/log.c 2012-05-06 11:03:18.057814189 -0700
9 @@ -167,6 +167,12 @@
10 #ifndef X_NOT_IMPLEMENTED_STRING
11 #define X_NOT_IMPLEMENTED_STRING "(NI)"
12 #endif
13 +#ifndef X_DEBUG_STRING
14 +#define X_DEBUG_STRING "(DB)"
15 +#endif
16 +#ifndef X_NONE_STRING
17 +#define X_NONE_STRING ""
18 +#endif
20 /*
21 * LogInit is called to start logging to a file. It is also called (with
22 @@ -223,7 +229,7 @@
23 * needed.
24 */
25 if (saveBuffer && bufferSize > 0) {
26 - free(saveBuffer); /* Must be free(), not free() */
27 + free(saveBuffer);
28 saveBuffer = NULL;
29 bufferSize = 0;
30 }
31 @@ -265,36 +271,19 @@
32 }
34 /* This function does the actual log message writes. */
35 -
36 -void
37 -LogVWrite(int verb, const char *f, va_list args)
38 +static void
39 +LogSWrite(int verb, const char *buf, size_t len, Bool end_line)
40 {
41 - static char tmpBuffer[1024];
42 - int len = 0;
43 static Bool newline = TRUE;
45 - if (newline) {
46 - sprintf(tmpBuffer, "[%10.3f] ", GetTimeInMillis() / 1000.0);
47 - len = strlen(tmpBuffer);
48 - if (logFile)
49 - fwrite(tmpBuffer, len, 1, logFile);
50 - }
51 -
52 - /*
53 - * Since a va_list can only be processed once, write the string to a
54 - * buffer, and then write the buffer out to the appropriate output
55 - * stream(s).
56 - */
57 - if (verb < 0 || logFileVerbosity >= verb || logVerbosity >= verb) {
58 - vsnprintf(tmpBuffer, sizeof(tmpBuffer), f, args);
59 - len = strlen(tmpBuffer);
60 - }
61 - newline = (tmpBuffer[len-1] == '\n');
62 - if ((verb < 0 || logVerbosity >= verb) && len > 0)
63 - fwrite(tmpBuffer, len, 1, stderr);
64 - if ((verb < 0 || logFileVerbosity >= verb) && len > 0) {
65 + if (verb < 0 || logVerbosity >= verb)
66 + fwrite(buf, len, 1, stderr);
67 + if (verb < 0 || logFileVerbosity >= verb) {
68 if (logFile) {
69 - fwrite(tmpBuffer, len, 1, logFile);
70 + if (newline)
71 + fprintf(logFile, "[%10.3f] ", GetTimeInMillis() / 1000.0);
72 + newline = end_line;
73 + fwrite(buf, len, 1, logFile);
74 if (logFlush) {
75 fflush(logFile);
76 #ifndef WIN32
77 @@ -311,13 +300,19 @@
78 FatalError("realloc() failed while saving log messages\n");
79 }
80 bufferUnused -= len;
81 - memcpy(saveBuffer + bufferPos, tmpBuffer, len);
82 + memcpy(saveBuffer + bufferPos, buf, len);
83 bufferPos += len;
84 }
85 }
86 }
88 void
89 +LogVWrite(int verb, const char *f, va_list args)
90 +{
91 + return LogVMessageVerb(X_NONE, verb, f, args);
92 +}
93 +
94 +void
95 LogWrite(int verb, const char *f, ...)
96 {
97 va_list args;
98 @@ -327,60 +322,75 @@
99 va_end(args);
100 }
102 -void
103 -LogVMessageVerb(MessageType type, int verb, const char *format, va_list args)
104 +/* Returns the Message Type string to prepend to a logging message, or NULL
105 + * if the message will be dropped due to insufficient verbosity. */
106 +static const char *
107 +LogMessageTypeVerbString(MessageType type, int verb)
108 {
109 - const char *s = X_UNKNOWN_STRING;
110 - char tmpBuf[1024];
111 + if (type == X_ERROR)
112 + verb = 0;
114 - /* Ignore verbosity for X_ERROR */
115 - if (logVerbosity >= verb || logFileVerbosity >= verb || type == X_ERROR) {
116 - switch (type) {
117 - case X_PROBED:
118 - s = X_PROBE_STRING;
119 - break;
120 - case X_CONFIG:
121 - s = X_CONFIG_STRING;
122 - break;
123 - case X_DEFAULT:
124 - s = X_DEFAULT_STRING;
125 - break;
126 - case X_CMDLINE:
127 - s = X_CMDLINE_STRING;
128 - break;
129 - case X_NOTICE:
130 - s = X_NOTICE_STRING;
131 - break;
132 - case X_ERROR:
133 - s = X_ERROR_STRING;
134 - if (verb > 0)
135 - verb = 0;
136 - break;
137 - case X_WARNING:
138 - s = X_WARNING_STRING;
139 - break;
140 - case X_INFO:
141 - s = X_INFO_STRING;
142 - break;
143 - case X_NOT_IMPLEMENTED:
144 - s = X_NOT_IMPLEMENTED_STRING;
145 - break;
146 - case X_UNKNOWN:
147 - s = X_UNKNOWN_STRING;
148 - break;
149 - case X_NONE:
150 - s = NULL;
151 - break;
152 - }
153 + if (logVerbosity < verb && logFileVerbosity < verb)
154 + return NULL;
156 - /* if s is not NULL we need a space before format */
157 - snprintf(tmpBuf, sizeof(tmpBuf), "%s%s%s", s ? s : "",
158 - s ? " " : "",
159 - format);
160 - LogVWrite(verb, tmpBuf, args);
161 + switch (type) {
162 + case X_PROBED:
163 + return X_PROBE_STRING;
164 + case X_CONFIG:
165 + return X_CONFIG_STRING;
166 + case X_DEFAULT:
167 + return X_DEFAULT_STRING;
168 + case X_CMDLINE:
169 + return X_CMDLINE_STRING;
170 + case X_NOTICE:
171 + return X_NOTICE_STRING;
172 + case X_ERROR:
173 + return X_ERROR_STRING;
174 + case X_WARNING:
175 + return X_WARNING_STRING;
176 + case X_INFO:
177 + return X_INFO_STRING;
178 + case X_NOT_IMPLEMENTED:
179 + return X_NOT_IMPLEMENTED_STRING;
180 + case X_UNKNOWN:
181 + return X_UNKNOWN_STRING;
182 + case X_NONE:
183 + return X_NONE_STRING;
184 + case X_DEBUG:
185 + return X_DEBUG_STRING;
186 + default:
187 + return X_UNKNOWN_STRING;
188 }
189 }
191 +void
192 +LogVMessageVerb(MessageType type, int verb, const char *format, va_list args)
193 +{
194 + const char *type_str;
195 + char buf[1024];
196 + const size_t size = sizeof(buf);
197 + Bool newline;
198 + size_t len = 0;
199 +
200 + type_str = LogMessageTypeVerbString(type, verb);
201 + if (!type_str)
202 + return;
203 +
204 + /* if type_str is not "", prepend it and ' ', to message */
205 + if (type_str[0] != '\0')
206 + len += Xscnprintf(&buf[len], size - len, "%s ", type_str);
207 +
208 + if (size - len > 1)
209 + len += Xvscnprintf(&buf[len], size - len, format, args);
210 +
211 + /* Force '\n' at end of truncated line */
212 + if (size - len == 1)
213 + buf[len - 1] = '\n';
214 +
215 + newline = (buf[len - 1] == '\n');
216 + LogSWrite(verb, buf, len, newline);
217 +}
218 +
219 /* Log message with verbosity level specified. */
220 void
221 LogMessageVerb(MessageType type, int verb, const char *format, ...)
222 @@ -404,6 +414,49 @@
223 }
225 void
226 +LogVHdrMessageVerb(MessageType type, int verb, const char *msg_format,
227 + va_list msg_args, const char *hdr_format, va_list hdr_args)
228 +{
229 + const char *type_str;
230 + char buf[1024];
231 + const size_t size = sizeof(buf);
232 + Bool newline;
233 + size_t len = 0;
234 +
235 + type_str = LogMessageTypeVerbString(type, verb);
236 + if (!type_str)
237 + return;
238 +
239 + /* if type_str is not "", prepend it and ' ', to message */
240 + if (type_str[0] != '\0')
241 + len += Xscnprintf(&buf[len], size - len, "%s ", type_str);
242 +
243 + if (hdr_format && size - len > 1)
244 + len += Xvscnprintf(&buf[len], size - len, hdr_format, hdr_args);
245 +
246 + if (msg_format && size - len > 1)
247 + len += Xvscnprintf(&buf[len], size - len, msg_format, msg_args);
248 +
249 + /* Force '\n' at end of truncated line */
250 + if (size - len == 1)
251 + buf[len - 1] = '\n';
252 +
253 + newline = (buf[len - 1] == '\n');
254 + LogSWrite(verb, buf, len, newline);
255 +}
256 +
257 +void
258 +LogHdrMessageVerb(MessageType type, int verb, const char *msg_format,
259 + va_list msg_args, const char *hdr_format, ...)
260 +{
261 + va_list hdr_args;
262 +
263 + va_start(hdr_args, hdr_format);
264 + LogVHdrMessageVerb(type, verb, msg_format, msg_args, hdr_format, hdr_args);
265 + va_end(hdr_args);
266 +}
267 +
268 +void
269 AbortServer(void) _X_NORETURN;
270 void
271 SigAbortServer(int signo) _X_NORETURN;
272 Index: xorg-server-1.11.4/include/Xprintf.h
273 ===================================================================
274 --- xorg-server-1.11.4.orig/include/Xprintf.h 2012-05-06 10:32:42.436348011 -0700
275 +++ xorg-server-1.11.4/include/Xprintf.h 2012-05-06 11:03:18.057814189 -0700
276 @@ -66,4 +66,16 @@
277 # define vasprintf Xvasprintf
278 #endif
280 +/*
281 + * These functions provide a portable implementation of the linux kernel
282 + * scnprintf & vscnprintf routines that return the number of bytes actually
283 + * copied during a snprintf, (excluding the final '\0').
284 + */
285 +extern _X_EXPORT int
286 +Xscnprintf(char *s, int n, const char * _X_RESTRICT_KYWD fmt, ...)
287 +_X_ATTRIBUTE_PRINTF(3,4);
288 +extern _X_EXPORT int
289 +Xvscnprintf(char *s, int n, const char * _X_RESTRICT_KYWD fmt, va_list va)
290 +_X_ATTRIBUTE_PRINTF(3,0);
291 +
292 #endif /* XPRINTF_H */
293 Index: xorg-server-1.11.4/os/xprintf.c
294 ===================================================================
295 --- xorg-server-1.11.4.orig/os/xprintf.c 2012-05-06 10:32:42.472348510 -0700
296 +++ xorg-server-1.11.4/os/xprintf.c 2012-05-06 11:03:18.057814189 -0700
297 @@ -182,6 +182,50 @@
298 return size;
299 }
301 +/**
302 + * Varargs snprintf that returns the actual number of bytes (excluding final
303 + * '\0') that were copied into the buffer.
304 + * This is opposed to the normal sprintf() usually returns the number of bytes
305 + * that would have been written.
306 + *
307 + * @param s buffer to copy into
308 + * @param n size of buffer s
309 + * @param format printf style format string
310 + * @param va variable argument list
311 + * @return number of bytes actually copied, excluding final '\0'
312 + */
313 +int
314 +Xvscnprintf(char *s, int n, const char *format, va_list args)
315 +{
316 + int x;
317 + if (n == 0)
318 + return 0;
319 + x = vsnprintf(s, n , format, args);
320 + return (x >= n) ? (n - 1) : x;
321 +}
322 +
323 +/**
324 + * snprintf that returns the actual number of bytes (excluding final '\0') that
325 + * were copied into the buffer.
326 + * This is opposed to the normal sprintf() usually returns the number of bytes
327 + * that would have been written.
328 + *
329 + * @param s buffer to copy into
330 + * @param n size of buffer s
331 + * @param format printf style format string
332 + * @param ... arguments for specified format
333 + * @return number of bytes actually copied, excluding final '\0'
334 + */
335 +int Xscnprintf(char *s, int n, const char *format, ...)
336 +{
337 + int x;
338 + va_list ap;
339 + va_start(ap, format);
340 + x = Xvscnprintf(s, n, format, ap);
341 + va_end(ap);
342 + return x;
343 +}
344 +
345 /* Old api, now deprecated, may be removed in the future */
346 char *
347 Xvprintf(const char *format, va_list va)
348 Index: xorg-server-1.11.4/hw/xfree86/common/xf86Helper.c
349 ===================================================================
350 --- xorg-server-1.11.4.orig/hw/xfree86/common/xf86Helper.c 2012-05-06 10:32:42.488348731 -0700
351 +++ xorg-server-1.11.4/hw/xfree86/common/xf86Helper.c 2012-05-06 11:03:18.057814189 -0700
352 @@ -1036,25 +1036,13 @@
353 xf86VDrvMsgVerb(int scrnIndex, MessageType type, int verb, const char *format,
354 va_list args)
355 {
356 - char *tmpFormat;
357 -
358 /* Prefix the scrnIndex name to the format string. */
359 if (scrnIndex >= 0 && scrnIndex < xf86NumScreens &&
360 - xf86Screens[scrnIndex]->name) {
361 - tmpFormat = malloc(strlen(format) +
362 - strlen(xf86Screens[scrnIndex]->name) +
363 - PREFIX_SIZE + 1);
364 - if (!tmpFormat)
365 - return;
366 -
367 - snprintf(tmpFormat, PREFIX_SIZE + 1, "%s(%d): ",
368 - xf86Screens[scrnIndex]->name, scrnIndex);
369 -
370 - strcat(tmpFormat, format);
371 - LogVMessageVerb(type, verb, tmpFormat, args);
372 - free(tmpFormat);
373 - } else
374 - LogVMessageVerb(type, verb, format, args);
375 + xf86Screens[scrnIndex]->name)
376 + LogHdrMessageVerb(type, verb, format, args, "%s(%d): ",
377 + xf86Screens[scrnIndex]->name, scrnIndex);
378 + else
379 + LogVMessageVerb(type, verb, format, args);
380 }
381 #undef PREFIX_SIZE
383 @@ -1087,15 +1075,18 @@
384 xf86VIDrvMsgVerb(InputInfoPtr dev, MessageType type, int verb, const char *format,
385 va_list args)
386 {
387 - char *msg;
388 + const char *driverName = NULL;
389 + const char *deviceName = NULL;
391 - if (asprintf(&msg, "%s: %s: %s", dev->drv->driverName, dev->name, format)
392 - == -1) {
393 - LogVMessageVerb(type, verb, "%s", args);
394 - } else {
395 - LogVMessageVerb(type, verb, msg, args);
396 - free(msg);
397 + /* Prefix driver and device names to formatted message. */
398 + if (dev) {
399 + deviceName = dev->name;
400 + if (dev->drv)
401 + driverName = dev->drv->driverName;
402 }
403 +
404 + LogHdrMessageVerb(type, verb, format, args, "%s: %s: ", driverName,
405 + deviceName);
406 }
408 /* Print input driver message, with verbose level specified directly */
409 Index: xorg-server-1.11.4/include/os.h
410 ===================================================================
411 --- xorg-server-1.11.4.orig/include/os.h 2012-05-06 11:03:17.621808123 -0700
412 +++ xorg-server-1.11.4/include/os.h 2012-05-06 11:03:29.353971366 -0700
413 @@ -514,6 +514,7 @@
414 X_INFO, /* Informational message */
415 X_NONE, /* No prefix */
416 X_NOT_IMPLEMENTED, /* Not implemented */
417 + X_DEBUG, /* Debug message */
418 X_UNKNOWN = -1 /* unknown -- this must always be last */
419 } MessageType;
421 @@ -528,6 +529,20 @@
422 ...) _X_ATTRIBUTE_PRINTF(3,4);
423 extern _X_EXPORT void LogMessage(MessageType type, const char *format, ...)
424 _X_ATTRIBUTE_PRINTF(2,3);
425 +
426 +extern _X_EXPORT void
427 +LogVHdrMessageVerb(MessageType type, int verb,
428 + const char *msg_format, va_list msg_args,
429 + const char *hdr_format, va_list hdr_args)
430 +_X_ATTRIBUTE_PRINTF(3, 0)
431 +_X_ATTRIBUTE_PRINTF(5, 0);
432 +extern _X_EXPORT void
433 +LogHdrMessageVerb(MessageType type, int verb,
434 + const char *msg_format, va_list msg_args,
435 + const char *hdr_format, ...)
436 +_X_ATTRIBUTE_PRINTF(3, 0)
437 +_X_ATTRIBUTE_PRINTF(5, 6);
438 +
439 extern _X_EXPORT void FreeAuditTimer(void);
440 extern _X_EXPORT void AuditF(const char *f, ...) _X_ATTRIBUTE_PRINTF(1,2);
441 extern _X_EXPORT void VAuditF(const char *f, va_list args) _X_ATTRIBUTE_PRINTF(1,0);