Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

lib/fonts: Create font_data_t from struct console_font with font_data_import()

Add font_data_import() and update consoles to use it.

The implementation of font_data_import() is based on code from fbcon,
which supports overflow checks and crc32 checksums. Fbcon uses the crc32
checksum.

Newport_con now implements the same overflow checks as fbcon. As before,
this console does not support checksums, which are optional. Newport_con
can now also handle input font data with a vertical pitch other than 32
bytes. (The vertical pitch is the offset between two glyphs in the font
data.)

As an internal change, remove the const qualifier from the data field
if struct font_data. This allows font_data_import() to write the data
without type casting. For all users of the font data via font_data_t,
the stored data is still read only.

v3:
- fix typos

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Signed-off-by: Helge Deller <deller@gmx.de>

authored by

Thomas Zimmermann and committed by
Helge Deller
514d0de7 1e3c49aa

+75 -53
+4 -18
drivers/video/console/newport_con.c
··· 501 501 { 502 502 int w = op->width; 503 503 int h = op->height; 504 - int size = h * op->charcount; 505 504 int i; 506 505 font_data_t *new_data; 507 - unsigned char *data = op->data, *p; 508 506 509 507 /* ladis: when I grow up, there will be a day... and more sizes will 510 508 * be supported ;-) */ 511 - if ((w != 8) || (h != 16) || (vpitch != 32) 512 - || (op->charcount != 256 && op->charcount != 512)) 509 + if (w != 8 || h != 16 || (op->charcount != 256 && op->charcount != 512)) 513 510 return -EINVAL; 514 511 515 - if (!(new_data = kmalloc(FONT_EXTRA_WORDS * sizeof(int) + size, 516 - GFP_USER))) return -ENOMEM; 517 - 518 - new_data += FONT_EXTRA_WORDS * sizeof(int); 519 - FNTSIZE(new_data) = size; 520 - REFCOUNT(new_data) = 1; /* usage counter */ 521 - FNTSUM(new_data) = 0; 522 - 523 - p = (unsigned char *)font_data_buf(new_data); 524 - for (i = 0; i < op->charcount; i++) { 525 - memcpy(p, data, h); 526 - data += 32; 527 - p += h; 528 - } 512 + new_data = font_data_import(op, vpitch, NULL); 513 + if (IS_ERR(new_data)) 514 + return PTR_ERR(new_data); 529 515 530 516 /* check if font is already used by other console */ 531 517 for (i = 0; i < MAX_NR_CONSOLES; i++) {
+4 -34
drivers/video/fbdev/core/fbcon.c
··· 2039 2039 updatescrollmode_accel(p, info, vc); 2040 2040 } 2041 2041 2042 - #define PITCH(w) (((w) + 7) >> 3) 2043 - 2044 2042 static int fbcon_resize(struct vc_data *vc, unsigned int width, 2045 2043 unsigned int height, bool from_user) 2046 2044 { ··· 2422 2424 resize = (w != vc->vc_font.width) || (h != vc->vc_font.height); 2423 2425 p->fontdata = data; 2424 2426 vc->vc_font.data = font_data_buf(p->fontdata); 2425 - 2426 2427 old_width = vc->vc_font.width; 2427 2428 old_height = vc->vc_font.height; 2428 2429 old_charcount = vc->vc_font.charcount; ··· 2479 2482 unsigned charcount = font->charcount; 2480 2483 int w = font->width; 2481 2484 int h = font->height; 2482 - int size, alloc_size; 2483 - int i, csum, ret; 2485 + int i, ret; 2484 2486 font_data_t *new_data; 2485 - const u8 *data = font->data; 2486 - int pitch = PITCH(font->width); 2487 2487 2488 2488 /* Is there a reason why fbconsole couldn't handle any charcount >256? 2489 2489 * If not this check should be changed to charcount < 256 */ ··· 2504 2510 if (fbcon_invalid_charcount(info, charcount)) 2505 2511 return -EINVAL; 2506 2512 2507 - /* Check for integer overflow in font size calculation */ 2508 - if (check_mul_overflow(h, pitch, &size) || 2509 - check_mul_overflow(size, charcount, &size)) 2510 - return -EINVAL; 2513 + new_data = font_data_import(font, vpitch, crc32); 2514 + if (IS_ERR(new_data)) 2515 + return PTR_ERR(new_data); 2511 2516 2512 - /* Check for overflow in allocation size calculation */ 2513 - if (check_add_overflow(FONT_EXTRA_WORDS * sizeof(int), size, &alloc_size)) 2514 - return -EINVAL; 2515 - 2516 - new_data = kmalloc(alloc_size, GFP_USER); 2517 - 2518 - if (!new_data) 2519 - return -ENOMEM; 2520 - 2521 - memset((u8 *)new_data, 0, FONT_EXTRA_WORDS * sizeof(int)); 2522 - 2523 - new_data += FONT_EXTRA_WORDS * sizeof(int); 2524 - FNTSIZE(new_data) = size; 2525 - REFCOUNT(new_data) = 1; /* usage counter */ 2526 - for (i=0; i< charcount; i++) { 2527 - memcpy((u8 *)new_data + i * h * pitch, data + i * vpitch * pitch, h * pitch); 2528 - } 2529 - 2530 - /* Since linux has a nice crc32 function use it for counting font 2531 - * checksums. */ 2532 - csum = crc32(0, new_data, size); 2533 - 2534 - FNTSUM(new_data) = csum; 2535 2517 /* Check if the same font is on some other console already */ 2536 2518 for (i = first_fb_vc; i <= last_fb_vc; i++) { 2537 2519 if (fb_display[i].fontdata &&
+5 -1
include/linux/font.h
··· 13 13 14 14 #include <linux/types.h> 15 15 16 + struct console_font; 17 + 16 18 /* 17 19 * font_data_t and helpers 18 20 */ ··· 56 54 return (const unsigned char *)fd; 57 55 } 58 56 57 + font_data_t *font_data_import(const struct console_font *font, unsigned int vpitch, 58 + u32 (*calc_csum)(u32, const void *, size_t)); 59 59 void font_data_get(font_data_t *fd); 60 60 bool font_data_put(font_data_t *fd); 61 61 unsigned int font_data_size(font_data_t *fd); ··· 128 124 129 125 struct font_data { 130 126 unsigned int extra[FONT_EXTRA_WORDS]; 131 - const unsigned char data[]; 127 + unsigned char data[]; 132 128 } __packed; 133 129 134 130 #endif /* _VIDEO_FONT_H */
+62
lib/fonts/fonts.c
··· 14 14 15 15 #include <linux/container_of.h> 16 16 #include <linux/font.h> 17 + #include <linux/kd.h> 17 18 #include <linux/module.h> 19 + #include <linux/overflow.h> 18 20 #include <linux/slab.h> 19 21 #include <linux/string.h> 20 22 #include <linux/types.h> ··· 24 22 #if defined(__mc68000__) 25 23 #include <asm/setup.h> 26 24 #endif 25 + 26 + #define console_font_pitch(font) DIV_ROUND_UP((font)->width, 8) 27 27 28 28 /* 29 29 * Helpers for font_data_t ··· 45 41 { 46 42 kfree(to_font_data_struct(fd)); 47 43 } 44 + 45 + /** 46 + * font_data_import - Allocates and initializes font data from user space 47 + * @font: A font from user space 48 + * @vpitch: The size of a single glyph in @font in bytes 49 + * @calc_csum: An optional helper to calculate a chechsum 50 + * 51 + * Font data from user space must be translated to the kernel's format. The 52 + * font's glyph geometry and data is provided in @font. The parameter @vpitch 53 + * gives the number of bytes per glyph, including trailing bytes. 54 + * 55 + * The parameter @calc_csum is optional. Fbcon passes crc32() to calculate the 56 + * font data's checksum. 57 + * 58 + * Returns: 59 + * Newly initialized font data on success, or a pointer-encoded errno value otherwise. 60 + */ 61 + font_data_t *font_data_import(const struct console_font *font, unsigned int vpitch, 62 + u32 (*calc_csum)(u32, const void *, size_t)) 63 + { 64 + unsigned int pitch = console_font_pitch(font); 65 + unsigned int h = font->height; 66 + unsigned int charcount = font->charcount; 67 + const unsigned char *data = font->data; 68 + u32 csum = 0; 69 + struct font_data *font_data; 70 + int size, alloc_size; 71 + unsigned int i; 72 + font_data_t *fd; 73 + 74 + /* Check for integer overflow in font-size calculation */ 75 + if (check_mul_overflow(h, pitch, &size) || 76 + check_mul_overflow(size, charcount, &size)) 77 + return ERR_PTR(-EINVAL); 78 + 79 + /* Check for overflow in allocation size calculation */ 80 + if (check_add_overflow(sizeof(*font_data), size, &alloc_size)) 81 + return ERR_PTR(-EINVAL); 82 + 83 + font_data = kmalloc(alloc_size, GFP_USER); 84 + if (!font_data) 85 + return ERR_PTR(-ENOMEM); 86 + memset(font_data->extra, 0, sizeof(font_data->extra)); 87 + 88 + for (i = 0; i < charcount; ++i) 89 + memcpy(font_data->data + i * h * pitch, data + i * vpitch * pitch, h * pitch); 90 + 91 + if (calc_csum) 92 + csum = calc_csum(0, font_data->data, size); 93 + 94 + fd = font_data->data; 95 + REFCOUNT(fd) = 1; /* start with reference acquired */ 96 + FNTSIZE(fd) = size; 97 + FNTSUM(fd) = csum; 98 + 99 + return fd; 100 + } 101 + EXPORT_SYMBOL_GPL(font_data_import); 48 102 49 103 /** 50 104 * font_data_get - Acquires a reference on font data