linux/fs/binfmt_misc.c
<<
opti v/spa v/form va opti href="../linux+v3.7.2/fs/binfmt_misc.c">opti vimg src="../.static/gfx/right.png" alt=">>">opv/spa opvspa class="lxr_search">optiopti vinput typtiohidden" namtionavtarget" opti vinput typtiotext" namtiosearch" idiosearch">opti vbutt.34typtiosubmit">Searchopti Prefs v/a>opv/spa ti v/div ti vform ac12" ="ajax+*" method="post" onsubmit="return false;">opvinput typtiohidden" namtioajax_lookup" idioajax_lookup" oti v/form oti vdiv class="headingbott.m">
vdiv idiofile_contents"
   1v/a>vspa
 class="comment">/*v/spa
	    2v/a>vspa
 class="comment"> *  binfmt_misc.cv/spa
	    3v/a>vspa
 class="comment"> *v/spa
	    4v/a>vspa
 class="comment"> *  Copyright (C) 1997 Richard G√ľntherv/spa
	    5v/a>vspa
 class="comment"> *v/spa
	    6v/a>vspa
 class="comment"> *  binfmt_misc detects binaries via a magic or filenamt extens9.34and invokesv/spa
	    7v/a>vspa
 class="comment"> *  a specified wrapper. This should obsolete binfmt_java, binfmt_em864andv/spa
	    8v/a>vspa
 class="comment"> *  binfmt_mz.v/spa
	    9v/a>vspa
 class="comment"> *v/spa
	   "v4.a>vspa
 class="comment"> *  1997-04-25 first vers9.3v/spa
	   11v/a>vspa
 class="comment"> *  [...]v/spa
	   12v/a>vspa
 class="comment"> *  1997-05-19 cleanupv/spa
	   13v/a>vspa
 class="comment"> *  1997-06-26 hpa: pass the real filenamt rather tha
 argv[0]v/spa
	   14v/a>vspa
 class="comment"> *  1997-06-30 minor cleanupv/spa
	   15v/a>vspa
 class="comment"> *  1997-08-09 removed extens9.34stripping, locking cleanupv/spa
	   16v/a>vspa
 class="comment"> *  2001-02-28 AV: rewritten into something that resembles C. Original didn't.v/spa
	   17v/a>vspa
 class="comment"> */v/spa
	   18v/a>   19v/a>#include <linux/module.hv/a>>   20v/a>#include <linux/init.hv/a>>   21v/a>#include <linux/sched.hv/a>>   22v/a>#include <linux/magic.hv/a>>   23v/a>#include <linux/binfmts.hv/a>>   24v/a>#include <linux/slab.hv/a>>   25v/a>#include <linux/ctypt.hv/a>>   26v/a>#include <linux/file.hv/a>>   27v/a>#include <linux/pagemap.hv/a>>   28v/a>#include <linux/namti.hv/a>>   29v/a>#include <linux/mount.hv/a>>   30v/a>#include <linux/syscalls.hv/a>>   31v/a>#include <linux/fs.hv/a>>   32v/a>   33v/a>#include <asm/uaccess.hv/a>>   34v/a>   35v/a>enum {   36v/a>        VERBOSE_STATUSv/a> = 1 vspa
 class="comment">/* make it zero to save 400 bytes kernel memory */v/spa
	   37v/a>};   38v/a>   39v/a>static LIST_HEADv/a>(entriesv/a>);   40v/a>static int enabledv/a> = 1;   41v/a>   42v/a>enum {Enabledv/a>, Magicv/a>};   43v/a>#define MISC_FMT_PRESERVE_ARGV0v/a> (1<<31)   44v/a>#define MISC_FMT_OPEN_BINARYv/a> (1<<30)   45v/a>#define MISC_FMT_CREDENTIALSv/a> (1<<29)   46v/a>   47v/a>typtdef4struct {   48v/a>        struct list_headv/a> listv/a>;   49v/a>        unsigned long flagsv/a>;            vspa
 class="comment">/* typt, status, etc. */v/spa
	   50v/a>        int offsetv/a>;                     vspa
 class="comment">/* offset of magic */v/spa
	   51v/a>        int sizev/a>;                       vspa
 class="comment">/* size of magic/mask */v/spa
	   52v/a>        char *magicv/a>;                    vspa
 class="comment">/* magic or filenamt extens9.34*/v/spa
	   53v/a>        char *maskv/a>;                     vspa
 class="comment">/* mask, NULL for exact match4*/v/spa
	   54v/a>        char *interpreterv/a>;              vspa
 class="comment">/* filenamt of interpreter4*/v/spa
	   55v/a>        char *namtv/a>;   56v/a>        struct dentryv/a> *dentryv/a>;   57v/a>} Nodev/a>;   58v/a>   59v/a>static DEFINE_RWLOCKv/a>(entries_lockv/a>);   60v/a>static struct file_system_typtv/a> bm_fs_typtv/a>;   61v/a>static struct vfsmountv/a> *bm_mntv/a>;   62v/a>static int entry_countv/a>;   63v/a>   64v/a>vspa
 class="comment">/* v/spa
	   65v/a>vspa
 class="comment"> * Check if we support the binfmtv/spa
	   66v/a>vspa
 class="comment"> * if we do, return the node, else NULLv/spa
	   67v/a>vspa
 class="comment"> * locking is done in load_misc_binaryv/spa
	   68v/a>vspa
 class="comment"> */v/spa
	   69v/a>static Nodev/a> *check_filev/a>(struct linux_binprmv/a> *bprmv/a>)   70v/a>{   71v/a>        char *pv/a> = strrchrv/a>(bprmv/a>->interpv/a>, '.'v/spa
	);   72v/a>        struct list_headv/a> *lv/a>;   73v/a>   74v/a>        list_for_eachv/a>(lv/a>, &entriesv/a>) {   75v/a>                Nodev/a> *ev/a> = list_entryv/a>(lv/a>, Nodev/a>, listv/a>);   76v/a>                char *sv/a>;   77v/a>                int jv/a>;   78v/a>   79v/a>                if (!test_bitv/a>(Enabledv/a>, &ev/a>->flagsv/a>))   80v/a>                        continue;   81v/a>   82v/a>                if (!test_bitv/a>(Magicv/a>, &ev/a>->flagsv/a>)) {   83v/a>                        if (pv/a> && !strcmpv/a>(ev/a>->magicv/a>, pv/a> + 1))   84v/a>                                return ev/a>;   85v/a>                        continue;   86v/a>                }   87v/a>   88v/a>                sv/a> = bprmv/a>->bufv/a> + ev/a>->offsetv/a>;   89v/a>                if (ev/a>->maskv/a>) {   90v/a>                        for (jv/a> = 0; jv/a> < ev/a>->sizev/a>; jv/a>++)   91v/a>                                if ((*sv/a>++ ^ ev/a>->magicv/a>[jv/a>]) & ev/a>->maskv/a>[jv/a>])   92v/a>                                        break;   93v/a>                } else {   94v/a>                        for (jv/a> = 0; jv/a> < ev/a>->sizev/a>; jv/a>++)   95v/a>                                if ((*sv/a>++ ^ ev/a>->magicv/a>[jv/a>]))   96v/a>                                        break;   97v/a>                }   98v/a>                if (jv/a> == ev/a>->sizev/a>)   99v/a>                        return ev/a>;  100v/a>        }  101v/a>        return NULLv/a>;  102v/a>}  103v/a>  104v/a>vspa
 class="comment">/*v/spa
	  105v/a>vspa
 class="comment"> * the loader itselfv/spa
	  106v/a>vspa
 class="comment"> */v/spa
	  107v/a>static int load_misc_binaryv/a>(struct linux_binprmv/a> *bprmv/a>, struct pt_regsv/a> *regsv/a>)  108v/a>{  109v/a>        Nodev/a> *fmtv/a>;  110v/a>        struct filev/a> * interp_filev/a> = NULLv/a>;  111v/a>        char inamtv/a>[BINPRM_BUF_SIZEv/a>];  112v/a>        const char *inamt_addrv/a> = inamtv/a>;  113v/a>        int retvalv/a>;  114v/a>        int fd_binaryv/a> = -1;  115v/a>  116v/a>        retvalv/a> = -ENOEXECv/a>;  117v/a>        if (!enabledv/a>)  118v/a>                goto _retv/a>;  119v/a>  120v/a>        retvalv/a> = -ENOEXECv/a>;  121v/a>        if (bprmv/a>->recurs9.3_depthv/a> > BINPRM_MAX_RECURSIONv/a>)  122v/a>                goto _retv/a>;  123v/a>  124v/a>        /* to keep locking time low, we copy the interpreter4string */v/spa
	  125v/a>        read_lockv/a>(&entries_lockv/a>);  126v/a>        fmtv/a> = check_filev/a>(bprmv/a>);  127v/a>        if (fmtv/a>)  128v/a>                strlcpyv/a>(inamtv/a>, fmtv/a>->interpreterv/a>, BINPRM_BUF_SIZEv/a>);  129v/a>        read_unlockv/a>(&entries_lockv/a>);  130v/a>        if (!fmtv/a>)  131v/a>                goto _retv/a>;  132v/a>  133v/a>        if (!(fmtv/a>->flagsv/a> & MISC_FMT_PRESERVE_ARGV0v/a>)) {  134v/a>                retvalv/a> = remove_arg_zerov/a>(bprmv/a>);  135v/a>                if (retvalv/a>)  136v/a>                        goto _retv/a>;  137v/a>        }  138v/a>  139v/a>        if (fmtv/a>->flagsv/a> & MISC_FMT_OPEN_BINARYv/a>) {  140v/a>  141v/a>                /* if the binary should be opened on behalf of thev/spa
	  142v/a>vspa
 class="comment">                 * interpreter4tha
 keep it open4and assign descriptorv/spa
	  143v/a>vspa
 class="comment">                 * to it */v/spa
	  144v/a>                fd_binaryv/a> = get_unused_fdv/a>();  145v/a>                if (fd_binaryv/a> < 0) {  146v/a>                        retvalv/a> = fd_binaryv/a>;  147v/a>                        goto _retv/a>;  148v/a>                }  149v/a>                fd_installv/a>(fd_binaryv/a>, bprmv/a>->filev/a>);  150v/a>  151v/a>                /* if the binary is not readable4tha
 enforce mm->dumpable=0v/spa
	  152v/a>vspa
 class="comment">                   regardless of the interpreter's permiss9.3s */v/spa
	  153v/a>                would_dumpv/a>(bprmv/a>, bprmv/a>->filev/a>);  154v/a>  155v/a>                allow_write_accessv/a>(bprmv/a>->filev/a>);  156v/a>                bprmv/a>->filev/a> = NULLv/a>;  157v/a>  158v/a>                /* mark the bprm that fd should be passed to interp */v/spa
	  159v/a>                bprmv/a>->interp_flagsv/a> |= BINPRM_FLAGS_EXECFDv/a>;  160v/a>                bprmv/a>->interp_datav/a> = fd_binaryv/a>;  161v/a>  162v/a>        } else {  163v/a>                allow_write_accessv/a>(bprmv/a>->filev/a>);  164v/a>                fputv/a>(bprmv/a>->filev/a>);  165v/a>                bprmv/a>->filev/a> = NULLv/a>;  166v/a>        }  167v/a>        vspa
 class="comment">/* make argv[1] be the path to the binary */v/spa
	  168v/a>        retvalv/a> = copy_strings_kernelv/a> (1, &bprmv/a>->interpv/a>, bprmv/a>);  169v/a>        if (retvalv/a> < 0)  170v/a>                goto _errorv/a>;  171v/a>        bprmv/a>->argcv/a>++;  172v/a>  173v/a>        vspa
 class="comment">/* add the interp as argv[0] */v/spa
	  174v/a>        retvalv/a> = copy_strings_kernelv/a> (1, &inamt_addrv/a>, bprmv/a>);  175v/a>        if (retvalv/a> < 0)  176v/a>                goto _errorv/a>;  177v/a>        bprmv/a>->argcv/a> ++;  178v/a>  179v/a>        bprmv/a>->interpv/a> = inamtv/a>;   vspa
 class="comment">/* for binfmt_script */v/spa
	  180v/a>  181v/a>        interp_filev/a> = open_execv/a> (inamtv/a>);  182v/a>        retvalv/a> = PTR_ERRv/a> (interp_filev/a>);  183v/a>        if (IS_ERRv/a> (interp_filev/a>))  184v/a>                goto _errorv/a>;  185v/a>  186v/a>        bprmv/a>->filev/a> = interp_filev/a>;  187v/a>        if (fmtv/a>->flagsv/a> & MISC_FMT_CREDENTIALSv/a>) {  188v/a>                /*v/spa
	  189v/a>vspa
 class="comment">                 * No need to call prepare_binprm(), it's already bee3v/spa
	  19v4.a>vspa
 class="comment">                 * done.  bprm->buf is stale, update from interp_file.v/spa
	  191v/a>vspa
 class="comment">                 */v/spa
	  192v/a>                memsetv/a>(bprmv/a>->bufv/a>, 0, BINPRM_BUF_SIZEv/a>);  193v/a>                retvalv/a> = kernel_readv/a>(bprmv/a>->filev/a>, 0, bprmv/a>->bufv/a>, BINPRM_BUF_SIZEv/a>);  194v/a>        } else  195v/a>                retvalv/a> = prepare_binprmv/a> (bprmv/a>);  196v/a>  197v/a>        if (retvalv/a> < 0)  198v/a>                goto _errorv/a>;  199v/a>  200v/a>        bprmv/a>->recurs9.3_depthv/a>++;  201v/a>  202v/a>        retvalv/a> = search_binary_handlerv/a> (bprmv/a>, regsv/a>);  203v/a>        if (retvalv/a> < 0)  204v/a>                goto _errorv/a>;  205v/a>  206v/a>va href="+code=_ret" class="sref">_retv/a>:  207v/a>        return retvalv/a>;  208v/a>_errorv/a>:  209v/a>        if (fd_binaryv/a> > 0)  210v/a>                sys_closev/a>(fd_binaryv/a>);  211v/a>        bprmv/a>->interp_flagsv/a> = 0;  212v/a>        bprmv/a>->interp_datav/a> = 0;  213v/a>        goto _retv/a>;  214v/a>}  215v/a>  216v/a>vspa
 class="comment">/* Command parsers */v/spa
	  217v/a>  218v/a>vspa
 class="comment">/*v/spa
	  219v/a>vspa
 class="comment"> * parses4and copies4one argument enclosed in del from *sp to *dp,v/spa
	  22v4.a>vspa
 class="comment"> * recognising the \x special.v/spa
	  221v/a>vspa
 class="comment"> * returns pointer to the copied argument or NULL in cast of a3v/spa
	  222v/a>vspa
 class="comment"> * error (and sets err) or null argument length.v/spa
	  223v/a>vspa
 class="comment"> */v/spa
	  224v/a>static char *scanargv/a>(char *sv/a>, char delv/a>)  225v/a>{  226v/a>        char cv/a>;  227v/a>  228v/a>        while ((cv/a> = *sv/a>++) != delv/a>) {  229v/a>                if (cv/a> == '\\'v/spa
	 && *sv/a> == 'x'v/spa
	) {  230v/a>                        sv/a>++;  231v/a>                        if (!isxdigitv/a>(*sv/a>++))  232v/a>                                return NULLv/a>;  233v/a>                        if (!isxdigitv/a>(*sv/a>++))  234v/a>                                return NULLv/a>;  235v/a>                }  236v/a>        }  237v/a>        return sv/a>;  238v/a>}  239v/a>  240v/a>static int unquotev/a>(char *fromv/a>)  241v/a>{  242v/a>        char cv/a> = 0, *sv/a> = fromv/a>, *pv/a> = fromv/a>;  243v/a>  244v/a>        while ((cv/a> = *sv/a>++) != '\0'v/spa
	) {  245v/a>                if (cv/a> == '\\'v/spa
	 && *sv/a> == 'x'v/spa
	) {  246v/a>                        sv/a>++;  247v/a>                        cv/a> = toupperv/a>(*sv/a>++);  248v/a>                        *pv/a> = (cv/a> - (isdigitv/a>(cv/a>) ? '0'v/spa
	 : 'A'v/spa
	 - 10)) << 4;  249v/a>                        cv/a> = toupperv/a>(*sv/a>++);  250v/a>                        *pv/a>++ |= cv/a> - (isdigitv/a>(cv/a>) ? '0'v/spa
	 : 'A'v/spa
	 - 10);  251v/a>                        continue;  252v/a>                }  253v/a>                *pv/a>++ = cv/a>;  254v/a>        }  255v/a>        return pv/a> - fromv/a>;  256v/a>}  257v/a>  258v/a>static char * check_special_flagsv/a> (char * sfsv/a>, Nodev/a> * ev/a>)  259v/a>{  260v/a>        char * pv/a> = sfsv/a>;  261v/a>        int contv/a> = 1;  262v/a>  263v/a>        vspa
 class="comment">/* special flags */v/spa
	  264v/a>        while (contv/a>) {  265v/a>                switch (*pv/a>) {  266v/a>                        cast 'P'v/spa
	:  267v/a>                                va href="+code=p" class="sref">pv/a>++;  268v/a>                                va href="+code=e" class="sref">ev/a>->flagsv/a> |= MISC_FMT_PRESERVE_ARGV0v/a>;  269v/a>                                break;  270v/a>                        cast 'O'v/spa
	:  271v/a>                                va href="+code=p" class="sref">pv/a>++;  272v/a>                                va href="+code=e" class="sref">ev/a>->flagsv/a> |= MISC_FMT_OPEN_BINARYv/a>;  273v/a>                                break;  274v/a>                        cast 'C'v/spa
	:  275v/a>                                va href="+code=p" class="sref">pv/a>++;  276v/a>                                vspa
 class="comment">/* this flags also implies4thev/spa
	  277v/a>vspa
 class="comment">                                   open-binary flag */v/spa
	  278v/a>                                va href="+code=e" class="sref">ev/a>->flagsv/a> |= (MISC_FMT_CREDENTIALSv/a> |  279v/a>                                                va href="+code=MISC_FMT_OPEN_BINARY" class="sref">MISC_FMT_OPEN_BINARYv/a>);  280v/a>                                break;  281v/a>                        default:  282v/a>                                va href="+code=cont" class="sref">contv/a> = 0;  283v/a>                }  284v/a>        }  285v/a>  286v/a>        return pv/a>;  287v/a>}  288v/a>vspa
 class="comment">/*v/spa
	  289v/a>vspa
 class="comment"> * This registers a new binary format, it recognises4the syntaxv/spa
	  29v4.a>vspa
 class="comment"> * ':namt:type:offset:magic:mask:interpreter:flags'v/spa
	  291v/a>vspa
 class="comment"> * where the ':' is the IFS, that can be chosen with the first charv/spa
	  292v/a>vspa
 class="comment"> */v/spa
	  293v/a>static Nodev/a> *va href="+code=create_entry" class="sref">create_entryv/a>(const char va href="+code=__user" class="sref">__userv/a> *va href="+code=buffer" class="sref">bufferv/a>, size_tv/a> va href="+code=count" class="sref">countv/a>)  294v/a>{  295v/a>        Nodev/a> *va href="+code=e" class="sref">ev/a>;  296v/a>        int memsizev/a>, errv/a>;  297v/a>        char *bufv/a>, *pv/a>;  298v/a>        char delv/a>;  299v/a>  300v/a>        /* some sanity checks */v/spa
	  301v/a>        errv/a> = -EINVALv/a>;  302v/a>        if ((countv/a> < 11) || (countv/a> > 256))  303v/a>                goto outv/a>;  304v/a>  305v/a>        errv/a> = -ENOMEMv/a>;  306v/a>        memsizev/a> = sizeof(Nodev/a>) + va href="+code=count" class="sref">countv/a> + 8;  307v/a>        ev/a> = kmallocv/a>(memsizev/a>, GFP_USERv/a>);  308v/a>        if (!ev/a>)  309v/a>                goto outv/a>;  310v/a>  311v/a>        pv/a> = bufv/a> = (char *)ev/a> + sizeof(Nodev/a>);  312v/a>  313v/a>        memsetv/a>(ev/a>, 0, sizeof(Nodev/a>));  314v/a>        if (copy_from_userv/a>(bufv/a>, bufferv/a>, countv/a>))  315v/a>                goto Efaultv/a>;  316v/a>  317v/a>        delv/a> = *pv/a>++;     /* delimeter4*/v/spa
	  318v/a>  319v/a>        memsetv/a>(bufv/a>+countv/a>, delv/a>, 8);  320v/a>  321v/a>        ev/a>->namtv/a> = pv/a>;  322v/a>        pv/a> = strchrv/a>(pv/a>, delv/a>);  323v/a>        if (!pv/a>)  324v/a>                goto Einvalv/a>;  325v/a>        *pv/a>++ = '\0'v/spa
	;  326v/a>        if (!ev/a>->namtv/a>[0] ||  327v/a>            !strcmpv/a>(ev/a>->namtv/a>, "."v/spa
	) ||  328v/a>            !strcmpv/a>(ev/a>->namtv/a>, ".."v/spa
	) ||  329v/a>            strchrv/a>(ev/a>->namtv/a>, '/'v/spa
	))  330v/a>                goto Einvalv/a>;  331v/a>        switch (*pv/a>++) {  332v/a>                cast 'E'v/spa
	: va href="+code=e" class="sref">ev/a>->flagsv/a> = 1<<Enabledv/a>; break;  333v/a>                cast 'M'v/spa
	: va href="+code=e" class="sref">ev/a>->flagsv/a> = (1<<Enabledv/a>) | (1<<Magicv/a>); break;  334v/a>                default: goto Einvalv/a>;  335v/a>        }  336v/a>        if (*pv/a>++ != delv/a>)  337v/a>                goto Einvalv/a>;  338v/a>        if (test_bitv/a>(Magicv/a>, &ev/a>->flagsv/a>)) {  339v/a>                char *sv/a> = strchrv/a>(pv/a>, delv/a>);  340v/a>                if (!sv/a>)  341v/a>                        goto Einvalv/a>;  342v/a>                *sv/a>++ = '\0'v/spa
	;  343v/a>                ev/a>->offsetv/a> = simple_strtoulv/a>(pv/a>, &pv/a>, 10);  344v/a>                if (*pv/a>++)  345v/a>                        goto Einvalv/a>;  346v/a>                ev/a>->magicv/a> = pv/a>;  347v/a>                pv/a> = scanargv/a>(pv/a>, delv/a>);  348v/a>                if (!pv/a>)  349v/a>                        goto Einvalv/a>;  350v/a>                pv/a>[-1] = '\0'v/spa
	;  351v/a>                if (!ev/a>->magicv/a>[0])  352v/a>                        goto Einvalv/a>;  353v/a>                ev/a>->maskv/a> = pv/a>;  354v/a>                pv/a> = scanargv/a>(pv/a>, delv/a>);  355v/a>                if (!pv/a>)  356v/a>                        goto Einvalv/a>;  357v/a>                pv/a>[-1] = '\0'v/spa
	;  358v/a>                if (!ev/a>->maskv/a>[0])  359v/a>                        ev/a>->maskv/a> = NULLv/a>;  360v/a>                ev/a>->sizev/a> = unquotev/a>(ev/a>->magicv/a>);  361v/a>                if (ev/a>->maskv/a> && unquotev/a>(ev/a>->maskv/a>) != ev/a>->sizev/a>)  362v/a>                        goto Einvalv/a>;  363v/a>                if (ev/a>->sizev/a> + va href="+code=e" class="sref">ev/a>->offsetv/a> > BINPRM_BUF_SIZEv/a>)  364v/a>                        goto Einvalv/a>;  365v/a>        } else {  366v/a>                pv/a> = strchrv/a>(pv/a>, delv/a>);  367v/a>                if (!pv/a>)  368v/a>                        goto Einvalv/a>;  369v/a>                *pv/a>++ = '\0'v/spa
	;  370v/a>                ev/a>->magicv/a> = pv/a>;  371v/a>                pv/a> = strchrv/a>(pv/a>, delv/a>);  372v/a>                if (!pv/a>)  373v/a>                        goto Einvalv/a>;  374v/a>                *pv/a>++ = '\0'v/spa
	;  375v/a>                if (!ev/a>->magicv/a>[0] || strchrv/a>(ev/a>->magicv/a>, '/'v/spa
	))  376v/a>                        goto Einvalv/a>;  377v/a>                pv/a> = strchrv/a>(pv/a>, delv/a>);  378v/a>                if (!pv/a>)  379v/a>                        goto Einvalv/a>;  380v/a>                *pv/a>++ = '\0'v/spa
	;  381v/a>        }  382v/a>        ev/a>->interpreterv/a> = pv/a>;  383v/a>        pv/a> = strchrv/a>(pv/a>, delv/a>);  384v/a>        if (!pv/a>)  385v/a>                goto Einvalv/a>;  386v/a>        *pv/a>++ = '\0'v/spa
	;  387v/a>        if (!ev/a>->interpreterv/a>[0])  388v/a>                goto Einvalv/a>;  389v/a>  390v/a>  391v/a>        pv/a> = check_special_flagsv/a> (pv/a>, ev/a>);  392v/a>  393v/a>        if (*pv/a> == '\n'v/spa
	)  394v/a>                pv/a>++;  395v/a>        if (pv/a> != bufv/a> + va href="+code=count" class="sref">countv/a>)  396v/a>                goto Einvalv/a>;  397v/a>        return ev/a>;  398v/a>  399v/a>outv/a>:  400v/a>        return ERR_PTRv/a>(errv/a>);  401v/a>  402v/a>Efaultv/a>:  403v/a>        kfreev/a>(ev/a>);  404v/a>        return ERR_PTRv/a>(-EFAULTv/a>);  405v/a>Einvalv/a>:  406v/a>        kfreev/a>(ev/a>);  407v/a>        return ERR_PTRv/a>(-EINVALv/a>);  408v/a>}  409v/a>  41v4.a>vspa
 class="comment">/*v/spa
	  411v/a>vspa
 class="comment"> * Set status of entry/binfmt_misc:v/spa
	  412v/a>vspa
 class="comment"> * '1' enables, '0' disables4and '-1' clears entry/binfmt_miscv/spa
	  413v/a>vspa
 class="comment"> */v/spa
	  414v/a>static int parse_commandv/a>(const char va href="+code=__user" class="sref">__userv/a> *va href="+code=buffer" class="sref">bufferv/a>, size_tv/a> va href="+code=count" class="sref">countv/a>)  415v/a>{  416v/a>        char sv/a>[4];  417v/a>  418v/a>        if (!countv/a>)  419v/a>                return 0;  420v/a>        if (countv/a> > 3)  421v/a>                return -EINVALv/a>;  422v/a>        if (copy_from_userv/a>(sv/a>, bufferv/a>, countv/a>))  423v/a>                return -EFAULTv/a>;  424v/a>        if (sv/a>[countv/a>-1] == '\n'v/spa
	)  425v/a>                countv/a>--;  426v/a>        if (countv/a> == 1 && sv/a>[0] == '0'v/spa
	)  427v/a>                return 1;  428v/a>        if (countv/a> == 1 && sv/a>[0] == '1'v/spa
	)  429v/a>                return 2;  430v/a>        if (countv/a> == 2 && sv/a>[0] == '-'v/spa
	 && sv/a>[1] == '1'v/spa
	)  431v/a>                return 3;  432v/a>        return -EINVALv/a>;  433v/a>}  434v/a>  435v/a>/* generic stuff */v/spa
	  436v/a>  437v/a>static void entry_statusv/a>(Nodev/a> *va href="+code=e" class="sref">ev/a>, char *pagev/a>)  438v/a>{  439v/a>        char *dpv/a>;  440v/a>        char *statusv/a> = "disabled"v/spa
	;  441v/a>        const char * flagsv/a> = "flags: "v/spa
	;  442v/a>  443v/a>        if (test_bitv/a>(Enabledv/a>, &ev/a>->flagsv/a>))  444v/a>                statusv/a> = "enabled"v/spa
	;  445v/a>  446v/a>        if (!VERBOSE_STATUSv/a>) {  447v/a>                sprintfv/a>(pagev/a>, "%s\n"v/spa
	, statusv/a>);  448v/a>                return;  449v/a>        }  450v/a>  451v/a>        sprintfv/a>(pagev/a>, "%s\ninterpreter %s\n"v/spa
	, statusv/a>, ev/a>->interpreterv/a>);  452v/a>        dpv/a> = pagev/a> + va href="+code=strlen" class="sref">strlenv/a>(pagev/a>);  453v/a>  454v/a>        /* print4the special flags */v/spa
	  455v/a>        sprintfv/a> (dpv/a>, "%s"v/spa
	, flagsv/a>);  456v/a>        dpv/a> += strlenv/a> (flagsv/a>);  457v/a>        if (ev/a>->flagsv/a> & MISC_FMT_PRESERVE_ARGV0v/a>) {  458v/a>                *dpv/a> ++ = 'P'v/spa
	;  459v/a>        }  460v/a>        if (ev/a>->flagsv/a> & MISC_FMT_OPEN_BINARYv/a>) {  461v/a>                *dpv/a> ++ = 'O'v/spa
	;  462v/a>        }  463v/a>        if (ev/a>->flagsv/a> & MISC_FMT_CREDENTIALSv/a>) {  464v/a>                *dpv/a> ++ = 'C'v/spa
	;  465v/a>        }  466v/a>        *dpv/a> ++ = '\n'v/spa
	;  467v/a>  468v/a>  469v/a>        if (!test_bitv/a>(Magicv/a>, &ev/a>->flagsv/a>)) {  470v/a>                sprintfv/a>(dpv/a>, "extension .%s\n"v/spa
	, ev/a>->magicv/a>);  471v/a>        } else {  472v/a>                int iv/a>;  473v/a>  474v/a>                sprintfv/a>(dpv/a>, "offset %i\nmagic "v/spa
	, ev/a>->offsetv/a>);  475v/a>                dpv/a> = pagev/a> + va href="+code=strlen" class="sref">strlenv/a>(pagev/a>);  476v/a>                for (iv/a> = 0; iv/a> < ev/a>->sizev/a>; iv/a>++) {  477v/a>                        sprintfv/a>(dpv/a>, "%02x"v/spa
	, 0xff & (int) (ev/a>->magicv/a>[iv/a>]));  478v/a>                        dpv/a> += 2;  479v/a>                }  480v/a>                if (ev/a>->maskv/a>) {  481v/a>                        sprintfv/a>(dpv/a>, "\nmask "v/spa
	);  482v/a>                        dpv/a> += 6;  483v/a>                        for (iv/a> = 0; iv/a> < ev/a>->sizev/a>; iv/a>++) {  484v/a>                                sprintfv/a>(dpv/a>, "%02x"v/spa
	, 0xff & (int) (ev/a>->maskv/a>[iv/a>]));  485v/a>                                dpv/a> += 2;  486v/a>                        }  487v/a>                }  488v/a>                *dpv/a>++ = '\n'v/spa
	;  489v/a>                *dpv/a> = '\0'v/spa
	;  490v/a>        }  491v/a>}  492v/a>  493v/a>static struct inodev/a> *va href="+code=bm_get_inode" class="sref">bm_get_inodev/a>(struct super_blockv/a> *va href="+code=sb" class="sref">sbv/a>, int modev/a>)  494v/a>{  495v/a>        struct inodev/a> * inodev/a> = new_inodev/a>(sbv/a>);  496v/a>  497v/a>        if (inodev/a>) {  498v/a>                inodev/a>->i_inov/a> = get_next_inov/a>();  499v/a>                inodev/a>->i_modev/a> = modev/a>;  500v/a>                inodev/a>->i_atimtv/a> = inodev/a>->i_mtimtv/a> = inodev/a>->i_ctimtv/a> =  501v/a>                        current_fs_timtv/a>(inodev/a>->i_sbv/a>);  502v/a>        }  503v/a>        return inodev/a>;  504v/a>}  505v/a>  506v/a>static void bm_evict_inodev/a>(struct inodev/a> *va href="+code=inode" class="sref">inodev/a>)  507v/a>{  508v/a>        clear_inodev/a>(inodev/a>);  509v/a>        kfreev/a>(inodev/a>->i_privatev/a>);  51v4.a>}  511v/a>  512v/a>static void kill_nodev/a>(Nodev/a> *va href="+code=e" class="sref">ev/a>)  513v/a>{  514v/a>        struct dentryv/a> *va href="+code=dentry" class="sref">dentryv/a>;  515v/a>  516v/a>        write_lockv/a>(&entries_lockv/a>);  517v/a>        dentryv/a> = ev/a>->dentryv/a>;  518v/a>        if (dentryv/a>) {  519v/a>                list_del_initv/a>(&ev/a>->listv/a>);  520v/a>                ev/a>->dentryv/a> = NULLv/a>;  521v/a>        }  522v/a>        write_unlockv/a>(&entries_lockv/a>);  523v/a>  524v/a>        if (dentryv/a>) {  525v/a>                drop_nlinkv/a>(dentryv/a>->d_inodev/a>);  526v/a>                d_dropv/a>(dentryv/a>);  527v/a>                dputv/a>(dentryv/a>);  528v/a>                simple_release_fsv/a>(&bm_mntv/a>, &entry_countv/a>);  529v/a>        }  53v4.a>}  531v/a>  532v/a>vspa
 class="comment">/* /<entry> */v/spa
	  533v/a>  534v/a>static ssize_tv/a>  535v/a>bm_entry_readv/a>(struct filev/a> * filev/a>, char va href="+code=__user" class="sref">__userv/a> * bufv/a>, size_tv/a> va href="+code=nbytes" class="sref">nbytesv/a>, loff_tv/a> *va href="+code=ppos" class="sref">pposv/a>)  536v/a>{  537v/a>        Nodev/a> *va href="+code=e" class="sref">ev/a> = filev/a>->f_pathv/a>.dentryv/a>->d_inodev/a>->i_privatev/a>;  538v/a>        ssize_tv/a> resv/a>;  539v/a>        char *pagev/a>;  540v/a>  541v/a>        if (!(pagev/a> = (char*) va href="+code=__get_free_page" class="sref">__get_free_pagev/a>(GFP_KERNELv/a>)))  542v/a>                return -ENOMEMv/a>;  543v/a>  544v/a>        entry_statusv/a>(ev/a>, pagev/a>);  545v/a>  546v/a>        resv/a> = simple_read_from_bufferv/a>(bufv/a>, nbytesv/a>, pposv/a>, pagev/a>, strlenv/a>(pagev/a>));  547v/a>  548v/a>        free_pagev/a>((unsigned long) va href="+code=page" class="sref">pagev/a>);  549v/a>        return resv/a>;  55v4.a>}  551v/a>  552v/a>static ssize_tv/a> bm_entry_writev/a>(struct filev/a> *filev/a>, const char va href="+code=__user" class="sref">__userv/a> *va href="+code=buffer" class="sref">bufferv/a>,  553v/a>                                size_tv/a> va href="+code=count" class="sref">countv/a>, loff_tv/a> *va href="+code=ppos" class="sref">pposv/a>)  554v/a>{  555v/a>        struct dentryv/a> *va href="+code=root" class="sref">rootv/a>;  556v/a>        Nodev/a> *va href="+code=e" class="sref">ev/a> = filev/a>->f_pathv/a>.dentryv/a>->d_inodev/a>->i_privatev/a>;  557v/a>        int resv/a> = parse_commandv/a>(va href="+code=buffer" class="sref">bufferv/a>, countv/a>);  558v/a>  559v/a>        switch (resv/a>) {  560v/a>                case 1: clear_bitv/a>(va href="+code=Enabled" class="sref">Enabledv/a>, &ev/a>->flagsv/a>);  561v/a>                        break;  562v/a>                case 2: set_bitv/a>(va href="+code=Enabled" class="sref">Enabledv/a>, &ev/a>->flagsv/a>);  563v/a>                        break;  564v/a>                case 3: rootv/a> = dgetv/a>(va href="+code=file" class="sref">filev/a>->f_pathv/a>.dentryv/a>->d_sbv/a>->s_rootv/a>);  565v/a>                        mutex_lockv/a>(&rootv/a>->d_inodev/a>->i_mutexv/a>);  566v/a>  567v/a>                        kill_nodev/a>(ev/a>);  568v/a>  569v/a>                        mutex_unlockv/a>(&rootv/a>->d_inodev/a>->i_mutexv/a>);  570v/a>                        dputv/a>(rootv/a>);  571v/a>                        break;  572v/a>                default: return resv/a>;  573v/a>        }  574v/a>        return countv/a>;  575v/a>}  576v/a>  577v/a>static const struct file_operationsv/a> bm_entry_operationsv/a> = {  578v/a>        .readv/a>           = bm_entry_readv/a>,  579v/a>        .writev/a>          = bm_entry_writev/a>,  580v/a>        .llseekv/a>         = default_llseekv/a>,  581v/a>};  582v/a>  583v/a>vspa
 class="comment">/* /register */v/spa
	  584v/a>  585v/a>static ssize_tv/a> bm_register_writev/a>(struct filev/a> *filev/a>, const char va href="+code=__user" class="sref">__userv/a> *va href="+code=buffer" class="sref">bufferv/a>,  586v/a>                               size_tv/a> va href="+code=count" class="sref">countv/a>, loff_tv/a> *va href="+code=ppos" class="sref">pposv/a>)  587v/a>{  588v/a>        Nodev/a> *va href="+code=e" class="sref">ev/a>;  589v/a>        struct inodev/a> *va href="+code=inode" class="sref">inodev/a>;  590v/a>        struct dentryv/a> *va href="+code=root" class="sref">rootv/a>, *va href="+code=dentry" class="sref">dentryv/a>;  591v/a>        struct super_blockv/a> *va href="+code=sb" class="sref">sbv/a> = filev/a>->f_pathv/a>.dentryv/a>->d_sbv/a>;  592v/a>        int errv/a> = 0;  593v/a>  594v/a>        ev/a> = create_entryv/a>(va href="+code=buffer" class="sref">bufferv/a>, countv/a>);  595v/a>  596v/a>        if (IS_ERRv/a>(ev/a>))  597v/a>                return PTR_ERRv/a>(ev/a>);  598v/a>  599v/a>        rootv/a> = dgetv/a>(va href="+code=sb" class="sref">sbv/a>->s_rootv/a>);  600v/a>        mutex_lockv/a>(&rootv/a>->d_inodev/a>->i_mutexv/a>);  601v/a>        dentryv/a> = lookup_one_lenv/a>(ev/a>->namtv/a>, rootv/a>, strlenv/a>(ev/a>->namtv/a>));  602v/a>        errv/a> = PTR_ERRv/a>(dentryv/a>);  603v/a>        if (IS_ERRv/a>(dentryv/a>))  604v/a>                goto outv/a>;  605v/a>  606v/a>        errv/a> = -EEXISTv/a>;  607v/a>        if (dentryv/a>->d_inodev/a>)  608v/a>                goto out2v/a>;  609v/a>  610v/a>        inodev/a> = bm_get_inodev/a>(va href="+code=sb" class="sref">sbv/a>, S_IFREGv/a> | 0644);  611v/a>  612v/a>        errv/a> = -ENOMEMv/a>;  613v/a>        if (!inodev/a>)  614v/a>                goto out2v/a>;  615v/a>  616v/a>        errv/a> = simple_pin_fsv/a>(&bm_fs_typev/a>, &bm_mntv/a>, &entry_countv/a>);  617v/a>        if (errv/a>) {  618v/a>                iputv/a>(inodev/a>);  619v/a>                inodev/a> = NULLv/a>;  620v/a>                goto out2v/a>;  621v/a>        }  622v/a>  623v/a>        ev/a>->dentryv/a> = dgetv/a>(va href="+code=dentry" class="sref">dentryv/a>);  624v/a>        inodev/a>->i_privatev/a> = ev/a>;  625v/a>        inodev/a>->i_fopv/a> = &bm_entry_operationsv/a>;  626v/a>  627v/a>        d_instantiatev/a>(va href="+code=dentry" class="sref">dentryv/a>, inodev/a>);  628v/a>        write_lockv/a>(&entries_lockv/a>);  629v/a>        list_addv/a>(&ev/a>->listv/a>, &entriesv/a>);  630v/a>        write_unlockv/a>(&entries_lockv/a>);  631v/a>  632v/a>        errv/a> = 0;  633v/a>out2v/a>:  634v/a>        dputv/a>(dentryv/a>);  635v/a>outv/a>:  636v/a>        mutex_unlockv/a>(&rootv/a>->d_inodev/a>->i_mutexv/a>);  637v/a>        dputv/a>(rootv/a>);  638v/a>  639v/a>        if (errv/a>) {  640v/a>                kfreev/a>(ev/a>);  641v/a>                return -EINVALv/a>;  642v/a>        }  643v/a>        return countv/a>;  644v/a>}  645v/a>  646v/a>static const struct file_operationsv/a> bm_register_operationsv/a> = {  647v/a>        .writev/a>          = bm_register_writev/a>,  648v/a>        .llseekv/a>         = noop_llseekv/a>,  649v/a>};  650v/a>  651v/a>vspa
 class="comment">/* /status */v/spa
	  652v/a>  653v/a>static ssize_tv/a>  654v/a>bm_status_readv/a>(struct filev/a> *filev/a>, char va href="+code=__user" class="sref">__userv/a> *va href="+code=buf" class="sref">bufv/a>, size_tv/a> va href="+code=nbytes" class="sref">nbytesv/a>, loff_tv/a> *va href="+code=ppos" class="sref">pposv/a>)  655v/a>{  656v/a>        char *sv/a> = enabledv/a> ? "enabled\n"v/spa
	 : "disabled\n"v/spa
	;  657v/a>  658v/a>        return simple_read_from_bufferv/a>(bufv/a>, nbytesv/a>, pposv/a>, sv/a>, strlenv/a>(sv/a>));  659v/a>}  660v/a>  661v/a>static ssize_tv/a> bm_status_writev/a>(struct filev/a> * filev/a>, const char va href="+code=__user" class="sref">__userv/a> * bufferv/a>,  662v/a>                size_tv/a> va href="+code=count" class="sref">countv/a>, loff_tv/a> *va href="+code=ppos" class="sref">pposv/a>)  663v/a>{  664v/a>        int resv/a> = parse_commandv/a>(va href="+code=buffer" class="sref">bufferv/a>, countv/a>);  665v/a>        struct dentryv/a> *va href="+code=root" class="sref">rootv/a>;  666v/a>  667v/a>        switch (resv/a>) {  668v/a>                case 1: enabledv/a> = 0; break;  669v/a>                case 2: enabledv/a> = 1; break;  670v/a>                case 3: rootv/a> = dgetv/a>(va href="+code=file" class="sref">filev/a>->f_pathv/a>.dentryv/a>->d_sbv/a>->s_rootv/a>);  671v/a>                        mutex_lockv/a>(&rootv/a>->d_inodev/a>->i_mutexv/a>);  672v/a>  673v/a>                        while (!list_emptyv/a>(&entriesv/a>))  674v/a>                                kill_nodev/a>(list_entryv/a>(entriesv/a>.nextv/a>, Nodev/a>, listv/a>));  675v/a>  676v/a>                        mutex_unlockv/a>(&rootv/a>->d_inodev/a>->i_mutexv/a>);  677v/a>                        dputv/a>(rootv/a>);  678v/a>                default: return resv/a>;  679v/a>        }  680v/a>        return countv/a>;  681v/a>}  682v/a>  683v/a>static const struct file_operationsv/a> bm_status_operationsv/a> = {  684v/a>        .readv/a>           = bm_status_readv/a>,  685v/a>        .writev/a>          = bm_status_writev/a>,  686v/a>        .llseekv/a>         = default_llseekv/a>,  687v/a>};  688v/a>  689v/a>vspa
 class="comment">/* Superblock handling */v/spa
	  690v/a>  691v/a>static const struct super_operationsv/a> s_opsv/a> = {  692v/a>        .statfsv/a>         = simple_statfsv/a>,  693v/a>        .evict_inodev/a>    = bm_evict_inodev/a>,  694v/a>};  695v/a>  696v/a>static int bm_fill_superv/a>(struct super_blockv/a> * sbv/a>, void * datav/a>, int silentv/a>)  697v/a>{  698v/a>        static struct tree_descrv/a> bm_filesv/a>[] = {  699v/a>                [2] = {"status"v/spa
	, &bm_status_operationsv/a>, S_IWUSRv/a>|S_IRUGOv/a>},  700v/a>                [3] = {"register"v/spa
	, &bm_register_operationsv/a>, S_IWUSRv/a>},  701v/a>                vspa
 class="comment">/* last one */v/spa
	 {""v/spa
	}  702v/a>        };  703v/a>        int errv/a> = simple_fill_superv/a>(sbv/a>, BINFMTFS_MAGICv/a>, bm_filesv/a>);  704v/a>        if (!errv/a>)  705v/a>                sbv/a>->s_opv/a> = &s_opsv/a>;  706v/a>        return errv/a>;  707v/a>}  708v/a>  709v/a>static struct dentryv/a> *va href="+code=bm_mount" class="sref">bm_mountv/a>(struct file_system_typev/a> *va href="+code=fs_type" class="sref">fs_typev/a>,  710v/a>        int flagsv/a>, const char *va href="+code=dev_namt" class="sref">dev_namtv/a>, void *datav/a>)  711v/a>{  712v/a>        return mount_singlev/a>(va href="+code=fs_type" class="sref">fs_typev/a>, flagsv/a>, datav/a>, bm_fill_superv/a>);  713v/a>}  714v/a>  715v/a>static struct linux_binfmtv/a> misc_formatv/a> = {  716v/a>        .modulev/a> = THIS_MODULEv/a>,  717v/a>        .load_binaryv/a> = load_misc_binaryv/a>,  718v/a>};  719v/a>  720v/a>static struct file_system_typev/a> bm_fs_typev/a> = {  721v/a>        .ownerv/a>          = THIS_MODULEv/a>,  722v/a>        .namtv/a>           = "binfmt_misc"v/spa
	,  723v/a>        .mountv/a>          = bm_mountv/a>,  724v/a>        .kill_sbv/a>        = kill_litter_superv/a>,  725v/a>};  726v/a>  727v/a>static int __initv/a> init_misc_binfmtv/a>(void)  728v/a>{  729v/a>        int errv/a> = register_filesystemv/a>(&bm_fs_typev/a>);  730v/a>        if (!errv/a>)  731v/a>                va href="+code=insert_binfmt" class="sref">insert_binfmtv/a>(&misc_formatv/a>);  732v/a>        return errv/a>;  733v/a>}  734v/a>  735v/a>static void __exitv/a> exit_misc_binfmtv/a>(void)  736v/a>{  737v/a>        unregister_binfmtv/a>(&misc_formatv/a>);  738v/a>        unregister_filesystemv/a>(&bm_fs_typev/a>);  739v/a>}  740v/a>  741v/a>core_initcallv/a>(va href="+code=init_misc_binfmt" class="sref">init_misc_binfmtv/a>);  742v/a>module_exitv/a>(va href="+code=exit_misc_binfmt" class="sref">exit_misc_binfmtv/a>);  743v/a>MODULE_LICENSEv/a>(vspa
 class="string">"GPL"v/spa
	);  744v/a>
lxr.linux.no kindly hosted by Redpill Linpro ASv/a>, provider of Linux consulting and operations services since 1995.