~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/fs/binfmt_misc.c

Version: ~ [ linux-5.3 ] ~ [ linux-5.2.15 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.73 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.144 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.193 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.193 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.73 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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_inode(file)->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_inode(file)->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 MODULE_ALIAS_FS("binfmt_misc");
724 
725 static int __init init_misc_binfmt(void)
726 {
727         int err = register_filesystem(&bm_fs_type);
728         if (!err)
729                 insert_binfmt(&misc_format);
730         return err;
731 }
732 
733 static void __exit exit_misc_binfmt(void)
734 {
735         unregister_binfmt(&misc_format);
736         unregister_filesystem(&bm_fs_type);
737 }
738 
739 core_initcall(init_misc_binfmt);
740 module_exit(exit_misc_binfmt);
741 MODULE_LICENSE("GPL");
742 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp