section id="vs1.27-linux2.4.25-manual-patch"
rcsinfo="$Header: /home/radek/cvs/unix-book/unix.xml,v 1.7 2009-03-07 03:52:40 radek Exp $"
Následující příklad je spíše než ukázkou překladu jádra ukázkou řešení problému při záplatování. Vlastně jsem prováděl celé záplatování zbytečně neb jsem vycházel z mylného předpokladu že nový patch vyřeší můj „problém“. Problém s nefungováním příkazu hostname pro nastavení jména počítače ve virtuálním serveru. Jak jsem posléze zjistil toto se nastavuje v hostitelském serveru v konfiguračním souboru virtuálního stroje. Dále tedy následuje uvedený, „zbytečný“ postup.
Protože jsem nebyl spokojený s předchozím jádrem, rozhodl jsem se připravit si jádro s poslední stabilní záplatou vserveru vs1.27. Postupoval jsem následovně.
Stáhl jsem si poslední záplatu a utility.
# wget http://www.13thfloor.at/vserver/s_release/v1.27/patch-2.4.25-vs1.27.diff.bz2 # wget http://www.13thfloor.at/vserver/s_release/v1.27/util-vserver-0.29.3.tar.bz2
Záplaty jsem aplikoval na zdroje jádra.
# cd /usr/src/linux # bzcat /home/radek/work/vserver/patch-2.4.25-vs1.27.diff.bz2 \ | patch -p1 | tee patch.log
Celý průběh záplatování jsem si nechal zapsat do souboru patch.log aby jej mohl podrobně prozkoumat. Záplatování s v několika kouscích (hunk) nepovedlo, tak se podíváme na neúspěchy.
# grep FAILED patch.log
Hunk #1 FAILED at 807.
Hunk #2 FAILED at 1088.
2 out of 2 hunks FAILED -- saving rejects to file arch/ppc64/kernel/misc.S.rej
Hunk #1 FAILED at 29.
1 out of 1 hunk FAILED -- saving rejects to file include/net/ip.h.rej
Hunk #2 FAILED at 168.
1 out of 2 hunks FAILED -- saving rejects to file include/net/route.h.rej
Hunk #6 FAILED at 557.
1 out of 7 hunks FAILED -- saving rejects to file net/ipv4/udp.c.rejNezbylo mi než se zahloubat do kódu a aplikovat neúspěšné kousky ručně.
Začal jsem odmítnutým kódem v souboru include/net/ip.h.rej. Tato část je nejjednodušší.
*************** *** 29,34 **** #include <linux/netdevice.h> #include <linux/inetdevice.h> #include <linux/in_route.h> #include <net/route.h> #include <net/arp.h> --- 29,35 ---- #include <linux/netdevice.h> #include <linux/inetdevice.h> #include <linux/in_route.h> + #include <linux/vcontext.h> #include <net/route.h> #include <net/arp.h>
Tady byla oprava triviální. Za řádku
#include <linux/in_route.h>
jsem vsunul potřebnou řádku
#include <linux/vcontext.h>
Poté jsem pokračoval souborem include/net/route.h.rej. Tady je neúspěšný kód již delší.
***************
*** 167,172 ****
static inline int ip_route_connect(struct rtable **rp, u32 dst, u32 src, u32 tos, int oif)
{
int err;
err = ip_route_output(rp, dst, src, tos, oif);
if (err || (dst && src))
return err;
--- 168,211 ----
static inline int ip_route_connect(struct rtable **rp, u32 dst, u32 src, u32 tos, int oif)
{
int err;
+ struct iproot_info *ip_info = current->ip_info;
+ if (ip_info != NULL) {
+ __u32 ipv4root = ip_info->ipv4[0];
+ if (ipv4root != 0) {
+ int n = ip_info->nbipv4;
+ if (src == 0) {
+ if (n > 1) {
+ u32 foundsrc;
+ int i;
+ err = ip_route_output(rp, dst, src, tos, oif);
+ if (err) return err;
+ foundsrc = (*rp)->rt_src;
+ ip_rt_put(*rp);
+ for (i=0; i<n; i++){
+ u32 mask = ip_info->mask[i];
+ u32 ipv4 = ip_info->ipv4[i];
+ u32 netipv4 = ipv4 & mask;
+ if ((foundsrc & mask) == netipv4) {
+ src = ipv4;
+ break;
+ }
+ }
+ }
+ if (src == 0)
+ src = dst == 0x0100007f
+ ? 0x0100007f: ipv4root;
+ } else {
+ int i;
+ for (i=0; i<n; i++) {
+ if (ip_info->ipv4[i] == src) break;
+ }
+ if (i == n)
+ return -EPERM;
+ }
+ if (dst == 0x0100007f && !vx_check(0, VX_ADMIN))
+ dst = ipv4root;
+ }
+ }
err = ip_route_output(rp, dst, src, tos, oif);
if (err || (dst && src))
return err;Po ruční opravě vypadá rozdíl takto
@@ -156,6 +157,45 @@
.dport = dport } } };
int err;
+ struct iproot_info *ip_info = current->ip_info;
+ if (ip_info != NULL) {
+ __u32 ipv4root = ip_info->ipv4[0];
+ if (ipv4root != 0) {
+ int n = ip_info->nbipv4;
+ if (src == 0) {
+ if (n > 1) {
+ u32 foundsrc;
+ int i;
+ err = ip_route_output_flow(rp, &fl, sk, 0);
+ if (err) return err;
+ foundsrc = (*rp)->rt_src;
+ ip_rt_put(*rp);
+ for (i=0; i<n; i++){
+ u32 mask = ip_info->mask[i];
+ u32 ipv4 = ip_info->ipv4[i];
+ u32 netipv4 = ipv4 & mask;
+ if ((foundsrc & mask) == netipv4) {
+ src = ipv4;
+ break;
+ }
+ }
+ }
+ if (src == 0)
+ src = dst == 0x0100007f
+ ? 0x0100007f: ipv4root;
+ } else {
+ int i;
+ for (i=0; i<n; i++) {
+ if (ip_info->ipv4[i] == src) break;
+ }
+ if (i == n)
+ return -EPERM;
+ }
+ if (dst == 0x0100007f && !vx_check(0, VX_ADMIN))
+ dst = ipv4root;
+ }
+ }
+Poslední kousek který neuspěl je include/net/ipv4/udp.c.rej
***************
*** 540,545 ****
rt = (struct rtable*)sk_dst_check(sk, 0);
if (rt == NULL) {
err = ip_route_output(&rt, daddr, ufh.saddr, tos, ipc.oif);
if (err)
goto out;
--- 557,574 ----
rt = (struct rtable*)sk_dst_check(sk, 0);
if (rt == NULL) {
+ struct iproot_info *ip_info = current->ip_info;
+
+ if (ip_info != NULL) {
+ __u32 ipv4root = ip_info->ipv4[0];
+ if (ipv4root) {
+ if (daddr == 0x0100007f &&
+ !vx_check(0, VX_ADMIN))
+ daddr = ipv4root;
+ if (ufh.saddr == 0)
+ ufh.saddr = ipv4root;
+ }
+ }
err = ip_route_output(&rt, daddr, ufh.saddr, tos, ipc.oif);
if (err)
goto out;Záplatu jsem vsunul za řádku 618
.dport = dport } } };
@@ -599,6 +616,19 @@
.uli_u = { .ports =
{ .sport = sk->sport,
.dport = dport } } };
+ struct iproot_info *ip_info = current->ip_info;
+
+ if (ip_info != NULL) {
+ __u32 ipv4root = ip_info->ipv4[0];
+ if (ipv4root) {
+ if (daddr == 0x0100007f &&
+ !vx_check(0, VX_ADMIN))
+ daddr = ipv4root;
+ if (fl.nl_u.ip4_u.saddr == 0)
+ fl.nl_u.ip4_u.saddr = ipv4root;
+ }
+ }
+
err = ip_route_output_flow(&rt, &fl, sk, !(msg->msg_flags&MSG_DONTWAIT));
if (err)
goto out;
Záplatováním souboru arch/ppc64/kernel/misc.S jsem se nazabýval, neb jádro použiji jen na platformě Intel.
Uschování ozáplatovaných zdrojů
# cd /usr/src # mv kernel-source-2.4.25 kernel-source-2.4.25-vs1.27 # cd kernel-source-2.4.25-vs1.27 # make mrproper # cd .. # tar cf kernel-source-2.4.25-vs1.27.tar kernel-source-2.4.25-vs1.27 # bzip2 --best kernel-source-2.4.25-vs1.27.tar.bz2
Vlastní překlad jádra
# /root/sbin/build-kernel yoda 6