Import 2.3.6
[davej-history.git] / fs / binfmt_misc.c
blob7b9cead81959bb570cc07d22e21be6b75159b52b
1 /*
2 * binfmt_misc.c
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
8 * binfmt_mz.
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
18 #include <linux/config.h>
19 #include <linux/module.h>
21 #include <linux/kernel.h>
22 #include <linux/errno.h>
23 #include <linux/fs.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
38 * fixed..
40 #ifndef CONFIG_PROC_FS
41 #error You really need /proc support for binfmt_misc. Please reconfigure!
42 #endif
44 #define VERBOSE_STATUS /* undef this to save 400 bytes kernel memory */
46 struct binfmt_entry {
47 struct binfmt_entry *next;
48 long id;
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 */
55 char *proc_name;
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 = {
67 #ifndef MODULE
68 NULL, 0, load_misc_binary, NULL, NULL
69 #else
70 NULL, &__this_module, load_misc_binary, NULL, NULL
71 #endif
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);
91 ep = &entries;
92 while (*ep && ((*ep)->id != id))
93 ep = &((*ep)->next);
94 if ((e = *ep))
95 *ep = e->next;
96 write_unlock(&entries_lock);
98 if (e) {
99 entry_proc_cleanup(e);
100 kfree(e);
105 * Clear all registered binary formats
107 static void clear_entries(void)
109 struct binfmt_entry *e, *n;
111 write_lock(&entries_lock);
112 n = entries;
113 entries = NULL;
114 write_unlock(&entries_lock);
116 while ((e = n)) {
117 n = e->next;
118 entry_proc_cleanup(e);
119 kfree(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);
131 e = entries;
132 while (e && (e->id != id))
133 e = e->next;
134 if (!e)
135 read_unlock(&entries_lock);
136 return e;
140 * unlock entry
142 static inline void put_entry(struct binfmt_entry *e)
144 if (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, '.');
158 int j;
160 e = entries;
161 while (e) {
162 if (e->flags & ENTRY_ENABLED) {
163 if (!(e->flags & ENTRY_MAGIC)) {
164 if (p && !strcmp(e->magic, p + 1))
165 return e;
166 } else {
167 j = 0;
168 while ((j < e->size) &&
169 !((bprm->buf[e->offset + j] ^ e->magic[j])
170 & (e->mask ? e->mask[j] : 0xff)))
171 j++;
172 if (j == e->size)
173 return e;
176 e = e->next;
178 return NULL;
182 * the loader itself
184 static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs)
186 struct binfmt_entry *fmt;
187 struct dentry * dentry;
188 char iname[128];
189 char *iname_addr = iname;
190 int retval;
192 MOD_INC_USE_COUNT;
193 retval = -ENOEXEC;
194 if (!enabled)
195 goto _ret;
197 /* to keep locking time low, we copy the interpreter string */
198 read_lock(&entries_lock);
199 fmt = check_file(bprm);
200 if (fmt) {
201 strncpy(iname, fmt->interpreter, 127);
202 iname[127] = '\0';
204 read_unlock(&entries_lock);
205 if (!fmt)
206 goto _ret;
208 dput(bprm->dentry);
209 bprm->dentry = NULL;
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;
215 bprm->argc++;
216 retval = copy_strings_kernel(1, &iname_addr, bprm);
217 if (retval < 0) goto _ret;
218 bprm->argc++;
219 bprm->filename = iname; /* for binfmt_script */
221 dentry = open_namei(iname, 0, 0);
222 retval = PTR_ERR(dentry);
223 if (IS_ERR(dentry))
224 goto _ret;
225 bprm->dentry = dentry;
227 retval = prepare_binprm(bprm);
228 if (retval >= 0)
229 retval = search_binary_handler(bprm, regs);
230 _ret:
231 MOD_DEC_USE_COUNT;
232 return retval;
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)) {
253 switch (c) {
254 case '\\':
255 if (special && (**sp == 'x')) {
256 if (!isxdigit(c = toupper(*(++*sp))))
257 *err = -EINVAL;
258 **dp = (c - (isdigit(c) ? '0' : 'A' - 10)) * 16;
259 if (!isxdigit(c = toupper(*(++*sp))))
260 *err = -EINVAL;
261 *((*dp)++) += c - (isdigit(c) ? '0' : 'A' - 10);
262 ++*sp;
263 *count -= 3;
264 break;
266 default:
267 *((*dp)++) = c;
270 if (*err || (c != del) || (res == *dp))
271 res = NULL;
272 else if (!special)
273 *((*dp)++) = '\0';
274 return res;
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)
285 const char *sp;
286 char del, *dp;
287 struct binfmt_entry *e;
288 int memsize, cnt = count - 1, err;
290 /* some sanity checks */
291 err = -EINVAL;
292 if ((count < 11) || (count > 256))
293 goto _err;
295 err = -ENOMEM;
296 memsize = sizeof(struct binfmt_entry) + count;
297 if (!(e = (struct binfmt_entry *) kmalloc(memsize, GFP_USER)))
298 goto _err;
300 err = 0;
301 sp = buffer + 1;
302 del = buffer[0];
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))
310 err = -EINVAL;
311 else
312 e->flags = (*sp++ & (ENTRY_MAGIC | ENTRY_ENABLED));
313 cnt -= 2; sp++;
315 e->offset = 0;
316 while (cnt-- && isdigit(*sp))
317 e->offset = e->offset * 10 + *sp++ - '0';
318 if (*sp++ != del)
319 err = -EINVAL;
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))
325 err = -EINVAL;
326 e->interpreter = copyarg(&dp, &sp, &cnt, del, 0, &err);
327 e->id = free_id++;
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))
333 goto free_err;
335 write_lock(&entries_lock);
336 e->next = entries;
337 entries = e;
338 write_unlock(&entries_lock);
340 err = count;
341 _err:
342 return err;
343 free_err:
344 kfree(e);
345 err = -EINVAL;
346 goto _err;
350 * Get status of entry/binfmt_misc
351 * FIXME? should an entry be marked disabled if binfmt_misc is disabled though
352 * entry is enabled?
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;
358 char *dp;
359 int elen, i, err;
361 #ifndef VERBOSE_STATUS
362 if (data) {
363 if (!(e = get_entry((int) data))) {
364 err = -ENOENT;
365 goto _err;
367 i = e->flags & ENTRY_ENABLED;
368 put_entry(e);
369 } else {
370 i = enabled;
372 sprintf(page, "%s\n", (i ? "enabled" : "disabled"));
373 #else
374 if (!data)
375 sprintf(page, "%s\n", (enabled ? "enabled" : "disabled"));
376 else {
377 if (!(e = get_entry((long) data))) {
378 err = -ENOENT;
379 goto _err;
381 sprintf(page, "%s\ninterpreter %s\n",
382 (e->flags & ENTRY_ENABLED ? "enabled" : "disabled"),
383 e->interpreter);
384 dp = page + strlen(page);
385 if (!(e->flags & ENTRY_MAGIC)) {
386 sprintf(dp, "extension .%s\n", e->magic);
387 dp = page + strlen(page);
388 } else {
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]));
393 dp += 2;
395 if (e->mask) {
396 sprintf(dp, "\nmask ");
397 dp += 6;
398 for (i = 0; i < e->size; i++) {
399 sprintf(dp, "%02x", 0xff & (int) (e->mask[i]));
400 dp += 2;
403 *dp++ = '\n';
404 *dp = '\0';
406 put_entry(e);
408 #endif
410 elen = strlen(page) - off;
411 if (elen < 0)
412 elen = 0;
413 *eof = (elen <= count) ? 1 : 0;
414 *start = page + off;
415 err = elen;
417 _err:
418 return err;
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;
429 int res = count;
431 if (buffer[count-1] == '\n')
432 count--;
433 if ((count == 1) && !(buffer[0] & ~('0' | '1'))) {
434 if (data) {
435 if ((e = get_entry((long) data)))
436 e->flags = (e->flags & ~ENTRY_ENABLED)
437 | (int)(buffer[0] - '0');
438 put_entry(e);
439 } else {
440 enabled = buffer[0] - '0';
442 } else if ((count == 2) && (buffer[0] == '-') && (buffer[1] == '1')) {
443 if (data)
444 clear_entry((long) data);
445 else
446 clear_entries();
447 } else {
448 res = -EINVAL;
450 return res;
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");
470 return -ENOENT;
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;
475 return 0;
478 #ifdef MODULE
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)
489 if (fill)
490 MOD_INC_USE_COUNT;
491 else
492 MOD_DEC_USE_COUNT;
494 #endif
496 int __init init_misc_binfmt(void)
498 int error = -ENOENT;
499 struct proc_dir_entry *status = NULL, *reg;
501 bm_dir = create_proc_entry("sys/fs/binfmt_misc", S_IFDIR, NULL);
502 if (!bm_dir)
503 goto out;
504 #ifdef MODULE
505 bm_dir->fill_inode = bm_modcount;
506 #endif
508 status = create_proc_entry("status", S_IFREG | S_IRUGO | S_IWUSR,
509 bm_dir);
510 if (!status)
511 goto cleanup_bm;
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);
516 if (!reg)
517 goto cleanup_status;
518 reg->write_proc = proc_write_register;
520 error = register_binfmt(&misc_format);
521 out:
522 return error;
524 cleanup_status:
525 remove_proc_entry("status", bm_dir);
526 cleanup_bm:
527 remove_proc_entry("sys/fs/binfmt_misc", NULL);
528 goto out;
531 #ifdef MODULE
532 EXPORT_NO_SYMBOLS;
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);
543 clear_entries();
544 remove_proc_entry("sys/fs/binfmt_misc", NULL);
546 #endif
547 #undef VERBOSE_STATUS