The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/fs/binfmt_misc.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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. This should obsolete binfmt_java, binfmt_em86 and
    8  *  binfmt_mz.
    9  *
   10  *  1997-04-25 first version
   11  *  [...]
   12  *  1997-05-19 cleanup
   13  *  1997-06-26 hpa: pass the real filename rather than argv[0]
   14  *  1997-06-30 minor cleanup
   15  *  1997-08-09 removed extension stripping, locking cleanup
   16  *  2001-02-28 AV: rewritten into something that resembles C. Original didn't.
   17  */
   18 
   19 #include <linux/module.h>
   20 #include <linux/init.h>
   21 #include <linux/sched.h>
   22 #include <linux/magic.h>
   23 #include <linux/binfmts.h>
   24 #include <linux/slab.h>
   25 #include <linux/ctype.h>
   26 #include <linux/file.h>
   27 #include <linux/pagemap.h>
   28 #include <linux/namei.h>
   29 #include <linux/mount.h>
   30 #include <linux/syscalls.h>
   31 #include <linux/fs.h>
   32 
   33 #include <asm/uaccess.h>
   34 
   35 enum {
   36         VERBOSE_STATUS = 1 /* make it zero to save 400 bytes kernel memory */
   37 };
   38 
   39 static LIST_HEAD(entries);
   40 static int enabled = 1;
   41 
   42 enum {Enabled, Magic};
   43 #define MISC_FMT_PRESERVE_ARGV0 (1<<31)
   44 #define MISC_FMT_OPEN_BINARY (1<<30)
   45 #define MISC_FMT_CREDENTIALS (1<<29)
   46 
   47 typedef struct {
   48         struct list_head list;
   49         unsigned long flags;            /* type, status, etc. */
   50         int offset;                     /* offset of magic */
   51         int size;                       /* size of magic/mask */
   52         char *magic;                    /* magic or filename extension */
   53         char *mask;                     /* mask, NULL for exact match */
   54         char *interpreter;              /* filename of interpreter */
   55         char *name;
   56         struct dentry *dentry;
   57 } Node;
   58 
   59 static DEFINE_RWLOCK(entries_lock);
   60 static struct file_system_type bm_fs_type;
   61 static struct vfsmount *bm_mnt;
   62 static int entry_count;
   63 
   64 /* 
   65  * Check if we support the binfmt
   66  * if we do, return the node, else NULL
   67  * locking is done in load_misc_binary
   68  */
   69 static Node *check_file(struct linux_binprm *bprm)
   70 {
   71         char *p = strrchr(bprm->interp, '.');
   72         struct list_head *l;
   73 
   74         list_for_each(l, &entries) {
   75                 Node *e = list_entry(l, Node, list);
   76                 char *s;
   77                 int j;
   78 
   79                 if (!test_bit(Enabled, &e->flags))
   80                         continue;
   81 
   82                 if (!test_bit(Magic, &e->flags)) {
   83                         if (p && !strcmp(e->magic, p + 1))
   84                                 return e;
   85                         continue;
   86                 }
   87 
   88                 s = bprm->buf + e->offset;
   89                 if (e->mask) {
   90                         for (j = 0; j < e->size; j++)
   91                                 if ((*s++ ^ e->magic[j]) & e->mask[j])
   92                                         break;
   93                 } else {
   94                         for (j = 0; j < e->size; j++)
   95                                 if ((*s++ ^ e->magic[j]))
   96                                         break;
   97                 }
   98                 if (j == e->size)
   99                         return e;
  100         }
  101         return NULL;
  102 }
  103 
  104 /*
  105  * the loader itself
  106  */
  107 static int load_misc_binary(struct linux_binprm *bprm)
  108 {
  109         Node *fmt;
  110         struct file * interp_file = NULL;
  111         char iname[BINPRM_BUF_SIZE];
  112         const char *iname_addr = iname;
  113         int retval;
  114         int fd_binary = -1;
  115 
  116         retval = -ENOEXEC;
  117         if (!enabled)
  118                 goto _ret;
  119 
  120         /* to keep locking time low, we copy the interpreter string */
  121         read_lock(&entries_lock);
  122         fmt = check_file(bprm);
  123         if (fmt)
  124                 strlcpy(iname, fmt->interpreter, BINPRM_BUF_SIZE);
  125         read_unlock(&entries_lock);
  126         if (!fmt)
  127                 goto _ret;
  128 
  129         if (!(fmt->flags & MISC_FMT_PRESERVE_ARGV0)) {
  130                 retval = remove_arg_zero(bprm);
  131                 if (retval)
  132                         goto _ret;
  133         }
  134 
  135         if (fmt->flags & MISC_FMT_OPEN_BINARY) {
  136 
  137                 /* if the binary should be opened on behalf of the
  138                  * interpreter than keep it open and assign descriptor
  139                  * to it */
  140                 fd_binary = get_unused_fd();
  141                 if (fd_binary < 0) {
  142                         retval = fd_binary;
  143                         goto _ret;
  144                 }
  145                 fd_install(fd_binary, bprm->file);
  146 
  147                 /* if the binary is not readable than enforce mm->dumpable=0
  148                    regardless of the interpreter's permissions */
  149                 would_dump(bprm, bprm->file);
  150 
  151                 allow_write_access(bprm->file);
  152                 bprm->file = NULL;
  153 
  154                 /* mark the bprm that fd should be passed to interp */
  155                 bprm->interp_flags |= BINPRM_FLAGS_EXECFD;
  156                 bprm->interp_data = fd_binary;
  157 
  158         } else {
  159                 allow_write_access(bprm->file);
  160                 fput(bprm->file);
  161                 bprm->file = NULL;
  162         }
  163         /* make argv[1] be the path to the binary */
  164         retval = copy_strings_kernel (1, &bprm->interp, bprm);
  165         if (retval < 0)
  166                 goto _error;
  167         bprm->argc++;
  168 
  169         /* add the interp as argv[0] */
  170         retval = copy_strings_kernel (1, &iname_addr, bprm);
  171         if (retval < 0)
  172                 goto _error;
  173         bprm->argc ++;
  174 
  175         /* Update interp in case binfmt_script needs it. */
  176         retval = bprm_change_interp(iname, bprm);
  177         if (retval < 0)
  178                 goto _error;
  179 
  180         interp_file = open_exec (iname);
  181         retval = PTR_ERR (interp_file);
  182         if (IS_ERR (interp_file))
  183                 goto _error;
  184 
  185         bprm->file = interp_file;
  186         if (fmt->flags & MISC_FMT_CREDENTIALS) {
  187                 /*
  188                  * No need to call prepare_binprm(), it's already been
  189                  * done.  bprm->buf is stale, update from interp_file.
  190                  */
  191                 memset(bprm->buf, 0, BINPRM_BUF_SIZE);
  192                 retval = kernel_read(bprm->file, 0, bprm->buf, BINPRM_BUF_SIZE);
  193         } else
  194                 retval = prepare_binprm (bprm);
  195 
  196         if (retval < 0)
  197                 goto _error;
  198 
  199         retval = search_binary_handler(bprm);
  200         if (retval < 0)
  201                 goto _error;
  202 
  203 _ret:
  204         return retval;
  205 _error:
  206         if (fd_binary > 0)
  207                 sys_close(fd_binary);
  208         bprm->interp_flags = 0;
  209         bprm->interp_data = 0;
  210         goto _ret;
  211 }
  212 
  213 /* Command parsers */
  214 
  215 /*
  216  * parses and copies one argument enclosed in del from *sp to *dp,
  217  * recognising the \x special.
  218  * returns pointer to the copied argument or NULL in case of an
  219  * error (and sets err) or null argument length.
  220  */
  221 static char *scanarg(char *s, char del)
  222 {
  223         char c;
  224 
  225         while ((c = *s++) != del) {
  226                 if (c == '\\' && *s == 'x') {
  227                         s++;
  228                         if (!isxdigit(*s++))
  229                                 return NULL;
  230                         if (!isxdigit(*s++))
  231                                 return NULL;
  232                 }
  233         }
  234         return s;
  235 }
  236 
  237 static int unquote(char *from)
  238 {
  239         char c = 0, *s = from, *p = from;
  240 
  241         while ((c = *s++) != '\0') {
  242                 if (c == '\\' && *s == 'x') {
  243                         s++;
  244                         c = toupper(*s++);
  245                         *p = (c - (isdigit(c) ? '' : 'A' - 10)) << 4;
  246                         c = toupper(*s++);
  247                         *p++ |= c - (isdigit(c) ? '' : 'A' - 10);
  248                         continue;
  249                 }
  250                 *p++ = c;
  251         }
  252         return p - from;
  253 }
  254 
  255 static char * check_special_flags (char * sfs, Node * e)
  256 {
  257         char * p = sfs;
  258         int cont = 1;
  259 
  260         /* special flags */
  261         while (cont) {
  262                 switch (*p) {
  263                         case 'P':
  264                                 p++;
  265                                 e->flags |= MISC_FMT_PRESERVE_ARGV0;
  266                                 break;
  267                         case 'O':
  268                                 p++;
  269                                 e->flags |= MISC_FMT_OPEN_BINARY;
  270                                 break;
  271                         case 'C':
  272                                 p++;
  273                                 /* this flags also implies the
  274                                    open-binary flag */
  275                                 e->flags |= (MISC_FMT_CREDENTIALS |
  276                                                 MISC_FMT_OPEN_BINARY);
  277                                 break;
  278                         default:
  279                                 cont = 0;
  280                 }
  281         }
  282 
  283         return p;
  284 }
  285 /*
  286  * This registers a new binary format, it recognises the syntax
  287  * ':name:type:offset:magic:mask:interpreter:flags'
  288  * where the ':' is the IFS, that can be chosen with the first char
  289  */
  290 static Node *create_entry(const char __user *buffer, size_t count)
  291 {
  292         Node *e;
  293         int memsize, err;
  294         char *buf, *p;
  295         char del;
  296 
  297         /* some sanity checks */
  298         err = -EINVAL;
  299         if ((count < 11) || (count > 256))
  300                 goto out;
  301 
  302         err = -ENOMEM;
  303         memsize = sizeof(Node) + count + 8;
  304         e = kmalloc(memsize, GFP_USER);
  305         if (!e)
  306                 goto out;
  307 
  308         p = buf = (char *)e + sizeof(Node);
  309 
  310         memset(e, 0, sizeof(Node));
  311         if (copy_from_user(buf, buffer, count))
  312                 goto Efault;
  313 
  314         del = *p++;     /* delimeter */
  315 
  316         memset(buf+count, del, 8);
  317 
  318         e->name = p;
  319         p = strchr(p, del);
  320         if (!p)
  321                 goto Einval;
  322         *p++ = '\0';
  323         if (!e->name[0] ||
  324             !strcmp(e->name, ".") ||
  325             !strcmp(e->name, "..") ||
  326             strchr(e->name, '/'))
  327                 goto Einval;
  328         switch (*p++) {
  329                 case 'E': e->flags = 1<<Enabled; break;
  330                 case 'M': e->flags = (1<<Enabled) | (1<<Magic); break;
  331                 default: goto Einval;
  332         }
  333         if (*p++ != del)
  334                 goto Einval;
  335         if (test_bit(Magic, &e->flags)) {
  336                 char *s = strchr(p, del);
  337                 if (!s)
  338                         goto Einval;
  339                 *s++ = '\0';
  340                 e->offset = simple_strtoul(p, &p, 10);
  341                 if (*p++)
  342                         goto Einval;
  343                 e->magic = p;
  344                 p = scanarg(p, del);
  345                 if (!p)
  346                         goto Einval;
  347                 p[-1] = '\0';
  348                 if (!e->magic[0])
  349                         goto Einval;
  350                 e->mask = p;
  351                 p = scanarg(p, del);
  352                 if (!p)
  353                         goto Einval;
  354                 p[-1] = '\0';
  355                 if (!e->mask[0])
  356                         e->mask = NULL;
  357                 e->size = unquote(e->magic);
  358                 if (e->mask && unquote(e->mask) != e->size)
  359                         goto Einval;
  360                 if (e->size + e->offset > BINPRM_BUF_SIZE)
  361                         goto Einval;
  362         } else {
  363                 p = strchr(p, del);
  364                 if (!p)
  365                         goto Einval;
  366                 *p++ = '\0';
  367                 e->magic = p;
  368                 p = strchr(p, del);
  369                 if (!p)
  370                         goto Einval;
  371                 *p++ = '\0';
  372                 if (!e->magic[0] || strchr(e->magic, '/'))
  373                         goto Einval;
  374                 p = strchr(p, del);
  375                 if (!p)
  376                         goto Einval;
  377                 *p++ = '\0';
  378         }
  379         e->interpreter = p;
  380         p = strchr(p, del);
  381         if (!p)
  382                 goto Einval;
  383         *p++ = '\0';
  384         if (!e->interpreter[0])
  385                 goto Einval;
  386 
  387 
  388         p = check_special_flags (p, e);
  389 
  390         if (*p == '\n')
  391                 p++;
  392         if (p != buf + count)
  393                 goto Einval;
  394         return e;
  395 
  396 out:
  397         return ERR_PTR(err);
  398 
  399 Efault:
  400         kfree(e);
  401         return ERR_PTR(-EFAULT);
  402 Einval:
  403         kfree(e);
  404         return ERR_PTR(-EINVAL);
  405 }
  406 
  407 /*
  408  * Set status of entry/binfmt_misc:
  409  * '1' enables, '' disables and '-1' clears entry/binfmt_misc
  410  */
  411 static int parse_command(const char __user *buffer, size_t count)
  412 {
  413         char s[4];
  414 
  415         if (!count)
  416                 return 0;
  417         if (count > 3)
  418                 return -EINVAL;
  419         if (copy_from_user(s, buffer, count))
  420                 return -EFAULT;
  421         if (s[count-1] == '\n')
  422                 count--;
  423         if (count == 1 && s[0] == '')
  424                 return 1;
  425         if (count == 1 && s[0] == '1')
  426                 return 2;
  427         if (count == 2 && s[0] == '-' && s[1] == '1')
  428                 return 3;
  429         return -EINVAL;
  430 }
  431 
  432 /* generic stuff */
  433 
  434 static void entry_status(Node *e, char *page)
  435 {
  436         char *dp;
  437         char *status = "disabled";
  438         const char * flags = "flags: ";
  439 
  440         if (test_bit(Enabled, &e->flags))
  441                 status = "enabled";
  442 
  443         if (!VERBOSE_STATUS) {
  444                 sprintf(page, "%s\n", status);
  445                 return;
  446         }
  447 
  448         sprintf(page, "%s\ninterpreter %s\n", status, e->interpreter);
  449         dp = page + strlen(page);
  450 
  451         /* print the special flags */
  452         sprintf (dp, "%s", flags);
  453         dp += strlen (flags);
  454         if (e->flags & MISC_FMT_PRESERVE_ARGV0) {
  455                 *dp ++ = 'P';
  456         }
  457         if (e->flags & MISC_FMT_OPEN_BINARY) {
  458                 *dp ++ = 'O';
  459         }
  460         if (e->flags & MISC_FMT_CREDENTIALS) {
  461                 *dp ++ = 'C';
  462         }
  463         *dp ++ = '\n';
  464 
  465 
  466         if (!test_bit(Magic, &e->flags)) {
  467                 sprintf(dp, "extension .%s\n", e->magic);
  468         } else {
  469                 int i;
  470 
  471                 sprintf(dp, "offset %i\nmagic ", e->offset);
  472                 dp = page + strlen(page);
  473                 for (i = 0; i < e->size; i++) {
  474                         sprintf(dp, "%02x", 0xff & (int) (e->magic[i]));
  475                         dp += 2;
  476                 }
  477                 if (e->mask) {
  478                         sprintf(dp, "\nmask ");
  479                         dp += 6;
  480                         for (i = 0; i < e->size; i++) {
  481                                 sprintf(dp, "%02x", 0xff & (int) (e->mask[i]));
  482                                 dp += 2;
  483                         }
  484                 }
  485                 *dp++ = '\n';
  486                 *dp = '\0';
  487         }
  488 }
  489 
  490 static struct inode *bm_get_inode(struct super_block *sb, int mode)
  491 {
  492         struct inode * inode = new_inode(sb);
  493 
  494         if (inode) {
  495                 inode->i_ino = get_next_ino();
  496                 inode->i_mode = mode;
  497                 inode->i_atime = inode->i_mtime = inode->i_ctime =
  498                         current_fs_time(inode->i_sb);
  499         }
  500         return inode;
  501 }
  502 
  503 static void bm_evict_inode(struct inode *inode)
  504 {
  505         clear_inode(inode);
  506         kfree(inode->i_private);
  507 }
  508 
  509 static void kill_node(Node *e)
  510 {
  511         struct dentry *dentry;
  512 
  513         write_lock(&entries_lock);
  514         dentry = e->dentry;
  515         if (dentry) {
  516                 list_del_init(&e->list);
  517                 e->dentry = NULL;
  518         }
  519         write_unlock(&entries_lock);
  520 
  521         if (dentry) {
  522                 drop_nlink(dentry->d_inode);
  523                 d_drop(dentry);
  524                 dput(dentry);
  525                 simple_release_fs(&bm_mnt, &entry_count);
  526         }
  527 }
  528 
  529 /* /<entry> */
  530 
  531 static ssize_t
  532 bm_entry_read(struct file * file, char __user * buf, size_t nbytes, loff_t *ppos)
  533 {
  534         Node *e = file->f_path.dentry->d_inode->i_private;
  535         ssize_t res;
  536         char *page;
  537 
  538         if (!(page = (char*) __get_free_page(GFP_KERNEL)))
  539                 return -ENOMEM;
  540 
  541         entry_status(e, page);
  542 
  543         res = simple_read_from_buffer(buf, nbytes, ppos, page, strlen(page));
  544 
  545         free_page((unsigned long) page);
  546         return res;
  547 }
  548 
  549 static ssize_t bm_entry_write(struct file *file, const char __user *buffer,
  550                                 size_t count, loff_t *ppos)
  551 {
  552         struct dentry *root;
  553         Node *e = file->f_path.dentry->d_inode->i_private;
  554         int res = parse_command(buffer, count);
  555 
  556         switch (res) {
  557                 case 1: clear_bit(Enabled, &e->flags);
  558                         break;
  559                 case 2: set_bit(Enabled, &e->flags);
  560                         break;
  561                 case 3: root = dget(file->f_path.dentry->d_sb->s_root);
  562                         mutex_lock(&root->d_inode->i_mutex);
  563 
  564                         kill_node(e);
  565 
  566                         mutex_unlock(&root->d_inode->i_mutex);
  567                         dput(root);
  568                         break;
  569                 default: return res;
  570         }
  571         return count;
  572 }
  573 
  574 static const struct file_operations bm_entry_operations = {
  575         .read           = bm_entry_read,
  576         .write          = bm_entry_write,
  577         .llseek         = default_llseek,
  578 };
  579 
  580 /* /register */
  581 
  582 static ssize_t bm_register_write(struct file *file, const char __user *buffer,
  583                                size_t count, loff_t *ppos)
  584 {
  585         Node *e;
  586         struct inode *inode;
  587         struct dentry *root, *dentry;
  588         struct super_block *sb = file->f_path.dentry->d_sb;
  589         int err = 0;
  590 
  591         e = create_entry(buffer, count);
  592 
  593         if (IS_ERR(e))
  594                 return PTR_ERR(e);
  595 
  596         root = dget(sb->s_root);
  597         mutex_lock(&root->d_inode->i_mutex);
  598         dentry = lookup_one_len(e->name, root, strlen(e->name));
  599         err = PTR_ERR(dentry);
  600         if (IS_ERR(dentry))
  601                 goto out;
  602 
  603         err = -EEXIST;
  604         if (dentry->d_inode)
  605                 goto out2;
  606 
  607         inode = bm_get_inode(sb, S_IFREG | 0644);
  608 
  609         err = -ENOMEM;
  610         if (!inode)
  611                 goto out2;
  612 
  613         err = simple_pin_fs(&bm_fs_type, &bm_mnt, &entry_count);
  614         if (err) {
  615                 iput(inode);
  616                 inode = NULL;
  617                 goto out2;
  618         }
  619 
  620         e->dentry = dget(dentry);
  621         inode->i_private = e;
  622         inode->i_fop = &bm_entry_operations;
  623 
  624         d_instantiate(dentry, inode);
  625         write_lock(&entries_lock);
  626         list_add(&e->list, &entries);
  627         write_unlock(&entries_lock);
  628 
  629         err = 0;
  630 out2:
  631         dput(dentry);
  632 out:
  633         mutex_unlock(&root->d_inode->i_mutex);
  634         dput(root);
  635 
  636         if (err) {
  637                 kfree(e);
  638                 return -EINVAL;
  639         }
  640         return count;
  641 }
  642 
  643 static const struct file_operations bm_register_operations = {
  644         .write          = bm_register_write,
  645         .llseek         = noop_llseek,
  646 };
  647 
  648 /* /status */
  649 
  650 static ssize_t
  651 bm_status_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
  652 {
  653         char *s = enabled ? "enabled\n" : "disabled\n";
  654 
  655         return simple_read_from_buffer(buf, nbytes, ppos, s, strlen(s));
  656 }
  657 
  658 static ssize_t bm_status_write(struct file * file, const char __user * buffer,
  659                 size_t count, loff_t *ppos)
  660 {
  661         int res = parse_command(buffer, count);
  662         struct dentry *root;
  663 
  664         switch (res) {
  665                 case 1: enabled = 0; break;
  666                 case 2: enabled = 1; break;
  667                 case 3: root = dget(file->f_path.dentry->d_sb->s_root);
  668                         mutex_lock(&root->d_inode->i_mutex);
  669 
  670                         while (!list_empty(&entries))
  671                                 kill_node(list_entry(entries.next, Node, list));
  672 
  673                         mutex_unlock(&root->d_inode->i_mutex);
  674                         dput(root);
  675                 default: return res;
  676         }
  677         return count;
  678 }
  679 
  680 static const struct file_operations bm_status_operations = {
  681         .read           = bm_status_read,
  682         .write          = bm_status_write,
  683         .llseek         = default_llseek,
  684 };
  685 
  686 /* Superblock handling */
  687 
  688 static const struct super_operations s_ops = {
  689         .statfs         = simple_statfs,
  690         .evict_inode    = bm_evict_inode,
  691 };
  692 
  693 static int bm_fill_super(struct super_block * sb, void * data, int silent)
  694 {
  695         static struct tree_descr bm_files[] = {
  696                 [2] = {"status", &bm_status_operations, S_IWUSR|S_IRUGO},
  697                 [3] = {"register", &bm_register_operations, S_IWUSR},
  698                 /* last one */ {""}
  699         };
  700         int err = simple_fill_super(sb, BINFMTFS_MAGIC, bm_files);
  701         if (!err)
  702                 sb->s_op = &s_ops;
  703         return err;
  704 }
  705 
  706 static struct dentry *bm_mount(struct file_system_type *fs_type,
  707         int flags, const char *dev_name, void *data)
  708 {
  709         return mount_single(fs_type, flags, data, bm_fill_super);
  710 }
  711 
  712 static struct linux_binfmt misc_format = {
  713         .module = THIS_MODULE,
  714         .load_binary = load_misc_binary,
  715 };
  716 
  717 static struct file_system_type bm_fs_type = {
  718         .owner          = THIS_MODULE,
  719         .name           = "binfmt_misc",
  720         .mount          = bm_mount,
  721         .kill_sb        = kill_litter_super,
  722 };
  723 
  724 static int __init init_misc_binfmt(void)
  725 {
  726         int err = register_filesystem(&bm_fs_type);
  727         if (!err)
  728                 insert_binfmt(&misc_format);
  729         return err;
  730 }
  731 
  732 static void __exit exit_misc_binfmt(void)
  733 {
  734         unregister_binfmt(&misc_format);
  735         unregister_filesystem(&bm_fs_type);
  736 }
  737 
  738 core_initcall(init_misc_binfmt);
  739 module_exit(exit_misc_binfmt);
  740 MODULE_LICENSE("GPL");

Cache object: 17bdb477fcdac344fba8952e65e35233


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.