Keeping
FreeBSD Up to Date
Richard Bejtlich
The purpose of this article is to explain the simplest means possible
to keep a fairly stock FreeBSD system up to date. For many years,
FreeBSD users have relied on a standard set of tools to update the
FreeBSD operating system and its applications. In this article,
I will introduce somewhat newer methods to streamline and improve
the process.
The audience for this article is an administrator who has just
installed a fresh copy of FreeBSD on a new server. Those familiar
with Microsoft installations will no doubt look for a "Windows Update"-type
way to patch the FreeBSD OS and applications. I will show how to
accomplish that goal.
The techniques and tools described in this article apply to both
FreeBSD 5.x and 6.x. At the time of writing, FreeBSD 5.4 RELEASE
was the latest available version in the 5.x tree. Many updates to
the OS and applications have occurred in the months since the release
of 5.4 in May 2005. At the time of writing, FreeBSD 6.0 RELEASE
was just being published; therefore, it has no update history. Thus,
I will demonstrate command syntax and output using FreeBSD 5.4 RELEASE
and point out where slight differences exist in FreeBSD 6.0 RELEASE
and greater.
It is important to realize that this article does not show how
to bring a FreeBSD 5.4 RELEASE system up to the absolute latest
version of FreeBSD. The true cutting edge of FreeBSD OS development
is called CURRENT, which at the time of writing could be considered
"FreeBSD 7.x". I will explain how to operate a FreeBSD 5.4 system
within the "security" branch, which in this case is FreeBSD 5.4
RELEASE plus patches and critical bug fixes.
Adding Bash as a Package
I will equip this FreeBSD system almost exclusively using packages
to simplify the deployment process. Although packages are the fastest
way to deploy applications on FreeBSD, administrators always have
the option to use the FreeBSD ports tree to compile applications
from source code. It is important to understand that any application
installed using the FreeBSD ports tree ends up on the system as
a package. Therefore, in some cases the terms "port" and "package"
are used interchangeably, but they still refer to third-party applications
not packaged with the OS userland.
To demonstrate adding a package, I will install the Bash shell.
By default, a user-level account in FreeBSD is given the /bin/sh
(Bourne) shell; Bash is not included by default. FreeBSD packages
bear the .tbz suffix and are similar to precompiled packages found
on other operating systems.
You must have root privileges to install packages. To begin, set
the PACKAGESITE environment variable in root's csh shell. The variable
can be modified to use any of the FreeBSD FTP servers. Here I choose
ftp2.freebsd.org, but I recommend selecting a FTP server close to
your location. The FreeBSD FTP servers host thousands of precompiled
packages built for many architectures on the FreeBSD package building
cluster. These packages are updated at regular intervals, but may
lag their source code counterparts.
The purpose of setting this variable is to instruct FreeBSD's
package deployment tools to use the latest available package when
adding new applications. If the PACKAGESITE variable is left unchanged,
packages built at the time FreeBSD 5.4 RELEASE was published will
be installed (many of the commands that follow have been broken
over multiple lines to facilitate printing this article. For example,
the following ftp:// URL consists of a single line, but had to be
broken after the i386/ component):
samsonov# setenv PACKAGESITE \
ftp://ftp2.freebsd.org/pub/FreeBSD/ports/i386/ \
packages-5-stable/Latest/
For FreeBSD 6.0 and other releases in the 6.x tree, replace "packages-5-stable"
with "packages-6-stable" in the variable.
The PACKAGESITE variable I use ends in Latest/ and not an alternative
-- All/. If I had used All/, I would need to check for the actual
name of the version of the Bash package available on the FTP server
(e.g., bash-3.0.16_1.tbz).
Next, we use the pkg_add tool to install the Bash shell.
The -r switch tells pkg_add to retrieve a remote package.
Notice that pkg_add is smart enough to resolve any dependencies.
In the output below, we see that libiconv-1.9.2_1.tbz and gettext-0.14.5.tbz
are dependent packages that pkg_add automatically installs:
samsonov# pkg_add -r bash
Fetching ftp://ftp2.freebsd.org/pub/FreeBSD/ports/i386/ \
packages-5-stable/Latest/bash.tbz... Done.
Fetching ftp://ftp2.freebsd.org/pub/FreeBSD/ports/i386/ \
packages-5-stable/All/libiconv-1.9.2_1.tbz... Done.
Fetching ftp://ftp2.freebsd.org/pub/FreeBSD/ports/i386/ \
packages-5-stable/All/gettext-0.14.5.tbz... Done.
Updating the Operating System
Next I will show how to install the freebsd-update tool written
by Colin Percival. Freebsd-update enables binary updates
of the FreeBSD OS. Administrators who begin with a RELEASE system,
who do not make any changes to the FreeBSD GENERIC kernel, and who
have not made any changes to userland tools have a strong case for
using binary upgrades.
Those running custom kernels cannot use freebsd-update
to replace their kernel. Instructions for configuring and recompiling
the FreeBSD kernel are found in the FreeBSD Handbook.
To add freebsd-update as a package, do the following:
samsonov:/root# pkg_add -r freebsd-update
Fetching ftp://ftp2.freebsd.org/pub/FreeBSD/ports/i386/ \
packages-5-stable/Latest/freebsd-update.tbz... Done.
Fetching ftp://ftp2.freebsd.org/pub/FreeBSD/ports/i386/ \
packages-5-stable/All/bsdiff-4.2.tbz... Done.
...truncated...
Next, execute the rehash command to rebuild the table which
tells root's csh shell where system executables can be found. Copy
the freebsd-update configuration file and make a directory
for updates:
samsonov:/root# rehash
samsonov:/root# cp /usr/local/etc/freebsd-update.conf.sample \
/usr/local/etc/freebsd-update.conf
samsonov:/root# mkdir /usr/local/freebsd-update
Before running freebsd-update, take a look at uname
output:
samsonov:/root# uname -a
FreeBSD samsonov.taosecurity.com 5.4-RELEASE \
FreeBSD 5.4-RELEASE #0: Sun May 8 10:21:06 UTC 2005 \
root@harlow.cse.buffalo.edu:/usr/obj/usr/src/sys/GENERIC i386
From this, we see that we are running 5.4-RELEASE #0, which means
this is a system just deployed from FreeBSD RELEASE sources; no patches
or changes have been applied.
At this point, we can run freebsd-update with the fetch
command. This process connects to a server run by Colin Percival
to retrieve updates using HTTP.
samsonov:/root# freebsd-update fetch
Fetching public key...
Fetching updates signature...
Fetching updates...
Fetching hash list signature...
Fetching hash list...
Examining local system...
Fetching updates...
/boot/kernel/kernel...
/boot/loader...
/boot/pxeboot...
/lib/libz.so.2...
/usr/bin/bunzip2...
/usr/bin/bzcat...
/usr/bin/bzip2...
/usr/bin/cvsbug...
/usr/bin/gunzip...
/usr/bin/gzcat...
/usr/bin/gzip...
/usr/bin/zcat...
/usr/include/machine/cpufunc.h...
/usr/include/netinet/tcp_seq.h...
/usr/lib/libbz2.a...
/usr/lib/libbz2.so.1...
/usr/lib/libbz2_p.a...
/usr/lib/libssl.a...
/usr/lib/libssl.so.3...
/usr/lib/libssl_p.a...
/usr/lib/libstand.a...
/usr/lib/libz.a...
/usr/lib/libz_p.a...
/usr/sbin/tcpdump...
Updates fetched
To install these updates, run:
/usr/local/sbin/freebsd-update install
Remember to rebuild any statically linked ports to use the
updated libraries after you install them.
The previous list shows all of the files (including the kernel) affected
by security updates from the moment FreeBSD 5.4 RELEASE was published
to the date of the last refresh of the binary updates. Once the binary
updates are downloaded, freebsd-update install applies
them:
samsonov:/root# freebsd-update install
Backing up /boot/kernel/kernel...
Installing new /boot/kernel/kernel...
Backing up /boot/loader...
Installing new /boot/loader...
Backing up /boot/pxeboot...
Installing new /boot/pxeboot...
Backing up /lib/libz.so.2...
Installing new /lib/libz.so.2...
Backing up /usr/bin/bunzip2...
Installing new /usr/bin/bunzip2...
Backing up /usr/bin/bzcat...
Recreating hard link from /usr/bin/bunzip2 to /usr/bin/bzcat...
Backing up /usr/bin/bzip2...
Recreating hard link from /usr/bin/bunzip2 to /usr/bin/bzip2...
Backing up /usr/bin/cvsbug...
Installing new /usr/bin/cvsbug...
Backing up /usr/bin/gunzip...
Installing new /usr/bin/gunzip...
Backing up /usr/bin/gzcat...
Recreating hard link from /usr/bin/gunzip to /usr/bin/gzcat...
...edited...
Backing up /usr/sbin/tcpdump...
Installing new /usr/sbin/tcpdump...
Now it is time to reboot the system. Because the kernel was updated,
it must be activated by the shutdown -r now command:
samsonov:/root# shutdown -r now
Once the system is up, we see it is running the "security" branch,
current as of July 20 08:57:11 UTC 2005:
samsonov:/root# uname -a
FreeBSD samsonov.taosecurity.com 5.4-SECURITY \
FreeBSD 5.4-SECURITY #0: Wed Jul 20 08:57:11 UTC 2005 \
root@builder.daemonology.net:/usr/obj/usr/src/sys/GENERIC i386
The kernel was rebuilt in July, because that was the last time a vulnerability
(FreeBSD-SA-05:17.devfs) required a kernel recompile.
The FreeBSD 5.4 OS is patched for all known vulnerabilities. To
verify that no other updates are available, you can rerun freebsd-update
fetch as root:
samsonov:/root# freebsd-update fetch
Fetching updates signature...
Fetching hash list signature...
Examining local system...
No updates available
With the OS patched, it is time to turn to applications.
Identifying Vulnerable Applications
In this section, I'll address keeping applications up-to-date.
This section only applies to programs installed as packages or using
the FreeBSD ports tree. It does not address programs installed strictly
as source code outside the ports system or binaries that are run
on the host independent of the FreeBSD package system.
The first priority is identifying installed packages with security
problems. We can use the portaudit application to perform
this task. We do not need to update the FreeBSD ports tree to use
portaudit, because it has its own vulnerability database:
samsonov:/root# setenv PACKAGESITE ftp://ftp2.freebsd.org/pub/FreeBSD/ \
ports/i386/packages-5-stable/Latest/
samsonov:/root# pkg_add -r portaudit
Fetching ftp://ftp2.freebsd.org/pub/FreeBSD/ \
ports/i386/packages-5-stable/ \
Latest/portaudit.tbz... Done.
samsonov:/root# rehash
samsonov:/root# portaudit -Fda
auditfile.tbz 100% of 31 kB 65 kBps
New database installed.
Database created: Thu Nov 3 16:40:14 EST 2005
Affected package: xorg-server-6.8.2
Type of problem: X11 server -- pixmap
allocation vulnerability.
Reference: <http://www.FreeBSD.org/ports/portaudit/ \
a863aa74-24be-11da-8882-000e0c33c2dc.html>
1 problem(s) in your installed packages found.
You are advised to update or de-install the affected package(s) immediately.
We see that xorg-server-6.8.2 has a security problem, which we will
address shortly. First, however, we must update the FreeBSD ports
tree, which is a hierarchy of directories and files that helps FreeBSD
build applications from source code. We will also use the ports tree
to leverage upgrades using precompiled packages.
Updating the Ports Tree
We must now use Colin Percival's portsnap tool. Portsnap
fetches and updates compressed snapshots of the FreeBSD ports tree,
and extracts and updates an uncompressed ports tree. For FreeBSD
5.x, we install the portsnap package. (Portsnap comes bundled
with the OS on FreeBSD 6.x.)
samsonov:/root# pkg_add -r portsnap
Fetching ftp://ftp2.freebsd.org/pub/FreeBSD/ports/i386/ \
packages-5-stable/Latest/portsnap.tbz... Done.
...truncated...
We must copy a configuration file, create a directory, and manually
add a dependency that is not natively resolved (freebsd-sha256):
samsonov:/root# rehash
samsonov:/root# cp /usr/local/etc/portsnap.conf.sample /usr/local/etc/portsnap.conf
samsonov:/root# pkg_add -r freebsd-sha256
Fetching ftp://ftp2.freebsd.org/pub/FreeBSD/ports/i386/ \
packages-5-stable/Latest/freebsd-sha256.tbz... Done.
Now we can use portsnap fetch to retrieve an updated FreeBSD
ports tree:
samsonov:/root# portsnap fetch
Fetching public key... done.
Fetching snapshot tag... done.
Fetching snapshot metadata... done.
Fetching snapshot generated at Wed Nov 2 20:10:15 EST 2005:
eb4f715374a1e33aea09bc0b045462bdbefe63b4134a83 35% of \
36 MB 519 kBps 00m47s
Extracting snapshot... done.
Verifying snapshot integrity... done.
Fetching snapshot tag... done.
Fetching snapshot metadata... done.
Updating from Wed Nov 2 20:10:15 EST 2005 to Thu Nov 3 \
14:01:55 EST 2005.
Fetching 4 metadata patches... done.
Applying metadata patches... done.
Fetching 0 metadata files... done.
Fetching 75 patches.....10....20....30....40....50....60....70.. done.
Applying patches... done.
Fetching 2 new ports or files... done.
Using portsnap extract, we apply the updates:
samsonov:/root# portsnap extract
/usr/ports/.cvsignore
/usr/ports/CHANGES
/usr/ports/COPYRIGHT
/usr/ports/LEGAL
/usr/ports/MOVED
/usr/ports/Makefile
/usr/ports/Mk/bsd.autotools.mk
/usr/ports/Mk/bsd.emacs.mk
...edited...
/usr/ports/x11/yelp/
/usr/ports/x11/zenity/
Building new INDEX files... done.
In the future, to update ports, rerun portsnap fetch and then
run portsnap update (not portsnap extract):
samsonov:/root# portsnap fetch
Fetching snapshot tag... done.
Fetching snapshot metadata... done.
Updating from Thu Nov 3 14:01:55 EST 2005 to Thu Nov 3 \
19:52:58 EST 2005.
Fetching 4 metadata patches... done.
Applying metadata patches... done.
Fetching 0 metadata files... done.
Fetching 30 patches.....10....20....30 done.
Applying patches... done.
Fetching 1 new ports or files... done.
samsonov:/root# portsnap update
Removing old files and directories... done.
Extracting new files:
/usr/ports/audio/gramofile/
/usr/ports/databases/py-PySQLite2/
...edited...
/usr/ports/sysutils/apachetop/
/usr/ports/www/raqdevil/
Building new INDEX files... done.
With the ports tree up to date, we can use it to upgrade applications.
Updating Applications
The next step in the application upgrade process requires installing
portupgrade. This tool is the easiest way to more or less
automatically update a large number of applications:
samsonov:/root# pkg_add -r portupgrade
Fetching ftp://ftp2.freebsd.org/pub/FreeBSD/ports/i386/ \
packages-5-stable/Latest/portupgrade.tbz... Done.
Fetching ftp://ftp2.freebsd.org/pub/FreeBSD/ports/i386/ \
packages-5-stable/All/ruby-1.8.2_4.tbz... Done.
Deinstalling obsoleted packages that are now part of ruby...
...edited...
Fetching ftp://ftp2.freebsd.org/pub/FreeBSD/ports/i386/ \
packages-5-stable/All/ruby18-bdb1-0.2.2.tbz... Done.
pkg_add: warning: package 'portupgrade-20041226_7' requires \
'perl-5.8.7', but 'perl-5.8.6_2' is installed
samsonov:/root# rehash
Once portupgrade is installed, we run the portversion
tool to see which applications need to be upgraded. Portversion
simply compares installed applications against the versions listed
in the FreeBSD ports tree; this is not a security check as was provided
by portaudit. Notice that invoking portaudit rebuilds
the package database (pkgdb) automatically.
samsonov:/root# portversion -v -l "<"
[Rebuilding the pkgdb <format:bdb1_btree> in /var/db/pkg ... \
- 31 packages found (-0 +31) ............................... done]
expat-1.95.8 < needs updating (port has 1.95.8_3)
freetype2-2.1.9 < needs updating (port has 2.1.10_1)
libXft-2.1.6_1 < needs updating (port has 2.1.7)
perl-5.8.6_2 < needs updating (port has 5.8.7)
pkgconfig-0.15.0_1 < needs updating (port has 0.17.2)
png-1.2.8_1 < needs updating (port has 1.2.8_2)
portupgrade-20041226_7 < needs updating (port has 20041226_8)
ruby-1.8.2_4 < needs updating (port has 1.8.2_5)
xorg-server-6.8.2 < needs updating (port has 6.8.2_6)
xterm-200_2 < needs updating (port has 205_1)
Here portversion identifies 31 packages, of which 10 require
updating. It is important to check the contents of the /usr/ports/UPDATING
file to see whether any of the ports requiring updates have special
instructions.
After reviewing /usr/ports/UPDATING, we are ready to tell portupgrade
to begin updating applications. Invoke portupdate with the
-varRPP switches, where v means verbose, a means all, rR
means act on upward and downward dependencies, and PP means only
upgrade using packages. Rather than recompiling all of these applications,
we will try to use the FreeBSD package cluster to retrieve precompiled
packages:
samsonov:/root# portupgrade -varRPP
---> Session started at: Thu, 03 Nov 2005 17:15:09 -0500
...edited...
---> Listing the results (+:done / -:ignored / *:skipped / !:failed)
+ graphics/png (png-1.2.8_1)
- sysutils/freebsd-sha256 (freebsd-sha256-20050310)
- security/portaudit (portaudit-0.5.10)
! lang/ruby18 (ruby-1.8.2_4) (package not found)
* databases/ruby-bdb1 (ruby18-bdb1-0.2.2)
- converters/libiconv (libiconv-1.9.2_1)
- devel/gettext (gettext-0.14.5)
+ devel/pkgconfig (pkgconfig-0.15.0_1)
+ lang/perl5.8 (perl-5.8.6_2)
* sysutils/portupgrade (portupgrade-20041226_7)
- misc/bsdiff (bsdiff-4.2)
- sysutils/portsnap (portsnap-0.9.5)
+ textproc/expat2 (expat-1.95.8)
- security/freebsd-update (freebsd-update-1.6_1)
- devel/imake-6 (imake-6.8.2)
- x11/xorg-documents (xorg-documents-6.8.2)
- x11/xorg-manpages (xorg-manpages-6.8.2)
- shells/bash (bash-3.0.16_1)
+ print/freetype2 (freetype2-2.1.9)
- x11-fonts/fontconfig (fontconfig-2.2.3,1)
- x11/xorg-libraries (xorg-libraries-6.8.2)
- x11-fonts/bitstream-vera (bitstream-vera-1.10_1)
+ x11-fonts/libXft (libXft-2.1.6_1)
+ x11/xterm (xterm-200_2)
- x11/xorg-clients (xorg-clients-6.8.2)
+ x11-servers/xorg-server (xorg-server-6.8.2)
- x11-fonts/xorg-fonts-encodings (xorg-fonts-encodings-6.8.2)
- x11-fonts/xorg-fonts-miscbitmaps \
(xorg-fonts-miscbitmaps-6.8.2)
- x11-fonts/xorg-fonts-truetype (xorg-fonts-truetype-6.8.2)
- x11-fonts/xorg-fonts-75dpi (xorg-fonts-75dpi-6.8.2)
- x11-fonts/xorg-fonts-100dpi (xorg-fonts-100dpi-6.8.2)
---> Packages processed: 8 done, 20 ignored, 2 skipped and 1 failed
---> Session ended at: Thu, 03 Nov 2005 17:18:28 \
-0500 (consumed 00:03:18)
These results show that Ruby could not be updated because no suitable
package was found. Thus, updates to ruby-bdb and portupgrade
(which depends on Ruby) also failed.
To remedy the situation, we rerun portupgrade without the
PP switches. This tells portupgrade to update all out-of-date
ports by compiling them from source code:
samsonov:/root# portupgrade -varR
---> Session started at: Thu, 03 Nov 2005 19:28:46 -0500
...edited...
---> Upgrade of lang/ruby18 started at: Thu, 03 Nov 2005 \
19:28:49 -0500
---> Upgrading 'ruby-1.8.2_4' to 'ruby-1.8.2_5' (lang/ruby18)
---> Build of lang/ruby18 started at: Thu, 03 Nov 2005 \
19:28:49 -0500
---> Building '/usr/ports/lang/ruby18'
===> Cleaning for ruby-1.8.2_5
=> ruby-1.8.2.tar.gz doesn't seem to exist in \
/usr/ports/distfiles/ruby.
=> Attempting to fetch from ftp://ftp.iij.ad.jp/pub/lang/ruby/1.8/.
ruby-1.8.2.tar.gz 49% of 3542 kB 156 kBps 00m12s
...edited...
---> Listing the results (+:done / -:ignored / *:skipped / !:failed)
- lang/perl5.8 (perl-5.8.7)
- misc/bsdiff (bsdiff-4.2)
+ lang/ruby18 (ruby-1.8.2_4)
- converters/libiconv (libiconv-1.9.2_1)
- graphics/png (png-1.2.8_2)
- security/portaudit (portaudit-0.5.10)
- devel/gettext (gettext-0.14.5)
- shells/bash (bash-3.0.16_1)
- security/freebsd-update (freebsd-update-1.6_1)
- devel/pkgconfig (pkgconfig-0.17.2)
- devel/imake-6 (imake-6.8.2)
- x11/xorg-manpages (xorg-manpages-6.8.2)
- x11/xorg-documents (xorg-documents-6.8.2)
- databases/ruby-bdb1 (ruby18-bdb1-0.2.2)
+ sysutils/portupgrade (portupgrade-20041226_7)
...edited...
---> Packages processed: 2 done, 29 ignored, 0 skipped and 0 failed
---> Session ended at: Thu, 03 Nov 2005 19:32:43 -0500 \
(consumed 00:03:57)
At the end of the process, we rerun portversion and portaudit
to verify they are satisfied with the state of our applications:
samsonov:/root# portversion -v -l "<"
samsonov:/root# portaudit -Fda
auditfile.tbz 100% of 31 kB 58 kBps
New database installed.
Database created: Thu Nov 3 19:10:17 EST 2005
0 problem(s) in your installed packages found.
All of our applications are up to date, and there are no security
vulnerabilities present:
Conclusion
In this article, I presented the simplest ways to keep FreeBSD
systems up to date. I did not address situations where non-GENERIC
kernels are used, where port/package updates fail, or other problematic
situations. With this information, however, most FreeBSD administrators
can take good care of many of their systems.
Richard Bejtlich (richard@taosecurity.com) is founder
of TaoSecurity (www.taosecurity.com) and the TaoSecurity
blog (taosecurity.blogspot.com). He is also author of The
Tao of Network Security Monitoring and Extrusion Detection
and co-author of Real Digital Forensics. |