On Mon, May 07, 2001 at 12:51:32PM -0700, Rob Hudson wrote:
> When a security fix comes out, what is the best way to incorporate
> that fix into the current system?
> 
> On debian, it's real easy b/c it shows up on security.debian.org and
> the apt-get update files and updates it if you have it installed.
> 
> I don't have sources on my FreeBSD box, and CVSing the source files
> and running 'make world' is scary to me.  Is there a way to binary
> upgrade so FreeBSD is patched up?
> 
> Thanks,
> Rob
>
Actually, I'm working on the concept of binary patches for OpenBSD :)
That's why I've been trying to get people to install OpenBSD, so
I could hopefully persuade some EUGLUGgers to do some testing.
I know there's some work being done in FreeBSD on this, but our approach
is, well, different than any approach I've seen.  I also feel that
our approach would work on any BSD, though perhaps no as easily.
URL: http://openbsd.rutgers.edu/openbsd/binarypatch/
This project was started about 2 weeks ago, so there's not much accomplished
yet.  I attached a script I wrote, which does a good portion of the work.

<[EMAIL PROTECTED]>
#!/usr/bin/perl -w

# distdiff - compares OpenBSD distributions for changed files
# author - Jacob Meuser <[EMAIL PROTECTED]>
# license - BSD style with NO GUARANTEES 
#
# History:
#   0.0.1   2001-04-27    First tests
#   0.0.2   2001-04-28    Added ar extraction
#   0.0.3   2001-04-29    Split binary and text diff output
#   0.0.4   2001-04-29    Added perl packing list modification
#   0.0.5   2001-05-01    Added obsolete file list                     
#   0.0.9   2001-05-02    A revelation! Compare the release tarballs 
#                         separately, not the whole distribution at once.
#                         This will make packaging much easier.
#                         
# To do:
#   Test, test, test
#   Incorporate support for the X11/XF4 tarballs.
#   Deal with /dev special files, and /etc, and /var.  Currently
#     creating a diff for the "etc" tarball, and diff doesn't know
#     much about special files.
#   Add some error checking.
#   Clean and comment the code.
#   
#
# ************************ README **********************************
# Before using this script it is assumed you have been following the
# instructions for making a release as laid out in release(8), and 
# you have just finished the "make build" step.
# This script will put the $RELEASEDIR and $DESTDIR from release(8)
# in the directory it is called from.  This script will also
# create a "work" directory in the directory is is called from where
# the release tarballs will be unpacked.  The files nescesary to make 
# the packages will also be put in the "work" directory. 
# ******************************************************************
#
# Author's note:
# It may seem a bit overboard to go through the process of making
# the distribution install sets, but AFAIK no one is distributing
# the install sets made from patched (-stable) sources.  The 2.8
# sets for i386 on ftp.openbsd.org are all dated Nov 27 2000.

use File::Copy;
use strict;

# need to use 'distdiff first' to prepare for future distdiffs
# This should only be done for the first release!!
my $makerelease = "yes";
my $makediff = "yes";
if ($ARGV[0] eq "first") {
    $makediff = "no";  # nothing to compare yet
} elsif ($ARGV[0] eq "diffonly") {
    $diffonly = "yes";
}
if ($ARGV[1] eq "skiprelease") {
    $makerelease = "no";
}
# get infos for naming purposes
my $startdir = `pwd`;
chomp $startdir;

my $uname = `uname -a`;
chomp $uname;
my ($release, $version, $machine) = (split (/ /, $uname))[2,3,4];
$release =~ s/\.//;

# this is a little weak; uses the build # from the kernel; need to
# decide how the patches will be named
my $build = (split (/\#/, $version))[1];
my $old_build = $build - 1;

my $destdir = "$startdir/dest-$machine-$release-$build";
my $releasedir = "$startdir/release-$machine-$release-$build";

# perl version of the rest of release(8)
if (-d $destdir) {
    move ($destdir, "$destdir-");
    system ("rm -rf \"$destdir-\"") == 0 
        or warn "Problem removing old destdir, \"$destdir-\": $?";
}
mkdir $destdir;

if (! (-d $releasedir)) {
    mkdir $releasedir;
}

print qq (
          makedif = $makediff 
          startdir = $startdir 
          uname = $uname 
          release = $release 
          version = $version 
          machine = $machine 
          build = $build 
          old_build = $old_build
          destdir = $destdir 
          releasedir = $releasedir
          \n);

if ($makerelease ne "no") {
    chdir "/usr/src/distrib/crunch";
    system ("make clean && make && make install") == 0
        or die "Couldn't make and install crunch tools: $?";

    chdir "/usr/src/etc";
    system ("env DESTDIR=$destdir RELEASEDIR=$releasedir nice make release") == 0
        or die "Couldn't make the release: $?";

    chdir "/usr/src/distrib/sets";
    system ("env DESTDIR=$destdir RELEASEDIR=$releasedir csh checkflist") == 0
        or die "Error from checkflist: $?"; 

    chdir "$startdir";
}

# get the names of the tarballs
opendir (RELEASEDIR, "$releasedir") or die "Could not open $releasedir: $!\n";
my @tarball = grep (/\.tgz$/, readdir (RELEASEDIR));
closedir (RELEASEDIR);

# set up a directory to unpack the tar balls in
my $workdir = "$startdir" . "/" . "work-" . "$machine" . "-" . "$release" . "-" . 
"$build";
my $old_workdir = "$startdir" . "/" . "work-" . "$machine" . "-" . "$release" . "-" . 
"$old_build";

# see if we have something to compare to, let through if "first" release
if ($makediff ne "no") {
    if (! (-d $old_workdir)) {
        die "There is no old_workdir to compare the release you've made to!\n";
    }
}

my $pwd = `pwd`;
chomp $pwd;

print qq (
          pwd = $pwd
          workdir = $workdir
          old_workdir = $old_workdir
          tarballs = @tarball
          \n);

mkdir $workdir;
chdir $workdir;

# unpack the tarballs and do some prep work for reasons described below
foreach my $tarball (@tarball) {
    print `pwd`;
    print "$tarball\n";
    my $tarball_dir = $tarball;
    $tarball_dir =~ s/$release\.tgz$//;
    print "$tarball_dir\n";
    mkdir "$tarball_dir";
    chdir "$tarball_dir";
    system ("tar zxf $releasedir/$tarball");
    if ($tarball_dir eq "base") {
        # fix libdata/perl5 packing list
        # $DESTDIR gets added to the front of the paths, producing
        # a large and useless diff 
        print "Making new perl packing list in $workdir/$tarball_dir.\n";
        my $perlpack = "./usr/libdata/perl5/$machine-openbsd/5.6.0/.packlist";
        my $perlpack_new = "$perlpack" . ".new";
        open (PP, "$perlpack") or die "Can't open $perlpack: $!\n";
        open (PPTMP, ">$perlpack_new") or die "Can't open $perlpack_new: $!\n";
        while (<PP>) {
            s|$destdir|/home/dest-$machine|g;
            print PPTMP $_;
        }
        close (PPTMP);
        close (PP);
        copy ($perlpack_new, $perlpack);
        unlink $perlpack_new;
    }
    # find and extract ar archive random libraries; diff will always
    # tell us they differ because ar adds timestamps
    # extract and delete original archoives
    if (($tarball_dir ne "etc") && ($tarball_dir ne "man")) { 
        my @endinas = `find . -name \*.a -print`;
        foreach (@endinas) {
            my $file = `file $_`;
            chomp $file;
            if ($file =~ s/\: current ar archive random library$//) {
                my $extdir = "$file" . "-ar_dir";
                print `pwd`;
                print "making $extdir\n";
                mkdir $extdir;
                chdir $extdir;
                my $file_path = "$workdir" . "/" . "$tarball_dir" . "/" . "$file";
                system ("ar -x $file_path");
                unlink "$file_path";
                chdir "$workdir/$tarball_dir";
            }     
        }
    }
    # Option to skip the diff process
    if ($makediff eq "yes") {
        my $new_tbdir_path = "$workdir/$tarball_dir";
        my $old_tbdir_path = "$old_workdir/$tarball_dir";
        &dodiff ($old_tbdir_path, $new_tbdir_path, $tarball_dir);
    }
    chdir "$workdir";
}

sub dodiff {
    my ($old_tbdir_path, $new_tbdir_path, $tarballdir) = @_;
    my $patchdir = "$new_tbdir_path/../$tarballdir-patch";
    mkdir "$patchdir";
    chdir "$patchdir";
    my $pid = open (DIFFOUT, "diff -u -r $old_tbdir_path $new_tbdir_path |") 
        or die "Couldn't fork diff for $tarballdir: $!\n";
    print "Starting $tarballdir diff with pid $pid\n";
    open (DIFFIN, ">difftext.diff") or die "Can't open difftext.diff: $!\n";
    open (DIFFBINS, ">diffbins.list") or die "Can't open diffbins.list: $!\n";
    open (OBSOLETE, ">obsolete.list") or die "Can't open obsolete.list: $!\n";
    open (NEWBINS, ">newbins.list") or die "Can't open newbins.list: $!\n";
    my %have;
    while (<DIFFOUT>) {
        if (! /special file/) {  # Need good method to deal with special files
            if (s/^Binary files //) {
                my $binary = (split (/ /, $_))[0]; 
                $binary =~ s/$old_tbdir_path//;
                $binary =~ s|(\.a)_ar_extract_dir/.*|$1|;
                if ($have{$binary} ne "yes") {   # work around archives where
                    print DIFFBINS "$binary\n";  # more than one binary changed
                    $have{$binary} = "yes";
                }
            } elsif (s/^Only in $old_tbdir_path\://) {  # not in the new tball
                print OBSOLETE $_;
            } elsif (s/^Only in $new_tbdir_path\://) {  # NEW binaries
                print NEWBINS $_;
            } else {
                next if (/^diff/);  # get rid of the diff command lines
                s/^--- $old_tbdir_path/--- /;
                s/^\+\+\+ $new_tbdir_path/\+\+\+ /;
                print DIFFIN $_;
            }
        } 
    }
    close (DIFFOUT);
    close (DIFFIN);
    close (DIFFBINS);
    close (OBSOLETE);
    close (NEWBINS);
    return;
}

print "done\n";

exit (0);

Reply via email to