Import 2.3.12pre9
[davej-history.git] / fs / binfmt_misc.c
blob69920f45b151e6345b4f14bd927c99c36322d708
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 NULL,
68 #ifndef MODULE
69 NULL,
70 #else
71 &__this_module,
72 #endif
73 load_misc_binary, NULL, NULL, 0
76 static struct proc_dir_entry *bm_dir = NULL;
78 static struct binfmt_entry *entries = NULL;
79 static int free_id = 1;
80 static int enabled = 1;
82 static rwlock_t entries_lock __attribute__((unused)) = RW_LOCK_UNLOCKED;
86 * Unregister one entry
88 static void clear_entry(int id)
90 struct binfmt_entry **ep, *e;
92 write_lock(&entries_lock);
93 ep = &entries;
94 while (*ep && ((*ep)->id != id))
95 ep = &((*ep)->next);
96 if ((e = *ep))
97 *ep = e->next;
98 write_unlock(&entries_lock);
100 if (e) {
101 entry_proc_cleanup(e);
102 kfree(e);
107 * Clear all registered binary formats
109 static void clear_entries(void)
111 struct binfmt_entry *e, *n;
113 write_lock(&entries_lock);
114 n = entries;
115 entries = NULL;
116 write_unlock(&entries_lock);
118 while ((e = n)) {
119 n = e->next;
120 entry_proc_cleanup(e);
121 kfree(e);
126 * Find entry through id and lock it
128 static struct binfmt_entry *get_entry(int id)
130 struct binfmt_entry *e;
132 read_lock(&entries_lock);
133 e = entries;
134 while (e && (e->id != id))
135 e = e->next;
136 if (!e)
137 read_unlock(&entries_lock);
138 return e;
142 * unlock entry
144 static inline void put_entry(struct binfmt_entry *e)
146 if (e)
147 read_unlock(&entries_lock);
152 * Check if we support the binfmt
153 * if we do, return the binfmt_entry, else NULL
154 * locking is done in load_misc_binary
156 static struct binfmt_entry *check_file(struct linux_binprm *bprm)
158 struct binfmt_entry *e;
159 char *p = strrchr(bprm->filename, '.');
160 int j;
162 e = entries;
163 while (e) {
164 if (e->flags & ENTRY_ENABLED) {
165 if (!(e->flags & ENTRY_MAGIC)) {
166 if (p && !strcmp(e->magic, p + 1))
167 return e;
168 } else {
169 j = 0;
170 while ((j < e->size) &&
171 !((bprm->buf[e->offset + j] ^ e->magic[j])
172 & (e->mask ? e->mask[j] : 0xff)))
173 j++;
174 if (j == e->size)
175 return e;
178 e = e->next;
180 return NULL;
184 * the loader itself
186 static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs)
188 struct binfmt_entry *fmt;
189 struct dentry * dentry;
190 char iname[128];
191 char *iname_addr = iname;
192 int retval;
194 MOD_INC_USE_COUNT;
195 retval = -ENOEXEC;
196 if (!enabled)
197 goto _ret;
199 /* to keep locking time low, we copy the interpreter string */
200 read_lock(&entries_lock);
201 fmt = check_file(bprm);
202 if (fmt) {
203 strncpy(iname, fmt->interpreter, 127);
204 iname[127] = '\0';
206 read_unlock(&entries_lock);
207 if (!fmt)
208 goto _ret;
210 dput(bprm->dentry);
211 bprm->dentry = NULL;
213 /* Build args for interpreter */
214 remove_arg_zero(bprm);
215 retval = copy_strings_kernel(1, &bprm->filename, bprm);
216 if (retval < 0) goto _ret;
217 bprm->argc++;
218 retval = copy_strings_kernel(1, &iname_addr, bprm);
219 if (retval < 0) goto _ret;
220 bprm->argc++;
221 bprm->filename = iname; /* for binfmt_script */
223 dentry = open_namei(iname, 0, 0);
224 retval = PTR_ERR(dentry);
225 if (IS_ERR(dentry))
226 goto _ret;
227 bprm->dentry = dentry;
229 retval = prepare_binprm(bprm);
230 if (retval >= 0)
231 retval = search_binary_handler(bprm, regs);
232 _ret:
233 MOD_DEC_USE_COUNT;
234 return retval;
240 * /proc handling routines
244 * parses and copies one argument enclosed in del from *sp to *dp,
245 * recognising the \x special.
246 * returns pointer to the copied argument or NULL in case of an
247 * error (and sets err) or null argument length.
249 static char *copyarg(char **dp, const char **sp, int *count,
250 char del, int special, int *err)
252 char c = 0, *res = *dp;
254 while (!*err && ((c = *((*sp)++)), (*count)--) && (c != del)) {
255 switch (c) {
256 case '\\':
257 if (special && (**sp == 'x')) {
258 if (!isxdigit(c = toupper(*(++*sp))))
259 *err = -EINVAL;
260 **dp = (c - (isdigit(c) ? '0' : 'A' - 10)) * 16;
261 if (!isxdigit(c = toupper(*(++*sp))))
262 *err = -EINVAL;
263 *((*dp)++) += c - (isdigit(c) ? '0' : 'A' - 10);
264 ++*sp;
265 *count -= 3;
266 break;
268 default:
269 *((*dp)++) = c;
272 if (*err || (c != del) || (res == *dp))
273 res = NULL;
274 else if (!special)
275 *((*dp)++) = '\0';
276 return res;
280 * This registers a new binary format, it recognises the syntax
281 * ':name:type:offset:magic:mask:interpreter:'
282 * where the ':' is the IFS, that can be chosen with the first char
284 static int proc_write_register(struct file *file, const char *buffer,
285 unsigned long count, void *data)
287 const char *sp;
288 char del, *dp;
289 struct binfmt_entry *e;
290 int memsize, cnt = count - 1, err;
292 /* some sanity checks */
293 err = -EINVAL;
294 if ((count < 11) || (count > 256))
295 goto _err;
297 err = -ENOMEM;
298 memsize = sizeof(struct binfmt_entry) + count;
299 if (!(e = (struct binfmt_entry *) kmalloc(memsize, GFP_USER)))
300 goto _err;
302 err = 0;
303 sp = buffer + 1;
304 del = buffer[0];
305 dp = (char *)e + sizeof(struct binfmt_entry);
307 e->proc_name = copyarg(&dp, &sp, &cnt, del, 0, &err);
309 /* we can use bit 3 of type for ext/magic
310 flag due to the nice encoding of E and M */
311 if ((*sp & ~('E' | 'M')) || (sp[1] != del))
312 err = -EINVAL;
313 else
314 e->flags = (*sp++ & (ENTRY_MAGIC | ENTRY_ENABLED));
315 cnt -= 2; sp++;
317 e->offset = 0;
318 while (cnt-- && isdigit(*sp))
319 e->offset = e->offset * 10 + *sp++ - '0';
320 if (*sp++ != del)
321 err = -EINVAL;
323 e->magic = copyarg(&dp, &sp, &cnt, del, (e->flags & ENTRY_MAGIC), &err);
324 e->size = dp - e->magic;
325 e->mask = copyarg(&dp, &sp, &cnt, del, 1, &err);
326 if (e->mask && ((dp - e->mask) != e->size))
327 err = -EINVAL;
328 e->interpreter = copyarg(&dp, &sp, &cnt, del, 0, &err);
329 e->id = free_id++;
331 /* more sanity checks */
332 if (err || !(!cnt || (!(--cnt) && (*sp == '\n'))) ||
333 (e->size < 1) || ((e->size + e->offset) > 127) ||
334 !(e->proc_name) || !(e->interpreter) || entry_proc_setup(e))
335 goto free_err;
337 write_lock(&entries_lock);
338 e->next = entries;
339 entries = e;
340 write_unlock(&entries_lock);
342 err = count;
343 _err:
344 return err;
345 free_err:
346 kfree(e);
347 err = -EINVAL;
348 goto _err;
352 * Get status of entry/binfmt_misc
353 * FIXME? should an entry be marked disabled if binfmt_misc is disabled though
354 * entry is enabled?
356 static int proc_read_status(char *page, char **start, off_t off,
357 int count, int *eof, void *data)
359 struct binfmt_entry *e;
360 char *dp;
361 int elen, i, err;
363 #ifndef VERBOSE_STATUS
364 if (data) {
365 if (!(e = get_entry((int) data))) {
366 err = -ENOENT;
367 goto _err;
369 i = e->flags & ENTRY_ENABLED;
370 put_entry(e);
371 } else {
372 i = enabled;
374 sprintf(page, "%s\n", (i ? "enabled" : "disabled"));
375 #else
376 if (!data)
377 sprintf(page, "%s\n", (enabled ? "enabled" : "disabled"));
378 else {
379 if (!(e = get_entry((long) data))) {
380 err = -ENOENT;
381 goto _err;
383 sprintf(page, "%s\ninterpreter %s\n",
384 (e->flags & ENTRY_ENABLED ? "enabled" : "disabled"),
385 e->interpreter);
386 dp = page + strlen(page);
387 if (!(e->flags & ENTRY_MAGIC)) {
388 sprintf(dp, "extension .%s\n", e->magic);
389 dp = page + strlen(page);
390 } else {
391 sprintf(dp, "offset %i\nmagic ", e->offset);
392 dp = page + strlen(page);
393 for (i = 0; i < e->size; i++) {
394 sprintf(dp, "%02x", 0xff & (int) (e->magic[i]));
395 dp += 2;
397 if (e->mask) {
398 sprintf(dp, "\nmask ");
399 dp += 6;
400 for (i = 0; i < e->size; i++) {
401 sprintf(dp, "%02x", 0xff & (int) (e->mask[i]));
402 dp += 2;
405 *dp++ = '\n';
406 *dp = '\0';
408 put_entry(e);
410 #endif
412 elen = strlen(page) - off;
413 if (elen < 0)
414 elen = 0;
415 *eof = (elen <= count) ? 1 : 0;
416 *start = page + off;
417 err = elen;
419 _err:
420 return err;
424 * Set status of entry/binfmt_misc:
425 * '1' enables, '0' disables and '-1' clears entry/binfmt_misc
427 static int proc_write_status(struct file *file, const char *buffer,
428 unsigned long count, void *data)
430 struct binfmt_entry *e;
431 int res = count;
433 if (buffer[count-1] == '\n')
434 count--;
435 if ((count == 1) && !(buffer[0] & ~('0' | '1'))) {
436 if (data) {
437 if ((e = get_entry((long) data)))
438 e->flags = (e->flags & ~ENTRY_ENABLED)
439 | (int)(buffer[0] - '0');
440 put_entry(e);
441 } else {
442 enabled = buffer[0] - '0';
444 } else if ((count == 2) && (buffer[0] == '-') && (buffer[1] == '1')) {
445 if (data)
446 clear_entry((long) data);
447 else
448 clear_entries();
449 } else {
450 res = -EINVAL;
452 return res;
456 * Remove the /proc-dir entries of one binfmt
458 static void entry_proc_cleanup(struct binfmt_entry *e)
460 remove_proc_entry(e->proc_name, bm_dir);
464 * Create the /proc-dir entry for binfmt
466 static int entry_proc_setup(struct binfmt_entry *e)
468 if (!(e->proc_dir = create_proc_entry(e->proc_name,
469 S_IFREG | S_IRUGO | S_IWUSR, bm_dir)))
471 printk(KERN_WARNING "Unable to create /proc entry.\n");
472 return -ENOENT;
474 e->proc_dir->data = (void *) (e->id);
475 e->proc_dir->read_proc = proc_read_status;
476 e->proc_dir->write_proc = proc_write_status;
477 return 0;
480 #ifdef MODULE
482 * This is called as the fill_inode function when an inode
483 * is going into (fill = 1) or out of service (fill = 0).
484 * We use it here to manage the module use counts.
486 * Note: only the top-level directory needs to do this; if
487 * a lower level is referenced, the parent will be as well.
489 static void bm_modcount(struct inode *inode, int fill)
491 if (fill)
492 MOD_INC_USE_COUNT;
493 else
494 MOD_DEC_USE_COUNT;
496 #endif
498 int __init init_misc_binfmt(void)
500 int error = -ENOENT;
501 struct proc_dir_entry *status = NULL, *reg;
503 bm_dir = create_proc_entry("sys/fs/binfmt_misc", S_IFDIR, NULL);
504 if (!bm_dir)
505 goto out;
506 #ifdef MODULE
507 bm_dir->fill_inode = bm_modcount;
508 #endif
510 status = create_proc_entry("status", S_IFREG | S_IRUGO | S_IWUSR,
511 bm_dir);
512 if (!status)
513 goto cleanup_bm;
514 status->read_proc = proc_read_status;
515 status->write_proc = proc_write_status;
517 reg = create_proc_entry("register", S_IFREG | S_IWUSR, bm_dir);
518 if (!reg)
519 goto cleanup_status;
520 reg->write_proc = proc_write_register;
522 error = register_binfmt(&misc_format);
523 out:
524 return error;
526 cleanup_status:
527 remove_proc_entry("status", bm_dir);
528 cleanup_bm:
529 remove_proc_entry("sys/fs/binfmt_misc", NULL);
530 goto out;
533 #ifdef MODULE
534 EXPORT_NO_SYMBOLS;
535 int init_module(void)
537 return init_misc_binfmt();
540 void cleanup_module(void)
542 unregister_binfmt(&misc_format);
543 remove_proc_entry("register", bm_dir);
544 remove_proc_entry("status", bm_dir);
545 clear_entries();
546 remove_proc_entry("sys/fs/binfmt_misc", NULL);
548 #endif
549 #undef VERBOSE_STATUS