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


The original LXR software by the string">&http://sourcevL"ge.net/projects/lx"">LXR 98">uf=""69al version by string">&mailto:lx"@a hre.no">lx"@a hre.noa hr. lx".a hre.no kindly hoL6ad by string">&http://www.redp="+-a hpro.no">Redp="+ L hpro ASa hrefprovider of L huxref="ultvspaand ter_operat refvicet rince 1995.