aboutsummaryrefslogtreecommitdiffstats
path: root/fs/binfmt_misc.c
diff options
context:
space:
mode:
authorMike Frysinger <vapier@gentoo.org>2014-12-10 18:52:08 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2014-12-10 20:41:12 -0500
commit6b899c4e9a049dfca759d990bd53b14f81c3626c (patch)
treef2321ebef1293c81a1bac05e2361d075b977f5d0 /fs/binfmt_misc.c
parent5e4f6ba5eb7facb0dbf2734f5a12033c70f8eb53 (diff)
binfmt_misc: add comments & debug logs
When trying to develop a custom format handler, the errors returned all effectively get bucketed as EINVAL with no kernel messages. The other errors (ENOMEM/EFAULT) are internal/obvious and basic. Thus any time a bad handler is rejected, the developer has to walk the dense code and try to guess where it went wrong. Needing to dive into kernel code is itself a fairly high barrier for a lot of people. To improve this situation, let's deploy extensive pr_debug markers at logical parse points, and add comments to the dense parsing logic. It let's you see exactly where the parsing aborts, the string the kernel received (useful when dealing with shell code), how it translated the buffers to binary data, and how it will apply the mask at runtime. Some example output: $ echo ':qemu-foo:M::\x7fELF\xAD\xAD\x01\x00:\xff\xff\xff\xff\xff\x00\xff\x00:/usr/bin/qemu-foo:POC' > register $ dmesg binfmt_misc: register: received 92 bytes binfmt_misc: register: delim: 0x3a {:} binfmt_misc: register: name: {qemu-foo} binfmt_misc: register: type: M (magic) binfmt_misc: register: offset: 0x0 binfmt_misc: register: magic[raw]: 5c 78 37 66 45 4c 46 5c 78 41 44 5c 78 41 44 5c \x7fELF\xAD\xAD\ binfmt_misc: register: magic[raw]: 78 30 31 5c 78 30 30 00 x01\x00. binfmt_misc: register: mask[raw]: 5c 78 66 66 5c 78 66 66 5c 78 66 66 5c 78 66 66 \xff\xff\xff\xff binfmt_misc: register: mask[raw]: 5c 78 66 66 5c 78 30 30 5c 78 66 66 5c 78 30 30 \xff\x00\xff\x00 binfmt_misc: register: mask[raw]: 00 . binfmt_misc: register: magic/mask length: 8 binfmt_misc: register: magic[decoded]: 7f 45 4c 46 ad ad 01 00 .ELF.... binfmt_misc: register: mask[decoded]: ff ff ff ff ff 00 ff 00 ........ binfmt_misc: register: magic[masked]: 7f 45 4c 46 ad 00 01 00 .ELF.... binfmt_misc: register: interpreter: {/usr/bin/qemu-foo} binfmt_misc: register: flag: P (preserve argv0) binfmt_misc: register: flag: O (open binary) binfmt_misc: register: flag: C (preserve creds) The [raw] lines show us exactly what was received from userspace. The lines after that show us how the kernel has decoded things. Signed-off-by: Mike Frysinger <vapier@gentoo.org> Cc: Al Viro <viro@zeniv.linux.org.uk> Cc: Joe Perches <joe@perches.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/binfmt_misc.c')
-rw-r--r--fs/binfmt_misc.c136
1 files changed, 121 insertions, 15 deletions
diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c
index 1cc5377ba955..d87ddc7c4b14 100644
--- a/fs/binfmt_misc.c
+++ b/fs/binfmt_misc.c
@@ -16,6 +16,8 @@
16 * 2001-02-28 AV: rewritten into something that resembles C. Original didn't. 16 * 2001-02-28 AV: rewritten into something that resembles C. Original didn't.
17 */ 17 */
18 18
19#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
20
19#include <linux/module.h> 21#include <linux/module.h>
20#include <linux/init.h> 22#include <linux/init.h>
21#include <linux/sched.h> 23#include <linux/sched.h>
@@ -30,8 +32,13 @@
30#include <linux/mount.h> 32#include <linux/mount.h>
31#include <linux/syscalls.h> 33#include <linux/syscalls.h>
32#include <linux/fs.h> 34#include <linux/fs.h>
35#include <linux/uaccess.h>
33 36
34#include <asm/uaccess.h> 37#ifdef DEBUG
38# define USE_DEBUG 1
39#else
40# define USE_DEBUG 0
41#endif
35 42
36enum { 43enum {
37 VERBOSE_STATUS = 1 /* make it zero to save 400 bytes kernel memory */ 44 VERBOSE_STATUS = 1 /* make it zero to save 400 bytes kernel memory */
@@ -87,20 +94,24 @@ static Node *check_file(struct linux_binprm *bprm)
87 char *p = strrchr(bprm->interp, '.'); 94 char *p = strrchr(bprm->interp, '.');
88 struct list_head *l; 95 struct list_head *l;
89 96
97 /* Walk all the registered handlers. */
90 list_for_each(l, &entries) { 98 list_for_each(l, &entries) {
91 Node *e = list_entry(l, Node, list); 99 Node *e = list_entry(l, Node, list);
92 char *s; 100 char *s;
93 int j; 101 int j;
94 102
103 /* Make sure this one is currently enabled. */
95 if (!test_bit(Enabled, &e->flags)) 104 if (!test_bit(Enabled, &e->flags))
96 continue; 105 continue;
97 106
107 /* Do matching based on extension if applicable. */
98 if (!test_bit(Magic, &e->flags)) { 108 if (!test_bit(Magic, &e->flags)) {
99 if (p && !strcmp(e->magic, p + 1)) 109 if (p && !strcmp(e->magic, p + 1))
100 return e; 110 return e;
101 continue; 111 continue;
102 } 112 }
103 113
114 /* Do matching based on magic & mask. */
104 s = bprm->buf + e->offset; 115 s = bprm->buf + e->offset;
105 if (e->mask) { 116 if (e->mask) {
106 for (j = 0; j < e->size; j++) 117 for (j = 0; j < e->size; j++)
@@ -259,14 +270,17 @@ static char * check_special_flags (char * sfs, Node * e)
259 while (cont) { 270 while (cont) {
260 switch (*p) { 271 switch (*p) {
261 case 'P': 272 case 'P':
273 pr_debug("register: flag: P (preserve argv0)\n");
262 p++; 274 p++;
263 e->flags |= MISC_FMT_PRESERVE_ARGV0; 275 e->flags |= MISC_FMT_PRESERVE_ARGV0;
264 break; 276 break;
265 case 'O': 277 case 'O':
278 pr_debug("register: flag: O (open binary)\n");
266 p++; 279 p++;
267 e->flags |= MISC_FMT_OPEN_BINARY; 280 e->flags |= MISC_FMT_OPEN_BINARY;
268 break; 281 break;
269 case 'C': 282 case 'C':
283 pr_debug("register: flag: C (preserve creds)\n");
270 p++; 284 p++;
271 /* this flags also implies the 285 /* this flags also implies the
272 open-binary flag */ 286 open-binary flag */
@@ -292,6 +306,8 @@ static Node *create_entry(const char __user *buffer, size_t count)
292 char *buf, *p; 306 char *buf, *p;
293 char del; 307 char del;
294 308
309 pr_debug("register: received %zu bytes\n", count);
310
295 /* some sanity checks */ 311 /* some sanity checks */
296 err = -EINVAL; 312 err = -EINVAL;
297 if ((count < 11) || (count > MAX_REGISTER_LENGTH)) 313 if ((count < 11) || (count > MAX_REGISTER_LENGTH))
@@ -311,8 +327,12 @@ static Node *create_entry(const char __user *buffer, size_t count)
311 327
312 del = *p++; /* delimeter */ 328 del = *p++; /* delimeter */
313 329
330 pr_debug("register: delim: %#x {%c}\n", del, del);
331
332 /* Pad the buffer with the delim to simplify parsing below. */
314 memset(buf+count, del, 8); 333 memset(buf+count, del, 8);
315 334
335 /* Parse the 'name' field. */
316 e->name = p; 336 e->name = p;
317 p = strchr(p, del); 337 p = strchr(p, del);
318 if (!p) 338 if (!p)
@@ -323,46 +343,113 @@ static Node *create_entry(const char __user *buffer, size_t count)
323 !strcmp(e->name, "..") || 343 !strcmp(e->name, "..") ||
324 strchr(e->name, '/')) 344 strchr(e->name, '/'))
325 goto Einval; 345 goto Einval;
346
347 pr_debug("register: name: {%s}\n", e->name);
348
349 /* Parse the 'type' field. */
326 switch (*p++) { 350 switch (*p++) {
327 case 'E': e->flags = 1<<Enabled; break; 351 case 'E':
328 case 'M': e->flags = (1<<Enabled) | (1<<Magic); break; 352 pr_debug("register: type: E (extension)\n");
329 default: goto Einval; 353 e->flags = 1 << Enabled;
354 break;
355 case 'M':
356 pr_debug("register: type: M (magic)\n");
357 e->flags = (1 << Enabled) | (1 << Magic);
358 break;
359 default:
360 goto Einval;
330 } 361 }
331 if (*p++ != del) 362 if (*p++ != del)
332 goto Einval; 363 goto Einval;
364
333 if (test_bit(Magic, &e->flags)) { 365 if (test_bit(Magic, &e->flags)) {
334 char *s = strchr(p, del); 366 /* Handle the 'M' (magic) format. */
367 char *s;
368
369 /* Parse the 'offset' field. */
370 s = strchr(p, del);
335 if (!s) 371 if (!s)
336 goto Einval; 372 goto Einval;
337 *s++ = '\0'; 373 *s++ = '\0';
338 e->offset = simple_strtoul(p, &p, 10); 374 e->offset = simple_strtoul(p, &p, 10);
339 if (*p++) 375 if (*p++)
340 goto Einval; 376 goto Einval;
377 pr_debug("register: offset: %#x\n", e->offset);
378
379 /* Parse the 'magic' field. */
341 e->magic = p; 380 e->magic = p;
342 p = scanarg(p, del); 381 p = scanarg(p, del);
343 if (!p) 382 if (!p)
344 goto Einval; 383 goto Einval;
345 p[-1] = '\0'; 384 p[-1] = '\0';
346 if (!e->magic[0]) 385 if (p == e->magic)
347 goto Einval; 386 goto Einval;
387 if (USE_DEBUG)
388 print_hex_dump_bytes(
389 KBUILD_MODNAME ": register: magic[raw]: ",
390 DUMP_PREFIX_NONE, e->magic, p - e->magic);
391
392 /* Parse the 'mask' field. */
348 e->mask = p; 393 e->mask = p;
349 p = scanarg(p, del); 394 p = scanarg(p, del);
350 if (!p) 395 if (!p)
351 goto Einval; 396 goto Einval;
352 p[-1] = '\0'; 397 p[-1] = '\0';
353 if (!e->mask[0]) 398 if (p == e->mask) {
354 e->mask = NULL; 399 e->mask = NULL;
400 pr_debug("register: mask[raw]: none\n");
401 } else if (USE_DEBUG)
402 print_hex_dump_bytes(
403 KBUILD_MODNAME ": register: mask[raw]: ",
404 DUMP_PREFIX_NONE, e->mask, p - e->mask);
405
406 /*
407 * Decode the magic & mask fields.
408 * Note: while we might have accepted embedded NUL bytes from
409 * above, the unescape helpers here will stop at the first one
410 * it encounters.
411 */
355 e->size = string_unescape_inplace(e->magic, UNESCAPE_HEX); 412 e->size = string_unescape_inplace(e->magic, UNESCAPE_HEX);
356 if (e->mask && 413 if (e->mask &&
357 string_unescape_inplace(e->mask, UNESCAPE_HEX) != e->size) 414 string_unescape_inplace(e->mask, UNESCAPE_HEX) != e->size)
358 goto Einval; 415 goto Einval;
359 if (e->size + e->offset > BINPRM_BUF_SIZE) 416 if (e->size + e->offset > BINPRM_BUF_SIZE)
360 goto Einval; 417 goto Einval;
418 pr_debug("register: magic/mask length: %i\n", e->size);
419 if (USE_DEBUG) {
420 print_hex_dump_bytes(
421 KBUILD_MODNAME ": register: magic[decoded]: ",
422 DUMP_PREFIX_NONE, e->magic, e->size);
423
424 if (e->mask) {
425 int i;
426 char *masked = kmalloc(e->size, GFP_USER);
427
428 print_hex_dump_bytes(
429 KBUILD_MODNAME ": register: mask[decoded]: ",
430 DUMP_PREFIX_NONE, e->mask, e->size);
431
432 if (masked) {
433 for (i = 0; i < e->size; ++i)
434 masked[i] = e->magic[i] & e->mask[i];
435 print_hex_dump_bytes(
436 KBUILD_MODNAME ": register: magic[masked]: ",
437 DUMP_PREFIX_NONE, masked, e->size);
438
439 kfree(masked);
440 }
441 }
442 }
361 } else { 443 } else {
444 /* Handle the 'E' (extension) format. */
445
446 /* Skip the 'offset' field. */
362 p = strchr(p, del); 447 p = strchr(p, del);
363 if (!p) 448 if (!p)
364 goto Einval; 449 goto Einval;
365 *p++ = '\0'; 450 *p++ = '\0';
451
452 /* Parse the 'magic' field. */
366 e->magic = p; 453 e->magic = p;
367 p = strchr(p, del); 454 p = strchr(p, del);
368 if (!p) 455 if (!p)
@@ -370,11 +457,16 @@ static Node *create_entry(const char __user *buffer, size_t count)
370 *p++ = '\0'; 457 *p++ = '\0';
371 if (!e->magic[0] || strchr(e->magic, '/')) 458 if (!e->magic[0] || strchr(e->magic, '/'))
372 goto Einval; 459 goto Einval;
460 pr_debug("register: extension: {%s}\n", e->magic);
461
462 /* Skip the 'mask' field. */
373 p = strchr(p, del); 463 p = strchr(p, del);
374 if (!p) 464 if (!p)
375 goto Einval; 465 goto Einval;
376 *p++ = '\0'; 466 *p++ = '\0';
377 } 467 }
468
469 /* Parse the 'interpreter' field. */
378 e->interpreter = p; 470 e->interpreter = p;
379 p = strchr(p, del); 471 p = strchr(p, del);
380 if (!p) 472 if (!p)
@@ -382,10 +474,10 @@ static Node *create_entry(const char __user *buffer, size_t count)
382 *p++ = '\0'; 474 *p++ = '\0';
383 if (!e->interpreter[0]) 475 if (!e->interpreter[0])
384 goto Einval; 476 goto Einval;
477 pr_debug("register: interpreter: {%s}\n", e->interpreter);
385 478
386 479 /* Parse the 'flags' field. */
387 p = check_special_flags (p, e); 480 p = check_special_flags (p, e);
388
389 if (*p == '\n') 481 if (*p == '\n')
390 p++; 482 p++;
391 if (p != buf + count) 483 if (p != buf + count)
@@ -553,11 +645,17 @@ static ssize_t bm_entry_write(struct file *file, const char __user *buffer,
553 int res = parse_command(buffer, count); 645 int res = parse_command(buffer, count);
554 646
555 switch (res) { 647 switch (res) {
556 case 1: clear_bit(Enabled, &e->flags); 648 case 1:
649 /* Disable this handler. */
650 clear_bit(Enabled, &e->flags);
557 break; 651 break;
558 case 2: set_bit(Enabled, &e->flags); 652 case 2:
653 /* Enable this handler. */
654 set_bit(Enabled, &e->flags);
559 break; 655 break;
560 case 3: root = dget(file->f_path.dentry->d_sb->s_root); 656 case 3:
657 /* Delete this handler. */
658 root = dget(file->f_path.dentry->d_sb->s_root);
561 mutex_lock(&root->d_inode->i_mutex); 659 mutex_lock(&root->d_inode->i_mutex);
562 660
563 kill_node(e); 661 kill_node(e);
@@ -661,9 +759,17 @@ static ssize_t bm_status_write(struct file * file, const char __user * buffer,
661 struct dentry *root; 759 struct dentry *root;
662 760
663 switch (res) { 761 switch (res) {
664 case 1: enabled = 0; break; 762 case 1:
665 case 2: enabled = 1; break; 763 /* Disable all handlers. */
666 case 3: root = dget(file->f_path.dentry->d_sb->s_root); 764 enabled = 0;
765 break;
766 case 2:
767 /* Enable all handlers. */
768 enabled = 1;
769 break;
770 case 3:
771 /* Delete all handlers. */
772 root = dget(file->f_path.dentry->d_sb->s_root);
667 mutex_lock(&root->d_inode->i_mutex); 773 mutex_lock(&root->d_inode->i_mutex);
668 774
669 while (!list_empty(&entries)) 775 while (!list_empty(&entries))