Merge ~slyon/ubuntu/+source/s390-tools:slyon/xenial-SRUs into ubuntu/+source/s390-tools:ubuntu/xenial-devel

Proposed by Lukas Märdian
Status: Merged
Merge reported by: Lukas Märdian
Merged at revision: ba49dedf1213fd1eb02660eb3174443a0e93693f
Proposed branch: ~slyon/ubuntu/+source/s390-tools:slyon/xenial-SRUs
Merge into: ubuntu/+source/s390-tools:ubuntu/xenial-devel
Diff against target: 763 lines (+717/-0)
7 files modified
debian/changelog (+17/-0)
debian/patches/0024-zipl-libc-Introduce-vsnprintf.patch (+302/-0)
debian/patches/0025-zipl-libc-Fix-potential-buffer-overflow-in-printf.patch (+46/-0)
debian/patches/0026-zipl-libc-Replace-sprintf-with-snprintf.patch (+224/-0)
debian/patches/0027-zipl-libc-Indicate-truncated-lines-in-printf-with.patch (+69/-0)
debian/patches/0028-zipl-boot-libc-add-memmove-function.patch (+54/-0)
debian/patches/series (+5/-0)
Reviewer Review Type Date Requested Status
Julian Andres Klode (community) Approve
git-ubuntu developers Pending
Review via email: mp+394248@code.launchpad.net

Description of the change

To post a comment you must log in.
Revision history for this message
Julian Andres Klode (juliank) wrote :

Uploaded

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/debian/changelog b/debian/changelog
2index 4122a3d..ac3e30d 100644
3--- a/debian/changelog
4+++ b/debian/changelog
5@@ -1,3 +1,20 @@
6+s390-tools (1.34.0-0ubuntu8.11) xenial; urgency=medium
7+
8+ * Cherry-pick zipl/libc fixes for potential buffer overflow (LP: #1865032)
9+ - debian/patches/0033-zipl-boot-libc-add-memmove-function.patch:
10+ Prerequisite for the other 4 patches, taken as part of upstream commit
11+ e764f460c457ab2a6000acb5f2eb7169866ce192
12+ - debian/patches/0029-zipl-libc-Introduce-vsnprintf.patch:
13+ 6fe9e6c55c69c14971dca55551009f5060418aae
14+ - d/p/0030-zipl-libc-Fix-potential-buffer-overflow-in-printf.patch:
15+ 8874b908254c47c8a6fd7a1aca2c7371c11035c4
16+ - debian/patches/0031-zipl-libc-Replace-sprintf-with-snprintf.patch:
17+ f7430027b41d5ad6220e962a179c2a5213330a44
18+ - d/p/0032-zipl-libc-Indicate-truncated-lines-in-printf-with.patch:
19+ 36fed0e6c6590631c4ce1707c8fe3c3397bcce4d
20+
21+ -- Lukas Märdian <lukas.maerdian@canonical.com> Fri, 20 Nov 2020 15:27:08 +0100
22+
23 s390-tools (1.34.0-0ubuntu8.10) xenial; urgency=medium
24
25 * chreipl: fix chreipl node for virtio devices LP: #1825099
26diff --git a/debian/patches/0024-zipl-libc-Introduce-vsnprintf.patch b/debian/patches/0024-zipl-libc-Introduce-vsnprintf.patch
27new file mode 100644
28index 0000000..d0ad858
29--- /dev/null
30+++ b/debian/patches/0024-zipl-libc-Introduce-vsnprintf.patch
31@@ -0,0 +1,302 @@
32+From: Philipp Rudo <prudo@linux.ibm.com>
33+Date: Tue, 11 Feb 2020 11:13:59 +0100
34+Subject: zipl/libc: Introduce vsnprintf
35+MIME-Version: 1.0
36+Content-Type: text/plain; charset="utf-8"
37+Content-Transfer-Encoding: 8bit
38+
39+The zipl boot loaders have their own minimalistic libc implementation.
40+In it printf and sprintf use vsprintf for string formatting. Per
41+definition vsprintf assumes that the buffer it writes to is large enough
42+to contain the formatted string and performs no size checks. This is
43+problematic for the boot loaders because the buffer they use are often
44+allocated on the stack. Thus even small changes to the string format can
45+potentially cause buffer overflows on the stack with the well known
46+consequences. Protect against such errors by implementing vsnprintf.
47+Later patches will make use of it.
48+
49+This implementation of vsnprintf only supports a small subset of format
50+options defined in the C standard. In particular it allows the
51+specifiers:
52+ * %s (strings)
53+ * %o (unsigned int octal)
54+ * %u (unsigned int decimal)
55+ * %x (unsigned int hexadecimal)
56+
57+Integer specifiers (o, u, and x) always use the long form, i.e. assume the
58+argument to be of type 'unsigned long int'. The length modified 'l' can
59+be given but is ignored.
60+
61+Furthermore, it is possible to provide the optional field width (aligned
62+to the right only) and precision as decimal integer (i.e. not via '*')
63+as well as the flag for zero padding integers (i.e. '0').
64+
65+The implementation was heavily inspired by the implementation in
66+lib/vsprintf.c from the Linux kernel tree.
67+
68+Signed-off-by: Philipp Rudo <prudo@linux.ibm.com>
69+Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
70+Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
71+---
72+ zipl/boot/libc.c | 248 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
73+ 1 file changed, 248 insertions(+)
74+
75+diff --git a/zipl/boot/libc.c b/zipl/boot/libc.c
76+index fd9d1a3..b43d417 100644
77+--- a/zipl/boot/libc.c
78++++ b/zipl/boot/libc.c
79+@@ -196,6 +196,254 @@ unsigned long ebcstrtoul(char *nptr, char **endptr, int base)
80+ return val;
81+ }
82+
83++static int skip_atoi(const char **c)
84++{
85++ int i = 0;
86++
87++ do {
88++ i = i*10 + *((*c)++) - '0';
89++ } while (isdigit(**c));
90++
91++ return i;
92++}
93++
94++enum format_type {
95++ FORMAT_TYPE_NONE,
96++ FORMAT_TYPE_STR,
97++ FORMAT_TYPE_ULONG,
98++};
99++
100++struct printf_spec {
101++ unsigned int type:8; /* format_type enum */
102++ signed int field_width:24; /* width of output field */
103++ unsigned int zeropad:1; /* pad numbers with zero */
104++ unsigned int base:8; /* number base, 8, 10 or 16 only */
105++ signed int precision:16; /* # of digits/chars */
106++};
107++
108++#define FIELD_WIDTH_MAX ((1 << 23) - 1)
109++
110++static int format_decode(const char *fmt, struct printf_spec *spec)
111++{
112++ const char *start = fmt;
113++
114++ spec->type = FORMAT_TYPE_NONE;
115++ while (*fmt) {
116++ if (*fmt == '%')
117++ break;
118++ fmt++;
119++ }
120++
121++ /* return current non-format string */
122++ if (fmt != start || !*fmt)
123++ return fmt - start;
124++
125++ /* first char is '%', skip it */
126++ fmt++;
127++ if (*fmt == '0') {
128++ spec->zeropad = 1;
129++ fmt++;
130++ }
131++
132++ spec->field_width = -1;
133++ if (isdigit(*fmt))
134++ spec->field_width = skip_atoi(&fmt);
135++
136++ spec->precision = -1;
137++ if (*fmt == '.') {
138++ fmt++;
139++ if (isdigit(*fmt))
140++ spec->precision = skip_atoi(&fmt);
141++ }
142++
143++ /* always use long form, i.e. ignore long qualifier */
144++ if (*fmt == 'l')
145++ fmt++;
146++
147++ switch (*fmt) {
148++ case 's':
149++ spec->type = FORMAT_TYPE_STR;
150++ break;
151++
152++ case 'o':
153++ spec->base = 8;
154++ spec->type = FORMAT_TYPE_ULONG;
155++ break;
156++
157++ case 'u':
158++ spec->base = 10;
159++ spec->type = FORMAT_TYPE_ULONG;
160++ break;
161++
162++ case 'x':
163++ spec->base = 16;
164++ spec->type = FORMAT_TYPE_ULONG;
165++ break;
166++
167++ default:
168++ libc_stop(EINTERNAL);
169++ }
170++
171++ return ++fmt - start;
172++}
173++
174++static char *string(char *buf, char *end, const char *s,
175++ struct printf_spec *spec)
176++{
177++ int limit = spec->precision;
178++ int len = 0;
179++ int spaces;
180++
181++ /* Copy string to buffer */
182++ while (limit--) {
183++ char c = *s++;
184++ if (!c)
185++ break;
186++ if (buf < end)
187++ *buf = c;
188++ buf++;
189++ len++;
190++ }
191++
192++ /* right align if necessary */
193++ if (len < spec->field_width && buf < end) {
194++ spaces = spec->field_width - len;
195++ if (spaces >= end - buf)
196++ spaces = end - buf;
197++ memmove(buf + spaces, buf, len);
198++ memset(buf, ' ', spaces);
199++ buf += spaces;
200++ }
201++
202++ return buf;
203++}
204++
205++static char *number(char *buf, char *end, unsigned long val,
206++ struct printf_spec *spec)
207++{
208++ /* temporary buffer to prepare the string.
209++ * Worst case: base = 8 -> 3 bits per char -> 2.67 chars per byte */
210++ char tmp[3 * sizeof(val)];
211++ static const char vec[] = {'0', '1', '2', '3', '4', '5', '6', '7',
212++ '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
213++ int field_width = spec->field_width;
214++ int precision = spec->precision;
215++ int len;
216++
217++ /* prepare string in reverse order */
218++ len = 0;
219++ while (val) {
220++ tmp[len++] = vec[val % spec->base];
221++ val /= spec->base;
222++ }
223++
224++ if (len > precision)
225++ precision = len;
226++
227++ field_width -= precision;
228++ while (field_width-- > 0) {
229++ char c = spec->zeropad ? '0' : ' ';
230++ if (buf < end)
231++ *buf = c;
232++ buf++;
233++ }
234++
235++ /* needed if no field width but a precision is given */
236++ while (len < precision--) {
237++ if (buf < end)
238++ *buf = '0';
239++ buf++;
240++ }
241++
242++ while (len-- > 0) {
243++ if (buf < end)
244++ *buf = tmp[len];
245++ buf++;
246++ }
247++
248++ return buf;
249++}
250++
251++/*
252++ * vsnprintf - Format string and place in a buffer
253++ *
254++ * This funcion only supports a subset of format options defined in the
255++ * C standard, i.e.
256++ * specifiers:
257++ * * %s (strings)
258++ * * %o (unsigned int octal)
259++ * * %u (unsigned int decimal)
260++ * * %x (unsigned int hexadecimal)
261++ *
262++ * length modifier:
263++ * * 'l' (ignored, see below)
264++ *
265++ * flag:
266++ * * '0' (zero padding for integers)
267++ *
268++ * precision and field width as integers, i.e. _not_ by asterix '*'.
269++ *
270++ * The integer specifiers (o, u and, x) always use the long form, i.e.
271++ * assume the argument to be of type 'unsigned long int'.
272++ *
273++ * Returns the number of characters the function would have generated for
274++ * the given input (excluding the trailing '\0'. If the return value is
275++ * greater than or equal @size the resulting string is trunctuated.
276++ */
277++static int vsnprintf(char *buf, unsigned long size, const char *fmt,
278++ va_list args)
279++{
280++ struct printf_spec spec = {0};
281++ char *str, *end;
282++
283++ str = buf;
284++ end = buf + size;
285++
286++ /* use negative (large positive) buffer sizes as indication for
287++ * unknown/unlimited buffer sizes. */
288++ if (end < buf) {
289++ end = ((void *)-1);
290++ size = end - buf;
291++ }
292++
293++ while (*fmt) {
294++ const char *old_fmt = fmt;
295++ int read = format_decode(fmt, &spec);
296++ int copy;
297++
298++ fmt += read;
299++
300++ switch (spec.type) {
301++ case FORMAT_TYPE_NONE:
302++ copy = read;
303++ if (str < end) {
304++ if (copy > end - str)
305++ copy = end - str;
306++ memcpy(str, old_fmt, copy);
307++ }
308++ str += read;
309++ break;
310++
311++ case FORMAT_TYPE_STR:
312++ str = string(str, end, va_arg(args, char *), &spec);
313++ break;
314++
315++ case FORMAT_TYPE_ULONG:
316++ str = number(str, end, va_arg(args, unsigned long),
317++ &spec);
318++ break;
319++ }
320++ }
321++
322++ if (size) {
323++ if (str < end)
324++ *str = '\0';
325++ else
326++ end[-1] = '\0';
327++ }
328++ return str - buf;
329++}
330++
331+ /*
332+ * Convert string to number with given base
333+ */
334diff --git a/debian/patches/0025-zipl-libc-Fix-potential-buffer-overflow-in-printf.patch b/debian/patches/0025-zipl-libc-Fix-potential-buffer-overflow-in-printf.patch
335new file mode 100644
336index 0000000..826ed7d
337--- /dev/null
338+++ b/debian/patches/0025-zipl-libc-Fix-potential-buffer-overflow-in-printf.patch
339@@ -0,0 +1,46 @@
340+From: Philipp Rudo <prudo@linux.ibm.com>
341+Date: Tue, 11 Feb 2020 13:34:14 +0100
342+Subject: zipl/libc: Fix potential buffer overflow in printf
343+MIME-Version: 1.0
344+Content-Type: text/plain; charset="utf-8"
345+Content-Transfer-Encoding: 8bit
346+
347+Per definition vsprint assumes that the provided buffer it writes to is
348+large enough to contain the formatted string. As printf uses a fixed
349+sized buffer (81 bytes) and has no size checks the use of vsprintf can
350+easily cause buffer overflows. Protect against these buffer overflows by
351+using vsnprintf instead.
352+
353+While at it fix a typo in the comment.
354+
355+Reported-by: Marc Hartmayer <mhartmay@linux.ibm.com>
356+Signed-off-by: Philipp Rudo <prudo@linux.ibm.com>
357+Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
358+Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
359+Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
360+---
361+ zipl/boot/libc.c | 4 ++--
362+ 1 file changed, 2 insertions(+), 2 deletions(-)
363+
364+diff --git a/zipl/boot/libc.c b/zipl/boot/libc.c
365+index b43d417..a3a306c 100644
366+--- a/zipl/boot/libc.c
367++++ b/zipl/boot/libc.c
368+@@ -508,7 +508,7 @@ void sprintf(char *str, const char *fmt, ...)
369+ }
370+
371+ /*
372+- * Print formated string
373++ * Print formatted string to console
374+ */
375+ void printf(const char *fmt, ...)
376+ {
377+@@ -516,7 +516,7 @@ void printf(const char *fmt, ...)
378+ va_list va;
379+
380+ va_start(va, fmt);
381+- vsprintf(buf, fmt, va);
382++ vsnprintf(buf, sizeof(buf), fmt, va);
383+ sclp_print(buf);
384+ va_end(va);
385+ }
386diff --git a/debian/patches/0026-zipl-libc-Replace-sprintf-with-snprintf.patch b/debian/patches/0026-zipl-libc-Replace-sprintf-with-snprintf.patch
387new file mode 100644
388index 0000000..9189345
389--- /dev/null
390+++ b/debian/patches/0026-zipl-libc-Replace-sprintf-with-snprintf.patch
391@@ -0,0 +1,224 @@
392+From: Philipp Rudo <prudo@linux.ibm.com>
393+Date: Tue, 11 Feb 2020 16:12:21 +0100
394+Subject: zipl/libc: Replace sprintf with snprintf
395+MIME-Version: 1.0
396+Content-Type: text/plain; charset="utf-8"
397+Content-Transfer-Encoding: 8bit
398+
399+The use of sprintf can easily result in buffer overflows as it assumes
400+that the buffer it writes to is large enough to contain the formatted
401+string. Thus replace sprintf by snprintf and update its users.
402+
403+This removes the last user of vsprintf. Thus also remove vsprintf and
404+its dependencies.
405+
406+Signed-off-by: Philipp Rudo <prudo@linux.ibm.com>
407+Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
408+Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
409+Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
410+---
411+ zipl/boot/libc.c | 132 ++------------------------------------------------
412+ zipl/boot/libc.h | 3 +-
413+ zipl/boot/menu.c | 2 +-
414+ zipl/boot/tape2dump.c | 2 +-
415+ 4 files changed, 6 insertions(+), 133 deletions(-)
416+
417+diff --git a/zipl/boot/libc.c b/zipl/boot/libc.c
418+index a3a306c..4020458 100644
419+--- a/zipl/boot/libc.c
420++++ b/zipl/boot/libc.c
421+@@ -103,81 +103,6 @@ int strncmp(const char *s1, const char *s2, unsigned long count)
422+ return 0;
423+ }
424+
425+-/*
426+- * Convert number to string
427+- *
428+- * Parameters:
429+- *
430+- * - buf: Output buffer
431+- * - base: Base used for formatting (e.g. 10 or 16)
432+- * - val: Number to format
433+- * - zero: If > 0, fill with leading zeros, otherwise use blanks
434+- * - count: Minimum number of characters used for output string
435+- */
436+-static int num_to_str(char *buf, int base, unsigned long val, int zero,
437+- unsigned long count)
438+-{
439+- static const char conv_vec[] = {'0', '1', '2', '3', '4', '5', '6', '7',
440+- '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
441+- unsigned long num = 0, val_work = val, in_number = 1;
442+- int i;
443+-
444+- /* Count number of characters needed for number */
445+- do {
446+- num++;
447+- val_work /= base;
448+- } while (val_work);
449+- /* Real character number overwrites count */
450+- if (count < num)
451+- count = num;
452+- /* Format number */
453+- for (i = count - 1; i >= 0; i--) {
454+- if (in_number) {
455+- buf[i] = conv_vec[val % base];
456+- val /= base;
457+- in_number = val ? 1 : 0;
458+- } else {
459+- buf[i] = zero ? '0' : ' ';
460+- }
461+- }
462+- buf[count] = 0;
463+- return count;
464+-}
465+-
466+-/*
467+- * Convert string to string with indentation
468+- */
469+-static int str_to_str(char *buf, const char *str, unsigned long count)
470+-{
471+- unsigned long size;
472+-
473+- size = strlen(str);
474+- if (count < size)
475+- count = size;
476+- else
477+- memset(buf, ' ', count - size);
478+- strcpy(buf + (count - size), str);
479+- return count;
480+-}
481+-
482+-/*
483+- * Convert string to number with given base
484+- */
485+-unsigned long strtoul(const char *nptr, char **endptr, int base)
486+-{
487+- unsigned long val = 0;
488+-
489+- while (isdigit(*nptr)) {
490+- if (val != 0)
491+- val *= base;
492+- val += *nptr - '0';
493+- nptr++;
494+- }
495+- if (endptr)
496+- *endptr = (char *) nptr;
497+- return val;
498+-}
499+-
500+ /*
501+ * Convert ebcdic string to number with given base
502+ */
503+@@ -445,65 +370,14 @@ static int vsnprintf(char *buf, unsigned long size, const char *fmt,
504+ }
505+
506+ /*
507+- * Convert string to number with given base
508+- */
509+-static int sprintf_fmt(char type, char *buf, unsigned long val, int zero,
510+- int count)
511+-{
512+- switch (type) {
513+- case 's':
514+- return str_to_str(buf, (const char *) val, count);
515+- case 'x':
516+- return num_to_str(buf, 16, val, zero, count);
517+- case 'u':
518+- return num_to_str(buf, 10, val, zero, count);
519+- default:
520+- libc_stop(EINTERNAL);
521+- }
522+- return 0;
523+-}
524+-
525+-/*
526+- * Print formated string (va version)
527+- */
528+-static void vsprintf(char *str, const char *fmt, va_list va)
529+-{
530+- unsigned long val, zero, count;
531+- char *fmt_next;
532+-
533+- do {
534+- if (*fmt == '%') {
535+- fmt++;
536+- if (*fmt == '0') {
537+- zero = 1;
538+- fmt++;
539+- } else {
540+- zero = 0;
541+- }
542+- /* No number found by strtoul: count=0 fmt_next=fmt */
543+- count = strtoul(fmt, &fmt_next, 10);
544+- fmt = fmt_next;
545+- if (*fmt == 'l')
546+- fmt++;
547+- val = va_arg(va, unsigned long);
548+- str += sprintf_fmt(*fmt, str, val, zero, count);
549+- fmt++;
550+- } else {
551+- *str++ = *fmt++;
552+- }
553+- } while (*fmt);
554+- *str = 0;
555+-}
556+-
557+-/*
558+- * Write formated string to string
559++ * Write formatted string to buffer
560+ */
561+-void sprintf(char *str, const char *fmt, ...)
562++void snprintf(char *buf, unsigned long size, const char *fmt, ...)
563+ {
564+ va_list va;
565+
566+ va_start(va, fmt);
567+- vsprintf(str, fmt, va);
568++ vsnprintf(buf, size, fmt, va);
569+ va_end(va);
570+ }
571+
572+diff --git a/zipl/boot/libc.h b/zipl/boot/libc.h
573+index d66d230..85a078e 100644
574+--- a/zipl/boot/libc.h
575++++ b/zipl/boot/libc.h
576+@@ -46,12 +46,11 @@ typedef unsigned short uint16_t;
577+ typedef unsigned char uint8_t;
578+
579+ void printf(const char *, ...);
580+-void sprintf(char *, const char *, ...);
581++void snprintf(char *buf, unsigned long size, const char *fmt, ...);
582+ void *memcpy(void *, const void *, unsigned long);
583+ void *memset(void *, int c, unsigned long);
584+ char *strcat(char *, const char *);
585+ int strncmp(const char *, const char *, unsigned long);
586+-unsigned long strtoul(const char *, char **, int);
587+ unsigned long ebcstrtoul(char *, char **, int);
588+ int strlen(const char *);
589+ char *strcpy(char *, const char *);
590+diff --git a/zipl/boot/menu.c b/zipl/boot/menu.c
591+index 7187156..e668bb9 100644
592+--- a/zipl/boot/menu.c
593++++ b/zipl/boot/menu.c
594+@@ -184,7 +184,7 @@ boot:
595+ (void *)&__stage2_params + TEXT_OFFSET));
596+
597+ /* append 'BOOT_IMAGE=<num>' to parmline */
598+- sprintf(endstring, " BOOT_IMAGE=%u", value);
599++ snprintf(endstring, sizeof(endstring), " BOOT_IMAGE=%u", value);
600+ if ((strlen(cmd_line_extra) + strlen(endstring)) < COMMAND_LINE_SIZE)
601+ strcat(cmd_line_extra, endstring);
602+
603+diff --git a/zipl/boot/tape2dump.c b/zipl/boot/tape2dump.c
604+index 58b72f3..b11f42b 100644
605+--- a/zipl/boot/tape2dump.c
606++++ b/zipl/boot/tape2dump.c
607+@@ -184,7 +184,7 @@ static void progress_print_disp(unsigned long addr)
608+
609+ if (addr % (1024 * 1024 * 16) != 0)
610+ return;
611+- sprintf(msg, "%08u", addr >> 20);
612++ snprintf(msg, sizeof(msg), "%08u", addr >> 20);
613+ ccw_load_display(msg);
614+ }
615+
616diff --git a/debian/patches/0027-zipl-libc-Indicate-truncated-lines-in-printf-with.patch b/debian/patches/0027-zipl-libc-Indicate-truncated-lines-in-printf-with.patch
617new file mode 100644
618index 0000000..561368e
619--- /dev/null
620+++ b/debian/patches/0027-zipl-libc-Indicate-truncated-lines-in-printf-with.patch
621@@ -0,0 +1,69 @@
622+From: Philipp Rudo <prudo@linux.ibm.com>
623+Date: Wed, 12 Feb 2020 14:08:24 +0100
624+Subject: zipl/libc: Indicate truncated lines in printf with '...'
625+MIME-Version: 1.0
626+Content-Type: text/plain; charset="utf-8"
627+Content-Transfer-Encoding: 8bit
628+
629+Append '...' to lines exceeding the maximum line length instead of
630+silently truncating them.
631+
632+Suggested-by: Marc Hartmayer <mhartmay@linux.ibm.com>
633+Signed-off-by: Philipp Rudo <prudo@linux.ibm.com>
634+Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
635+Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
636+Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
637+---
638+ zipl/boot/libc.c | 10 ++++++++--
639+ zipl/boot/libc.h | 1 +
640+ zipl/boot/menu.h | 1 -
641+ 3 files changed, 9 insertions(+), 3 deletions(-)
642+
643+diff --git a/zipl/boot/libc.c b/zipl/boot/libc.c
644+index 4020458..7396455 100644
645+--- a/zipl/boot/libc.c
646++++ b/zipl/boot/libc.c
647+@@ -386,11 +386,17 @@ void snprintf(char *buf, unsigned long size, const char *fmt, ...)
648+ */
649+ void printf(const char *fmt, ...)
650+ {
651+- char buf[81];
652++ char buf[LINE_LENGTH + 1];
653++ int len;
654+ va_list va;
655+
656+ va_start(va, fmt);
657+- vsnprintf(buf, sizeof(buf), fmt, va);
658++ len = vsnprintf(buf, sizeof(buf), fmt, va);
659++ if (len > LINE_LENGTH) {
660++ buf[LINE_LENGTH - 1] = '.';
661++ buf[LINE_LENGTH - 2] = '.';
662++ buf[LINE_LENGTH - 3] = '.';
663++ }
664+ sclp_print(buf);
665+ va_end(va);
666+ }
667+diff --git a/zipl/boot/libc.h b/zipl/boot/libc.h
668+index 85a078e..8148e25 100644
669+--- a/zipl/boot/libc.h
670++++ b/zipl/boot/libc.h
671+@@ -39,6 +39,7 @@
672+ #define ENOTTY 25 /* Not a typewriter */
673+
674+ #define MIB (1024ULL * 1024)
675++#define LINE_LENGTH 80 /* max line length printed by printf */
676+
677+ typedef unsigned long long uint64_t;
678+ typedef unsigned int uint32_t;
679+diff --git a/zipl/boot/menu.h b/zipl/boot/menu.h
680+index edfe240..84d27aa 100644
681+--- a/zipl/boot/menu.h
682++++ b/zipl/boot/menu.h
683+@@ -18,7 +18,6 @@
684+ /* max command line length */
685+ #define COMMAND_LINE_SIZE 896
686+ #define BOOT_MENU_ENTRIES 63
687+-#define LINE_LENGTH 80
688+ #define PARAM_SIZE 8
689+ #define TEXT_OFFSET 4
690+
691diff --git a/debian/patches/0028-zipl-boot-libc-add-memmove-function.patch b/debian/patches/0028-zipl-boot-libc-add-memmove-function.patch
692new file mode 100644
693index 0000000..5d27d53
694--- /dev/null
695+++ b/debian/patches/0028-zipl-boot-libc-add-memmove-function.patch
696@@ -0,0 +1,54 @@
697+From: =?utf-8?q?Lukas_M=C3=A4rdian?= <lukas.maerdian@canonical.com>
698+Date: Tue, 17 Nov 2020 16:22:55 +0100
699+Subject: zipl/boot/libc: add memmove() function
700+
701+This was taken as a part of upstream commit:
702+https://github.com/ibm-s390-tools/s390-tools/commit/e764f460c457ab2a6000acb5f2eb7169866ce192
703+---
704+ zipl/boot/libc.c | 20 ++++++++++++++++++++
705+ zipl/boot/libc.h | 1 +
706+ 2 files changed, 21 insertions(+)
707+
708+diff --git a/zipl/boot/libc.c b/zipl/boot/libc.c
709+index 7396455..7b768cc 100644
710+--- a/zipl/boot/libc.c
711++++ b/zipl/boot/libc.c
712+@@ -56,6 +56,26 @@ void *memcpy(void *dest, const void *src, unsigned long n)
713+ return dest;
714+ }
715+
716++/*
717++ * Move @n bytes of memory from @src to @dest. The memory regions may overlap.
718++ */
719++void *memmove(void *dest, const void *src, unsigned long n)
720++{
721++ const char *s = src;
722++ char *d = dest;
723++
724++ if (s < d) {
725++ d += n;
726++ s += n;
727++ while (n--)
728++ *--d = *--s;
729++ } else {
730++ while (n--)
731++ *d++ = *s++;
732++ }
733++ return dest;
734++}
735++
736+ /*
737+ * Copy string
738+ */
739+diff --git a/zipl/boot/libc.h b/zipl/boot/libc.h
740+index 8148e25..2bd5063 100644
741+--- a/zipl/boot/libc.h
742++++ b/zipl/boot/libc.h
743+@@ -49,6 +49,7 @@ typedef unsigned char uint8_t;
744+ void printf(const char *, ...);
745+ void snprintf(char *buf, unsigned long size, const char *fmt, ...);
746+ void *memcpy(void *, const void *, unsigned long);
747++void *memmove(void *, const void *, unsigned long);
748+ void *memset(void *, int c, unsigned long);
749+ char *strcat(char *, const char *);
750+ int strncmp(const char *, const char *, unsigned long);
751diff --git a/debian/patches/series b/debian/patches/series
752index a600fb9..0003295 100644
753--- a/debian/patches/series
754+++ b/debian/patches/series
755@@ -21,3 +21,8 @@ d4398aea897475b95e4ab18cde4a32d0d70e6973.patch
756 dbginfo-use-dump2tar.patch
757 dump2tar-backport.patch
758 chreipl-fix-chreipl-node-for-virtio-devices.patch
759+0024-zipl-libc-Introduce-vsnprintf.patch
760+0025-zipl-libc-Fix-potential-buffer-overflow-in-printf.patch
761+0026-zipl-libc-Replace-sprintf-with-snprintf.patch
762+0027-zipl-libc-Indicate-truncated-lines-in-printf-with.patch
763+0028-zipl-boot-libc-add-memmove-function.patch

Subscribers

People subscribed via source and target branches