aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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))