======OS - BSD - OpenBSD - binpatch====== [[http://www.openbsd-stable.org/|Maurice Janssen - Binary Updates for OpenBSD]] maintains an FTP-server with stable (release) builds of a number of recent OpenBSD releases. \\ [[http://opensource.mtier.org/binpatchng.html|binpatchng]] is based on [[http://openbsdbinpatch.sourceforge.net/|binpatch]] but can package binpatches so that they can be installed/removed with the native OpenBSD pkg_* tools. \\ =====What is binpatch for OpenBSD?===== OpenBSD doesn't have update packages. To apply the patches from [[http://www.openbsd.org/errata.html|OpenBSD errata]] you need to do the following: - Make sure that the compiler set is installed on the server. - Download the sourcecode for the system and extract it. - Download the errata patches and apply these to the extracted sourcecode. - Compile the patched sourcecode and install the modified binaries. This process wil need to be repeated on each OpenBSD server, unless you upgrade to a new release or build your own install set from patched sourcecode and use this to upgrade. [[http://openbsdbinpatch.sourceforge.net/|Binpatch]] was created by Gerardo Santana to offer another option. With binpatch you only have to compile the patched sourcecode on one system (per architecture) and add the modified files to a binpatch archive ready to be extracted on other systems that need the patch. Binpatch creates a fake install directory and extracts the complete system with sourcecode to it. A Makefile is used to apply the patches to the fake install directory and monitor changed files to add to a binpatch archive. // Random observation: If after editing Makefile you run into the error ""Makefile", line 55: Missing dependency operator" check if there are no spaces in the file where they should not be. // =====Creating a binpatch computer===== Download [[http://sf.net/projects/openbsdbinpatch|binpatch]]. \\ If you don't have the official OpenBSD CD set, download src.tar.gz and sys.tar.gz from one of the [[http://www.openbsd.org/ftp.html|OpenBSD HTTP/FTP mirrors]]. \\ Install OpenBSD on a machine. Example disk layout for a VMware Workstation virtual machine with a 16 GB VMDK: |a|150M|/| |b|512M|swap| |d|4G|/usr| |e|6G|/var| |f|4G|/tmp| |g|1,3G|/home| ====Create work directories==== Execute the following commands to create the first few directories for binpatch: mkdir -p /var/binpatch/distfiles/`uname -m` mkdir /var/binpatch/patches Mount the correct CD for the architecture and copy the distfiles to the binpatch environment: mount /dev/cd0a /mnt cp /mnt/`uname -r`/`uname -m`/* /var/binpatch/distfiles/`uname -m`/ umount /dev/cd0a Mount the sparc64 CD (CD 3) and copy the compressed sourcetree: mount /dev/cd0a /mnt cp /mnt/src.tar.gz /var/binpatch/distfiles umount /dev/cd0a If you don't have CD 3, download the correct version of src.tar.gz and sys.tar.gz from one of the OpenBSD FTP mirrors and place this in /var/binpatch/distfiles. The src.tar.gz on CD 3 of an OpenBSD CD set also contains the contents of sys.tar.gz. Place x.x.tar.gz in /var/binpatch/patches. \\ Extract the patches: cd /var/binpatch/patches ftp ftp://ftp.openbsd.org/pub/OpenBSD/patches/`uname -r`.tar.gz tar xvzf `uname -r`.tar.gz Move the directories below /var/binpatch/patches/x.x/ to /var/binpatch/patches/: mv /var/binpatch/patches/`uname -r`/* /var/binpatch/patches/ Place binpatch-1.1.0.tar.gz in /var/binpatch, extract the file and move binpatch-1.1.0/* to /var/binpatch: cd /var/binpatch tar xvzf binpatch-1.1.0.tar.gz mv binpatch-1.1.0/* . Apply the following patch to bsd.binpatch.mk to handle: * Removal of misc set (since OpenBSD 4.9). * Patches signed with signify(1) (since OpenBSD 5.5, based on code from binpatchng). * Removing execute permission on compiled kernels. * Adding the _clean shortcut. --- bsd.binpatch.mk.original Thu May 22 00:02:11 2008 +++ bsd.binpatch.mk Sun Mar 1 11:59:39 2015 @@ -49,6 +49,9 @@ # Defaults to $ARCH DISTSUBDIR?=${ARCH} +# Wether to fetch signed patches +PATCH_SIGNED?=".sig" + # FETCH program FETCH=ftp @@ -56,6 +59,9 @@ MASTER_SITE_OPENBSD?=ftp://ftp.openbsd.org/pub MASTER_SITE_SUBDIR?=OpenBSD/patches/${OSREV} +# Used for building set names +_OSREV=${OSREV:S/.//g} + # The working directories. All of them will be created, and removed. WRKDIR?=${.CURDIR}/work-${DISTNAME} WRKSRC?=${WRKDIR}/src @@ -88,16 +94,20 @@ ${MAKE_ENV} make depend && \ ${MAKE_ENV} make && \ if [ ${_kern} = "GENERIC" ]; then \ - cp -p bsd ${WRKINST}; \ + cp -p bsd ${WRKINST}; \ + chmod -x ${WRKINST}/bsd; \ elif [ ${_kern} = "GENERIC.MP" ]; then \ - cp -p bsd ${WRKINST}/bsd.mp; \ + cp -p bsd ${WRKINST}/bsd.mp; \ + chmod -x ${WRKINST}/bsd.mp; \ else \ - cp -p bsd ${WRKINST}/bsd.${_kern}; \ + cp -p bsd ${WRKINST}/bsd.${_kern}; \ + chmod -x ${WRKINST}/bsd.${_kern}; \ fi .endfor # Shortcuts _obj=${MAKE_ENV} make obj +_clean=${MAKE_ENV} make clean _cleandir=${MAKE_ENV} make cleandir _depend=${MAKE_ENV} make depend _includes=${MAKE_ENV} make includes @@ -142,15 +153,26 @@ # Fetches the patch file ${PATCH_FILE_${_number}}: - @echo ">> ${.TARGET:T} doesn't seem to exist on this system." - @mkdir -p ${.TARGET:H} - @cd ${.TARGET:H} && \ - for site in ${MASTER_SITE_OPENBSD}; do \ - echo ">> Attempting to fetch ${.TARGET} from $${site}/${MASTER_SITE_SUBDIR}/"; \ - if ${FETCH} $${site}/${MASTER_SITE_SUBDIR}/${.TARGET:S@${PATCHDIR}/@@}; then \ - exit 0; \ - fi; \ - done; exit 1 + @if [ ! -f "${.TARGET}" ]; then \ + echo ">> ${.TARGET:T} doesn't seem to exist on this system."; \ + if [ -f "${PATCH_FILE_${_number}}${PATCH_SIGNED}" ]; then \ + echo ">> ${.TARGET:T}${PATCH_SIGNED} does seem to exist on this system. Using that file."; \ + if signify -Vep /etc/signify/openbsd-${_OSREV}-base.pub -x ${.TARGET}${PATCH_SIGNED} -m ${.TARGET}; then \ + exit 0; \ + fi; \ + else \ + mkdir -p ${.TARGET:H}; \ + cd ${.TARGET:H} && \ + for site in ${MASTER_SITE_OPENBSD}; do \ + echo ">> Attempting to fetch ${.TARGET}${PATCH_SIGNED} from $${site}/${MASTER_SITE_SUBDIR}/"; \ + if ${FETCH} $${site}/${MASTER_SITE_SUBDIR}/${.TARGET:S@${PATCHDIR}/@@}${PATCH_SIGNED}; then \ + if signify -Vep /etc/signify/openbsd-${_OSREV}-base.pub -x ${.TARGET:T}${PATCH_SIGNED} -m ${.TARGET:T}; then \ + exit 0; \ + fi; \ + fi; \ + done; \ + fi; \ + fi; exit 1 PATCH_COOKIE_${_number}:=${WRKDIR}/.${_patch}-applied @@ -218,7 +240,7 @@ @echo "===> Creating fake install tree" rm -rf ${WRKINST} mkdir -p ${WRKINST} -.for _pkg in base comp etc game man misc +.for _pkg in base comp etc game man tar xzpf ${DISTDIR}/${ARCH}/${_pkg}${OSrev}.tgz -C ${WRKINST} .endfor cp -p ${DISTDIR}/${ARCH}/bsd ${WRKINST} && \ ====Modify the Makefile==== Copy Makefile.sample to /var/binpatch/Makefile: cp Makefile.sample Makefile Use the **more** or similar command to look at the first few lines of each patch to figure out the steps needed to apply and compile the fix. You'll need this to create the Makefile for binpatch. \\ Open /var/binpatch/Makefile in a text editor. Change the line: PATCH_COMMON=001_cvs 002_getsockopt 003_sudo 004_libz 005_libz 006_nat-t To the list of patches for the OpenBSD version you are running. Here is an example for OpenBSD 4.2: PATCH_COMMON=001_dhcpd 002_openssl 004_pf 005_ifrtlabel 007_tcprespond 008_ip6rthdr 010_openssh 011_openssh2 Change the last part so the necessary steps to compile the different patches are present, use the information from the .patch files and the "documentation" in Makefile to do this. Here is an example for OpenBSD 4.2: 004_pf: _kernel 005_ifrtlabel: _kernel 007_tcprespond: _kernel 008_ip6rthdr: _kernel 001_dhcpd: cd ${WRKSRC}/usr.sbin/dhcpd && \ (${_obj}; ${_cleandir}; ${_depend}; ${_build}) 002_openssl: cd ${WRKSRC}/lib/libssl && \ (${_obj}; ${_depend}; ${_build}) 009_ppp: cd ${WRKSRC}/usr.sbin/ppp && \ (${_obj}; ${_depend}; ${_build}) .include "bsd.binpatch.mk" ====Multiple 'make directories' for one patch==== The 012_openssl.patch for OpenBSD 4.4 indicated that make should be run in two separate directories: This is version 2 of this patch. Apply by doing: cd /usr/src patch -p0 < 012_openssl.patch And then rebuild and install the library and statically-linked binaries that depend upon it: cd lib/libssl make depend make includes make make install cd ../../sbin make obj make depend make make install The extra 'cd' can be added to the Makefile as follows: 012_openssl: cd ${WRKSRC}/lib/libssl && \ (${_depend}; ${_includes}; ${_build}; \ cd ${WRKSRC}/sbin; ${_obj}; ${_depend}; ${_build}) For this example it will appear at compile time that all programs from /sbin will be added to the patch, but the resulting binpatch PLIST only contains the following files: ./usr/lib/libcrypto.so.14.0 ./usr/lib/libcrypto.a ./usr/lib/libcrypto_p.a ./usr/lib/libcrypto_pic.a ./usr/lib/libssl.a ./usr/lib/libssl_p.a ./usr/lib/libssl_pic.a ./usr/include/openssl/asn1.h ./sbin/isakmpd ./sbin/mount_vnd ./sbin/pfctl ./sbin/vnconfig ====Prepare workingdirectories==== If you copied src.tar.gz from CD3 of the official OpenBSD release set, you can indicate to binpatch 1.1.0 that it won't need a separate sys.tar.gz for the make extract command with the following command: export env CDSRC="" The following commands need to be executed before you can compile patches: cd /var/binpatch make init make extract Make init creates the fake directory structure and extracts the archives from /var/binpatch/distfiles/arch/ to it. \\ Make extract extracts the sourcecode archives. ====Multiple kernels==== After the above steps you have an environment in which you can create binpatches. \\ By default building the kernel will only be done for the GENERIC uniprocessor kernel and not the GENERIC.MP multiprocessor or other kernels. \\ If you also want to make patches for the GENERIC.MP or other kernels you can modify the Makefile by adding the kernel names that you want to build instead of or in addition to GENERIC, by adding: KERNEL=GENERIC GENERIC.MP ====Apply patches and create packages==== For each patch a set of commands have to be executed to get a package. \\ // Replace 00x in the examples below with the number of the patch that you are building. Make sure you apply patches in the order indicated by its number! // Apply the patch to the sourcecode: make PATCH=00x patch Build the patched sourcecode: make PATCH=00x build Create the PLIST file with the files that will be added to the binpatch archive: make PATCH=00x plist View the contents of the PLIST file to check if it contains the correct files: cat pkg/PLIST-i386-00x Create the binpatch package: make PATCH=00x package The following message appears: +------------------------- | | The binary patch has been created in | /var/binpatch/packages | | To install it run make install or: | | # cd /var/binpatch/packages | # tar xzpf binpatch-4.2-i386-001.tgz -C / | +------------------------- Repeat the above steps for each patch. Change to the packages directory after you have created all the binpatch archives: cd /var/binpatch/packages Create an SHA512 checksum file in /var/binpatch to distribute together with the binpatch archives: cksum -a sha512 * > ../checksums Check the SHA512 checksums with: cksum -c ../checksums Copy the binpatch archive for each patch to the servers that need them and extract the archives to the root of the filesystem with: mkdir /var/binpatch export PVER=00x && tar xvzpf binpatch-`uname -r`-`uname -m`-$PVER.tgz -C / && touch /var/binpatch/.$PVER-applied If you built multiple kernel patches then extracting the very last one is sufficient. \\ When in doubt, just extract the patches in the order indicated by its number. (001 first, 002 second, etc.)