|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24:
25: /* $NetBSD: umap_subr.c,v 1.4 1994/09/20 06:43:02 cgd Exp $ */
26:
27: /*
28: * Copyright (c) 1992, 1993
29: * The Regents of the University of California. All rights reserved.
30: *
31: * This code is derived from software donated to Berkeley by
32: * Jan-Simon Pendry.
33: *
34: * Redistribution and use in source and binary forms, with or without
35: * modification, are permitted provided that the following conditions
36: * are met:
37: * 1. Redistributions of source code must retain the above copyright
38: * notice, this list of conditions and the following disclaimer.
39: * 2. Redistributions in binary form must reproduce the above copyright
40: * notice, this list of conditions and the following disclaimer in the
41: * documentation and/or other materials provided with the distribution.
42: * 3. All advertising materials mentioning features or use of this software
43: * must display the following acknowledgement:
44: * This product includes software developed by the University of
45: * California, Berkeley and its contributors.
46: * 4. Neither the name of the University nor the names of its contributors
47: * may be used to endorse or promote products derived from this software
48: * without specific prior written permission.
49: *
50: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
51: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
52: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
53: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
54: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
55: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
56: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
57: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
58: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
59: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
60: * SUCH DAMAGE.
61: *
62: * from: Id: lofs_subr.c, v 1.11 1992/05/30 10:05:43 jsp Exp
63: * @(#)umap_subr.c 8.6 (Berkeley) 1/26/94
64: */
65:
66: #include <sys/param.h>
67: #include <sys/systm.h>
68: #include <sys/time.h>
69: #include <sys/types.h>
70: #include <sys/vnode.h>
71: #include <sys/mount.h>
72: #include <sys/namei.h>
73: #include <sys/malloc.h>
74: #include <miscfs/specfs/specdev.h>
75: #include <miscfs/umapfs/umap.h>
76:
77: #define LOG2_SIZEVNODE 7 /* log2(sizeof struct vnode) */
78: #define NUMAPNODECACHE 16
79:
80: /*
81: * Null layer cache:
82: * Each cache entry holds a reference to the target vnode
83: * along with a pointer to the alias vnode. When an
84: * entry is added the target vnode is VREF'd. When the
85: * alias is removed the target vnode is vrele'd.
86: */
87:
88: #define UMAP_NHASH(vp) \
89: (&umap_node_hashtbl[(((u_long)vp)>>LOG2_SIZEVNODE) & umap_node_hash])
90: LIST_HEAD(umap_node_hashhead, umap_node) *umap_node_hashtbl;
91: u_long umap_node_hash;
92:
93: /*
94: * Initialise cache headers
95: */
96: umapfs_init()
97: {
98:
99: #ifdef UMAPFS_DIAGNOSTIC
100: printf("umapfs_init\n"); /* printed during system boot */
101: #endif
102: umap_node_hashtbl = hashinit(NUMAPNODECACHE, M_CACHE, &umap_node_hash);
103: }
104:
105: /*
106: * umap_findid is called by various routines in umap_vnodeops.c to
107: * find a user or group id in a map.
108: */
109: static u_long
110: umap_findid(id, map, nentries)
111: u_long id;
112: u_long map[][2];
113: int nentries;
114: {
115: int i;
116:
117: /* Find uid entry in map */
118: i = 0;
119: while ((i<nentries) && ((map[i][0]) != id))
120: i++;
121:
122: if (i < nentries)
123: return (map[i][1]);
124: else
125: return (-1);
126:
127: }
128:
129: /*
130: * umap_reverse_findid is called by umap_getattr() in umap_vnodeops.c to
131: * find a user or group id in a map, in reverse.
132: */
133: u_long
134: umap_reverse_findid(id, map, nentries)
135: u_long id;
136: u_long map[][2];
137: int nentries;
138: {
139: int i;
140:
141: /* Find uid entry in map */
142: i = 0;
143: while ((i<nentries) && ((map[i][1]) != id))
144: i++;
145:
146: if (i < nentries)
147: return (map[i][0]);
148: else
149: return (-1);
150:
151: }
152:
153: /*
154: * Return alias for target vnode if already exists, else 0.
155: */
156: static struct vnode *
157: umap_node_find(mp, targetvp)
158: struct mount *mp;
159: struct vnode *targetvp;
160: {
161: struct umap_node_hashhead *hd;
162: struct umap_node *a;
163: struct vnode *vp;
164:
165: #ifdef UMAPFS_DIAGNOSTIC
166: printf("umap_node_find(mp = %x, target = %x)\n", mp, targetvp);
167: #endif
168:
169: /*
170: * Find hash base, and then search the (two-way) linked
171: * list looking for a umap_node structure which is referencing
172: * the target vnode. If found, the increment the umap_node
173: * reference count (but NOT the target vnode's VREF counter).
174: */
175: hd = UMAP_NHASH(targetvp);
176: loop:
177: for (a = hd->lh_first; a != 0; a = a->umap_hash.le_next) {
178: if (a->umap_lowervp == targetvp &&
179: a->umap_vnode->v_mount == mp) {
180: vp = UMAPTOV(a);
181: /*
182: * We need vget for the VXLOCK
183: * stuff, but we don't want to lock
184: * the lower node.
185: */
186: if (vget(vp, 0)) {
187: #ifdef UMAPFS_DIAGNOSTIC
188: printf ("umap_node_find: vget failed.\n");
189: #endif
190: goto loop;
191: }
192: return (vp);
193: }
194: }
195:
196: #ifdef UMAPFS_DIAGNOSTIC
197: printf("umap_node_find(%x, %x): NOT found\n", mp, targetvp);
198: #endif
199:
200: return (0);
201: }
202:
203: /*
204: * Make a new umap_node node.
205: * Vp is the alias vnode, lowervp is the target vnode.
206: * Maintain a reference to lowervp.
207: */
208: static int
209: umap_node_alloc(mp, lowervp, vpp)
210: struct mount *mp;
211: struct vnode *lowervp;
212: struct vnode **vpp;
213: {
214: struct umap_node_hashhead *hd;
215: struct umap_node *xp;
216: struct vnode *vp, *nvp;
217: int error;
218: extern int (**dead_vnodeop_p)();
219:
220: if (error = getnewvnode(VT_UMAP, mp, umap_vnodeop_p, &vp))
221: return (error);
222: vp->v_type = lowervp->v_type;
223:
224: MALLOC(xp, struct umap_node *, sizeof(struct umap_node), M_TEMP,
225: M_WAITOK);
226: if (vp->v_type == VBLK || vp->v_type == VCHR) {
227: MALLOC_ZONE(vp->v_specinfo, struct specinfo *,
228: sizeof(struct specinfo), M_VNODE, M_WAITOK);
229: vp->v_rdev = lowervp->v_rdev;
230: }
231:
232: vp->v_data = xp;
233: xp->umap_vnode = vp;
234: xp->umap_lowervp = lowervp;
235: /*
236: * Before we insert our new node onto the hash chains,
237: * check to see if someone else has beaten us to it.
238: * (We could have slept in MALLOC.)
239: */
240: if (nvp = umap_node_find(lowervp)) {
241: *vpp = nvp;
242:
243: /* free the substructures we've allocated. */
244: FREE(xp, M_TEMP);
245: if (vp->v_type == VBLK || vp->v_type == VCHR)
246: FREE_ZONE(vp->v_specinfo,
247: sizeof (struct specinfo), M_VNODE);
248:
249: vp->v_type = VBAD; /* node is discarded */
250: vp->v_op = dead_vnodeop_p; /* so ops will still work */
251: vrele(vp); /* get rid of it. */
252: return (0);
253: }
254:
255: /*
256: * XXX if it's a device node, it needs to be checkalias()ed.
257: * however, for locking reasons, that's just not possible.
258: * so we have to do most of the dirty work inline. Note that
259: * this is a limited case; we know that there's going to be
260: * an alias, and we know that that alias will be a "real"
261: * device node, i.e. not tagged VT_NON.
262: */
263: if (vp->v_type == VBLK || vp->v_type == VCHR) {
264: struct vnode *cvp, **cvpp;
265:
266: cvpp = &speclisth[SPECHASH(vp->v_rdev)];
267: loop:
268: for (cvp = *cvpp; cvp; cvp = cvp->v_specnext) {
269: if (vp->v_rdev != cvp->v_rdev ||
270: vp->v_type != cvp->v_type)
271: continue;
272:
273: /*
274: * Alias, but not in use, so flush it out.
275: */
276: if (cvp->v_usecount == 0) {
277: vgone(cvp);
278: goto loop;
279: }
280: if (vget(cvp, 0)) /* can't lock; will die! */
281: goto loop;
282: break;
283: }
284:
285: vp->v_hashchain = cvpp;
286: vp->v_specnext = *cvpp;
287: vp->v_specflags = 0;
288: *cvpp = vp;
289: #if DIAGNOSTIC
290: if (cvp == NULLVP)
291: panic("umap_node_alloc: no alias for device");
292: #endif
293: vp->v_flag |= VALIASED;
294: cvp->v_flag |= VALIASED;
295: vrele(cvp);
296: }
297: /* XXX end of transmogrified checkalias() */
298:
299: *vpp = vp;
300: VREF(lowervp); /* Extra VREF will be vrele'd in umap_node_create */
301: hd = UMAP_NHASH(lowervp);
302: LIST_INSERT_HEAD(hd, xp, umap_hash);
303: return (0);
304: }
305:
306:
307: /*
308: * Try to find an existing umap_node vnode refering
309: * to it, otherwise make a new umap_node vnode which
310: * contains a reference to the target vnode.
311: */
312: int
313: umap_node_create(mp, targetvp, newvpp)
314: struct mount *mp;
315: struct vnode *targetvp;
316: struct vnode **newvpp;
317: {
318: struct vnode *aliasvp;
319:
320: if (aliasvp = umap_node_find(mp, targetvp)) {
321: /*
322: * Take another reference to the alias vnode
323: */
324: #ifdef UMAPFS_DIAGNOSTIC
325: vprint("umap_node_create: exists", ap->umap_vnode);
326: #endif
327: /* VREF(aliasvp); */
328: } else {
329: int error;
330:
331: /*
332: * Get new vnode.
333: */
334: #ifdef UMAPFS_DIAGNOSTIC
335: printf("umap_node_create: create new alias vnode\n");
336: #endif
337: /*
338: * Make new vnode reference the umap_node.
339: */
340: if (error = umap_node_alloc(mp, targetvp, &aliasvp))
341: return (error);
342:
343: /*
344: * aliasvp is already VREF'd by getnewvnode()
345: */
346: }
347:
348: vrele(targetvp);
349:
350: #ifdef UMAPFS_DIAGNOSTIC
351: vprint("umap_node_create: alias", aliasvp);
352: vprint("umap_node_create: target", targetvp);
353: #endif
354:
355: *newvpp = aliasvp;
356: return (0);
357: }
358:
359: #ifdef UMAPFS_DIAGNOSTIC
360: int umap_checkvp_barrier = 1;
361: struct vnode *
362: umap_checkvp(vp, fil, lno)
363: struct vnode *vp;
364: char *fil;
365: int lno;
366: {
367: struct umap_node *a = VTOUMAP(vp);
368: #if 0
369: /*
370: * Can't do this check because vop_reclaim runs
371: * with funny vop vector.
372: */
373: if (vp->v_op != umap_vnodeop_p) {
374: printf ("umap_checkvp: on non-umap-node\n");
375: while (umap_checkvp_barrier) /*WAIT*/ ;
376: panic("umap_checkvp");
377: }
378: #endif
379: if (a->umap_lowervp == NULL) {
380: /* Should never happen */
381: int i; u_long *p;
382: printf("vp = %x, ZERO ptr\n", vp);
383: for (p = (u_long *) a, i = 0; i < 8; i++)
384: printf(" %x", p[i]);
385: printf("\n");
386: /* wait for debugger */
387: while (umap_checkvp_barrier) /*WAIT*/ ;
388: panic("umap_checkvp");
389: }
390: if (a->umap_lowervp->v_usecount < 1) {
391: int i; u_long *p;
392: printf("vp = %x, unref'ed lowervp\n", vp);
393: for (p = (u_long *) a, i = 0; i < 8; i++)
394: printf(" %x", p[i]);
395: printf("\n");
396: /* wait for debugger */
397: while (umap_checkvp_barrier) /*WAIT*/ ;
398: panic ("umap with unref'ed lowervp");
399: }
400: #if 0
401: printf("umap %x/%d -> %x/%d [%s, %d]\n",
402: a->umap_vnode, a->umap_vnode->v_usecount,
403: a->umap_lowervp, a->umap_lowervp->v_usecount,
404: fil, lno);
405: #endif
406: return (a->umap_lowervp);
407: }
408: #endif
409:
410: /* umap_mapids maps all of the ids in a credential, both user and group. */
411:
412: void
413: umap_mapids(v_mount, credp)
414: struct mount *v_mount;
415: struct ucred *credp;
416: {
417: int i, unentries, gnentries;
418: uid_t uid, *usermap;
419: gid_t gid, *groupmap;
420:
421: unentries = MOUNTTOUMAPMOUNT(v_mount)->info_nentries;
422: usermap = &(MOUNTTOUMAPMOUNT(v_mount)->info_mapdata[0][0]);
423: gnentries = MOUNTTOUMAPMOUNT(v_mount)->info_gnentries;
424: groupmap = &(MOUNTTOUMAPMOUNT(v_mount)->info_gmapdata[0][0]);
425:
426: /* Find uid entry in map */
427:
428: uid = (uid_t) umap_findid(credp->cr_uid, usermap, unentries);
429:
430: if (uid != -1)
431: credp->cr_uid = uid;
432: else
433: credp->cr_uid = (uid_t) NOBODY;
434:
435: #ifdef notdef
436: /* cr_gid is the same as cr_groups[0] in 4BSD */
437:
438: /* Find gid entry in map */
439:
440: gid = (gid_t) umap_findid(credp->cr_gid, groupmap, gnentries);
441:
442: if (gid != -1)
443: credp->cr_gid = gid;
444: else
445: credp->cr_gid = NULLGROUP;
446: #endif
447:
448: /* Now we must map each of the set of groups in the cr_groups
449: structure. */
450:
451: i = 0;
452: while (credp->cr_groups[i] != 0) {
453: gid = (gid_t) umap_findid(credp->cr_groups[i],
454: groupmap, gnentries);
455:
456: if (gid != -1)
457: credp->cr_groups[i++] = gid;
458: else
459: credp->cr_groups[i++] = NULLGROUP;
460: }
461: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.