* Extend the passed in credential to hold n items. */
| 2240 | * Extend the passed in credential to hold n items. |
| 2241 | */ |
| 2242 | void |
| 2243 | crextend(struct ucred *cr, int n) |
| 2244 | { |
| 2245 | int cnt; |
| 2246 | |
| 2247 | /* Truncate? */ |
| 2248 | if (n <= cr->cr_agroups) |
| 2249 | return; |
| 2250 | |
| 2251 | /* |
| 2252 | * We extend by 2 each time since we're using a power of two |
| 2253 | * allocator until we need enough groups to fill a page. |
| 2254 | * Once we're allocating multiple pages, only allocate as many |
| 2255 | * as we actually need. The case of processes needing a |
| 2256 | * non-power of two number of pages seems more likely than |
| 2257 | * a real world process that adds thousands of groups one at a |
| 2258 | * time. |
| 2259 | */ |
| 2260 | if ( n < PAGE_SIZE / sizeof(gid_t) ) { |
| 2261 | if (cr->cr_agroups == 0) |
| 2262 | cnt = MAX(1, MINALLOCSIZE / sizeof(gid_t)); |
| 2263 | else |
| 2264 | cnt = cr->cr_agroups * 2; |
| 2265 | |
| 2266 | while (cnt < n) |
| 2267 | cnt *= 2; |
| 2268 | } else |
| 2269 | cnt = roundup2(n, PAGE_SIZE / sizeof(gid_t)); |
| 2270 | |
| 2271 | /* Free the old array. */ |
| 2272 | if (cr->cr_groups != cr->cr_smallgroups) |
| 2273 | free(cr->cr_groups, M_CRED); |
| 2274 | |
| 2275 | cr->cr_groups = malloc(cnt * sizeof(gid_t), M_CRED, M_WAITOK | M_ZERO); |
| 2276 | cr->cr_agroups = cnt; |
| 2277 | } |
| 2278 | |
| 2279 | /* |
| 2280 | * Copy groups in to a credential, preserving any necessary invariants. |
no test coverage detected