Back to home page

LXR

 
 

    


0001 /*
0002  * binfmt_misc.c
0003  *
0004  * Copyright (C) 1997 Richard G√ľnther
0005  *
0006  * binfmt_misc detects binaries via a magic or filename extension and invokes
0007  * a specified wrapper. See Documentation/binfmt_misc.txt for more details.
0008  */
0009 
0010 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0011 
0012 #include <linux/kernel.h>
0013 #include <linux/module.h>
0014 #include <linux/init.h>
0015 #include <linux/sched.h>
0016 #include <linux/magic.h>
0017 #include <linux/binfmts.h>
0018 #include <linux/slab.h>
0019 #include <linux/ctype.h>
0020 #include <linux/string_helpers.h>
0021 #include <linux/file.h>
0022 #include <linux/pagemap.h>
0023 #include <linux/namei.h>
0024 #include <linux/mount.h>
0025 #include <linux/syscalls.h>
0026 #include <linux/fs.h>
0027 #include <linux/uaccess.h>
0028 
0029 #include "internal.h"
0030 
0031 #ifdef DEBUG
0032 # define USE_DEBUG 1
0033 #else
0034 # define USE_DEBUG 0
0035 #endif
0036 
0037 enum {
0038     VERBOSE_STATUS = 1 /* make it zero to save 400 bytes kernel memory */
0039 };
0040 
0041 static LIST_HEAD(entries);
0042 static int enabled = 1;
0043 
0044 enum {Enabled, Magic};
0045 #define MISC_FMT_PRESERVE_ARGV0 (1 << 31)
0046 #define MISC_FMT_OPEN_BINARY (1 << 30)
0047 #define MISC_FMT_CREDENTIALS (1 << 29)
0048 #define MISC_FMT_OPEN_FILE (1 << 28)
0049 
0050 typedef struct {
0051     struct list_head list;
0052     unsigned long flags;        /* type, status, etc. */
0053     int offset;         /* offset of magic */
0054     int size;           /* size of magic/mask */
0055     char *magic;            /* magic or filename extension */
0056     char *mask;         /* mask, NULL for exact match */
0057     char *interpreter;      /* filename of interpreter */
0058     char *name;
0059     struct dentry *dentry;
0060     struct file *interp_file;
0061 } Node;
0062 
0063 static DEFINE_RWLOCK(entries_lock);
0064 static struct file_system_type bm_fs_type;
0065 static struct vfsmount *bm_mnt;
0066 static int entry_count;
0067 
0068 /*
0069  * Max length of the register string.  Determined by:
0070  *  - 7 delimiters
0071  *  - name:   ~50 bytes
0072  *  - type:   1 byte
0073  *  - offset: 3 bytes (has to be smaller than BINPRM_BUF_SIZE)
0074  *  - magic:  128 bytes (512 in escaped form)
0075  *  - mask:   128 bytes (512 in escaped form)
0076  *  - interp: ~50 bytes
0077  *  - flags:  5 bytes
0078  * Round that up a bit, and then back off to hold the internal data
0079  * (like struct Node).
0080  */
0081 #define MAX_REGISTER_LENGTH 1920
0082 
0083 /*
0084  * Check if we support the binfmt
0085  * if we do, return the node, else NULL
0086  * locking is done in load_misc_binary
0087  */
0088 static Node *check_file(struct linux_binprm *bprm)
0089 {
0090     char *p = strrchr(bprm->interp, '.');
0091     struct list_head *l;
0092 
0093     /* Walk all the registered handlers. */
0094     list_for_each(l, &entries) {
0095         Node *e = list_entry(l, Node, list);
0096         char *s;
0097         int j;
0098 
0099         /* Make sure this one is currently enabled. */
0100         if (!test_bit(Enabled, &e->flags))
0101             continue;
0102 
0103         /* Do matching based on extension if applicable. */
0104         if (!test_bit(Magic, &e->flags)) {
0105             if (p && !strcmp(e->magic, p + 1))
0106                 return e;
0107             continue;
0108         }
0109 
0110         /* Do matching based on magic & mask. */
0111         s = bprm->buf + e->offset;
0112         if (e->mask) {
0113             for (j = 0; j < e->size; j++)
0114                 if ((*s++ ^ e->magic[j]) & e->mask[j])
0115                     break;
0116         } else {
0117             for (j = 0; j < e->size; j++)
0118                 if ((*s++ ^ e->magic[j]))
0119                     break;
0120         }
0121         if (j == e->size)
0122             return e;
0123     }
0124     return NULL;
0125 }
0126 
0127 /*
0128  * the loader itself
0129  */
0130 static int load_misc_binary(struct linux_binprm *bprm)
0131 {
0132     Node *fmt;
0133     struct file *interp_file = NULL;
0134     char iname[BINPRM_BUF_SIZE];
0135     const char *iname_addr = iname;
0136     int retval;
0137     int fd_binary = -1;
0138 
0139     retval = -ENOEXEC;
0140     if (!enabled)
0141         goto ret;
0142 
0143     /* to keep locking time low, we copy the interpreter string */
0144     read_lock(&entries_lock);
0145     fmt = check_file(bprm);
0146     if (fmt)
0147         strlcpy(iname, fmt->interpreter, BINPRM_BUF_SIZE);
0148     read_unlock(&entries_lock);
0149     if (!fmt)
0150         goto ret;
0151 
0152     /* Need to be able to load the file after exec */
0153     if (bprm->interp_flags & BINPRM_FLAGS_PATH_INACCESSIBLE)
0154         return -ENOENT;
0155 
0156     if (!(fmt->flags & MISC_FMT_PRESERVE_ARGV0)) {
0157         retval = remove_arg_zero(bprm);
0158         if (retval)
0159             goto ret;
0160     }
0161 
0162     if (fmt->flags & MISC_FMT_OPEN_BINARY) {
0163 
0164         /* if the binary should be opened on behalf of the
0165          * interpreter than keep it open and assign descriptor
0166          * to it
0167          */
0168         fd_binary = get_unused_fd_flags(0);
0169         if (fd_binary < 0) {
0170             retval = fd_binary;
0171             goto ret;
0172         }
0173         fd_install(fd_binary, bprm->file);
0174 
0175         /* if the binary is not readable than enforce mm->dumpable=0
0176            regardless of the interpreter's permissions */
0177         would_dump(bprm, bprm->file);
0178 
0179         allow_write_access(bprm->file);
0180         bprm->file = NULL;
0181 
0182         /* mark the bprm that fd should be passed to interp */
0183         bprm->interp_flags |= BINPRM_FLAGS_EXECFD;
0184         bprm->interp_data = fd_binary;
0185 
0186     } else {
0187         allow_write_access(bprm->file);
0188         fput(bprm->file);
0189         bprm->file = NULL;
0190     }
0191     /* make argv[1] be the path to the binary */
0192     retval = copy_strings_kernel(1, &bprm->interp, bprm);
0193     if (retval < 0)
0194         goto error;
0195     bprm->argc++;
0196 
0197     /* add the interp as argv[0] */
0198     retval = copy_strings_kernel(1, &iname_addr, bprm);
0199     if (retval < 0)
0200         goto error;
0201     bprm->argc++;
0202 
0203     /* Update interp in case binfmt_script needs it. */
0204     retval = bprm_change_interp(iname, bprm);
0205     if (retval < 0)
0206         goto error;
0207 
0208     if (fmt->flags & MISC_FMT_OPEN_FILE && fmt->interp_file) {
0209         interp_file = filp_clone_open(fmt->interp_file);
0210         if (!IS_ERR(interp_file))
0211             deny_write_access(interp_file);
0212     } else {
0213         interp_file = open_exec(iname);
0214     }
0215     retval = PTR_ERR(interp_file);
0216     if (IS_ERR(interp_file))
0217         goto error;
0218 
0219     bprm->file = interp_file;
0220     if (fmt->flags & MISC_FMT_CREDENTIALS) {
0221         /*
0222          * No need to call prepare_binprm(), it's already been
0223          * done.  bprm->buf is stale, update from interp_file.
0224          */
0225         memset(bprm->buf, 0, BINPRM_BUF_SIZE);
0226         retval = kernel_read(bprm->file, 0, bprm->buf, BINPRM_BUF_SIZE);
0227     } else
0228         retval = prepare_binprm(bprm);
0229 
0230     if (retval < 0)
0231         goto error;
0232 
0233     retval = search_binary_handler(bprm);
0234     if (retval < 0)
0235         goto error;
0236 
0237 ret:
0238     return retval;
0239 error:
0240     if (fd_binary > 0)
0241         sys_close(fd_binary);
0242     bprm->interp_flags = 0;
0243     bprm->interp_data = 0;
0244     goto ret;
0245 }
0246 
0247 /* Command parsers */
0248 
0249 /*
0250  * parses and copies one argument enclosed in del from *sp to *dp,
0251  * recognising the \x special.
0252  * returns pointer to the copied argument or NULL in case of an
0253  * error (and sets err) or null argument length.
0254  */
0255 static char *scanarg(char *s, char del)
0256 {
0257     char c;
0258 
0259     while ((c = *s++) != del) {
0260         if (c == '\\' && *s == 'x') {
0261             s++;
0262             if (!isxdigit(*s++))
0263                 return NULL;
0264             if (!isxdigit(*s++))
0265                 return NULL;
0266         }
0267     }
0268     s[-1] ='\0';
0269     return s;
0270 }
0271 
0272 static char *check_special_flags(char *sfs, Node *e)
0273 {
0274     char *p = sfs;
0275     int cont = 1;
0276 
0277     /* special flags */
0278     while (cont) {
0279         switch (*p) {
0280         case 'P':
0281             pr_debug("register: flag: P (preserve argv0)\n");
0282             p++;
0283             e->flags |= MISC_FMT_PRESERVE_ARGV0;
0284             break;
0285         case 'O':
0286             pr_debug("register: flag: O (open binary)\n");
0287             p++;
0288             e->flags |= MISC_FMT_OPEN_BINARY;
0289             break;
0290         case 'C':
0291             pr_debug("register: flag: C (preserve creds)\n");
0292             p++;
0293             /* this flags also implies the
0294                open-binary flag */
0295             e->flags |= (MISC_FMT_CREDENTIALS |
0296                     MISC_FMT_OPEN_BINARY);
0297             break;
0298         case 'F':
0299             pr_debug("register: flag: F: open interpreter file now\n");
0300             p++;
0301             e->flags |= MISC_FMT_OPEN_FILE;
0302             break;
0303         default:
0304             cont = 0;
0305         }
0306     }
0307 
0308     return p;
0309 }
0310 
0311 /*
0312  * This registers a new binary format, it recognises the syntax
0313  * ':name:type:offset:magic:mask:interpreter:flags'
0314  * where the ':' is the IFS, that can be chosen with the first char
0315  */
0316 static Node *create_entry(const char __user *buffer, size_t count)
0317 {
0318     Node *e;
0319     int memsize, err;
0320     char *buf, *p;
0321     char del;
0322 
0323     pr_debug("register: received %zu bytes\n", count);
0324 
0325     /* some sanity checks */
0326     err = -EINVAL;
0327     if ((count < 11) || (count > MAX_REGISTER_LENGTH))
0328         goto out;
0329 
0330     err = -ENOMEM;
0331     memsize = sizeof(Node) + count + 8;
0332     e = kmalloc(memsize, GFP_KERNEL);
0333     if (!e)
0334         goto out;
0335 
0336     p = buf = (char *)e + sizeof(Node);
0337 
0338     memset(e, 0, sizeof(Node));
0339     if (copy_from_user(buf, buffer, count))
0340         goto efault;
0341 
0342     del = *p++; /* delimeter */
0343 
0344     pr_debug("register: delim: %#x {%c}\n", del, del);
0345 
0346     /* Pad the buffer with the delim to simplify parsing below. */
0347     memset(buf + count, del, 8);
0348 
0349     /* Parse the 'name' field. */
0350     e->name = p;
0351     p = strchr(p, del);
0352     if (!p)
0353         goto einval;
0354     *p++ = '\0';
0355     if (!e->name[0] ||
0356         !strcmp(e->name, ".") ||
0357         !strcmp(e->name, "..") ||
0358         strchr(e->name, '/'))
0359         goto einval;
0360 
0361     pr_debug("register: name: {%s}\n", e->name);
0362 
0363     /* Parse the 'type' field. */
0364     switch (*p++) {
0365     case 'E':
0366         pr_debug("register: type: E (extension)\n");
0367         e->flags = 1 << Enabled;
0368         break;
0369     case 'M':
0370         pr_debug("register: type: M (magic)\n");
0371         e->flags = (1 << Enabled) | (1 << Magic);
0372         break;
0373     default:
0374         goto einval;
0375     }
0376     if (*p++ != del)
0377         goto einval;
0378 
0379     if (test_bit(Magic, &e->flags)) {
0380         /* Handle the 'M' (magic) format. */
0381         char *s;
0382 
0383         /* Parse the 'offset' field. */
0384         s = strchr(p, del);
0385         if (!s)
0386             goto einval;
0387         *s++ = '\0';
0388         e->offset = simple_strtoul(p, &p, 10);
0389         if (*p++)
0390             goto einval;
0391         pr_debug("register: offset: %#x\n", e->offset);
0392 
0393         /* Parse the 'magic' field. */
0394         e->magic = p;
0395         p = scanarg(p, del);
0396         if (!p)
0397             goto einval;
0398         if (!e->magic[0])
0399             goto einval;
0400         if (USE_DEBUG)
0401             print_hex_dump_bytes(
0402                 KBUILD_MODNAME ": register: magic[raw]: ",
0403                 DUMP_PREFIX_NONE, e->magic, p - e->magic);
0404 
0405         /* Parse the 'mask' field. */
0406         e->mask = p;
0407         p = scanarg(p, del);
0408         if (!p)
0409             goto einval;
0410         if (!e->mask[0]) {
0411             e->mask = NULL;
0412             pr_debug("register:  mask[raw]: none\n");
0413         } else if (USE_DEBUG)
0414             print_hex_dump_bytes(
0415                 KBUILD_MODNAME ": register:  mask[raw]: ",
0416                 DUMP_PREFIX_NONE, e->mask, p - e->mask);
0417 
0418         /*
0419          * Decode the magic & mask fields.
0420          * Note: while we might have accepted embedded NUL bytes from
0421          * above, the unescape helpers here will stop at the first one
0422          * it encounters.
0423          */
0424         e->size = string_unescape_inplace(e->magic, UNESCAPE_HEX);
0425         if (e->mask &&
0426             string_unescape_inplace(e->mask, UNESCAPE_HEX) != e->size)
0427             goto einval;
0428         if (e->size + e->offset > BINPRM_BUF_SIZE)
0429             goto einval;
0430         pr_debug("register: magic/mask length: %i\n", e->size);
0431         if (USE_DEBUG) {
0432             print_hex_dump_bytes(
0433                 KBUILD_MODNAME ": register: magic[decoded]: ",
0434                 DUMP_PREFIX_NONE, e->magic, e->size);
0435 
0436             if (e->mask) {
0437                 int i;
0438                 char *masked = kmalloc(e->size, GFP_KERNEL);
0439 
0440                 print_hex_dump_bytes(
0441                     KBUILD_MODNAME ": register:  mask[decoded]: ",
0442                     DUMP_PREFIX_NONE, e->mask, e->size);
0443 
0444                 if (masked) {
0445                     for (i = 0; i < e->size; ++i)
0446                         masked[i] = e->magic[i] & e->mask[i];
0447                     print_hex_dump_bytes(
0448                         KBUILD_MODNAME ": register:  magic[masked]: ",
0449                         DUMP_PREFIX_NONE, masked, e->size);
0450 
0451                     kfree(masked);
0452                 }
0453             }
0454         }
0455     } else {
0456         /* Handle the 'E' (extension) format. */
0457 
0458         /* Skip the 'offset' field. */
0459         p = strchr(p, del);
0460         if (!p)
0461             goto einval;
0462         *p++ = '\0';
0463 
0464         /* Parse the 'magic' field. */
0465         e->magic = p;
0466         p = strchr(p, del);
0467         if (!p)
0468             goto einval;
0469         *p++ = '\0';
0470         if (!e->magic[0] || strchr(e->magic, '/'))
0471             goto einval;
0472         pr_debug("register: extension: {%s}\n", e->magic);
0473 
0474         /* Skip the 'mask' field. */
0475         p = strchr(p, del);
0476         if (!p)
0477             goto einval;
0478         *p++ = '\0';
0479     }
0480 
0481     /* Parse the 'interpreter' field. */
0482     e->interpreter = p;
0483     p = strchr(p, del);
0484     if (!p)
0485         goto einval;
0486     *p++ = '\0';
0487     if (!e->interpreter[0])
0488         goto einval;
0489     pr_debug("register: interpreter: {%s}\n", e->interpreter);
0490 
0491     /* Parse the 'flags' field. */
0492     p = check_special_flags(p, e);
0493     if (*p == '\n')
0494         p++;
0495     if (p != buf + count)
0496         goto einval;
0497 
0498     return e;
0499 
0500 out:
0501     return ERR_PTR(err);
0502 
0503 efault:
0504     kfree(e);
0505     return ERR_PTR(-EFAULT);
0506 einval:
0507     kfree(e);
0508     return ERR_PTR(-EINVAL);
0509 }
0510 
0511 /*
0512  * Set status of entry/binfmt_misc:
0513  * '1' enables, '0' disables and '-1' clears entry/binfmt_misc
0514  */
0515 static int parse_command(const char __user *buffer, size_t count)
0516 {
0517     char s[4];
0518 
0519     if (count > 3)
0520         return -EINVAL;
0521     if (copy_from_user(s, buffer, count))
0522         return -EFAULT;
0523     if (!count)
0524         return 0;
0525     if (s[count - 1] == '\n')
0526         count--;
0527     if (count == 1 && s[0] == '0')
0528         return 1;
0529     if (count == 1 && s[0] == '1')
0530         return 2;
0531     if (count == 2 && s[0] == '-' && s[1] == '1')
0532         return 3;
0533     return -EINVAL;
0534 }
0535 
0536 /* generic stuff */
0537 
0538 static void entry_status(Node *e, char *page)
0539 {
0540     char *dp = page;
0541     const char *status = "disabled";
0542 
0543     if (test_bit(Enabled, &e->flags))
0544         status = "enabled";
0545 
0546     if (!VERBOSE_STATUS) {
0547         sprintf(page, "%s\n", status);
0548         return;
0549     }
0550 
0551     dp += sprintf(dp, "%s\ninterpreter %s\n", status, e->interpreter);
0552 
0553     /* print the special flags */
0554     dp += sprintf(dp, "flags: ");
0555     if (e->flags & MISC_FMT_PRESERVE_ARGV0)
0556         *dp++ = 'P';
0557     if (e->flags & MISC_FMT_OPEN_BINARY)
0558         *dp++ = 'O';
0559     if (e->flags & MISC_FMT_CREDENTIALS)
0560         *dp++ = 'C';
0561     if (e->flags & MISC_FMT_OPEN_FILE)
0562         *dp++ = 'F';
0563     *dp++ = '\n';
0564 
0565     if (!test_bit(Magic, &e->flags)) {
0566         sprintf(dp, "extension .%s\n", e->magic);
0567     } else {
0568         dp += sprintf(dp, "offset %i\nmagic ", e->offset);
0569         dp = bin2hex(dp, e->magic, e->size);
0570         if (e->mask) {
0571             dp += sprintf(dp, "\nmask ");
0572             dp = bin2hex(dp, e->mask, e->size);
0573         }
0574         *dp++ = '\n';
0575         *dp = '\0';
0576     }
0577 }
0578 
0579 static struct inode *bm_get_inode(struct super_block *sb, int mode)
0580 {
0581     struct inode *inode = new_inode(sb);
0582 
0583     if (inode) {
0584         inode->i_ino = get_next_ino();
0585         inode->i_mode = mode;
0586         inode->i_atime = inode->i_mtime = inode->i_ctime =
0587             current_time(inode);
0588     }
0589     return inode;
0590 }
0591 
0592 static void bm_evict_inode(struct inode *inode)
0593 {
0594     clear_inode(inode);
0595     kfree(inode->i_private);
0596 }
0597 
0598 static void kill_node(Node *e)
0599 {
0600     struct dentry *dentry;
0601 
0602     write_lock(&entries_lock);
0603     dentry = e->dentry;
0604     if (dentry) {
0605         list_del_init(&e->list);
0606         e->dentry = NULL;
0607     }
0608     write_unlock(&entries_lock);
0609 
0610     if ((e->flags & MISC_FMT_OPEN_FILE) && e->interp_file) {
0611         filp_close(e->interp_file, NULL);
0612         e->interp_file = NULL;
0613     }
0614 
0615     if (dentry) {
0616         drop_nlink(d_inode(dentry));
0617         d_drop(dentry);
0618         dput(dentry);
0619         simple_release_fs(&bm_mnt, &entry_count);
0620     }
0621 }
0622 
0623 /* /<entry> */
0624 
0625 static ssize_t
0626 bm_entry_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
0627 {
0628     Node *e = file_inode(file)->i_private;
0629     ssize_t res;
0630     char *page;
0631 
0632     page = (char *) __get_free_page(GFP_KERNEL);
0633     if (!page)
0634         return -ENOMEM;
0635 
0636     entry_status(e, page);
0637 
0638     res = simple_read_from_buffer(buf, nbytes, ppos, page, strlen(page));
0639 
0640     free_page((unsigned long) page);
0641     return res;
0642 }
0643 
0644 static ssize_t bm_entry_write(struct file *file, const char __user *buffer,
0645                 size_t count, loff_t *ppos)
0646 {
0647     struct dentry *root;
0648     Node *e = file_inode(file)->i_private;
0649     int res = parse_command(buffer, count);
0650 
0651     switch (res) {
0652     case 1:
0653         /* Disable this handler. */
0654         clear_bit(Enabled, &e->flags);
0655         break;
0656     case 2:
0657         /* Enable this handler. */
0658         set_bit(Enabled, &e->flags);
0659         break;
0660     case 3:
0661         /* Delete this handler. */
0662         root = file_inode(file)->i_sb->s_root;
0663         inode_lock(d_inode(root));
0664 
0665         kill_node(e);
0666 
0667         inode_unlock(d_inode(root));
0668         break;
0669     default:
0670         return res;
0671     }
0672 
0673     return count;
0674 }
0675 
0676 static const struct file_operations bm_entry_operations = {
0677     .read       = bm_entry_read,
0678     .write      = bm_entry_write,
0679     .llseek     = default_llseek,
0680 };
0681 
0682 /* /register */
0683 
0684 static ssize_t bm_register_write(struct file *file, const char __user *buffer,
0685                    size_t count, loff_t *ppos)
0686 {
0687     Node *e;
0688     struct inode *inode;
0689     struct super_block *sb = file_inode(file)->i_sb;
0690     struct dentry *root = sb->s_root, *dentry;
0691     int err = 0;
0692 
0693     e = create_entry(buffer, count);
0694 
0695     if (IS_ERR(e))
0696         return PTR_ERR(e);
0697 
0698     inode_lock(d_inode(root));
0699     dentry = lookup_one_len(e->name, root, strlen(e->name));
0700     err = PTR_ERR(dentry);
0701     if (IS_ERR(dentry))
0702         goto out;
0703 
0704     err = -EEXIST;
0705     if (d_really_is_positive(dentry))
0706         goto out2;
0707 
0708     inode = bm_get_inode(sb, S_IFREG | 0644);
0709 
0710     err = -ENOMEM;
0711     if (!inode)
0712         goto out2;
0713 
0714     err = simple_pin_fs(&bm_fs_type, &bm_mnt, &entry_count);
0715     if (err) {
0716         iput(inode);
0717         inode = NULL;
0718         goto out2;
0719     }
0720 
0721     if (e->flags & MISC_FMT_OPEN_FILE) {
0722         struct file *f;
0723 
0724         f = open_exec(e->interpreter);
0725         if (IS_ERR(f)) {
0726             err = PTR_ERR(f);
0727             pr_notice("register: failed to install interpreter file %s\n", e->interpreter);
0728             simple_release_fs(&bm_mnt, &entry_count);
0729             iput(inode);
0730             inode = NULL;
0731             goto out2;
0732         }
0733         e->interp_file = f;
0734     }
0735 
0736     e->dentry = dget(dentry);
0737     inode->i_private = e;
0738     inode->i_fop = &bm_entry_operations;
0739 
0740     d_instantiate(dentry, inode);
0741     write_lock(&entries_lock);
0742     list_add(&e->list, &entries);
0743     write_unlock(&entries_lock);
0744 
0745     err = 0;
0746 out2:
0747     dput(dentry);
0748 out:
0749     inode_unlock(d_inode(root));
0750 
0751     if (err) {
0752         kfree(e);
0753         return err;
0754     }
0755     return count;
0756 }
0757 
0758 static const struct file_operations bm_register_operations = {
0759     .write      = bm_register_write,
0760     .llseek     = noop_llseek,
0761 };
0762 
0763 /* /status */
0764 
0765 static ssize_t
0766 bm_status_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
0767 {
0768     char *s = enabled ? "enabled\n" : "disabled\n";
0769 
0770     return simple_read_from_buffer(buf, nbytes, ppos, s, strlen(s));
0771 }
0772 
0773 static ssize_t bm_status_write(struct file *file, const char __user *buffer,
0774         size_t count, loff_t *ppos)
0775 {
0776     int res = parse_command(buffer, count);
0777     struct dentry *root;
0778 
0779     switch (res) {
0780     case 1:
0781         /* Disable all handlers. */
0782         enabled = 0;
0783         break;
0784     case 2:
0785         /* Enable all handlers. */
0786         enabled = 1;
0787         break;
0788     case 3:
0789         /* Delete all handlers. */
0790         root = file_inode(file)->i_sb->s_root;
0791         inode_lock(d_inode(root));
0792 
0793         while (!list_empty(&entries))
0794             kill_node(list_entry(entries.next, Node, list));
0795 
0796         inode_unlock(d_inode(root));
0797         break;
0798     default:
0799         return res;
0800     }
0801 
0802     return count;
0803 }
0804 
0805 static const struct file_operations bm_status_operations = {
0806     .read       = bm_status_read,
0807     .write      = bm_status_write,
0808     .llseek     = default_llseek,
0809 };
0810 
0811 /* Superblock handling */
0812 
0813 static const struct super_operations s_ops = {
0814     .statfs     = simple_statfs,
0815     .evict_inode    = bm_evict_inode,
0816 };
0817 
0818 static int bm_fill_super(struct super_block *sb, void *data, int silent)
0819 {
0820     int err;
0821     static struct tree_descr bm_files[] = {
0822         [2] = {"status", &bm_status_operations, S_IWUSR|S_IRUGO},
0823         [3] = {"register", &bm_register_operations, S_IWUSR},
0824         /* last one */ {""}
0825     };
0826 
0827     err = simple_fill_super(sb, BINFMTFS_MAGIC, bm_files);
0828     if (!err)
0829         sb->s_op = &s_ops;
0830     return err;
0831 }
0832 
0833 static struct dentry *bm_mount(struct file_system_type *fs_type,
0834     int flags, const char *dev_name, void *data)
0835 {
0836     return mount_single(fs_type, flags, data, bm_fill_super);
0837 }
0838 
0839 static struct linux_binfmt misc_format = {
0840     .module = THIS_MODULE,
0841     .load_binary = load_misc_binary,
0842 };
0843 
0844 static struct file_system_type bm_fs_type = {
0845     .owner      = THIS_MODULE,
0846     .name       = "binfmt_misc",
0847     .mount      = bm_mount,
0848     .kill_sb    = kill_litter_super,
0849 };
0850 MODULE_ALIAS_FS("binfmt_misc");
0851 
0852 static int __init init_misc_binfmt(void)
0853 {
0854     int err = register_filesystem(&bm_fs_type);
0855     if (!err)
0856         insert_binfmt(&misc_format);
0857     return err;
0858 }
0859 
0860 static void __exit exit_misc_binfmt(void)
0861 {
0862     unregister_binfmt(&misc_format);
0863     unregister_filesystem(&bm_fs_type);
0864 }
0865 
0866 core_initcall(init_misc_binfmt);
0867 module_exit(exit_misc_binfmt);
0868 MODULE_LICENSE("GPL");