linux-mips-fnet
[Top] [All Lists]

CHALLENGE: forbidding processes to smash their stack

To: "'gbooker@acm.org'" <gbooker@acm.org>, "'hackers@cafe.anu.edu.au'" <hackers@cafe.anu.edu.au>, "'linux-mips@fnet.fr'" <linux-mips@fnet.fr>, "'cbeard@thepuffingroup.com'" <cbeard@thepuffingroup.com>, "'cort@cs.nmt.edu'" <cort@cs.nmt.edu>, "'jim@ic.uva.nl'" <jim@ic.uva.nl>
Subject: CHALLENGE: forbidding processes to smash their stack
From: "Biscondi, Philippe" <philippe.biscondi@icdc.caissedesdepots.fr>
Date: Thu, 11 May 2000 12:30:11 +0200
Return-receipt-to: "Biscondi, Philippe" <Philippe.Biscondi@tsexchange.idt.cdc.fr>
Sensitivity: Personal
WHY DO MOST (ALL?) SYSTEM ARCHITECTURES ALLOW PROCESSES OVERWRITE
INSTRUCTIONS ?

The problem, also known as buffer overflows/overruns, have been responsible
for hundreds of security holes in software yielding local/remote root
shells.

I posted messages in several newsgroups but they kept unanwsered. So i wrote
to
you, for i hope you know very skilled kernel programmers. As you face
different
platforms, it would be exciting to see how you each view the matter !

Reasons that may arise:
* processor has not to ability to lock memory segments.
* code overwriting is extensively used in the kernel:
  - to improve performance
  - for memory alignment
  - to solve&substitute symbols in librairies
  - signal handlers, long jumps, exec or fork calls need it ...
* standards would not be met (bin fomats, late bindings...)
...
and all in all it must be quite complicated to implement.

BUT DON'T YOU THINK THE CALLENGE IS EXCITING, MAKING LINUX VERY SECURE !

Note that you can find a non-official patch by rootshell.org for
sparc/sunOS5.x
but i haven't tried nor analyzed it. Here's the attachement...

#---------------------------------------------------------------------------
-----------------
#!/bin/sh
#
# Protect SPARC stack against unwanted exec access
# Side effect: growth in data segment also loses exec bit.
# This may break some programs.
#
# Install as:
#       /etc/init.d/protect_stack
#       ln /etc/init.d/protect_stack /etc/rc2.d/S07protect_stack
#
# And all programs except init are protected after the next reboot.
#
# After installing the scripts, first test with:
#
#       /etc/init.d/protect_stack start
#
#    Then start a new shell and test changes with /usr/proc/bin/pmap.
#
#       csh -fi
#       % pmap $$
#       ......
#       00047000   56K read/write               - instead of rwx
#       0004D000   32K     [ heap ]
#       ......
#       EFFFC000    8K read/write               - instead of rwx
#       EFFFC000   16K     [ stack ]
#       EFFFE000    8K read/write
#
#
# Seems to work on 2.4/2.5/2.5.1 but this may vary by patchlevel.
# Not all Sun MMUs support this, but it seems to haev effect on sun4m and
# sun4u, probably won't have an effect on sun4c.
#
# The assembly checking may need tweaking depending on OS level and
# patchlevel.
#
# Casper Dik (Casper.Dik@Holland.Sun.COM)
#
# The contents of this file  are intended to  be read as
# an example.  This  is not  a  supported product of Sun
# Microsystems  and  no hotline calls  will  be accepted
# which directly relate to this information.
#
# NO LIABILITY WILL BE  ACCEPTED BY SUN MICROSYSTEMS FOR
# ANY LOSS (DIRECT OR CONSEQUENTIAL) INCURRED IN ANY WAY
# BY ANY PARTY THROUGH THE USE OF THIS INFORMATION.
#
# NO WARRANTY  OF  ANY SORT  IS IMPLIED OR GIVEN FOR ANY
# CODE DERIVED FROM THIS INFORMATION.

PATH=/usr/bin:$PATH

#
#
# Set/get values using adb.
#
getvalue ()
{
    echo $1/$2 | adb -k /dev/ksyms /dev/mem | awk  "\"$1:\""' == $1 {print
$2}'
}
setvalue ()
{
    echo $1/$2$3 | adb -wk /dev/ksyms /dev/mem >/dev/null 2>&1
}

#
# Check whether setting/unsetting is not dangerous.
#

check ()
{
    map=`getvalue $mapaddr X`
    zfod=`getvalue $zfodaddr x`
    if [ "$map" = "$oldmap" -a "$zfod" = "$oldzfod" ]
    then
        old=true;
    else
        old=false
    fi
    if [ "$map" = "$newmap" -a "$zfod" = "$newzfod" ]
    then
        new=true
    else
        new=false
    fi
}


p=`basename $0`
zfodaddr=zfod_segvn_crargs+0xd
case "`uname -p`" in
sparc)

        #
        # Instruction should at $mapaddr should be: mov 0xf,%reg or mov
0xb,%reg
        # this is a synthetic instruction that encodes as or %g0,0xf,$reg
        # 10rr rrr0 0001 0000 0010 0000 0000 1x11
        #
        # Try and find it at several locations.  Addresses must be specified
        # the way adb prints them.
        #
        for mapaddr in map_hunk+8 map_hunk+0xc
        do
            mapval=`getvalue $mapaddr X`
            case $mapval in
            [9ab][02468ace]10200[bf])
                reg=`expr $mapval : '\(..\)'`
                break;;
            esac
        done
        if [ -z "$reg" ]
        then
            echo "${p}: Instruction doesn't match" 1>&2
            exit 1
        fi

        echo "${p}: Instruction prefix set to $reg ($mapval@$mapaddr)"

        oldmap=${reg}10200f
        newmap=${reg}10200b
        oldzfod=f0f
        newzfod=b0f

;;
i386)
        # Try and find it at several locations.  Addresses must be specified
        # the way adb prints them.
        #
        for mapaddr in map_hunk+0x19
        do
            mapval=`getvalue $mapaddr X`
            case $mapval in
            [bf]f545c6)
                reg=true
                break;;
            esac
        done
        if [ -z "$reg" ]
        then
            echo "${p}: Instruction doesn't match" 1>&2
            exit
        fi
        oldmap=ff545c6
        newmap=bf545c6
        oldzfod=f0f
        newzfod=f0b

;;
*)
        echo "Unknown kernel arch"
        exit 1
;;
esac

case "$1" in
start)
    check
    if $new
    then
        echo "${p}: Stack already protected" 1>&2
        exit 0
    fi
    if $old
    then
        setvalue $mapaddr W $newmap
        setvalue $zfodaddr w $newzfod
        echo "${p}: Stack protected"
    else
        echo "${p}: Kernel value mismatch $map != $oldmap or $zfod !=
$oldzfod" 1>&2
        exit 1
    fi
    ;;
stop)
    check
    if $old
    then
        echo "${p}: Stack already unprotected" 1>&2
        exit 0
    fi
    if $new
    then
        setvalue $mapaddr W $oldmap
        setvalue $zfodaddr w $oldzfod
        echo "${p}: Stack no longer protected"
    else
        echo "${p}: Kernel value mismatch $map != $newmap or $zfod !=
$newzfod" 1>&2
        exit 1
    fi
    ;;
*)
    echo "Usage: ${p} [start|stop]" 1>&2
    exit 1;;
esac

<Prev in Thread] Current Thread [Next in Thread>