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 <linux/spinlock.h> 31 #include <asm/uaccess.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 intload_misc_binary(struct linux_binprm
*bprm
,struct pt_regs
*regs
); 63 static voidentry_proc_cleanup(struct binfmt_entry
*e
); 64 static intentry_proc_setup(struct binfmt_entry
*e
); 66 static struct linux_binfmt misc_format
= { 67 NULL
, THIS_MODULE
, load_misc_binary
, NULL
, NULL
,0 70 static struct proc_dir_entry
*bm_dir
= NULL
; 72 static struct binfmt_entry
*entries
= NULL
; 73 static int free_id
=1; 74 static int enabled
=1; 76 static rwlock_t entries_lock
__attribute__((unused
)) = RW_LOCK_UNLOCKED
; 80 * Unregister one entry 82 static voidclear_entry(int id
) 84 struct binfmt_entry
**ep
, *e
; 86 write_lock(&entries_lock
); 88 while(*ep
&& ((*ep
)->id
!= id
)) 92 write_unlock(&entries_lock
); 95 entry_proc_cleanup(e
); 101 * Clear all registered binary formats 103 static voidclear_entries(void) 105 struct binfmt_entry
*e
, *n
; 107 write_lock(&entries_lock
); 110 write_unlock(&entries_lock
); 114 entry_proc_cleanup(e
); 120 * Find entry through id and lock it 122 static struct binfmt_entry
*get_entry(int id
) 124 struct binfmt_entry
*e
; 126 read_lock(&entries_lock
); 128 while(e
&& (e
->id
!= id
)) 131 read_unlock(&entries_lock
); 138 staticinlinevoidput_entry(struct binfmt_entry
*e
) 141 read_unlock(&entries_lock
); 146 * Check if we support the binfmt 147 * if we do, return the binfmt_entry, else NULL 148 * locking is done in load_misc_binary 150 static struct binfmt_entry
*check_file(struct linux_binprm
*bprm
) 152 struct binfmt_entry
*e
; 153 char*p
=strrchr(bprm
->filename
,'.'); 158 if(e
->flags
& ENTRY_ENABLED
) { 159 if(!(e
->flags
& ENTRY_MAGIC
)) { 160 if(p
&& !strcmp(e
->magic
, p
+1)) 164 while((j
< e
->size
) && 165 !((bprm
->buf
[e
->offset
+ j
] ^ e
->magic
[j
]) 166 & (e
->mask
? e
->mask
[j
] :0xff))) 180 static intload_misc_binary(struct linux_binprm
*bprm
,struct pt_regs
*regs
) 182 struct binfmt_entry
*fmt
; 183 struct dentry
* dentry
; 185 char*iname_addr
= iname
; 193 /* to keep locking time low, we copy the interpreter string */ 194 read_lock(&entries_lock
); 195 fmt
=check_file(bprm
); 197 strncpy(iname
, fmt
->interpreter
,127); 200 read_unlock(&entries_lock
); 207 /* Build args for interpreter */ 208 remove_arg_zero(bprm
); 209 retval
=copy_strings_kernel(1, &bprm
->filename
, bprm
); 210 if(retval
<0)goto _ret
; 212 retval
=copy_strings_kernel(1, &iname_addr
, bprm
); 213 if(retval
<0)goto _ret
; 215 bprm
->filename
= iname
;/* for binfmt_script */ 217 dentry
=open_namei(iname
,0,0); 218 retval
=PTR_ERR(dentry
); 221 bprm
->dentry
= dentry
; 223 retval
=prepare_binprm(bprm
); 225 retval
=search_binary_handler(bprm
, regs
); 234 * /proc handling routines 238 * parses and copies one argument enclosed in del from *sp to *dp, 239 * recognising the \x special. 240 * returns pointer to the copied argument or NULL in case of an 241 * error (and sets err) or null argument length. 243 static char*copyarg(char**dp
,const char**sp
,int*count
, 244 char del
,int special
,int*err
) 246 char c
=0, *res
= *dp
; 248 while(!*err
&& ((c
= *((*sp
)++)), (*count
)--) && (c
!= del
)) { 251 if(special
&& (**sp
=='x')) { 252 if(!isxdigit(c
=toupper(*(++*sp
)))) 254 **dp
= (c
- (isdigit(c
) ?'0':'A'-10)) *16; 255 if(!isxdigit(c
=toupper(*(++*sp
)))) 257 *((*dp
)++) += c
- (isdigit(c
) ?'0':'A'-10); 266 if(*err
|| (c
!= del
) || (res
== *dp
)) 274 * This registers a new binary format, it recognises the syntax 275 * ':name:type:offset:magic:mask:interpreter:' 276 * where the ':' is the IFS, that can be chosen with the first char 278 static intproc_write_register(struct file
*file
,const char*buffer
, 279 unsigned long count
,void*data
) 283 struct binfmt_entry
*e
; 284 int memsize
, cnt
= count
-1, err
; 286 /* some sanity checks */ 288 if((count
<11) || (count
>256)) 292 memsize
=sizeof(struct binfmt_entry
) + count
; 293 if(!(e
= (struct binfmt_entry
*)kmalloc(memsize
, GFP_USER
))) 299 dp
= (char*)e
+sizeof(struct binfmt_entry
); 301 e
->proc_name
=copyarg(&dp
, &sp
, &cnt
, del
,0, &err
); 303 /* we can use bit 3 of type for ext/magic 304 flag due to the nice encoding of E and M */ 305 if((*sp
& ~('E'|'M')) || (sp
[1] != del
)) 308 e
->flags
= (*sp
++ & (ENTRY_MAGIC
| ENTRY_ENABLED
)); 312 while(cnt
-- &&isdigit(*sp
)) 313 e
->offset
= e
->offset
*10+ *sp
++ -'0'; 317 e
->magic
=copyarg(&dp
, &sp
, &cnt
, del
, (e
->flags
& ENTRY_MAGIC
), &err
); 318 e
->size
= dp
- e
->magic
; 319 e
->mask
=copyarg(&dp
, &sp
, &cnt
, del
,1, &err
); 320 if(e
->mask
&& ((dp
- e
->mask
) != e
->size
)) 322 e
->interpreter
=copyarg(&dp
, &sp
, &cnt
, del
,0, &err
); 325 /* more sanity checks */ 326 if(err
|| !(!cnt
|| (!(--cnt
) && (*sp
=='\n'))) || 327 (e
->size
<1) || ((e
->size
+ e
->offset
) >127) || 328 !(e
->proc_name
) || !(e
->interpreter
) ||entry_proc_setup(e
)) 331 write_lock(&entries_lock
); 334 write_unlock(&entries_lock
); 346 * Get status of entry/binfmt_misc 347 * FIXME? should an entry be marked disabled if binfmt_misc is disabled though 350 static intproc_read_status(char*page
,char**start
, off_t off
, 351 int count
,int*eof
,void*data
) 353 struct binfmt_entry
*e
; 357 #ifndef VERBOSE_STATUS 359 if(!(e
=get_entry((int) data
))) { 363 i
= e
->flags
& ENTRY_ENABLED
; 368 sprintf(page
,"%s\n", (i
?"enabled":"disabled")); 371 sprintf(page
,"%s\n", (enabled
?"enabled":"disabled")); 373 if(!(e
=get_entry((long) data
))) { 377 sprintf(page
,"%s\ninterpreter %s\n", 378 (e
->flags
& ENTRY_ENABLED
?"enabled":"disabled"), 380 dp
= page
+strlen(page
); 381 if(!(e
->flags
& ENTRY_MAGIC
)) { 382 sprintf(dp
,"extension .%s\n", e
->magic
); 383 dp
= page
+strlen(page
); 385 sprintf(dp
,"offset %i\nmagic ", e
->offset
); 386 dp
= page
+strlen(page
); 387 for(i
=0; i
< e
->size
; i
++) { 388 sprintf(dp
,"%02x",0xff& (int) (e
->magic
[i
])); 392 sprintf(dp
,"\nmask "); 394 for(i
=0; i
< e
->size
; i
++) { 395 sprintf(dp
,"%02x",0xff& (int) (e
->mask
[i
])); 406 elen
=strlen(page
) - off
; 409 *eof
= (elen
<= count
) ?1:0; 418 * Set status of entry/binfmt_misc: 419 * '1' enables, '0' disables and '-1' clears entry/binfmt_misc 421 static intproc_write_status(struct file
*file
,const char*buffer
, 422 unsigned long count
,void*data
) 424 struct binfmt_entry
*e
; 427 if(buffer
[count
-1] =='\n') 429 if((count
==1) && !(buffer
[0] & ~('0'|'1'))) { 431 if((e
=get_entry((long) data
))) 432 e
->flags
= (e
->flags
& ~ENTRY_ENABLED
) 433 | (int)(buffer
[0] -'0'); 436 enabled
= buffer
[0] -'0'; 438 }else if((count
==2) && (buffer
[0] =='-') && (buffer
[1] =='1')) { 440 clear_entry((long) data
); 450 * Remove the /proc-dir entries of one binfmt 452 static voidentry_proc_cleanup(struct binfmt_entry
*e
) 454 remove_proc_entry(e
->proc_name
, bm_dir
); 458 * Create the /proc-dir entry for binfmt 460 static intentry_proc_setup(struct binfmt_entry
*e
) 462 if(!(e
->proc_dir
=create_proc_entry(e
->proc_name
, 463 S_IFREG
| S_IRUGO
| S_IWUSR
, bm_dir
))) 465 printk(KERN_WARNING
"Unable to create /proc entry.\n"); 468 e
->proc_dir
->data
= (void*) (e
->id
); 469 e
->proc_dir
->read_proc
= proc_read_status
; 470 e
->proc_dir
->write_proc
= proc_write_status
; 476 * This is called as the fill_inode function when an inode 477 * is going into (fill = 1) or out of service (fill = 0). 478 * We use it here to manage the module use counts. 480 * Note: only the top-level directory needs to do this; if 481 * a lower level is referenced, the parent will be as well. 483 static voidbm_modcount(struct inode
*inode
,int fill
) 492 static int __init
init_misc_binfmt(void) 495 struct proc_dir_entry
*status
= NULL
, *reg
; 497 bm_dir
=create_proc_entry("sys/fs/binfmt_misc", S_IFDIR
, NULL
); 501 bm_dir
->fill_inode
= bm_modcount
; 504 status
=create_proc_entry("status", S_IFREG
| S_IRUGO
| S_IWUSR
, 508 status
->read_proc
= proc_read_status
; 509 status
->write_proc
= proc_write_status
; 511 reg
=create_proc_entry("register", S_IFREG
| S_IWUSR
, bm_dir
); 514 reg
->write_proc
= proc_write_register
; 516 error
=register_binfmt(&misc_format
); 521 remove_proc_entry("status", bm_dir
); 523 remove_proc_entry("sys/fs/binfmt_misc", NULL
); 527 static void __exit
exit_misc_binfmt(void) 529 unregister_binfmt(&misc_format
); 530 remove_proc_entry("register", bm_dir
); 531 remove_proc_entry("status", bm_dir
); 533 remove_proc_entry("sys/fs/binfmt_misc", NULL
); 538 module_init(init_misc_binfmt
) 539 module_exit(exit_misc_binfmt
)