4 * Copyright (C) 1997 Richard Günther
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
10 * 1997-04-25 first version
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
18 #include <linux/config.h>
19 #include <linux/module.h>
21 #include <linux/kernel.h>
22 #include <linux/errno.h>
24 #include <linux/malloc.h>
25 #include <linux/binfmts.h>
26 #include <linux/init.h>
27 #include <linux/proc_fs.h>
28 #include <linux/string.h>
29 #include <linux/ctype.h>
30 #include <asm/uaccess.h>
31 #include <asm/spinlock.h>
34 * We should make this work with a "stub-only" /proc,
35 * which would just not be able to be configured.
36 * Right now the /proc-fs support is too black and white,
37 * though, so just remind people that this should be
40 #ifndef CONFIG_PROC_FS
41 #error You really need /proc support for binfmt_misc. Please reconfigure!
44 #define VERBOSE_STATUS /* undef this to save 400 bytes kernel memory */
47 struct binfmt_entry
*next
;
49 int 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 */
56 struct proc_dir_entry
*proc_dir
;
59 #define ENTRY_ENABLED 1 /* the old binfmt_entry.enabled */
60 #define ENTRY_MAGIC 8 /* not filename detection */
62 static int load_misc_binary(struct linux_binprm
*bprm
, struct pt_regs
*regs
);
63 static void entry_proc_cleanup(struct binfmt_entry
*e
);
64 static int entry_proc_setup(struct binfmt_entry
*e
);
66 static struct linux_binfmt misc_format
= {
68 NULL
, 0, load_misc_binary
, NULL
, NULL
70 NULL
, &__this_module
, load_misc_binary
, NULL
, NULL
74 static struct proc_dir_entry
*bm_dir
= NULL
;
76 static struct binfmt_entry
*entries
= NULL
;
77 static int free_id
= 1;
78 static int enabled
= 1;
80 static rwlock_t entries_lock
__attribute__((unused
)) = RW_LOCK_UNLOCKED
;
84 * Unregister one entry
86 static void clear_entry(int id
)
88 struct binfmt_entry
**ep
, *e
;
90 write_lock(&entries_lock
);
92 while (*ep
&& ((*ep
)->id
!= id
))
96 write_unlock(&entries_lock
);
99 entry_proc_cleanup(e
);
105 * Clear all registered binary formats
107 static void clear_entries(void)
109 struct binfmt_entry
*e
, *n
;
111 write_lock(&entries_lock
);
114 write_unlock(&entries_lock
);
118 entry_proc_cleanup(e
);
124 * Find entry through id and lock it
126 static struct binfmt_entry
*get_entry(int id
)
128 struct binfmt_entry
*e
;
130 read_lock(&entries_lock
);
132 while (e
&& (e
->id
!= id
))
135 read_unlock(&entries_lock
);
142 static inline void put_entry(struct binfmt_entry
*e
)
145 read_unlock(&entries_lock
);
150 * Check if we support the binfmt
151 * if we do, return the binfmt_entry, else NULL
152 * locking is done in load_misc_binary
154 static struct binfmt_entry
*check_file(struct linux_binprm
*bprm
)
156 struct binfmt_entry
*e
;
157 char *p
= strrchr(bprm
->filename
, '.');
162 if (e
->flags
& ENTRY_ENABLED
) {
163 if (!(e
->flags
& ENTRY_MAGIC
)) {
164 if (p
&& !strcmp(e
->magic
, p
+ 1))
168 while ((j
< e
->size
) &&
169 !((bprm
->buf
[e
->offset
+ j
] ^ e
->magic
[j
])
170 & (e
->mask
? e
->mask
[j
] : 0xff)))
184 static int load_misc_binary(struct linux_binprm
*bprm
, struct pt_regs
*regs
)
186 struct binfmt_entry
*fmt
;
187 struct dentry
* dentry
;
189 char *iname_addr
= iname
;
197 /* to keep locking time low, we copy the interpreter string */
198 read_lock(&entries_lock
);
199 fmt
= check_file(bprm
);
201 strncpy(iname
, fmt
->interpreter
, 127);
204 read_unlock(&entries_lock
);
211 /* Build args for interpreter */
212 remove_arg_zero(bprm
);
213 retval
= copy_strings_kernel(1, &bprm
->filename
, bprm
);
214 if (retval
< 0) goto _ret
;
216 retval
= copy_strings_kernel(1, &iname_addr
, bprm
);
217 if (retval
< 0) goto _ret
;
219 bprm
->filename
= iname
; /* for binfmt_script */
221 dentry
= open_namei(iname
, 0, 0);
222 retval
= PTR_ERR(dentry
);
225 bprm
->dentry
= dentry
;
227 retval
= prepare_binprm(bprm
);
229 retval
= search_binary_handler(bprm
, regs
);
238 * /proc handling routines
242 * parses and copies one argument enclosed in del from *sp to *dp,
243 * recognising the \x special.
244 * returns pointer to the copied argument or NULL in case of an
245 * error (and sets err) or null argument length.
247 static char *copyarg(char **dp
, const char **sp
, int *count
,
248 char del
, int special
, int *err
)
250 char c
= 0, *res
= *dp
;
252 while (!*err
&& ((c
= *((*sp
)++)), (*count
)--) && (c
!= del
)) {
255 if (special
&& (**sp
== 'x')) {
256 if (!isxdigit(c
= toupper(*(++*sp
))))
258 **dp
= (c
- (isdigit(c
) ? '0' : 'A' - 10)) * 16;
259 if (!isxdigit(c
= toupper(*(++*sp
))))
261 *((*dp
)++) += c
- (isdigit(c
) ? '0' : 'A' - 10);
270 if (*err
|| (c
!= del
) || (res
== *dp
))
278 * This registers a new binary format, it recognises the syntax
279 * ':name:type:offset:magic:mask:interpreter:'
280 * where the ':' is the IFS, that can be chosen with the first char
282 static int proc_write_register(struct file
*file
, const char *buffer
,
283 unsigned long count
, void *data
)
287 struct binfmt_entry
*e
;
288 int memsize
, cnt
= count
- 1, err
;
290 /* some sanity checks */
292 if ((count
< 11) || (count
> 256))
296 memsize
= sizeof(struct binfmt_entry
) + count
;
297 if (!(e
= (struct binfmt_entry
*) kmalloc(memsize
, GFP_USER
)))
303 dp
= (char *)e
+ sizeof(struct binfmt_entry
);
305 e
->proc_name
= copyarg(&dp
, &sp
, &cnt
, del
, 0, &err
);
307 /* we can use bit 3 of type for ext/magic
308 flag due to the nice encoding of E and M */
309 if ((*sp
& ~('E' | 'M')) || (sp
[1] != del
))
312 e
->flags
= (*sp
++ & (ENTRY_MAGIC
| ENTRY_ENABLED
));
316 while (cnt
-- && isdigit(*sp
))
317 e
->offset
= e
->offset
* 10 + *sp
++ - '0';
321 e
->magic
= copyarg(&dp
, &sp
, &cnt
, del
, (e
->flags
& ENTRY_MAGIC
), &err
);
322 e
->size
= dp
- e
->magic
;
323 e
->mask
= copyarg(&dp
, &sp
, &cnt
, del
, 1, &err
);
324 if (e
->mask
&& ((dp
- e
->mask
) != e
->size
))
326 e
->interpreter
= copyarg(&dp
, &sp
, &cnt
, del
, 0, &err
);
329 /* more sanity checks */
330 if (err
|| !(!cnt
|| (!(--cnt
) && (*sp
== '\n'))) ||
331 (e
->size
< 1) || ((e
->size
+ e
->offset
) > 127) ||
332 !(e
->proc_name
) || !(e
->interpreter
) || entry_proc_setup(e
))
335 write_lock(&entries_lock
);
338 write_unlock(&entries_lock
);
350 * Get status of entry/binfmt_misc
351 * FIXME? should an entry be marked disabled if binfmt_misc is disabled though
354 static int proc_read_status(char *page
, char **start
, off_t off
,
355 int count
, int *eof
, void *data
)
357 struct binfmt_entry
*e
;
361 #ifndef VERBOSE_STATUS
363 if (!(e
= get_entry((int) data
))) {
367 i
= e
->flags
& ENTRY_ENABLED
;
372 sprintf(page
, "%s\n", (i
? "enabled" : "disabled"));
375 sprintf(page
, "%s\n", (enabled
? "enabled" : "disabled"));
377 if (!(e
= get_entry((long) data
))) {
381 sprintf(page
, "%s\ninterpreter %s\n",
382 (e
->flags
& ENTRY_ENABLED
? "enabled" : "disabled"),
384 dp
= page
+ strlen(page
);
385 if (!(e
->flags
& ENTRY_MAGIC
)) {
386 sprintf(dp
, "extension .%s\n", e
->magic
);
387 dp
= page
+ strlen(page
);
389 sprintf(dp
, "offset %i\nmagic ", e
->offset
);
390 dp
= page
+ strlen(page
);
391 for (i
= 0; i
< e
->size
; i
++) {
392 sprintf(dp
, "%02x", 0xff & (int) (e
->magic
[i
]));
396 sprintf(dp
, "\nmask ");
398 for (i
= 0; i
< e
->size
; i
++) {
399 sprintf(dp
, "%02x", 0xff & (int) (e
->mask
[i
]));
410 elen
= strlen(page
) - off
;
413 *eof
= (elen
<= count
) ? 1 : 0;
422 * Set status of entry/binfmt_misc:
423 * '1' enables, '0' disables and '-1' clears entry/binfmt_misc
425 static int proc_write_status(struct file
*file
, const char *buffer
,
426 unsigned long count
, void *data
)
428 struct binfmt_entry
*e
;
431 if (buffer
[count
-1] == '\n')
433 if ((count
== 1) && !(buffer
[0] & ~('0' | '1'))) {
435 if ((e
= get_entry((long) data
)))
436 e
->flags
= (e
->flags
& ~ENTRY_ENABLED
)
437 | (int)(buffer
[0] - '0');
440 enabled
= buffer
[0] - '0';
442 } else if ((count
== 2) && (buffer
[0] == '-') && (buffer
[1] == '1')) {
444 clear_entry((long) data
);
454 * Remove the /proc-dir entries of one binfmt
456 static void entry_proc_cleanup(struct binfmt_entry
*e
)
458 remove_proc_entry(e
->proc_name
, bm_dir
);
462 * Create the /proc-dir entry for binfmt
464 static int entry_proc_setup(struct binfmt_entry
*e
)
466 if (!(e
->proc_dir
= create_proc_entry(e
->proc_name
,
467 S_IFREG
| S_IRUGO
| S_IWUSR
, bm_dir
)))
469 printk(KERN_WARNING
"Unable to create /proc entry.\n");
472 e
->proc_dir
->data
= (void *) (e
->id
);
473 e
->proc_dir
->read_proc
= proc_read_status
;
474 e
->proc_dir
->write_proc
= proc_write_status
;
480 * This is called as the fill_inode function when an inode
481 * is going into (fill = 1) or out of service (fill = 0).
482 * We use it here to manage the module use counts.
484 * Note: only the top-level directory needs to do this; if
485 * a lower level is referenced, the parent will be as well.
487 static void bm_modcount(struct inode
*inode
, int fill
)
496 int __init
init_misc_binfmt(void)
499 struct proc_dir_entry
*status
= NULL
, *reg
;
501 bm_dir
= create_proc_entry("sys/fs/binfmt_misc", S_IFDIR
, NULL
);
505 bm_dir
->fill_inode
= bm_modcount
;
508 status
= create_proc_entry("status", S_IFREG
| S_IRUGO
| S_IWUSR
,
512 status
->read_proc
= proc_read_status
;
513 status
->write_proc
= proc_write_status
;
515 reg
= create_proc_entry("register", S_IFREG
| S_IWUSR
, bm_dir
);
518 reg
->write_proc
= proc_write_register
;
520 error
= register_binfmt(&misc_format
);
525 remove_proc_entry("status", bm_dir
);
527 remove_proc_entry("sys/fs/binfmt_misc", NULL
);
533 int init_module(void)
535 return init_misc_binfmt();
538 void cleanup_module(void)
540 unregister_binfmt(&misc_format
);
541 remove_proc_entry("register", bm_dir
);
542 remove_proc_entry("status", bm_dir
);
544 remove_proc_entry("sys/fs/binfmt_misc", NULL
);
547 #undef VERBOSE_STATUS