How to apply a patch diff to ISC source code
Sometimes when a user has a problem with ISC-supplied software, our development team, as part of the process of providing and testing a fix for the problem, may offer a patch diff containing custom modifications to be applied to a specific version of BIND or Kea. Such a diff may contain a proposed fix for a bug, or might add instrumentation and logging instructions to help track down a difficult-to-diagnose problem that a server operator is experiencing.
It is also possible to pull your own patch diffs from the public Gitlab source repositories for ISC software products and a user might choose to do so if, for example, they wanted to try the code fix associated with a certain bug issue without waiting for releases that contain the proposed fix.
If you haven't used a patch diff before, they may seem a little intimidating, but they are a practical and elegant solution to the problem of distributing and applying small, isolated changes to the source code tree for a large project such as BIND, ISC DHCP, or Kea DHCP.
A patch diff is an ASCII text file containing instructions used by the "patch" utility (which is present on most POSIX systems, usually delivered with your compiler) directing that utility to modify files by adding, removing, or altering lines of contents within one or more files specified within the diff.
As an ordinary ASCII text file, the diff file could be delivered in a number of ways, e.g. as a MIME attachment to an e-mail message or a text section within the message body, as a downloadable link from a web page, etc. Figure out how to save a copy of the diff content to a file in local storage and make note of the filename.
The entire content of the patch file, including newlines, below the first instance of a changed file (for ex. lines beginning with
--- a/FILENAME) is important, and must be present for the patch to apply successfully. Copying and pasting patch files with your computer's clipboard can be prone to errors, especially considering that some editors like to mangle spaces and tabs.
Applying a patch diff
Diffs provided by ISC engineers will contain filenames that are relative to the top working directory of the product source code files (the un-packed source code tar-ball). For example, a sample diff file contains these lines:
--- a/CHANGES +++ b/CHANGES
Therefore you will need to place the patch file in the top directory of the source code that you are going to modify, and then have that as your current working directory when you apply the patch (which is where you would be usually anyway, if building from source yourself), using the following command:
patch -p0 < name_of_diff_file
Following successful application of the patch, you can then build your ISC product as usual.
Understanding what to expect
Most of the time, if you have been provided a custom patch by ISC, it should usually apply cleanly to a freshly unpacked copy of the source tree which it is meant to modify.
Successful application of the patch will report a list of "hunks" and the files which were modified. For example:
$ patch -p0 < CVE-2020-8620.patch Patching file lib/isc/netmgr/netmgr-int.h Hunk #1 succeeded at 560. Patching file lib/isc/netmgr/netmgr.c Hunk #1 succeeded at 976. Hunk #2 succeeded at 988. Patching file lib/isc/netmgr/tcp.c Hunk #1 succeeded at 519. Hunk #2 succeeded at 560. Patching file lib/isc/netmgr/udp.c Hunk #1 succeeded at 132. Hunk #2 succeeded at 204. done
If, however, your patch did not apply completely cleanly, there are multiple possibilities. It may fail to apply at all and the patch utility may exit with an error message. In such a case you are advised to contact the person who provided the patch and furnish the error message you received; hopefully they will provide you with an improved patch which addresses the problem that caused the error.
It's also possible that a patch may involve a bit of what the patch utility calls "fuzz". This occurs when the lines meant to be modified by the patch diff are not found exactly where the patch diff file tells the patch utility to expect them. One reason this might happen is because you might be applying a patch diff to a slightly different base version of the source than the one for which it was first prepared. Usually the patch utility can make an educated guess, as long as the line to be modified are near to where they were expected to be found, but sometimes the fuzz is too much for the utility. In such cases, proceed as though the patch diff has failed to apply and contact the party who provided it to ask for help if necessary.
It is important to check for any hunks that have failed to be applied, but with one exception, the CHANGES file. This is because the CHANGES log is sequential and it's unlikely that when applying a new change to older code, that the patch utility will be able to find where to put new new log entry. Therefore you can ignore this failure (ISC Engineers may anyway have omitted this change from the patch we provided to you).
Here is what a patch hunk failure will look like:
patching file CHANGES Hunk #1 FAILED at 1. 1 out of 1 hunk FAILED -- saving rejects to file CHANGES.rej