Management

Proposal

September 2001

Adrian Schuur - [email protected] Viktor Mihajlovski - [email protected]

Introduction

As described by John Williams there is a need for better management of patches in Linux especially in enterprise computing environments. Patch management in general covers a broad area, this paper concentrates on installation, recording and inventory of patches.

It is felt that it would be futile to suggest a totally new way of coding and distributing patches. Whatever we suggest, it should build upon existing procedures. In particular this means that the development community should not be asked to change the way they develop code and available patches. Patch control and conditioning should be performed outside this community; preferably by distributors or packaging groups.

The approach used is definitly minimalistic. We do not need modifications in either the patch or rpm commands. We think that by writing a few scripts we can show very quickly notable improvements in the area of patch management.

Deficiencies in Current Patch Process

In general, there is no sure and easy way to determine the actual patches installed in a particular component unless source rpms are available, but even there patches might have been installed without going through the rpm build process. Especially in binary only packages this impossible. Just adding patch information to rpm packages as done by Debian in its corresponding deb support does not tell us whether patches have been installed a later point in . Furthermore, the kernel is rarely handled using rpm packages; the kernel is probably the component having of the patches installed. All these situations cause problems for Linux support personnel. Package build process

In order to leave the development process unaltered and add patch management on we need to understand the package build process normally used.

.tar .spec

.patch 1 2 RPM RPM .rpm Build Install binaries

.src.rpm rpm-db

Distributor Customer

Figure 1. Package Build Process The description of this process centers around rpm, a similar approach is found with Debian’s deb as well. Basic assumptions are: use of pristine source, patches distributed from developer or community in general as .patch files, integration is done by either distributor, Value Added Reseller.

Adding a Source Patch

Adding a source patch is complex. It requires availability of the source package. In essence, the patch is added to .spec (3) and the RPM build process is invoked using the extended patch base on top of the pristine source (4). The resulting package is reinstalled (5). .src.rpm 1 2 RPM Save old Install .rpm

.spec .tar 4 5 RPM RPM .rpm Upgrade .patch Build binaries 3 Add new patch .src.rpm rpm-db

Figure 2 Adding a Source Patch

Step 1 is normally done only once: it establishes the pristine source code environment. Step 2 is optional; it prepares for eventual de-installation of patches. “RPM Upgrade” with the saved .rpm will effectively restore the component to its previous level. This process is normally executed at the site where the patch is deemed needed, by either a distributor, a Value Added Reseller or an administrator.

Improving the Patch Command

For reasons described above, software components itself should carry patch level information. This enables proper indication of patch levels in all environments, be it in a package handler managed environment or not.

The improvement is done by extending the patch command, or by wrapping patch command in a shell script that adds the additional function. xyz.c int f_x() { return x; } xyz.c (patched) int f_x() patch .p1 < { xyz-one.patch return x+1; xyz-one.patch } --- org/xyz.c Mon May 28 ... +++ new/xyz.c Mon May 28 ... @@ -1,4 +1,4 @@ int f() { - return x; + return x+1; }

Figure 3. Current patch processing

Figure three shows current patch processing. The source object is simply updated.

xyz.c int f_x() { return x; } xyz.c (patched) /* @@patchlog */ patch -p1 --log static char *patchlog[]={

Figure 4. Extended patch processing

Figure four shows how a logging function will be provided by extended patch functionality. A patchlog is maintained by the extended patch command. The first patch will cause the generation of a patchlog structure for keeping track of patches added to this source module and will insert details about the first patch. Subsequent extended patch invocations will extend this structure. Notice that the patch itself does is not changed, the extended patch command will generate this additional data.

PatchLog data structure

The patchlog structure and patch information format should be selected such that it can used in two environments, namely in kernel space and user space, both of will have slightly different requirements.

In kernel space it is suggested to have extensions to /proc filesystem. A special file in /proc will list the patches installed in the kernel and its active modules.

In user space we would like to use a simple command that lists installed patches for a file, a collection of files, or a directory.

In order to serve both environments the following structure will generated and extended by the extended patch command:

const char _PatchLog_[]= "\n@PatchLog@: \n\0" ... ;

The example in figure 4 would actually look like this:

extern constant char _PatchLog_xyz_c[]= "\n@PatchLog@: patch-one 0fd34577de211e May 28 16:15:50 2001>\n\0" ;

The second patch would be added to this string like this:

extern constant char _PatchLog_xyz_c[]= "\n@PatchLog@: patch-one 0fd34577de211e May 28 16:15:50 2001>\n\0" "\n@PatchLog@: patch-two 0be732af39adf7 Jun 25 09:12:00 2001>\n\0" ;

Using the PatchLog data

The basic techniques described here can be used to commands or scripts for accessing patch information. The techniques can be used to augment the extended patch command and made available as additional options.

In user space can be used directly to show patch information : grep -a @PatchLog@: will show patches installed in this particular file. In order to determine all patches installed in a particular rmp package the following command can be issued: grep -a @PatchLog@: `rpm -ql xyz`

This will show all patch in all files of package xyz. Notice that no change in rmp is required to get this information, the only requirement is that the patches have to installed using the extended patch command. In kernel space there are some difficulties in getting this data. Often the kernel is compressed and normally rpm is not used to install a kernel. A small script can be used at init time to collect patch information from the kernel and modules. All _PatchLog_xxx variables can be detected online by issuing grep _PatchLog_ /proc/ksyms

This results in the addresses of all _PatchLog_xxx variables in the kernel. This data will be used to access the individual PatchLog entries. All patches installed in modules can be gathered by grep - @PatchLog@: /lib/modules

The information gathered this way can be places in a file and made available for further processing or could be mapped through the /proc file system.

Extended patch support

We propose to write a script around the existing patch command, it will invoke the original patch command where needed. The following is proposed to for an extended patch functionallity:

patch --log ...

Performs extended patch logging as descibed before.

A second command, patchinfo, will be used to query patch data.

patchinfo --lst

Searches and lists patch information in the specified files or directory

patchinfo --lst --pkg

Searches and list patch information in the files that are part of the indicated package. "kernel" as package name is reserved for listing patches installed in kernel and modules.

patchinfo --gen --pkg

Searches and generates a file that can be included as description in a .spec file used by the rpm build process. “Kernel” as package name is reserved for gathering kernel and module patch information. This file will be used by patch --lst --pkg kernel described above.