Import Upstream version 1.8.5
[hcoop/debian/openafs.git] / src / export / export.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 * export - EXPORT kernel extension
12 */
13
14 /* Unsafe: conflicts with _KERNEL inclusion of headers below */
15 /* #include <afs/param.h> */
16 /* #include <afsconfig.h> */
17
18 #define _KERNEL
19 #include "sys/types.h"
20 #include "sys/user.h"
21 #include "sys/conf.h"
22 #include "sys/errno.h"
23 #include "sys/device.h"
24 #include "sys/uio.h"
25 #include "sys/pri.h"
26 #include "sys/malloc.h"
27 #include "sym.h"
28 #include "export.h"
29
30 #undef RELOC
31
32 sym_t *toc_syms; /* symbol table */
33 int toc_nsyms; /* # of symbols */
34 caddr_t toc_strs; /* string table */
35 int toc_size; /* size of toc_syms */
36
37 /*
38 * export - entry point to EXPORT kernel extension
39 *
40 * Input:
41 * cmd - add/delete command
42 * uiop - uio vector describing any config params
43 */
44 export(cmd, uiop)
45 struct uio *uiop;
46 {
47 int err, monster;
48 static once;
49
50 err = 0;
51 monster = lockl(&kernel_lock, LOCK_SHORT);
52
53 switch (cmd) {
54 case CFG_INIT: /* add EXPORT */
55 if (err = config(uiop))
56 export_cleanup();
57 break;
58
59 case CFG_TERM: /* remove EXPORT */
60 if (err = export_cleanup())
61 break;
62 break;
63
64 default:
65 err = EINVAL;
66 break;
67 }
68
69 if (monster != LOCK_NEST)
70 unlockl(&kernel_lock);
71
72 return err;
73 }
74
75 /*
76 * config - process configuration data
77 */
78 config(uiop)
79 struct uio *uiop;
80 {
81 struct k_conf conf;
82 struct export_nl *np;
83 sym_t *sym;
84 int err;
85
86 if (err = uiomove((char *)&conf, sizeof(conf), UIO_WRITE, uiop))
87 return err;
88
89 toc_nsyms = conf.nsyms;
90 toc_size = conf.symt_sz + conf.str_sz;
91
92 if (toc_nsyms * sizeof(sym_t) != conf.symt_sz || toc_size > (1024 * 1024))
93 #ifdef AFS_AIX51_ENV
94 return EFBIG;
95 #else
96 return EINVAL;
97 #endif
98
99 toc_syms = (sym_t *) xmalloc(toc_size, 2, kernel_heap);
100
101 if (!toc_syms)
102 return ENOMEM;
103
104 toc_strs = (char *)&toc_syms[toc_nsyms];
105
106 /*
107 * copy in the symbol table and the string table
108 */
109 if (err = copyin(conf.symtab, toc_syms, conf.symt_sz)
110 || (err = copyin(conf.strtab, toc_strs, conf.str_sz))) {
111 xmfree(toc_syms, kernel_heap);
112 toc_syms = 0;
113 return err;
114 }
115
116 /*
117 * `TOC' format in kernel has offsets relocated to point directly
118 * into the string table.
119 */
120 for (sym = toc_syms; sym < &toc_syms[toc_nsyms]; ++sym)
121 #ifndef __XCOFF64__
122 if (sym->n_zeroes == 0)
123 #endif
124 sym->n_nptr = sym->n_offset + toc_strs;
125
126 return 0;
127 }
128
129 /*
130 * export_cleanup - cleanup EXPORT prior to removing kernel extension
131 */
132 export_cleanup()
133 {
134
135 /*
136 * get rid of the symbol table
137 */
138 if (toc_syms) {
139 xmfree(toc_syms, kernel_heap);
140 toc_syms = 0;
141 toc_size = 0;
142 toc_strs = 0;
143 }
144
145 return 0;
146 }
147
148 /*
149 * import_kfunc - import a kernel function that was mistakenly left
150 * off the exports list
151 *
152 * NOTE:
153 * We are assuming that the functions we are importing from the
154 * kernel really are within the kernel. If they are actually
155 * exported from some other kernel extension (but referenced in
156 * the /unix symbol table) we are in trouble.
157 */
158 #ifdef __XCOFF64__
159 u_int64 *myg_toc;
160 #else
161 u_int32 *myg_toc;
162 #endif
163
164 import_kfunc(struct k_func * kfp)
165 {
166 sym_t *sym;
167 int i, pri;
168 #if 0
169 static caddr_t *g_toc;
170 #endif
171
172 if (!myg_toc) {
173 #ifdef __XCOFF64__
174 sym = sym_lookup("ktoc", 0);
175 #else
176 sym = sym_lookup("g_toc", 0);
177 #endif
178 if (!sym) {
179 printf("\nimport: can't ascertain kernel's TOC\n");
180 return EINVAL;
181 }
182 myg_toc = sym->n_value;
183 }
184
185 sym = sym_lookup(kfp->name, 0);
186 if (!sym) {
187 printf("\nimport: function `%s' not found\n", kfp->name);
188 return EINVAL;
189 }
190
191 kfp->fdesc[0] = sym->n_value;
192 kfp->fdesc[1] = *myg_toc;
193 kfp->fdesc[2] = 0;
194
195 #ifdef __XCOFF64__
196 *(u_int64 **) kfp->fpp = kfp->fdesc;
197 #else
198 *(u_int **) kfp->fpp = kfp->fdesc;
199 #endif
200
201 return 0;
202 }
203
204 /*
205 * import_kvar - import a kernel variable that was mistakenly left
206 * off the exports list
207 */
208 import_kvar(struct k_var * kvp, caddr_t * toc)
209 {
210 sym_t *sym;
211 int i, pri;
212 label_t jmpbuf;
213
214 switch (setjmpx(&jmpbuf)) {
215 case 0:
216 break;
217
218 default:
219 return EINVAL;
220 }
221
222 sym = sym_lookup(kvp->name, 0);
223 if (!sym) {
224 printf("\nimport: variable `%s' not found\n", kvp->name);
225 longjmpx(EINVAL);
226 }
227
228 /*
229 * look through the caller's TOC for the reference to his surrogate
230 * variable.
231 */
232 while (*toc != kvp->varp)
233 ++toc;
234
235 printf("import(%s): replacing my TOC at 0x%x: 0x%8x with 0x%8x\n",
236 kvp->name, toc, *toc, sym->n_value);
237
238 /*
239 * replace reference to surrogate with reference real
240 */
241 pri = i_disable(INTMAX);
242 *toc = (caddr_t) sym->n_value;
243 i_enable(pri);
244
245 clrjmpx(&jmpbuf);
246
247 return 0;
248 }
249
250
251 /*
252 * Call vanilla syscalls
253 */
254 #ifndef AFS_AIX51_ENV
255 osetgroups(ngroups, gidset)
256 int ngroups;
257 gid_t *gidset;
258 {
259 int error;
260
261 error = setgroups(ngroups, gidset);
262 return (error);
263 }
264 #endif
265
266 #ifdef AFS_AIX51_ENV
267 #ifdef AFS_64BIT_KERNEL
268 okioctl(fdes, cmd, arg, ext, arg2, arg3)
269 #else /* AFS_64BIT_KERNEL */
270 okioctl32(fdes, cmd, arg, ext, arg2, arg3)
271 #endif /* AFS_64BIT_KERNEL */
272 int fdes, cmd;
273 caddr_t ext, arg, arg2, arg3;
274 #else
275 okioctl(fdes, cmd, arg, ext)
276 int fdes, cmd, arg;
277 caddr_t ext;
278 #endif
279 {
280 int error;
281
282 #ifdef AFS_AIX51_ENV
283 #ifdef AFS_64BIT_KERNEL
284 error = kioctl(fdes, cmd, arg, ext, arg2, arg3);
285 #else /* AFS_64BIT_KERNEL */
286 error = kioctl32(fdes, cmd, arg, ext, arg2, arg3);
287 #endif /* AFS_64BIT_KERNEL */
288 #else
289 error = kioctl(fdes, cmd, arg, ext);
290 #endif
291 return (error);
292 }
293
294 #ifdef notdef
295 ocore(signo, sigctx)
296 char signo;
297 struct sigcontext *sigctx;
298 {
299 int error;
300 #include <sys/user.h>
301 u.u_sigflags[signo] |= SA_FULLDUMP; /* XXX */
302 error = core(signo, sigctx);
303 return (error);
304 }
305 #endif