Back to home page

OSCL-LXR

 
 

    


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