LINUX 5.3.0: Check for 'recurse' arg in keyring_search
[openafs.git] / src / afs / LINUX / osi_syscall.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 /*
11  * Linux module support routines.
12  *
13  */
14 #include <afsconfig.h>
15 #include "afs/param.h"
16
17 #ifdef LINUX_KEYRING_SUPPORT
18 /* The syscall probing stuff is unnecessary (and is never called) if we have
19  * keyrings support; we rely on keyrings instead of group ids to track PAGs.
20  * So if we have keyrings, just stub out the syscall functions to do nothing. */
21 int
22 osi_syscall_init(void)
23 {
24     return 0;
25 }
26 void
27 osi_syscall_clean(void)
28 {
29     return;
30 }
31
32 #else /* LINUX_KEYRING_SUPPORT */
33
34 #include <linux/module.h> /* early to avoid printf->printk mapping */
35 #include "afs/sysincludes.h"
36 #include "afsincludes.h"
37 #include <linux/unistd.h>               /* For syscall numbers. */
38 #include <linux/mm.h>
39
40 #ifdef AFS_AMD64_LINUX20_ENV
41 #include <asm/ia32_unistd.h>
42 #endif
43
44 #include <linux/proc_fs.h>
45 #include <linux/slab.h>
46 #include <linux/init.h>
47 #include <linux/sched.h>
48
49 #ifndef NR_syscalls
50 #define NR_syscalls 222
51 #endif
52
53 /* On SPARC64 and S390X, sys_call_table contains 32-bit entries
54  * even though pointers are 64 bit quantities.
55  * XXX unify this with osi_probe.c
56  */
57 #if defined(AFS_SPARC64_LINUX20_ENV) || defined(AFS_S390X_LINUX24_ENV)
58 #define SYSCALLTYPE unsigned int
59 #define POINTER2SYSCALL (unsigned int)(unsigned long)
60 #define SYSCALL2POINTER (void *)(long)
61 #else
62 #define SYSCALLTYPE void *
63 #define POINTER2SYSCALL (void *)
64 #define SYSCALL2POINTER (void *)
65 #endif
66
67 #if defined(AFS_S390X_LINUX24_ENV) 
68 #define INSERT_SYSCALL(SLOT, TMPPAGE, FUNC) \
69         if (SYSCALL2POINTER FUNC > 0x7fffffff) { \
70             TMPPAGE = kmalloc ( PAGE_SIZE, GFP_DMA|GFP_KERNEL );        \
71             if (SYSCALL2POINTER TMPPAGE > 0x7fffffff) { \
72                 printf("Cannot allocate page for FUNC syscall jump vector\n"); \
73                 return EINVAL; \
74             } \
75             memcpy(TMPPAGE, syscall_jump_code, sizeof(syscall_jump_code)); \
76             *(void **)(TMPPAGE + 0x0c) = &FUNC; \
77             afs_sys_call_table[_S(SLOT)] = POINTER2SYSCALL TMPPAGE; \
78         } else \
79             afs_sys_call_table[_S(SLOT)] = POINTER2SYSCALL FUNC;
80 #else
81 #define INSERT_SYSCALL(SLOT, TMPPAGE, FUNC) \
82     afs_sys_call_table[_S(SLOT)] = POINTER2SYSCALL FUNC;
83 #endif 
84
85 #if defined(AFS_IA64_LINUX20_ENV)
86 #define _S(x) ((x)-1024)
87 #else
88 #define _S(x) x
89 #endif
90
91
92 /***** ALL PLATFORMS *****/
93 extern asmlinkage long
94 afs_syscall(long syscall, long parm1, long parm2, long parm3, long parm4);
95
96 static SYSCALLTYPE *afs_sys_call_table;
97 static SYSCALLTYPE afs_ni_syscall = 0;
98
99 #ifdef AFS_S390X_LINUX24_ENV
100 static void *afs_sys_setgroups_page = 0;
101 #if defined(__NR_setgroups32)
102 static void *afs_sys_setgroups32_page = 0;
103 #endif
104 static void *afs_syscall_page = 0;
105
106 /* Because of how the syscall table is handled, we need to ensure our 
107    syscalls are within the first 2gb of address space. This means we need
108    self-modifying code we can inject to call our handlers if the module 
109    is loaded high. If keyrings had advanced as fast as false protection
110    this would be unnecessary. */
111
112 uint32_t syscall_jump_code[] = {
113   0xe3d0f030, 0x00240dd0, 0xa7f40006, 0xffffffff, 0xffffffff, 0xe310d004, 
114   0x0004e3d0, 0xf0300004, 0x07f10000, 
115 };
116 #endif
117
118 extern asmlinkage long afs_xsetgroups(int gidsetsize, gid_t * grouplist);
119 asmlinkage long (*sys_setgroupsp) (int gidsetsize, gid_t * grouplist);
120
121 extern asmlinkage long afs_xsetgroups32(int gidsetsize, gid_t * grouplist);
122 asmlinkage int (*sys_setgroups32p) (int gidsetsize,
123                                     __kernel_gid32_t * grouplist);
124
125 /***** AMD64 *****/
126 #ifdef AFS_AMD64_LINUX20_ENV
127 static SYSCALLTYPE *afs_ia32_sys_call_table;
128 static SYSCALLTYPE ia32_ni_syscall = 0;
129
130 extern asmlinkage long afs32_xsetgroups(int gidsetsize, u16 * grouplist);
131 asmlinkage long (*sys32_setgroupsp) (int gidsetsize, u16 * grouplist);
132 extern asmlinkage long afs32_xsetgroups32(int gidsetsize, gid_t * grouplist);
133 asmlinkage long (*sys32_setgroups32p) (int gidsetsize, gid_t * grouplist);
134 #endif /* AFS_AMD64_LINUX20_ENV */
135
136
137 /***** PPC64 *****/
138 #ifdef AFS_PPC64_LINUX26_ENV
139 static SYSCALLTYPE *afs_sys_call_table32;
140 static SYSCALLTYPE afs_ni_syscall32 = 0;
141 static SYSCALLTYPE old_sys_setgroupsp = 0;
142 static SYSCALLTYPE old_sys32_setgroupsp = 0;
143
144 asmlinkage long afs32_xsetgroups(int gidsetsize, gid_t *grouplist);
145 asmlinkage long (*sys32_setgroupsp)(int gidsetsize, gid_t *grouplist);
146
147 asmlinkage long sys_close(unsigned int fd);
148 static void sys_setgroups_stub(void)
149         __attribute__ ((pure,const,no_instrument_function));
150 static void sys_setgroups_stub(void)
151
152         printf("*** error! sys_setgroups_stub called\n");
153 }
154
155 static void sys32_setgroups_stub(void)
156         __attribute__ ((pure,const,no_instrument_function));
157 static void sys32_setgroups_stub(void)
158
159         printf("*** error! sys32_setgroups_stub called\n");
160 }
161
162 #endif /* AFS_PPC64_LINUX26_ENV */
163
164
165 /***** SPARC64 *****/
166 #ifdef AFS_SPARC64_LINUX26_ENV
167 static SYSCALLTYPE *afs_sys_call_table32;
168 static SYSCALLTYPE afs_ni_syscall32 = 0;
169
170 extern asmlinkage long afs32_xsetgroups(int gidsetsize, u16 * grouplist);
171 asmlinkage int (*sys32_setgroupsp) (int gidsetsize,
172                                     __kernel_gid32_t * grouplist);
173 /* This number is not exported for some bizarre reason. */
174 #define __NR_setgroups32      82
175 extern asmlinkage long afs32_xsetgroups32(int gidsetsize, gid_t * grouplist);
176 asmlinkage int (*sys32_setgroups32p) (int gidsetsize,
177                                       __kernel_gid32_t * grouplist);
178
179 asmlinkage int
180 afs_syscall32(long syscall, long parm1, long parm2, long parm3, long parm4,
181               long parm5)
182 {
183     __asm__ __volatile__("srl %o4, 0, %o4\n\t"
184                          "mov %o7, %i7\n\t"
185                          "call afs_syscall\n\t"
186                          "srl %o5, 0, %o5\n\t"
187                          "ret\n\t"
188                          "nop");
189 }
190 #endif /* AFS_SPARC64_LINUX20_ENV */
191
192
193 /***** IA64 *****/
194 #ifdef AFS_IA64_LINUX20_ENV
195
196 asmlinkage long
197 afs_syscall_stub(int r0, int r1, long r2, long r3, long r4, long gp)
198 {
199     __asm__ __volatile__("alloc r42 = ar.pfs, 8, 3, 6, 0\n\t"
200                          "mov r41 = b0\n\t"     /* save rp */
201                          "mov out0 = in0\n\t"
202                          "mov out1 = in1\n\t"
203                          "mov out2 = in2\n\t"
204                          "mov out3 = in3\n\t"
205                          "mov out4 = in4\n\t"
206                          "mov out5 = gp\n\t"    /* save gp */
207                          ";;\n"
208                          ".L1:\n\t"
209                          "mov r3 = ip\n\t"
210                          ";;\n\t"
211                          "addl r15=.fptr_afs_syscall-.L1,r3\n\t"
212                          ";;\n\t"
213                          "ld8 r15=[r15]\n\t"
214                          ";;\n\t"
215                          "ld8 r16=[r15],8\n\t"
216                          ";;\n\t"
217                          "ld8 gp=[r15]\n\t"
218                          "mov b6=r16\n\t"
219                          "br.call.sptk.many b0 = b6\n\t"
220                          ";;\n\t"
221                          "mov ar.pfs = r42\n\t"
222                          "mov b0 = r41\n\t"
223                          "mov gp = r48\n\t"     /* restore gp */
224                          "br.ret.sptk.many b0\n"
225                          ".fptr_afs_syscall:\n\t"
226                          "data8 @fptr(afs_syscall)\n\t"
227                          ".skip 8");
228 }
229
230 asmlinkage long
231 afs_xsetgroups_stub(int r0, int r1, long r2, long r3, long r4, long gp)
232 {
233     __asm__ __volatile__("alloc r42 = ar.pfs, 8, 3, 6, 0\n\t"
234                          "mov r41 = b0\n\t"     /* save rp */
235                          "mov out0 = in0\n\t"
236                          "mov out1 = in1\n\t"
237                          "mov out2 = in2\n\t"
238                          "mov out3 = in3\n\t"
239                          "mov out4 = in4\n\t"
240                          "mov out5 = gp\n\t"    /* save gp */
241                          ";;\n"
242                          ".L2:\n\t"
243                          "mov r3 = ip\n\t"
244                          ";;\n\t"
245                          "addl r15=.fptr_afs_xsetgroups - .L2,r3\n\t"
246                          ";;\n\t"
247                          "ld8 r15=[r15]\n\t"
248                          ";;\n\t"
249                          "ld8 r16=[r15],8\n\t"
250                          ";;\n\t"
251                          "ld8 gp=[r15]\n\t"
252                          "mov b6=r16\n\t"
253                          "br.call.sptk.many b0 = b6\n\t"
254                          ";;\n\t"
255                          "mov ar.pfs = r42\n\t"
256                          "mov b0 = r41\n\t"
257                          "mov gp = r48\n\t"     /* restore gp */
258                          "br.ret.sptk.many b0\n"
259                          ".fptr_afs_xsetgroups:\n\t"
260                          "data8 @fptr(afs_xsetgroups)\n\t"
261                          ".skip 8");
262 }
263
264 struct fptr {
265     void *ip;
266     unsigned long gp;
267 };
268
269 #endif /* AFS_IA64_LINUX20_ENV */
270
271 /***** PPC64 ***** 
272  * Spring 2005
273  * sys_call_table hook for PPC64 
274  * by Soewono Effendi <Soewono.Effendi@sysgo.de>
275  * for IBM Deutschland
276  * Thanks go to SYSGO's team for their support:
277  * Horst Birthelmer <Horst.Birthelmer@sysgo.de>
278  * Marius Groeger <Marius.Groeger@sysgo.de>
279  */
280 #if defined(AFS_PPC64_LINUX26_ENV)
281 extern void flush_cache(void *, unsigned long);
282 #define PPC_LO(v) ((v) & 0xffff)
283 #define PPC_HI(v) (((v) >> 16) & 0xffff)
284 #define PPC_HA(v) PPC_HI ((v) + 0x8000)
285 #define PPC_HLO(v) ((short)(((v) >> 32) & 0xffff))
286 #define PPC_HHI(v) ((short)(((v) >> 48) & 0xffff))
287
288 struct ppc64_opd
289 {
290         unsigned long funcaddr;
291         unsigned long r2;
292 };
293
294 struct ppc64_stub
295 {
296         unsigned char jump[136];
297         unsigned long r2;
298         unsigned long lr;
299         struct ppc64_opd opd;
300 } __attribute__ ((packed));
301
302 /* a stub to fix up r2 (TOC ptr) and to jump to our sys_call hook
303    function.  We patch the new r2 value and function pointer into 
304    the stub. */
305 #define PPC64_STUB(stub) \
306 static struct ppc64_stub stub = \
307 { .jump = { \
308         0xf8, 0x41, 0x00, 0x28, /*     std     r2,40(r1) */ \
309         0xfb, 0xc1, 0xff, 0xf0, /*     std     r30,-16(r1) */ \
310         0xfb, 0xa1, 0xff, 0xe8, /*     std     r29,-24(r1) */ \
311         0x7c, 0x5d, 0x13, 0x78, /*     mr      r29,r2 */ \
312         0x3c, 0x40, 0x12, 0x34, /*16:  lis     r2,4660 */ \
313         0x60, 0x42, 0x56, 0x78, /*20:  ori     r2,r2,22136 */ \
314         0x78, 0x42, 0x07, 0xc6, /*     rldicr  r2,r2,32,31 */ \
315         0x64, 0x42, 0x90, 0xab, /*28:  oris    r2,r2,37035 */ \
316         0x60, 0x42, 0xcd, 0xef, /*32:  ori     r2,r2,52719 */ \
317         0x3f, 0xc2, 0x00, 0x00, /*36:  addis   r30,r2,0 */ \
318         0x3b, 0xde, 0x00, 0x00, /*40:  addi    r30,r30,0 */ \
319         0xfb, 0xbe, 0x00, 0x88, /*     std     r29,136(r30) */ \
320         0x7f, 0xa8, 0x02, 0xa6, /*     mflr    r29 */ \
321         0xfb, 0xbe, 0x00, 0x90, /*     std     r29,144(r30) */ \
322         0xeb, 0xde, 0x00, 0x98, /*     ld      r30,152(r30) */ \
323         0x7f, 0xc8, 0x03, 0xa6, /*     mtlr    r30 */ \
324         0xeb, 0xa1, 0xff, 0xe8, /*     ld      r29,-24(r1) */ \
325         0xeb, 0xc1, 0xff, 0xf0, /*     ld      r30,-16(r1) */ \
326         0x4e, 0x80, 0x00, 0x21, /*     blrl */ \
327         0x3c, 0x40, 0x12, 0x34, /*76:  lis     r2,4660 */ \
328         0x60, 0x42, 0x56, 0x78, /*80:  ori     r2,r2,22136 */ \
329         0x78, 0x42, 0x07, 0xc6, /*     rldicr  r2,r2,32,31 */ \
330         0x64, 0x42, 0x90, 0xab, /*88:  oris    r2,r2,37035 */ \
331         0x60, 0x42, 0xcd, 0xef, /*92:  ori     r2,r2,52719 */ \
332         0xfb, 0xc1, 0xff, 0xf0, /*     std     r30,-16(r1) */ \
333         0xfb, 0xa1, 0xff, 0xe8, /*     std     r29,-24(r1) */ \
334         0x3f, 0xc2, 0xab, 0xcd, /*104: addis   r30,r2,-21555 */ \
335         0x3b, 0xde, 0x78, 0x90, /*108: addi    r30,r30,30864 */ \
336         0xeb, 0xbe, 0x00, 0x90, /*     ld      r29,144(r30) */ \
337         0x7f, 0xa8, 0x03, 0xa6, /*     mtlr    r29 */ \
338         0xe8, 0x5e, 0x00, 0x88, /*     ld      r2,136(r30) */ \
339         0xeb, 0xa1, 0xff, 0xe8, /*     ld      r29,-24(r1) */ \
340         0xeb, 0xc1, 0xff, 0xf0, /*     ld      r30,-16(r1) */ \
341         0x4e, 0x80, 0x00, 0x20  /*     blr */ \
342 }} 
343
344 static void * create_stub(struct ppc64_stub *stub,
345                           struct ppc64_opd *opd)
346 {
347         unsigned short *p1, *p2, *p3, *p4;
348         unsigned long addr;
349
350         stub->opd.funcaddr = opd->funcaddr;
351         stub->opd.r2 = opd->r2;
352         addr = (unsigned long) opd->r2;
353         p1 = (unsigned short*) &stub->jump[18];
354         p2 = (unsigned short*) &stub->jump[22];
355         p3 = (unsigned short*) &stub->jump[30];
356         p4 = (unsigned short*) &stub->jump[34];
357
358         *p1 = PPC_HHI(addr);
359         *p2 = PPC_HLO(addr);
360         *p3 = PPC_HI(addr);
361         *p4 = PPC_LO(addr);
362
363         addr = (unsigned long) stub - opd->r2;
364         p1 = (unsigned short*) &stub->jump[38];
365         p2 = (unsigned short*) &stub->jump[42];
366         *p1 = PPC_HA(addr);
367         *p2 = PPC_LO(addr);
368         p1 = (unsigned short*) &stub->jump[106];
369         p2 = (unsigned short*) &stub->jump[110];
370         *p1 = PPC_HA(addr);
371         *p2 = PPC_LO(addr);
372
373         addr = (unsigned long) opd->r2;
374         p1 = (unsigned short*) &stub->jump[78];
375         p2 = (unsigned short*) &stub->jump[82];
376         p3 = (unsigned short*) &stub->jump[90];
377         p4 = (unsigned short*) &stub->jump[94];
378
379         *p1 = PPC_HHI(addr);
380         *p2 = PPC_HLO(addr);
381         *p3 = PPC_HI(addr);
382         *p4 = PPC_LO(addr);
383
384         flush_cache((void *)stub, sizeof(*stub));
385         return ((void*)(stub));
386 }
387
388 PPC64_STUB(afs_sys_call_stub);
389 PPC64_STUB(afs_xsetgroups_stub);
390 PPC64_STUB(afs_xsetgroups32_stub);
391 #endif /* AFS_PPC64_LINUX26_ENV */
392
393
394 /**********************************************************************/
395 /********************* System Call Initialization *********************/
396 /**********************************************************************/
397
398 int osi_syscall_init(void)
399 {
400 /***** IA64 *****/
401 #ifdef AFS_IA64_LINUX20_ENV
402     /* This needs to be first because we are declaring variables, and
403      * also because the handling of syscall pointers is bizarre enough
404      * that we want to special-case even the "common" part.
405      */
406     unsigned long kernel_gp = 0;
407     static struct fptr sys_setgroups;
408
409     afs_sys_call_table = osi_find_syscall_table(0);
410     if (afs_sys_call_table) {
411
412         /* check we aren't already loaded */
413         /* XXX this can't be right */
414         if (SYSCALL2POINTER afs_sys_call_table[_S(__NR_afs_syscall)]
415             == afs_syscall) {
416             printf("AFS syscall entry point already in use!\n");
417             return -EBUSY;
418         }
419
420         /* setup AFS entry point */
421         afs_ni_syscall = afs_sys_call_table[_S(__NR_afs_syscall)];
422         afs_sys_call_table[_S(__NR_afs_syscall)] =
423                 POINTER2SYSCALL((struct fptr *)afs_syscall_stub)->ip;
424
425         /* setup setgroups */
426         sys_setgroupsp = (void *)&sys_setgroups;
427
428         ((struct fptr *)sys_setgroupsp)->ip =
429             SYSCALL2POINTER afs_sys_call_table[_S(__NR_setgroups)];
430         ((struct fptr *)sys_setgroupsp)->gp = kernel_gp;
431
432         afs_sys_call_table[_S(__NR_setgroups)] =
433             POINTER2SYSCALL((struct fptr *)afs_xsetgroups_stub)->ip;
434     }
435
436     /* XXX no 32-bit syscalls on IA64? */
437
438
439 #elif defined(AFS_PPC64_LINUX26_ENV)
440
441     afs_sys_call_table = osi_find_syscall_table(0);
442     if (afs_sys_call_table) {
443         SYSCALLTYPE p;
444         struct ppc64_opd* opd = (struct ppc64_opd*) sys_close;
445         unsigned long r2 = opd->r2;
446         opd = (struct ppc64_opd*) afs_syscall;
447         afs_sys_call_table32 = (unsigned long)afs_sys_call_table - 
448                 NR_syscalls * sizeof(SYSCALLTYPE);
449         /* check we aren't already loaded */
450         p = SYSCALL2POINTER afs_sys_call_table[_S(__NR_afs_syscall)];
451         if ((unsigned long)p == opd->funcaddr) {
452             printf("AFS syscall entry point already in use!\n");
453             return -EBUSY;
454         }
455         /* setup AFS entry point */
456         p = create_stub(&afs_sys_call_stub, opd);
457         afs_ni_syscall = afs_sys_call_table[_S(__NR_afs_syscall)];
458         afs_sys_call_table[_S(__NR_afs_syscall)] = POINTER2SYSCALL p;
459
460         /* setup setgroups */
461         opd = (struct ppc64_opd*) afs_xsetgroups;
462         p = create_stub(&afs_xsetgroups_stub, opd);
463         old_sys_setgroupsp = SYSCALL2POINTER afs_sys_call_table[_S(__NR_setgroups)];
464         afs_sys_call_table[_S(__NR_setgroups)] = POINTER2SYSCALL p;
465         opd = (struct ppc64_opd*) sys_setgroups_stub;
466         opd->funcaddr = old_sys_setgroupsp;
467         opd->r2 = r2;
468
469         /* setup setgroups32 */
470         opd = (struct ppc64_opd*) afs32_xsetgroups;
471         p = create_stub(&afs_xsetgroups32_stub, opd);
472         old_sys32_setgroupsp = SYSCALL2POINTER afs_sys_call_table32[_S(__NR_setgroups)];
473         afs_sys_call_table32[_S(__NR_setgroups)] = POINTER2SYSCALL p;
474         opd = (struct ppc64_opd*) sys32_setgroups_stub;
475         opd->funcaddr = old_sys32_setgroupsp;
476         opd->r2 = r2;
477
478         flush_cache((void *)afs_sys_call_table, 2*NR_syscalls*sizeof(void*));
479
480         sys_setgroupsp = POINTER2SYSCALL sys_setgroups_stub;
481         sys32_setgroupsp = POINTER2SYSCALL sys32_setgroups_stub;
482     }
483 /***** COMMON (except IA64 or PPC64) *****/
484 #else /* !AFS_IA64_LINUX20_ENV */
485
486     afs_sys_call_table = osi_find_syscall_table(0);
487     if (afs_sys_call_table) {
488
489         /* check we aren't already loaded */
490         if (SYSCALL2POINTER afs_sys_call_table[_S(__NR_afs_syscall)]
491             == afs_syscall) {
492             printf("AFS syscall entry point already in use!\n");
493             return -EBUSY;
494         }
495
496         /* setup AFS entry point */
497         afs_ni_syscall = afs_sys_call_table[_S(__NR_afs_syscall)];
498
499         INSERT_SYSCALL(__NR_afs_syscall, afs_syscall_page, afs_syscall)
500
501         /* setup setgroups */
502         sys_setgroupsp = SYSCALL2POINTER afs_sys_call_table[_S(__NR_setgroups)];
503         INSERT_SYSCALL(__NR_setgroups, afs_sys_setgroups_page, afs_xsetgroups)
504
505 #if defined(__NR_setgroups32)
506         /* setup setgroups32 */
507         sys_setgroups32p = SYSCALL2POINTER afs_sys_call_table[__NR_setgroups32];
508         INSERT_SYSCALL(__NR_setgroups32, afs_sys_setgroups32_page, afs_xsetgroups32)
509 #endif
510     }
511 #endif /* !AFS_IA64_LINUX20_ENV */
512
513
514 /***** AMD64 *****/
515 #ifdef AFS_AMD64_LINUX20_ENV
516     afs_ia32_sys_call_table = osi_find_syscall_table(1);
517     if (afs_ia32_sys_call_table) {
518         /* setup AFS entry point for IA32 */
519         ia32_ni_syscall = afs_ia32_sys_call_table[__NR_ia32_afs_syscall];
520         afs_ia32_sys_call_table[__NR_ia32_afs_syscall] =
521             POINTER2SYSCALL afs_syscall;
522
523         /* setup setgroups for IA32 */
524         sys32_setgroupsp =
525             SYSCALL2POINTER afs_ia32_sys_call_table[__NR_ia32_setgroups];
526         afs_ia32_sys_call_table[__NR_ia32_setgroups] =
527             POINTER2SYSCALL afs32_xsetgroups;
528
529         /* setup setgroups32 for IA32 */
530         sys32_setgroups32p =
531             SYSCALL2POINTER afs_ia32_sys_call_table[__NR_ia32_setgroups32];
532         afs_ia32_sys_call_table[__NR_ia32_setgroups32] =
533             POINTER2SYSCALL afs32_xsetgroups32;
534     }
535 #endif /* AFS_AMD64_LINUX20_ENV */
536
537
538 /***** SPARC64 *****/
539 #ifdef AFS_SPARC64_LINUX20_ENV
540     afs_sys_call_table32 = osi_find_syscall_table(1);
541     if (afs_sys_call_table32) {
542         /* setup AFS entry point for 32-bit SPARC */
543         afs_ni_syscall32 = afs_sys_call_table32[__NR_afs_syscall];
544         afs_sys_call_table32[__NR_afs_syscall] = POINTER2SYSCALL afs_syscall32;
545
546         /* setup setgroups for 32-bit SPARC */
547         sys32_setgroupsp = SYSCALL2POINTER afs_sys_call_table32[__NR_setgroups];
548         afs_sys_call_table32[__NR_setgroups] = POINTER2SYSCALL afs32_xsetgroups;
549
550         /* setup setgroups32 for 32-bit SPARC */
551         sys32_setgroups32p =
552             SYSCALL2POINTER afs_sys_call_table32[__NR_setgroups32];
553         afs_sys_call_table32[__NR_setgroups32] =
554             POINTER2SYSCALL afs32_xsetgroups32;
555     }
556 #endif /* AFS_SPARC64_LINUX20_ENV */
557     return 0;
558 }
559
560
561
562 /**********************************************************************/
563 /************************ System Call Cleanup *************************/
564 /**********************************************************************/
565
566 void osi_syscall_clean(void)
567 {
568 /***** COMMON *****/
569     if (afs_sys_call_table) {
570         /* put back the AFS entry point */
571         afs_sys_call_table[_S(__NR_afs_syscall)] = afs_ni_syscall;
572
573         /* put back setgroups */
574 #if defined(AFS_IA64_LINUX20_ENV)
575         afs_sys_call_table[_S(__NR_setgroups)] =
576             POINTER2SYSCALL((struct fptr *)sys_setgroupsp)->ip;
577 #elif defined(AFS_PPC64_LINUX26_ENV)
578         afs_sys_call_table[_S(__NR_setgroups)] =
579             POINTER2SYSCALL old_sys_setgroupsp;
580         /* put back setgroups32 for PPC64 */
581         afs_sys_call_table32[__NR_setgroups] =
582             POINTER2SYSCALL old_sys32_setgroupsp;
583 #else /* AFS_IA64_LINUX20_ENV */
584         afs_sys_call_table[_S(__NR_setgroups)] =
585             POINTER2SYSCALL sys_setgroupsp;
586 #endif
587
588 #if defined(__NR_setgroups32) && !defined(AFS_IA64_LINUX20_ENV)
589         /* put back setgroups32 */
590         afs_sys_call_table[__NR_setgroups32] = POINTER2SYSCALL sys_setgroups32p;
591 #endif
592 #if defined(AFS_S390X_LINUX24_ENV)
593 #if defined(__NR_setgroups32) && !defined(AFS_IA64_LINUX20_ENV)
594         if (afs_sys_setgroups32_page)
595             kfree(afs_sys_setgroups32_page);
596 #endif
597         if (afs_sys_setgroups_page)
598             kfree(afs_sys_setgroups_page);
599         if (afs_syscall_page)
600             kfree(afs_syscall_page);
601 #endif
602     }
603
604
605 /***** IA64 *****/
606 #ifdef AFS_IA64_LINUX20_ENV
607     /* XXX no 32-bit syscalls on IA64? */
608 #endif
609
610
611 /***** AMD64 *****/
612 #ifdef AFS_AMD64_LINUX20_ENV
613     if (afs_ia32_sys_call_table) {
614         /* put back AFS entry point for IA32 */
615         afs_ia32_sys_call_table[__NR_ia32_afs_syscall] =
616             POINTER2SYSCALL ia32_ni_syscall;
617
618         /* put back setgroups for IA32 */
619         afs_ia32_sys_call_table[__NR_ia32_setgroups] =
620             POINTER2SYSCALL sys32_setgroupsp;
621
622         /* put back setgroups32 for IA32 */
623         afs_ia32_sys_call_table[__NR_ia32_setgroups32] =
624             POINTER2SYSCALL sys32_setgroups32p;
625     }
626 #endif
627
628
629 /***** SPARC64 *****/
630 #ifdef AFS_SPARC64_LINUX20_ENV
631     if (afs_sys_call_table32) {
632         /* put back AFS entry point for 32-bit SPARC */
633         afs_sys_call_table32[__NR_afs_syscall] = afs_ni_syscall32;
634
635         /* put back setgroups for IA32 */
636         afs_sys_call_table32[__NR_setgroups] =
637             POINTER2SYSCALL sys32_setgroupsp;
638
639         /* put back setgroups32 for IA32 */
640         afs_sys_call_table32[__NR_setgroups32] =
641             POINTER2SYSCALL sys32_setgroups32p;
642     }
643 #endif
644 }
645
646 #endif /* !LINUX_KEYRING_SUPPORT */