source: rtems-libbsd/rtems/freebsd/rtems/rtems-bsd-prot.c @ d4f439f

4.1155-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since d4f439f was d4f439f, checked in by Joel Sherrill <joel.sherrill@…>, on 03/07/12 at 21:10:49

Add rmlock - almost links

  • Property mode set to 100644
File size: 5.1 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup rtems_bsd_rtems
5 *
6 * @brief TODO.
7 */
8
9/*
10 * Copyright (c) 2009, 2010 embedded brains GmbH.  All rights reserved.
11 *
12 *  embedded brains GmbH
13 *  Obere Lagerstr. 30
14 *  82178 Puchheim
15 *  Germany
16 *  <rtems@embedded-brains.de>
17 *
18 * The license and distribution terms for this file may be
19 * found in the file LICENSE in this distribution or at
20 * http://www.rtems.com/license/LICENSE.
21 */
22
23#include <rtems/freebsd/machine/rtems-bsd-config.h>
24
25#include <rtems/freebsd/sys/types.h>
26#include <rtems/freebsd/sys/systm.h>
27#include <rtems/freebsd/vm/uma.h>
28#include <rtems/freebsd/sys/malloc.h>
29#include <rtems/freebsd/sys/ucred.h>
30#include <rtems/freebsd/sys/refcount.h>
31
32static MALLOC_DEFINE(M_CRED, "cred", "credentials");
33
34static void crextend(struct ucred *cr, int n);
35static void crsetgroups_locked(struct ucred *cr, int ngrp,
36    gid_t *groups);
37
38
39
40/*
41 * Allocate a zeroed cred structure.
42 */
43struct ucred *
44crget(void)
45{
46  register struct ucred *cr;
47
48  cr = malloc(sizeof(*cr), M_CRED, M_WAITOK | M_ZERO);
49  refcount_init(&cr->cr_ref, 1);
50#ifdef AUDIT
51  audit_cred_init(cr);
52#endif
53#ifdef MAC
54  mac_cred_init(cr);
55#endif
56  crextend(cr, XU_NGROUPS);
57  return (cr);
58}
59
60/*
61 * Claim another reference to a ucred structure.
62 */
63struct ucred *
64crhold(struct ucred *cr)
65{
66
67  refcount_acquire(&cr->cr_ref);
68  return (cr);
69}
70
71/*
72 * Free a cred structure.  Throws away space when ref count gets to 0.
73 */
74void
75crfree(struct ucred *cr)
76{
77
78  KASSERT(cr->cr_ref > 0, ("bad ucred refcount: %d", cr->cr_ref));
79  KASSERT(cr->cr_ref != 0xdeadc0de, ("dangling reference to ucred"));
80  if (refcount_release(&cr->cr_ref)) {
81    /*
82     * Some callers of crget(), such as nfs_statfs(),
83     * allocate a temporary credential, but don't
84     * allocate a uidinfo structure.
85     */
86    if (cr->cr_uidinfo != NULL)
87      uifree(cr->cr_uidinfo);
88    if (cr->cr_ruidinfo != NULL)
89      uifree(cr->cr_ruidinfo);
90    /*
91     * Free a prison, if any.
92     */
93    if (cr->cr_prison != NULL)
94      prison_free(cr->cr_prison);
95#ifdef AUDIT
96    audit_cred_destroy(cr);
97#endif
98#ifdef MAC
99    mac_cred_destroy(cr);
100#endif
101    free(cr->cr_groups, M_CRED);
102    free(cr, M_CRED);
103  }
104}
105
106/*
107 * Check to see if this ucred is shared.
108 */
109int
110crshared(struct ucred *cr)
111{
112
113  return (cr->cr_ref > 1);
114}
115
116/*
117 * Copy a ucred's contents from a template.  Does not block.
118 */
119void
120crcopy(struct ucred *dest, struct ucred *src)
121{
122
123  KASSERT(crshared(dest) == 0, ("crcopy of shared ucred"));
124  bcopy(&src->cr_startcopy, &dest->cr_startcopy,
125      (unsigned)((caddr_t)&src->cr_endcopy -
126    (caddr_t)&src->cr_startcopy));
127  crsetgroups(dest, src->cr_ngroups, src->cr_groups);
128  uihold(dest->cr_uidinfo);
129  uihold(dest->cr_ruidinfo);
130  prison_hold(dest->cr_prison);
131#ifdef AUDIT
132  audit_cred_copy(src, dest);
133#endif
134#ifdef MAC
135  mac_cred_copy(src, dest);
136#endif
137}
138
139/*
140 * Dup cred struct to a new held one.
141 */
142struct ucred *
143crdup(struct ucred *cr)
144{
145  struct ucred *newcr;
146
147  newcr = crget();
148  crcopy(newcr, cr);
149  return (newcr);
150}
151
152/*
153 * Extend the passed in credential to hold n items.
154 */
155static void
156crextend(struct ucred *cr, int n)
157{
158        int cnt;
159
160        /* Truncate? */
161        if (n <= cr->cr_agroups)
162                return;
163
164        /*
165         * We extend by 2 each time since we're using a power of two
166         * allocator until we need enough groups to fill a page.
167         * Once we're allocating multiple pages, only allocate as many
168         * as we actually need.  The case of processes needing a
169         * non-power of two number of pages seems more likely than
170         * a real world process that adds thousands of groups one at a
171         * time.
172         */
173        if ( n < PAGE_SIZE / sizeof(gid_t) ) {
174                if (cr->cr_agroups == 0)
175                        cnt = MINALLOCSIZE / sizeof(gid_t);
176                else
177                        cnt = cr->cr_agroups * 2;
178
179                while (cnt < n)
180                        cnt *= 2;
181        } else
182                cnt = roundup2(n, PAGE_SIZE / sizeof(gid_t));
183
184        /* Free the old array. */
185        if (cr->cr_groups)
186                free(cr->cr_groups, M_CRED);
187
188        cr->cr_groups = malloc(cnt * sizeof(gid_t), M_CRED, M_WAITOK | M_ZERO);
189        cr->cr_agroups = cnt;
190}
191
192/*
193 * Copy groups in to a credential, preserving any necessary invariants.
194 * Currently this includes the sorting of all supplemental gids.
195 * crextend() must have been called before hand to ensure sufficient
196 * space is available.
197 */
198static void
199crsetgroups_locked(struct ucred *cr, int ngrp, gid_t *groups)
200{
201        int i;
202        int j;
203        gid_t g;
204       
205        KASSERT(cr->cr_agroups >= ngrp, ("cr_ngroups is too small"));
206
207        bcopy(groups, cr->cr_groups, ngrp * sizeof(gid_t));
208        cr->cr_ngroups = ngrp;
209
210        /*
211         * Sort all groups except cr_groups[0] to allow groupmember to
212         * perform a binary search.
213         *
214         * XXX: If large numbers of groups become common this should
215         * be replaced with shell sort like linux uses or possibly
216         * heap sort.
217         */
218        for (i = 2; i < ngrp; i++) {
219                g = cr->cr_groups[i];
220                for (j = i-1; j >= 1 && g < cr->cr_groups[j]; j--)
221                        cr->cr_groups[j + 1] = cr->cr_groups[j];
222                cr->cr_groups[j + 1] = g;
223        }
224}
225
226/*
227 * Copy groups in to a credential after expanding it if required.
228 * Truncate the list to (ngroups_max + 1) if it is too large.
229 */
230void
231crsetgroups(struct ucred *cr, int ngrp, gid_t *groups)
232{
233
234        if (ngrp > ngroups_max + 1)
235                ngrp = ngroups_max + 1;
236
237        crextend(cr, ngrp);
238        crsetgroups_locked(cr, ngrp, groups);
239}
240
Note: See TracBrowser for help on using the repository browser.