From b0407c1677cce9a2c2d97ecdde8fb349d8b59411 Mon Sep 17 00:00:00 2001 From: Russ Allbery Date: Tue, 17 Jul 2007 16:22:59 +0000 Subject: [PATCH] * Apply upstream patch from Jeffrey Hutzelman to fix syscall probing on AMD64 with Linux 2.6.22 kernels. (Closes: #430179) --- debian/changelog | 4 +++- src/afs/LINUX/osi_probe.c | 46 ++++++++++++++++++++++++++++++++++++--- 2 files changed, 46 insertions(+), 4 deletions(-) diff --git a/debian/changelog b/debian/changelog index 2c1b04547..1990b9e22 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,5 +1,7 @@ openafs (1.4.4.dfsg1-5) unstable; urgency=low + * Apply upstream patch from Jeffrey Hutzelman to fix syscall probing on + AMD64 with Linux 2.6.22 kernels. (Closes: #430179) * Add a union to des_ks_struct and reorder includes to get the correct alignment for DES code on SPARC. Thanks, Chaskiel Grundman. Partly addresses #415952. @@ -14,7 +16,7 @@ openafs (1.4.4.dfsg1-5) unstable; urgency=low KeyFile and CellServDB.old from /etc/openafs/server, and remove BosConfig from /etc/openafs. - -- Russ Allbery Mon, 16 Jul 2007 11:55:16 -0700 + -- Russ Allbery Tue, 17 Jul 2007 09:25:03 -0700 openafs (1.4.4.dfsg1-4) unstable; urgency=low diff --git a/src/afs/LINUX/osi_probe.c b/src/afs/LINUX/osi_probe.c index 16b5322dd..1a812367f 100644 --- a/src/afs/LINUX/osi_probe.c +++ b/src/afs/LINUX/osi_probe.c @@ -59,6 +59,7 @@ #include "afsincludes.h" #endif #include +#include #ifdef CONFIG_H_EXISTS #include #endif @@ -153,6 +154,7 @@ MODULE_PARM_DESC(probe_ignore_syscalls, "Syscalls to ignore in table checks"); * 0x0010 - detail - check_harder * 0x0020 - detail - check_harder/zapped * 0x0040 - automatically ignore setgroups and afs_syscall + * 0x0080 - detail - check_table_readable */ static int probe_debug = 0x41; #ifdef module_param @@ -298,6 +300,10 @@ typedef struct { int debug_ignore_NR[4]; /* syscalls to ignore for debugging */ } probectl; +#if defined(AFS_I386_LINUX26_ENV) || defined(AFS_AMD64_LINUX26_ENV) +static int check_access(unsigned long, int); +static int check_table_readable(probectl *, PROBETYPE *); +#endif /********** Probing Configuration: sys_call_table **********/ @@ -940,6 +946,11 @@ static int check_table(probectl *P, PROBETYPE *ptr) PROBETYPE *x; int i, j; +#if defined(AFS_I386_LINUX26_ENV) || defined(AFS_AMD64_LINUX26_ENV) + i = check_table_readable(P, ptr); + if (i >= 0) return i; +#endif + for (x = ptr, i = 0; i < _SS(NR_syscalls); i++, x++) { #ifdef OSI_PROBE_DEBUG if (probe_debug & 0x0040) { @@ -1062,6 +1073,11 @@ static int check_harder(probectl *P, PROBETYPE *p) unsigned long ip1; int i, s; +#if defined(AFS_I386_LINUX26_ENV) || defined(AFS_AMD64_LINUX26_ENV) + i = check_table_readable(P, p); + if (i >= 0) return 0; +#endif + /* Check zapped syscalls */ for (i = 1; i < P->n_zapped_syscalls; i++) { if (p[_SS(P->zapped_syscalls[i])] != p[_SS(P->zapped_syscalls[0])]) { @@ -1349,7 +1365,7 @@ static void *do_find_syscall_table(probectl *P, char **method) } #if defined(AFS_I386_LINUX26_ENV) || defined(AFS_AMD64_LINUX26_ENV) -static int check_writable(unsigned long address) +static int check_access(unsigned long address, int mode) { pgd_t *pgd = pgd_offset_k(address); #ifdef PUD_SIZE @@ -1374,10 +1390,34 @@ static int check_writable(unsigned long address) pte = (pte_t *)pmd; else pte = pte_offset_kernel(pmd, address); - if (pte_none(*pte) || !pte_present(*pte) || !pte_write(*pte)) + if (pte_none(*pte) || !pte_present(*pte)) + return 0; + if (mode && !pte_write(*pte)) return 0; return 1; } + +static int check_table_readable(probectl *P, PROBETYPE *ptr) +{ + PROBETYPE *next_page; + int i = 0, delta; + + while (i < _SS(NR_syscalls)) { + next_page = (PROBETYPE *)PAGE_ALIGN((unsigned long)(ptr+1)); + delta = next_page - ptr; + if (!check_access((unsigned long)ptr, 0)) { +#ifdef OSI_PROBE_DEBUG + if (probe_debug & 0x0080) + printk("<7>osi_probe: %s 0x%016lx not readable; delta=0x%lx\n", + P->symbol, (unsigned long)ptr, delta); +#endif + return delta - 1; + } + ptr += delta; + i += delta; + } + return -1; +} #endif void *osi_find_syscall_table(int which) @@ -1405,7 +1445,7 @@ void *osi_find_syscall_table(int which) } printk("Found %s at 0x%lx (%s)\n", P->desc, (unsigned long)answer, method); #if defined(AFS_I386_LINUX26_ENV) || defined(AFS_AMD64_LINUX26_ENV) - if (!check_writable((unsigned long)answer)) { + if (!check_access((unsigned long)answer, 1)) { printk("Address 0x%lx is not writable.\n", (unsigned long)answer); printk("System call hooks will not be installed; proceeding anyway\n"); return 0; -- 2.39.5