linux/fs/binfmt_misc.c
<<
>>
Prefs
   1/*
   2 * binfmt_misc.c
   3 *
   4 * Copyright (C) 1997 Richard G√ľnther
   5 *
   6 * binfmt_misc detects binaries via a magic or filename extension and invokes
   7 * a specified wrapper. See Documentation/binfmt_misc.txt for more details.
   8 */
   9
  10#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  11
  12#include <linux/kernel.h>
  13#include <linux/module.h>
  14#include <linux/init.h>
  15#include <linux/sched.h>
  16#include <linux/magic.h>
  17#include <linux/binfmts.h>
  18#include <linux/slab.h>
  19#include <linux/ctype.h>
  20#include <linux/string_helpers.h>
  21#include <linux/file.h>
  22#include <linux/pagemap.h>
  23#include <linux/namei.h>
  24#include <linux/mount.h>
  25#include <linux/syscalls.h>
  26#include <linux/fs.h>
  27#include <linux/uaccess.h>
  28
  29#include "internal.h"
  30
  31#ifdef DEBUG
  32# define USE_DEBUG 1
  33#else
  34# define USE_DEBUG 0
  35#endif
  36
  37enum {
  38        VERBOSE_STATUS = 1 /* make it zero to save 400 bytes kernel memory */
  39};
  40
  41static LIST_HEAD(entries);
  42static int enabled = 1;
  43
  44enum {Enabled, Magic};
  45#define MISC_FMT_PRESERVE_ARGV0 (1 << 31)
  46#define MISC_FMT_OPEN_BINARY (1 << 30)
  47#define MISC_FMT_CREDENTIALS (1 << 29)
  48#define MISC_FMT_OPEN_FILE (1 << 28)
  49
  50typedef struct {
  51        struct list_head list;
  52        unsigned long flags;            /* type, status, etc. */
  53        int offset;                     /* offset of magic */
  54        int size;                       /* size of magic/mask */
  55        char *magic;                    /* magic or filename extension */
  56        char *mask;                     /* mask, NULL for exact match */
  57        char *interpreter;              /* filename of interpreter */
  58        char *name;
  59        struct dentry *dentry;
  60        struct file *interp_file;
  61} Node;
  62
  63static DEFINE_RWLOCK(entries_lock);
  64static struct file_system_type bm_fs_type;
  65static struct vfsmount *bm_mnt;
  66static int entry_count;
  67
  68/*
  69 * Max length of the register string.  Determined by:
  70 *  - 7 delimiters
  71 *  - name:   ~50 bytes
  72 *  - type:   1 byte
  73 *  - offset: 3 bytes (has to be smaller than BINPRM_BUF_SIZE)
  74 *  - magic:  128 bytes (512 in escaped form)
  75 *  - mask:   128 bytes (512 in escaped form)
  76 *  - interp: ~50 bytes
  77 *  - flags:  5 bytes
  78 * Round that up a bit, and then back off to hold the internal data
  79 * (like struct Node).
  80 */
  81#define MAX_REGISTER_LENGTH 1920
  82
  83/*
  84 * Check if we support the binfmt
  85 * if we do, return the node, else NULL
  86 * locking is done in load_misc_binary
  87 */
  88static Node *check_file(struct linux_binprm *bprm)
  89{
  90        char *p = strrchr(bprm->interp, '.');
  91        struct list_head *l;
  92
  93        /* Walk all the registered handlers. */
  94        list_for_each(l, &entries) {
  95                Node *e = list_entry(l, Node, list);
  96                char *s;
  97                int j;
  98
  99                /* Make sure this one is currently enabled. */
 100                if (!test_bit(Enabled, &e->flags))
 101                        continue;
 102
 103                /* Do matching based on extension if applicable. */
 104                if (!test_bit(Magic, &e->flags)) {
 105                        if (p && !strcmp(e->magic, p + 1))
 106                                return e;
 107                        continue;
 108                }
 109
 110                /* Do matching based on magic & mask. */
 111                s = bprm->buf + e->offset;
 112                if (e->mask) {
 113                        for (j = 0; j < e->size; j++)
 114                                if ((*s++ ^ e->magic[j]) & e->mask[j])
 115                                        break;
 116                } else {
 117                        for (j = 0; j < e->size; j++)
 118                                if ((*s++ ^ e->magic[j]))
 119                                        break;
 120                }
 121                if (j == e->size)
 122                        return e;
 123        }
 124        return NULL;
 125}
 126
 127/*
 128 * the loader itself
 129 */
 130static int load_misc_binary(struct linux_binprm *bprm)
 131{
 132        Node *fmt;
 133        struct file *interp_file = NULL;
 134        char iname[BINPRM_BUF_SIZE];
 135        const char *iname_addr = iname;
 136        int retval;
 137        int fd_binary = -1;
 138
 139        retval = -ENOEXEC;
 140        if (!enabled)
 141                goto ret;
 142
 143        /* to keep locking time low, we copy the interpreter string */
 144        read_lock(&entries_lock);
 145        fmt = check_file(bprm);
 146        if (fmt)
 147                strlcpy(iname, fmt->interpreter, BINPRM_BUF_SIZE);
 148        read_unlock(&entries_lock);
 149        if (!fmt)
 150                goto ret;
 151
 152        /* Need to be able to load the file after exec */
 153        if (bprm->interp_flags & BINPRM_FLAGS_PATH_INACCESSIBLE)
 154                return -ENOENT;
 155
 156        if (!(fmt->flags & MISC_FMT_PRESERVE_ARGV0)) {
 157                retval = remove_arg_zero(bprm);
 158                if (retval)
 159                        goto ret;
 160        }
 161
 162        if (fmt->flags & MISC_FMT_OPEN_BINARY) {
 163
 164                /* if the binary should be opened on behalf of the
 165                 * interpreter than keep it open and assign descriptor
 166                 * to it
 167                 */
 168                fd_binary = get_unused_fd_flags(0);
 169                if (fd_binary < 0) {
 170                        retval = fd_binary;
 171                        goto ret;
 172                }
 173                fd_install(fd_binary, bprm->file);
 174
 175                /* if the binary is not readable than enforce mm->dumpable=0
 176                   regardless of the interpreter's permissions */
 177                would_dump(bprm, bprm->file);
 178
 179                allow_write_access(bprm->file);
 180                bprm->file = NULL;
 181
 182                /* mark the bprm that fd should be passed to interp */
 183                bprm->interp_flags |= BINPRM_FLAGS_EXECFD;
 184                bprm->interp_data = fd_binary;
 185
 186        } else {
 187                allow_write_access(bprm->file);
 188                fput(bprm->file);
 189                bprm->file = NULL;
 190        }
 191        /* make argv[1] be the path to the binary */
 192        retval = copy_strings_kernel(1, &bprm->interp, bprm);
 193        if (retval < 0)
 194                goto error;
 195        bprm->argc++;
 196
 197        /* add the interp as argv[0] */
 198        retval = copy_strings_kernel(1, &iname_addr, bprm);
 199        if (retval < 0)
 200                goto error;
 201        bprm->argc++;
 202
 203        /* Update interp in case binfmt_script needs it. */
 204        retval = bprm_change_interp(iname, bprm);
 205        if (retval < 0)
 206                goto error;
 207
 208        if (fmt->flags & MISC_FMT_OPEN_FILE && fmt->interp_file) {
 209                interp_file = filp_clone_open(fmt->interp_file);
 210                if (!IS_ERR(interp_file))
 211                        deny_write_access(interp_file);
 212        } else {
 213                interp_file = open_exec(iname);
 214        }
 215        retval = PTR_ERR(interp_file);
 216        if (IS_ERR(interp_file))
 217                goto error;
 218
 219        bprm->file = interp_file;
 220        if (fmt->flags & MISC_FMT_CREDENTIALS) {
 221                /*
 222                 * No need to call prepare_binprm(), it's already been
 223                 * done.  bprm->buf is stale, update from interp_file.
 224                 */
 225                memset(bprm->buf, 0, BINPRM_BUF_SIZE);
 226                retval = kernel_read(bprm->file, 0, bprm->buf, BINPRM_BUF_SIZE);
 227        } else
 228                retval = prepare_binprm(bprm);
 229
 230        if (retval < 0)
 231                goto error;
 232
 233        retval = search_binary_handler(bprm);
 234        if (retval < 0)
 235                goto error;
 236
 237ret:
 238        return retval;
 239error:
 240        if (fd_binary > 0)
 241                sys_close(fd_binary);
 242        bprm->interp_flags = 0;
 243        bprm->interp_data = 0;
 244        goto ret;
 245}
 246
 247/* Command parsers */
 248
 249/*
 250 * parses and copies one argument enclosed in del from *sp to *dp,
 251 * recognising the \x special.
 252 * returns pointer to the copied argument or NULL in case of an
 253 * error (and sets err) or null argument length.
 254 */
 255static char *scanarg(char *s, char del)
 256{
 257        char c;
 258
 259        while ((c = *s++) != del) {
 260                if (c == '\\' && *s == 'x') {
 261                        s++;
 262                        if (!isxdigit(*s++))
 263                                return NULL;
 264                        if (!isxdigit(*s++))
 265                                return NULL;
 266                }
 267        }
 268        s[-1] ='\0';
 269        return s;
 270}
 271
 272static char *check_special_flags(char *sfs, Node *e)
 273{
 274        char *p = sfs;
 275        int cont = 1;
 276
 277        /* special flags */
 278        while (cont) {
 279                switch (*p) {
 280                case 'P':
 281                        pr_debug("register: flag: P (preserve argv0)\n");
 282                        p++;
 283                        e->flags |= MISC_FMT_PRESERVE_ARGV0;
 284                        break;
 285                case 'O':
 286                        pr_debug("register: flag: O (open binary)\n");
 287                        p++;
 288                        e->flags |= MISC_FMT_OPEN_BINARY;
 289                        break;
 290                case 'C':
 291                        pr_debug("register: flag: C (preserve creds)\n");
 292                        p++;
 293                        /* this flags also implies the
 294                           open-binary flag */
 295                        e->flags |= (MISC_FMT_CREDENTIALS |
 296                                        MISC_FMT_OPEN_BINARY);
 297                        break;
 298                case 'F':
 299                        pr_debug("register: flag: F: open interpreter file now\n");
 300                        p++;
 301                        e->flags |= MISC_FMT_OPEN_FILE;
 302                        break;
 303                default:
 304                        cont = 0;
 305                }
 306        }
 307
 308        return p;
 309}
 310
 311/*
 312 * This registers a new binary format, it recognises the syntax
 313 * ':name:type:offset:magic:mask:interpreter:flags'
 314 * where the ':' is the IFS, that can be chosen with the first char
 315 */
 316static Node *create_entry(const char __user *buffer, size_t count)
 317{
 318        Node *e;
 319        int memsize, err;
 320        char *buf, *p;
 321        char del;
 322
 323        pr_debug("register: received %zu bytes\n", count);
 324
 325        /* some sanity checks */
 326        err = -EINVAL;
 327        if ((count < 11) || (count > MAX_REGISTER_LENGTH))
 328                goto out;
 329
 330        err = -ENOMEM;
 331        memsize = sizeof(Node) + count + 8;
 332        e = kmalloc(memsize, GFP_KERNEL);
 333        if (!e)
 334                goto out;
 335
 336        p = buf = (char *)e + sizeof(Node);
 337
 338        memset(e, 0, sizeof(Node));
 339        if (copy_from_user(buf, buffer, count))
 340                goto efault;
 341
 342        del = *p++;     /* delimeter */
 343
 344        pr_debug("register: delim: %#x {%c}\n", del, del);
 345
 346        /* Pad the buffer with the delim to simplify parsing below. */
 347        memset(buf + count, del, 8);
 348
 349        /* Parse the 'name' field. */
 350        e->name = p;
 351        p = strchr(p, del);
 352        if (!p)
 353                goto einval;
 354        *p++ = '\0';
 355        if (!e->name[0] ||
 356            !strcmp(e->name, ".") ||
 357            !strcmp(e->name, "..") ||
 358            strchr(e->name, '/'))
 359                goto einval;
 360
 361        pr_debug("register: name: {%s}\n", e->name);
 362
 363        /* Parse the 'type' field. */
 364        switch (*p++) {
 365        case 'E':
 366                pr_debug("register: type: E (extension)\n");
 367                e->flags = 1 << Enabled;
 368                break;
 369        case 'M':
 370                pr_debug("register: type: M (magic)\n");
 371                e->flags = (1 << Enabled) | (1 << Magic);
 372                break;
 373        default:
 374                goto einval;
 375        }
 376        if (*p++ != del)
 377                goto einval;
 378
 379        if (test_bit(Magic, &e->flags)) {
 380                /* Handle the 'M' (magic) format. */
 381                char *s;
 382
 383                /* Parse the 'offset' field. */
 384                s = strchr(p, del);
 385                if (!s)
 386                        goto einval;
 387                *s++ = '\0';
 388                e->offset = simple_strtoul(p, &p, 10);
 389                if (*p++)
 390                        goto einval;
 391                pr_debug("register: offset: %#x\n", e->offset);
 392
 393                /* Parse the 'magic' field. */
 394                e->magic = p;
 395                p = scanarg(p, del);
 396                if (!p)
 397                        goto einval;
 398                if (!e->magic[0])
 399                        goto einval;
 400                if (USE_DEBUG)
 401                        print_hex_dump_bytes(
 402                                KBUILD_MODNAME ": register: magic[raw]: ",
 403                                DUMP_PREFIX_NONE, e->magic, p - e->magic);
 404
 405                /* Parse the 'mask' field. */
 406                e->mask = p;
 407                p = scanarg(p, del);
 408                if (!p)
 409                        goto einval;
 410                if (!e->mask[0]) {
 411                        e->mask = NULL;
 412                        pr_debug("register:  mask[raw]: none\n");
 413                } else if (USE_DEBUG)
 414                        print_hex_dump_bytes(
 415                                KBUILD_MODNAME ": register:  mask[raw]: ",
 416                                DUMP_PREFIX_NONE, e->mask, p - e->mask);
 417
 418                /*
 419                 * Decode the magic & mask fields.
 420                 * Note: while we might have accepted embedded NUL bytes from
 421                 * above, the unescape helpers here will stop at the first one
 422                 * it encounters.
 423                 */
 424                e->size = string_unescape_inplace(e->magic, UNESCAPE_HEX);
 425                if (e->mask &&
 426                    string_unescape_inplace(e->mask, UNESCAPE_HEX) != e->size)
 427                        goto einval;
 428                if (e->size + e->offset > BINPRM_BUF_SIZE)
 429                        goto einval;
 430                pr_debug("register: magic/mask length: %i\n", e->size);
 431                if (USE_DEBUG) {
 432                        print_hex_dump_bytes(
 433                                KBUILD_MODNAME ": register: magic[decoded]: ",
 434                                DUMP_PREFIX_NONE, e->magic, e->size);
 435
 436                        if (e->mask) {
 437                                int i;
 438                                char *masked = kmalloc(e->size, GFP_KERNEL);
 439
 440                                print_hex_dump_bytes(
 441                                        KBUILD_MODNAME ": register:  mask[decoded]: ",
 442                                        DUMP_PREFIX_NONE, e->mask, e->size);
 443
 444                                if (masked) {
 445                                        for (i = 0; i < e->size; ++i)
 446                                                masked[i] = e->magic[i] & e->mask[i];
 447                                        print_hex_dump_bytes(
 448                                                KBUILD_MODNAME ": register:  magic[masked]: ",
 449                                                DUMP_PREFIX_NONE, masked, e->size);
 450
 451                                        kfree(masked);
 452                                }
 453                        }
 454                }
 455        } else {
 456                /* Handle the 'E' (extension) format. */
 457
 458                /* Skip the 'offset' field. */
 459                p = strchr(p, del);
 460                if (!p)
 461                        goto einval;
 462                *p++ = '\0';
 463
 464                /* Parse the 'magic' field. */
 465                e->magic = p;
 466                p = strchr(p, del);
 467                if (!p)
 468                        goto einval;
 469                *p++ = '\0';
 470                if (!e->magic[0] || strchr(e->magic, '/'))
 471                        goto einval;
 472                pr_debug("register: extension: {%s}\n", e->magic);
 473
 474                /* Skip the 'mask' field. */
 475                p = strchr(p, del);
 476                if (!p)
 477                        goto einval;
 478                *p++ = '\0';
 479        }
 480
 481        /* Parse the 'interpreter' field. */
 482        e->interpreter = p;
 483        p = strchr(p, del);
 484        if (!p)
 485                goto einval;
 486        *p++ = '\0';
 487        if (!e->interpreter[0])
 488                goto einval;
 489        pr_debug("register: interpreter: {%s}\n", e->interpreter);
 490
 491        /* Parse the 'flags' field. */
 492        p = check_special_flags(p, e);
 493        if (*p == '\n')
 494                p++;
 495        if (p != buf + count)
 496                goto einval;
 497
 498        return e;
 499
 500out:
 501        return ERR_PTR(err);
 502
 503efault:
 504        kfree(e);
 505        return ERR_PTR(-EFAULT);
 506einval:
 507        kfree(e);
 508        return ERR_PTR(-EINVAL);
 509}
 510
 511/*
 512 * Set status of entry/binfmt_misc:
 513 * '1' enables, '0' disables and '-1' clears entry/binfmt_misc
 514 */
 515static int parse_command(const char __user *buffer, size_t count)
 516{
 517        char s[4];
 518
 519        if (count > 3)
 520                return -EINVAL;
 521        if (copy_from_user(s, buffer, count))
 522                return -EFAULT;
 523        if (!count)
 524                return 0;
 525        if (s[count - 1] == '\n')
 526                count--;
 527        if (count == 1 && s[0] == '0')
 528                return 1;
 529        if (count == 1 && s[0] == '1')
 530                return 2;
 531        if (count == 2 && s[0] == '-' && s[1] == '1')
 532                return 3;
 533        return -EINVAL;
 534}
 535
 536/* generic stuff */
 537
 538static void entry_status(Node *e, char *page)
 539{
 540        char *dp = page;
 541        const char *status = "disabled";
 542
 543        if (test_bit(Enabled, &e->flags))
 544                status = "enabled";
 545
 546        if (!VERBOSE_STATUS) {
 547                sprintf(page, "%s\n", status);
 548                return;
 549        }
 550
 551        dp += sprintf(dp, "%s\ninterpreter %s\n", status, e->interpreter);
 552
 553        /* print the special flags */
 554        dp += sprintf(dp, "flags: ");
 555        if (e->flags & MISC_FMT_PRESERVE_ARGV0)
 556                *dp++ = 'P';
 557        if (e->flags & MISC_FMT_OPEN_BINARY)
 558                *dp++ = 'O';
 559        if (e->flags & MISC_FMT_CREDENTIALS)
 560                *dp++ = 'C';
 561        if (e->flags & MISC_FMT_OPEN_FILE)
 562                *dp++ = 'F';
 563        *dp++ = '\n';
 564
 565        if (!test_bit(Magic, &e->flags)) {
 566                sprintf(dp, "extension .%s\n", e->magic);
 567        } else {
 568                dp += sprintf(dp, "offset %i\nmagic ", e->offset);
 569                dp = bin2hex(dp, e->magic, e->size);
 570                if (e->mask) {
 571                        dp += sprintf(dp, "\nmask ");
 572                        dp = bin2hex(dp, e->mask, e->size);
 573                }
 574                *dp++ = '\n';
 575                *dp = '\0';
 576        }
 577}
 578
 579static struct inode *bm_get_inode(struct super_block *sb, int mode)
 580{
 581        struct inode *inode = new_inode(sb);
 582
 583        if (inode) {
 584                inode->i_ino = get_next_ino();
 585                inode->i_mode = mode;
 586                inode->i_atime = inode->i_mtime = inode->i_ctime =
 587                        current_time(inode);
 588        }
 589        return inode;
 590}
 591
 592static void bm_evict_inode(struct inode *inode)
 593{
 594        clear_inode(inode);
 595        kfree(inode->i_private);
 596}
 597
 598static void kill_node(Node *e)
 599{
 600        struct dentry *dentry;
 601
 602        write_lock(&entries_lock);
 603        dentry = e->dentry;
 604        if (dentry) {
 605                list_del_init(&e->list);
 606                e->dentry = NULL;
 607        }
 608        write_unlock(&entries_lock);
 609
 610        if ((e->flags & MISC_FMT_OPEN_FILE) && e->interp_file) {
 611                filp_close(e->interp_file, NULL);
 612                e->interp_file = NULL;
 613        }
 614
 615        if (dentry) {
 616                drop_nlink(d_inode(dentry));
 617                d_drop(dentry);
 618                dput(dentry);
 619                simple_release_fs(&bm_mnt, &entry_count);
 620        }
 621}
 622
 623/* /<entry> */
 624
 625static ssize_t
 626bm_entry_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
 627{
 628        Node *e = file_inode(file)->i_private;
 629        ssize_t res;
 630        char *page;
 631
 632        page = (char *) __get_free_page(GFP_KERNEL);
 633        if (!page)
 634                return -ENOMEM;
 635
 636        entry_status(e, page);
 637
 638        res = simple_read_from_buffer(buf, nbytes, ppos, page, strlen(page));
 639
 640        free_page((unsigned long) page);
 641        return res;
 642}
 643
 644static ssize_t bm_entry_write(struct file *file, const char __user *buffer,
 645                                size_t count, loff_t *ppos)
 646{
 647        struct dentry *root;
 648        Node *e = file_inode(file)->i_private;
 649        int res = parse_command(buffer, count);
 650
 651        switch (res) {
 652        case 1:
 653                /* Disable this handler. */
 654                clear_bit(Enabled, &e->flags);
 655                break;
 656        case 2:
 657                /* Enable this handler. */
 658                set_bit(Enabled, &e->flags);
 659                break;
 660        case 3:
 661                /* Delete this handler. */
 662                root = file_inode(file)->i_sb->s_root;
 663                inode_lock(d_inode(root));
 664
 665                kill_node(e);
 666
 667                inode_unlock(d_inode(root));
 668                break;
 669        default:
 670                return res;
 671        }
 672
 673        return count;
 674}
 675
 676static const struct file_operations bm_entry_operations = {
 677        .read           = bm_entry_read,
 678        .write          = bm_entry_write,
 679        .llseek         = default_llseek,
 680};
 681
 682/* /register */
 683
 684static ssize_t bm_register_write(struct file *file, const char __user *buffer,
 685                               size_t count, loff_t *ppos)
 686{
 687        Node *e;
 688        struct inode *inode;
 689        struct super_block *sb = file_inode(file)->i_sb;
 690        struct dentry *root = sb->s_root, *dentry;
 691        int err = 0;
 692
 693        e = create_entry(buffer, count);
 694
 695        if (IS_ERR(e))
 696                return PTR_ERR(e);
 697
 698        inode_lock(d_inode(root));
 699        dentry = lookup_one_len(e->name, root, strlen(e->name));
 700        err = PTR_ERR(dentry);
 701        if (IS_ERR(dentry))
 702                goto out;
 703
 704        err = -EEXIST;
 705        if (d_really_is_positive(dentry))
 706                goto out2;
 707
 708        inode = bm_get_inode(sb, S_IFREG | 0644);
 709
 710        err = -ENOMEM;
 711        if (!inode)
 712                goto out2;
 713
 714        err = simple_pin_fs(&bm_fs_type, &bm_mnt, &entry_count);
 715        if (err) {
 716                iput(inode);
 717                inode = NULL;
 718                goto out2;
 719        }
 720
 721        if (e->flags & MISC_FMT_OPEN_FILE) {
 722                struct file *f;
 723
 724                f = open_exec(e->interpreter);
 725                if (IS_ERR(f)) {
 726                        err = PTR_ERR(f);
 727                        pr_notice("register: failed to install interpreter file %s\n", e->interpreter);
 728                        simple_release_fs(&bm_mnt, &entry_count);
 729                        iput(inode);
 730                        inode = NULL;
 731                        goto out2;
 732                }
 733                e->interp_file = f;
 734        }
 735
 736        e->dentry = dget(dentry);
 737        inode->i_private = e;
 738        inode->i_fop = &bm_entry_operations;
 739
 740        d_instantiate(dentry, inode);
 741        write_lock(&entries_lock);
 742        list_add(&e->list, &entries);
 743        write_unlock(&entries_lock);
 744
 745        err = 0;
 746out2:
 747        dput(dentry);
 748out:
 749        inode_unlock(d_inode(root));
 750
 751        if (err) {
 752                kfree(e);
 753                return err;
 754        }
 755        return count;
 756}
 757
 758static const struct file_operations bm_register_operations = {
 759        .write          = bm_register_write,
 760        .llseek         = noop_llseek,
 761};
 762
 763/* /status */
 764
 765static ssize_t
 766bm_status_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
 767{
 768        char *s = enabled ? "enabled\n" : "disabled\n";
 769
 770        return simple_read_from_buffer(buf, nbytes, ppos, s, strlen(s));
 771}
 772
 773static ssize_t bm_status_write(struct file *file, const char __user *buffer,
 774                size_t count, loff_t *ppos)
 775{
 776        int res = parse_command(buffer, count);
 777        struct dentry *root;
 778
 779        switch (res) {
 780        case 1:
 781                /* Disable all handlers. */
 782                enabled = 0;
 783                break;
 784        case 2:
 785                /* Enable all handlers. */
 786                enabled = 1;
 787                break;
 788        case 3:
 789                /* Delete all handlers. */
 790                root = file_inode(file)->i_sb->s_root;
 791                inode_lock(d_inode(root));
 792
 793                while (!list_empty(&entries))
 794                        kill_node(list_entry(entries.next, Node, list));
 795
 796                inode_unlock(d_inode(root));
 797                break;
 798        default:
 799                return res;
 800        }
 801
 802        return count;
 803}
 804
 805static const struct file_operations bm_status_operations = {
 806        .read           = bm_status_read,
 807        .write          = bm_status_write,
 808        .llseek         = default_llseek,
 809};
 810
 811/* Superblock handling */
 812
 813static const struct super_operations s_ops = {
 814        .statfs         = simple_statfs,
 815        .evict_inode    = bm_evict_inode,
 816};
 817
 818static int bm_fill_super(struct super_block *sb, void *data, int silent)
 819{
 820        int err;
 821        static struct tree_descr bm_files[] = {
 822                [2] = {"status", &bm_status_operations, S_IWUSR|S_IRUGO},
 823                [3] = {"register", &bm_register_operations, S_IWUSR},
 824                /* last one */ {""}
 825        };
 826
 827        err = simple_fill_super(sb, BINFMTFS_MAGIC, bm_files);
 828        if (!err)
 829                sb->s_op = &s_ops;
 830        return err;
 831}
 832
 833static struct dentry *bm_mount(struct file_system_type *fs_type,
 834        int flags, const char *dev_name, void *data)
 835{
 836        return mount_single(fs_type, flags, data, bm_fill_super);
 837}
 838
 839static struct linux_binfmt misc_format = {
 840        .module = THIS_MODULE,
 841        .load_binary = load_misc_binary,
 842};
 843
 844static struct file_system_type bm_fs_type = {
 845        .owner          = THIS_MODULE,
 846        .name           = "binfmt_misc",
 847        .mount          = bm_mount,
 848        .kill_sb        = kill_litter_super,
 849};
 850MODULE_ALIAS_FS("binfmt_misc");
 851
 852static int __init init_misc_binfmt(void)
 853{
 854        int err = register_filesystem(&bm_fs_type);
 855        if (!err)
 856                insert_binfmt(&misc_format);
 857        return err;
 858}
 859
 860static void __exit exit_misc_binfmt(void)
 861{
 862        unregister_binfmt(&misc_format);
 863        unregister_filesystem(&bm_fs_type);
 864}
 865
 866core_initcall(init_misc_binfmt);
 867module_exit(exit_misc_binfmt);
 868MODULE_LICENSE("GPL");
 869