Bugtraq mailing list archives

Re: Solaris patchadd(1) (3) symlink vulnerabilty


From: Darren Moffat <Darren.Moffat () eng sun com>
Date: Fri, 22 Dec 2000 09:26:16 -0800

Since patchadd is a script the bug it pretty easy to fix, Sun does intend
to release patches but it would have helped if we had been given notification
of the bug first, I don't believe we were.

So here is a set of diffs to patchadd for those that really can't wait.

Please note these are my personal diffs they do not reflect the official
opinion of those in Sun responsible for the patchadd command and may not
reflect the fix that is eventually released.  Do NOT under any circumstances
log any support calls with Sun regarding these diffs, they are intended
only to show the true nature of the fix and to illustrate to those concerned
how it could be fixed.  If you decide to apply these diffs to your production
servers it is enterly your risk.

==============================================================================

    The contents of the attached document 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.

==============================================================================

*** patchadd.orig       Wed Dec 20 11:21:38 2000
--- patchadd    Wed Dec 20 11:21:42 2000
***************
*** 161,182 ****
  function set_globals
  {

!       EXISTFILES=/tmp/existfiles.$$
!       PATCHFILES=/tmp/patchfiles.$$
!       PKGCOFILE=/tmp/pkgchk.out.$$
!       VALERRFILE=/tmp/valerr.$$
!       VALWARNFILE=/tmp/valwarn.$$
!       ADMINTFILE=/tmp/admin.tmp.$$
!       ADMINFILE=/tmp/admin.$$
!       LOGFILE=/tmp/pkgaddlog.$$
!       TMP_ARCHIVE=/tmp/TmpArchive.$$
!       TMP_FILELIST=/tmp/FileList.$$
!       TMP_LIB_DIR=/tmp/TmpLibDir.$$
!       INSTPATCHES_FILE=/tmp/MyShowrevFile.$$
!       PARAMS_FILE=/tmp/ParamsFile.$$
!       RESPONSE_FILE=/tmp/response.$$
!       TEMP_REMOTE=/tmp/temp_remote.$$

        Obsoletes=
        Incompat=
        Requires=
--- 161,192 ----
  function set_globals
  {

!       if [ -z "$WORKDIR" ]; then
!               safedir=${TMPDIR:-/tmp}/patchadd${RANDOM}$$
!               mkdir -m 700 $safedir
!               if [ $? != 0 ]; then
!                       exit 1;
!               fi
!               WORKDIR=$safedir
!               unset safedir
!       fi

+       EXISTFILES=${WORKDIR}/existfiles.$$
+       PATCHFILES=${WORKDIR}/patchfiles.$$
+       PKGCOFILE=${WORKDIR}/pkgchk.out.$$
+       VALERRFILE=${WORKDIR}/valerr.$$
+       VALWARNFILE=${WORKDIR}/valwarn.$$
+       ADMINTFILE=${WORKDIR}/admin.tmp.$$
+       ADMINFILE=${WORKDIR}/admin.$$
+       LOGFILE=${WORKDIR}/pkgaddlog.$$
+       TMP_ARCHIVE=${WORKDIR}/TmpArchive.$$
+       TMP_FILELIST=${WORKDIR}/FileList.$$
+       TMP_LIB_DIR=${WORKDIR}/TmpLibDir.$$
+       INSTPATCHES_FILE=${WORKDIR}/MyShowrevFile.$$
+       PARAMS_FILE=${WORKDIR}/ParamsFile.$$
+       RESPONSE_FILE=${WORKDIR}/response.$$
+       TEMP_REMOTE=${WORKDIR}/temp_remote.$$
+
        Obsoletes=
        Incompat=
        Requires=
***************
*** 305,314 ****
        fi

        $RM -f $INSTPATCHES_FILE
-       $RM -f /tmp/*.$$.1
-       $RM -f /tmp/archive.cpio*
-       $RM -fr /tmp/*.$$
        $RM -f $patchFileStripped
  }

  #
--- 315,322 ----
        fi

        $RM -f $INSTPATCHES_FILE
        $RM -f $patchFileStripped
+       $RM -rf ${WORKDIR}
  }

  #
***************
*** 435,441 ****
                        /usr/bin/gettext "The postpatch script exited with return code $retcode.\n"
                        if [[ "$isapplied" = "no" ]]
                        then
!                               $CP $1/$2/log /tmp/log.$2
                                /usr/bin/gettext "Backing out patch:\n"
                                cd $3
                                if [[ "$ROOTDIR" != "/" ]]
--- 443,449 ----
                        /usr/bin/gettext "The postpatch script exited with return code $retcode.\n"
                        if [[ "$isapplied" = "no" ]]
                        then
!                               $CP $1/$2/log ${WORKDIR}/log.$2
                                /usr/bin/gettext "Backing out patch:\n"
                                cd $3
                                if [[ "$ROOTDIR" != "/" ]]
***************
*** 444,450 ****
                                else
                                        /usr/sbin/patchrm $2
                                fi
!                               /usr/bin/gettext "See /tmp/log.$2 for more details.\n"
                        else
                                /usr/bin/gettext "Not backing out patch because this is a re-installation.\nThe system 
may be in an unstable state!\nSee $1/$2/log for more details.\n"  |tee -a $1/$2/log
                        fi
--- 452,458 ----
                                else
                                        /usr/sbin/patchrm $2
                                fi
!                               /usr/bin/gettext "See ${WORKDIR}/log.$2 for more details.\n"
                        else
                                /usr/bin/gettext "Not backing out patch because this is a re-installation.\nThe system 
may be in an unstable state!\nSee $1/$2/log for more details.\n"  |tee -a $1/$2/log
                        fi
***************
*** 1527,1533 ****
  #
  function check_for_symbolic_link
  {
!       $RM -f /tmp/symlink.$$ > /dev/null 2>&1
        olddir=$(pwd)
        cd $patchdir
        for ii in * X
--- 1535,1541 ----
  #
  function check_for_symbolic_link
  {
!       $RM -f ${WORKDIR}/symlink.$$ > /dev/null 2>&1
        olddir=$(pwd)
        cd $patchdir
        for ii in * X
***************
*** 1551,1562 ****
                symlinks=
                symlinks=$($SED -n '/^[^        ]*[     ]*s[    ]/p' $1/$2/$ii/pkgmap)
                if [[ "$symlinks" != "" ]]; then
!                       /usr/bin/gettext "Symbolic link in package $ii.\n" >> /tmp/symlink.$$
                fi
        done
!       if [[ -s /tmp/symlink.$$ ]]
        then
!               cat /tmp/symlink.$$
                /usr/bin/gettext "Symbolic links cannot be part of a patch.\n"
                patch_quit 13 "no"
                return 0
--- 1559,1570 ----
                symlinks=
                symlinks=$($SED -n '/^[^        ]*[     ]*s[    ]/p' $1/$2/$ii/pkgmap)
                if [[ "$symlinks" != "" ]]; then
!                       /usr/bin/gettext "Symbolic link in package $ii.\n" >> ${WORKDIR}/symlink.$$
                fi
        done
!       if [[ -s ${WORKDIR}/symlink.$$ ]]
        then
!               cat ${WORKDIR}/symlink.$$
                /usr/bin/gettext "Symbolic links cannot be part of a patch.\n"
                patch_quit 13 "no"
                return 0
***************
*** 1840,1848 ****
                return
        fi

!       pkgfiles=/tmp/pkgfiles.$$
!       resfiles=/tmp/resolvedfiles.$$
!       macrofiles=/tmp/pkgmacros.$$
        pkginst=
        pkginfofile=
        patchpkg=
--- 1848,1856 ----
                return
        fi

!       pkgfiles=${WORKDIR}/pkgfiles.$$
!       resfiles=${WORKDIR}/resolvedfiles.$$
!       macrofiles=${WORKDIR}/pkgmacros.$$
        pkginst=
        pkginfofile=
        patchpkg=
***************
*** 2343,2350 ****
                        /usr/bin/gettext "Pkgadd of $i package failed with error code $pkgadderr.\n" |tee -a $1/$2/log
                        if [ "$isapplied" = "no" ]
                        then
!                               /usr/bin/gettext "See /tmp/log.$2 for reason for failure.\n"
!                               $CP $1/$2/log /tmp/log.$2
                                /usr/bin/gettext "Backing out patch:\n"
                                cd $3
                                if [ "$ROOTDIR" != "/" ]
--- 2351,2358 ----
                        /usr/bin/gettext "Pkgadd of $i package failed with error code $pkgadderr.\n" |tee -a $1/$2/log
                        if [ "$isapplied" = "no" ]
                        then
!                               /usr/bin/gettext "See ${WORKDIR}/log.$2 for reason for failure.\n"
!                               $CP $1/$2/log ${WORKDIR}/log.$2
                                /usr/bin/gettext "Backing out patch:\n"
                                cd $3
                                if [ "$ROOTDIR" != "/" ]
***************
*** 2988,2998 ****
                        $FIND . -print > $TMP_FILELIST

                        cd $ROOTDIR
!                       cpio -oL -O /tmp/archive.cpio < $EXISTFILES >/dev/null 2>&1
                        exit_code=$?

                        cd $TMP_ARCHIVE
!                       cpio -oAL -O /tmp/archive.cpio < $TMP_FILELIST >/dev/null 2>&1
                        exit_code=exit_code+$?

                        cd $ROOTDIR
--- 2996,3006 ----
                        $FIND . -print > $TMP_FILELIST

                        cd $ROOTDIR
!                       cpio -oL -O ${WORKDIR}/archive.cpio < $EXISTFILES >/dev/null 2>&1
                        exit_code=$?

                        cd $TMP_ARCHIVE
!                       cpio -oAL -O ${WORKDIR}/archive.cpio < $TMP_FILELIST >/dev/null 2>&1
                        exit_code=exit_code+$?

                        cd $ROOTDIR
***************
*** 3022,3028 ****
                        then
                                compress $archive_path/archive.cpio
                        else
!                               compress /tmp/archive.cpio
                        fi
                        if [ $? = 0 ]
                        then
--- 3030,3036 ----
                        then
                                compress $archive_path/archive.cpio
                        else
!                               compress ${WORKDIR}/archive.cpio
                        fi
                        if [ $? = 0 ]
                        then
***************
*** 3035,3041 ****
                fi
                if [ "$isapplied" = "yes" ]
                then
!                       $CP /tmp/archive.cpio* $1/$2/save
                fi
                chmod 600 $archive_path/archive.cpio*
                $TOUCH $1/$2/.oldfilessaved
--- 3043,3049 ----
                fi
                if [ "$isapplied" = "yes" ]
                then
!                       $CP ${WORKDIR}/archive.cpio* $1/$2/save
                fi
                chmod 600 $archive_path/archive.cpio*
                $TOUCH $1/$2/.oldfilessaved
***************
*** 3057,3063 ****
        then
                $MD -m 750 -p $1/$2
        fi
!       $MV -f /tmp/ACTION.$PatchNum $1/$2 >/dev/null 2>&1
        $CP -p README.$2 $1/$2 >/dev/null 2>&1
        
        # Note the following line should be removed for 2.7.
--- 3065,3071 ----
        then
                $MD -m 750 -p $1/$2
        fi
!       $MV -f ${WORKDIR}/ACTION.$PatchNum $1/$2 >/dev/null 2>&1
        $CP -p README.$2 $1/$2 >/dev/null 2>&1
        
        # Note the following line should be removed for 2.7.
***************
*** 3092,3102 ****
        else
                if [[ "$PATCH_UNDO_ARCHIVE" != "none" ]]
                then
!                       $CP /tmp/archive.cpio* $PATCH_UNDO_ARCHIVE/$2
                else
!                       $CP /tmp/archive.cpio* $1/$2/save
                fi
!               $RM -f /tmp/archive.cpio*
                /usr/bin/gettext "Patchadd Interrupted.\n" >> $1/$2/log
        fi
        patch_quit 12 "yes"
--- 3100,3110 ----
        else
                if [[ "$PATCH_UNDO_ARCHIVE" != "none" ]]
                then
!                       $CP ${WORKDIR}/archive.cpio* $PATCH_UNDO_ARCHIVE/$2
                else
!                       $CP ${WORKDIR}/archive.cpio* $1/$2/save
                fi
!               $RM -f ${WORKDIR}/archive.cpio*
                /usr/bin/gettext "Patchadd Interrupted.\n" >> $1/$2/log
        fi
        patch_quit 12 "yes"
***************
*** 3119,3125 ****
        fi
        if [[ "$isapplied" = "yes" ]]
        then
!               $RM -f /tmp/archive.cpio*
        fi
        patch_quit 12 "yes"
  }
--- 3127,3133 ----
        fi
        if [[ "$isapplied" = "yes" ]]
        then
!               $RM -f ${WORKDIR}/archive.cpio*
        fi
        patch_quit 12 "yes"
  }
***************
*** 3132,3138 ****
  function trap_notinstalled
  {
        /usr/bin/gettext "Interrupt signal detected. Patch not installed.\n"
!       $RM -fr /tmp/*.$$
        $RM -f $INSTPATCHES_FILE
        if [[ "$isapplied" = "no" ]]
        then
--- 3140,3146 ----
  function trap_notinstalled
  {
        /usr/bin/gettext "Interrupt signal detected. Patch not installed.\n"
!       $RM -fr ${WORKDIR}/*.$$
        $RM -f $INSTPATCHES_FILE
        if [[ "$isapplied" = "no" ]]
        then
***************
*** 3411,3417 ****
        typeset -i insPs=0

        patchFile=""
!       patchFileStripped=/tmp/patchDBstripped.$$

        if [[ "$validate" = "no" ]]
        then
--- 3419,3425 ----
        typeset -i insPs=0

        patchFile=""
!       patchFileStripped=${WORKDIR}/patchDBstripped.$$

        if [[ "$validate" = "no" ]]
        then
***************
*** 3796,3802 ****
      else
                if [[ "$netImage" = "boot" ]]
                then
!               backout_dir=$ROOTDIR/tmp
                else
                backout_dir=$PKGDB
                fi
--- 3804,3810 ----
      else
                if [[ "$netImage" = "boot" ]]
                then
!               backout_dir=$ROOTDIR${WORKDIR}
                else
                backout_dir=$PKGDB
                fi
***************
*** 3850,3856 ****
        dryrunExit=
        dryrunDir=

!       dryrunDir="/tmp/$PatchNum.$$"

        if [[ ! -d "$dryrunDir"  || "$1" != "0" ]]; then
                dryrunFailure="yes"
--- 3858,3864 ----
        dryrunExit=
        dryrunDir=

!       dryrunDir="${WORKDIR}/$PatchNum.$$"

        if [[ ! -d "$dryrunDir"  || "$1" != "0" ]]; then
                dryrunFailure="yes"
***************
*** 3955,3967 ****
                restore_net_image
        fi

!       # The .../Boot/.tmp_proto/root needs to be re-mapped to .../Boot/tmp in order
        # for the boot image to be patched successfully.

        if [[ -z "$RE_MINIROOT_PATCH" ]]; then
!               $MOUNT -F lofs -O $ROOTDIR/tmp $ROOTDIR/mnt
!               $MOUNT -F lofs -O $ROOTDIR/.tmp_proto $ROOTDIR/tmp
!               $MOUNT -F lofs -O $ROOTDIR/mnt/root/var $ROOTDIR/tmp/root/var
        fi

        # At this point patchadd thinks the net install image is just like
--- 3963,3975 ----
                restore_net_image
        fi

!       # The .../Boot/.tmp_proto/root needs to be re-mapped to .../Boot${WORKDIR} in order
        # for the boot image to be patched successfully.

        if [[ -z "$RE_MINIROOT_PATCH" ]]; then
!               $MOUNT -F lofs -O $ROOTDIR${WORKDIR} $ROOTDIR/mnt
!               $MOUNT -F lofs -O $ROOTDIR/.tmp_proto $ROOTDIR${WORKDIR}
!               $MOUNT -F lofs -O $ROOTDIR/mnt/root/var $ROOTDIR${WORKDIR}/root/var
        fi

        # At this point patchadd thinks the net install image is just like
***************
*** 3983,3990 ****
        fi

        if [[ -z "$RE_MINIROOT_PATCH" ]]; then
!               $UMOUNT $ROOTDIR/tmp/root/var
!               $UMOUNT $ROOTDIR/tmp
                $UMOUNT $ROOTDIR/mnt
        fi
  }
--- 3991,3998 ----
        fi

        if [[ -z "$RE_MINIROOT_PATCH" ]]; then
!               $UMOUNT $ROOTDIR${WORKDIR}/root/var
!               $UMOUNT $ROOTDIR${WORKDIR}
                $UMOUNT $ROOTDIR/mnt
        fi
  }
***************
*** 4168,4176 ****

      if [[ $pkgadd_code == 5 ]]  # administration
      then
!               mv $LOGFILE /var/tmp/$PatchNum.log.$$ > /dev/null 2>&1
                [ $? = 0 ] && !                         /usr/bin/gettext "\nPkgadd failed. See 
/var/tmp/$PatchNum.log.$$ for details\n"

                remove_patch_meta_data "$pkg"
                [ -n "$pkgsAlreadyInstalled" ] && remove_patch
--- 4176,4184 ----

      if [[ $pkgadd_code == 5 ]]  # administration
      then
!               mv $LOGFILE /var${WORKDIR}/$PatchNum.log.$$ > /dev/null 2>&1
                [ $? = 0 ] && !                         /usr/bin/gettext "\nPkgadd failed. See 
/var${WORKDIR}/$PatchNum.log.$$ for details\n"

                remove_patch_meta_data "$pkg"
                [ -n "$pkgsAlreadyInstalled" ] && remove_patch
***************
*** 4188,4196 ****
                fi
      elif [[ $pkgadd_code != 0 ]]
      then
!               mv $LOGFILE /var/tmp/$PatchNum.log.$$ > /dev/null 2>&1
                [ $? = 0 ] && !                         /usr/bin/gettext "\nPkgadd failed. See 
/var/tmp/$PatchNum.log.$$ for details\n"

                # If there are more pkgs in the list skip them
                # since this patch will not be installed.
--- 4196,4204 ----
                fi
      elif [[ $pkgadd_code != 0 ]]
      then
!               mv $LOGFILE /var${WORKDIR}/$PatchNum.log.$$ > /dev/null 2>&1
                [ $? = 0 ] && !                         /usr/bin/gettext "\nPkgadd failed. See 
/var${WORKDIR}/$PatchNum.log.$$ for details\n"

                # If there are more pkgs in the list skip them
                # since this patch will not be installed.
***************
*** 4321,4331 ****
                                if [[ "$firstTimeThru" = "yes" ]]
                                then
                                        if [[ "$PKGADD_DEBUG" = "yes" ]]; then
!                                               pkgadd -v -D /tmp/$PatchNum.$$ -S -n -a $ADMINTFILE                     
                                $MOPTION -r $RESPONSE_FILE.1 -R $ROOTDIR                                                
        -d . $pkglist
                                        else
!                                               pkgadd -D /tmp/$PatchNum.$$ -S -n -a $ADMINTFILE                        
                                $MOPTION -r $RESPONSE_FILE.1                                            -R $ROOTDIR -d 
. $pkglist                                                       1>>$LOGFILE </dev/null 2>&1
--- 4329,4339 ----
                                if [[ "$firstTimeThru" = "yes" ]]
                                then
                                        if [[ "$PKGADD_DEBUG" = "yes" ]]; then
!                                               pkgadd -v -D ${WORKDIR}/$PatchNum.$$ -S -n -a $ADMINTFILE               
                                        $MOPTION -r $RESPONSE_FILE.1 -R $ROOTDIR                                        
                -d . $pkglist
                                        else
!                                               pkgadd -D ${WORKDIR}/$PatchNum.$$ -S -n -a $ADMINTFILE                  
                                        $MOPTION -r $RESPONSE_FILE.1                                            -R 
$ROOTDIR -d . $pkglist                                                       1>>$LOGFILE </dev/null 2>&1

Current thread: