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