On Tue, 22 Jun 1999, Brian F. Feldman wrote:

> Date: Tue, 22 Jun 1999 01:08:04 -0400 (EDT)
> From: Brian F. Feldman <gr...@unixhelp.org>
> To: Kris Kennaway <kkenn...@physics.adelaide.edu.au>
> Cc: Peter Wemm <pe...@netplex.com.au>, Jean-Marc Zucconi <j...@freebsd.org>,
     h...@freebsd.org, cvs-committ...@freebsd.org, cvs-...@freebsd.org
> Subject: Re: cvs commit: src/sys/kern imgact_gzip.c 
> 
> On Tue, 22 Jun 1999, Kris Kennaway wrote:
> 
> > On Tue, 22 Jun 1999, Peter Wemm wrote:
> > 
> > > Ahh yes, I forgot that / was read-write for MFS boots.  However:
> > > 
> > > #!/bin/sh
> > > skip=18
> > > if /usr/bin/tail +$skip $0 | gzip -cd > /tmp/gztmp$$; then
> > >   chmod 700 /tmp/gztmp$$
> > >   prog="`echo $0 | sed 's|^.*/||'`"
> > >   if /bin/ln /tmp/gztmp$$ "/tmp/$prog" 2>/dev/null; then
> > >     trap '/bin/rm -f /tmp/gztmp$$ "/tmp/$prog"; exit $res' 0
> > >     (/bin/sleep 5; /bin/rm -f /tmp/gztmp$$ "/tmp/$prog") 2>/dev/null &
> > >     /tmp/"$prog" ${1+"$@"}; res=$?
> > >   else
> > >     trap '/bin/rm -f /tmp/gztmp$$; exit $res' 0
> > >     (/bin/sleep 5; /bin/rm -f /tmp/gztmp$$) 2>/dev/null &
> > >     /tmp/gztmp$$ ${1+"$@"}; res=$?
> > >   fi
> > > else
> > >   echo Cannot decompress $0; exit 1
> > > fi; exit $res
> > 
> > This is the unpatched (insecure) version of gzexe (all the /tmp/gztmp$$'s),
> > but it's functionally the same.
> > 
> > > Now, if tail, sh, gzip, chmod, ln, sleep, rm, etc are all in the gzexe'd
> > > crunched linked binary, how is it supposed to decompress itself?  "sh" 
> > > itself
> > > is part of the crunched binary, so what is going to decode sh when sh 
> > > itself
> > > is a shell script?
> > 
> > Yes, that seems to be a problem - gzexe depends on those executables. 
> > However
> > it shouldn't be too hard to recode this decompressor in C to perform the 
> > same
> > job without any external dependencies. The question is whether that would be
> > easier than fixing the kernel to handle gzipped ELF binaries transparently -
> > almost certainly it would be.
> 
> How's what I attached?

[Context left in for cross-post to hackers]

Hmm..I don't have a deflate on my system. This should be linked static as
well, otherwise you need the runtime linker + libraries, and that has a 69k
overhead (when stripped). Possibly this could be optimized further..I don't
know if this is small enough to be useful however.

Mike's suggestion of a gzipped MFS image is probably best for things like boot
floppies.

Kris

>  Brian Fundakowski Feldman      _ __ ___ ____  ___ ___ ___  
>  gr...@freebsd.org                   _ __ ___ | _ ) __|   \ 
>      FreeBSD: The Power to Serve!        _ __ | _ \._ \ |) |
>        http://www.FreeBSD.org/              _ |___/___/___/ 
> 

-----
"Never criticize anybody until you have walked a mile in their shoes,
because by that time you will be a mile away and have their shoes."
    -- Unknown
#!/bin/sh
of=`basename $1`_z
cs=$of.c
cat > $cs << .
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/wait.h>
#include <sys/stat.h>

#include <zlib.h>
#include <err.h>
#include <unistd.h>
#include <stdio.h>

$(deflate < $1 | file2c 'u_char program[] = { ' ' };')

int
main(int argc, char **argv) {
        int status;
        u_long destLen = sizeof(program);
        void *outputaddr;
        char outputname[256];
        int outputfd;

        snprintf(outputname, sizeof(outputname), "%s.XXXXXX", argv[0]);
        if ((outputfd = mkstemp(outputname)) == -1)
                err(1, "mkstemp");
        outputaddr = mmap(NULL, destLen, PROT_WRITE, MAP_SHARED, outputfd, 0);
        if (outputaddr == MAP_FAILED)
                err(1, "mmap");

        status = uncompress(outputaddr, &destLen, program, sizeof(program));
        switch (status) {
        case Z_MEM_ERROR:
                err(1, "Z_MEM_ERROR");
        case Z_BUF_ERROR:
                err(1, "Z_BUF_ERROR");
        case Z_DATA_ERROR:
                err(1, "Z_DATA_ERROR");
        default:
                break;
        }
        msync(outputaddr, 0, MS_SYNC);
        munmap(outputaddr, destLen);
        ftruncate(outputfd, destLen);
        fchmod(outputfd, 0755);
        close(outputfd);
        switch (fork()) {
                case 0:
                        execv(outputname, argv);
                case -1:
                        err(1, "fork");
                default:
                        wait(&status);
        }
        unlink(outputname);
        exit(status);
}
.
cc -lz -O -Wall $cs -o $of
rm $cs

Reply via email to