Print this page
uts: add a concept of a 'default' set of privileges, separate from 'basic'
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/os/cred.c
+++ new/usr/src/uts/common/os/cred.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright (c) 2013, Ira Cooper. All rights reserved.
23 23 */
24 24 /*
25 25 * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
26 26 */
27 27
28 28 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
29 29 /* All Rights Reserved */
30 30
31 31 /*
32 32 * University Copyright- Copyright (c) 1982, 1986, 1988
33 33 * The Regents of the University of California
34 34 * All Rights Reserved
35 35 *
36 36 * University Acknowledgment- Portions of this document are derived from
37 37 * software developed by the University of California, Berkeley, and its
38 38 * contributors.
39 39 */
40 40
41 41 #include <sys/types.h>
42 42 #include <sys/sysmacros.h>
43 43 #include <sys/param.h>
44 44 #include <sys/systm.h>
45 45 #include <sys/cred_impl.h>
46 46 #include <sys/policy.h>
47 47 #include <sys/vnode.h>
48 48 #include <sys/errno.h>
49 49 #include <sys/kmem.h>
50 50 #include <sys/user.h>
51 51 #include <sys/proc.h>
52 52 #include <sys/syscall.h>
53 53 #include <sys/debug.h>
54 54 #include <sys/atomic.h>
55 55 #include <sys/ucred.h>
56 56 #include <sys/prsystm.h>
57 57 #include <sys/modctl.h>
58 58 #include <sys/avl.h>
59 59 #include <sys/door.h>
60 60 #include <c2/audit.h>
61 61 #include <sys/zone.h>
62 62 #include <sys/tsol/label.h>
63 63 #include <sys/sid.h>
64 64 #include <sys/idmap.h>
65 65 #include <sys/klpd.h>
66 66 #include <sys/varargs.h>
67 67 #include <sys/sysconf.h>
68 68 #include <util/qsort.h>
69 69
70 70
71 71 /* Ephemeral IDs Zones specific data */
72 72 typedef struct ephemeral_zsd {
73 73 uid_t min_uid;
74 74 uid_t last_uid;
75 75 gid_t min_gid;
76 76 gid_t last_gid;
77 77 kmutex_t eph_lock;
78 78 cred_t *eph_nobody;
79 79 } ephemeral_zsd_t;
80 80
81 81 static void crgrphold(credgrp_t *);
82 82
83 83 #define CREDGRPSZ(ngrp) (sizeof (credgrp_t) + ((ngrp - 1) * sizeof (gid_t)))
84 84
85 85 static kmutex_t ephemeral_zone_mutex;
86 86 static zone_key_t ephemeral_zone_key;
87 87
88 88 static struct kmem_cache *cred_cache;
89 89 static size_t crsize = 0;
90 90 static int audoff = 0;
91 91 uint32_t ucredsize;
92 92 cred_t *kcred;
93 93 static cred_t *dummycr;
94 94
95 95 int rstlink; /* link(2) restricted to files owned by user? */
96 96
97 97 static int get_c2audit_load(void);
98 98
99 99 #define CR_AUINFO(c) (auditinfo_addr_t *)((audoff == 0) ? NULL : \
100 100 ((char *)(c)) + audoff)
101 101
102 102 #define REMOTE_PEER_CRED(c) ((c)->cr_gid == -1)
103 103
104 104 #define BIN_GROUP_SEARCH_CUTOFF 16
105 105
106 106 static boolean_t hasephids = B_FALSE;
107 107
108 108 static ephemeral_zsd_t *
109 109 get_ephemeral_zsd(zone_t *zone)
110 110 {
111 111 ephemeral_zsd_t *eph_zsd;
112 112
113 113 eph_zsd = zone_getspecific(ephemeral_zone_key, zone);
114 114 if (eph_zsd != NULL) {
115 115 return (eph_zsd);
116 116 }
117 117
118 118 mutex_enter(&ephemeral_zone_mutex);
119 119 eph_zsd = zone_getspecific(ephemeral_zone_key, zone);
120 120 if (eph_zsd == NULL) {
121 121 eph_zsd = kmem_zalloc(sizeof (ephemeral_zsd_t), KM_SLEEP);
122 122 eph_zsd->min_uid = MAXUID;
123 123 eph_zsd->last_uid = IDMAP_WK__MAX_UID;
124 124 eph_zsd->min_gid = MAXUID;
125 125 eph_zsd->last_gid = IDMAP_WK__MAX_GID;
126 126 mutex_init(&eph_zsd->eph_lock, NULL, MUTEX_DEFAULT, NULL);
127 127
128 128 /*
129 129 * nobody is used to map SID containing CRs.
130 130 */
131 131 eph_zsd->eph_nobody = crdup(zone->zone_kcred);
132 132 (void) crsetugid(eph_zsd->eph_nobody, UID_NOBODY, GID_NOBODY);
133 133 CR_FLAGS(eph_zsd->eph_nobody) = 0;
134 134 eph_zsd->eph_nobody->cr_zone = zone;
135 135
136 136 (void) zone_setspecific(ephemeral_zone_key, zone, eph_zsd);
137 137 }
138 138 mutex_exit(&ephemeral_zone_mutex);
139 139 return (eph_zsd);
140 140 }
141 141
142 142 static cred_t *crdup_flags(const cred_t *, int);
143 143 static cred_t *cralloc_flags(int);
144 144
145 145 /*
146 146 * This function is called when a zone is destroyed
147 147 */
148 148 static void
149 149 /* ARGSUSED */
150 150 destroy_ephemeral_zsd(zoneid_t zone_id, void *arg)
151 151 {
152 152 ephemeral_zsd_t *eph_zsd = arg;
153 153 if (eph_zsd != NULL) {
154 154 mutex_destroy(&eph_zsd->eph_lock);
155 155 crfree(eph_zsd->eph_nobody);
156 156 kmem_free(eph_zsd, sizeof (ephemeral_zsd_t));
157 157 }
158 158 }
159 159
160 160
161 161
162 162 /*
163 163 * Initialize credentials data structures.
164 164 */
165 165
166 166 void
167 167 cred_init(void)
168 168 {
169 169 priv_init();
170 170
171 171 crsize = sizeof (cred_t);
172 172
173 173 if (get_c2audit_load() > 0) {
174 174 #ifdef _LP64
175 175 /* assure audit context is 64-bit aligned */
176 176 audoff = (crsize +
177 177 sizeof (int64_t) - 1) & ~(sizeof (int64_t) - 1);
178 178 #else /* _LP64 */
179 179 audoff = crsize;
180 180 #endif /* _LP64 */
181 181 crsize = audoff + sizeof (auditinfo_addr_t);
182 182 crsize = (crsize + sizeof (int) - 1) & ~(sizeof (int) - 1);
183 183 }
184 184
185 185 cred_cache = kmem_cache_create("cred_cache", crsize, 0,
186 186 NULL, NULL, NULL, NULL, NULL, 0);
187 187
188 188 /*
189 189 * dummycr is used to copy initial state for creds.
190 190 */
191 191 dummycr = cralloc();
192 192 bzero(dummycr, crsize);
193 193 dummycr->cr_ref = 1;
194 194 dummycr->cr_uid = (uid_t)-1;
195 195 dummycr->cr_gid = (gid_t)-1;
196 196 dummycr->cr_ruid = (uid_t)-1;
197 197 dummycr->cr_rgid = (gid_t)-1;
198 198 dummycr->cr_suid = (uid_t)-1;
199 199 dummycr->cr_sgid = (gid_t)-1;
200 200
201 201
202 202 /*
203 203 * kcred is used by anything that needs all privileges; it's
204 204 * also the template used for crget as it has all the compatible
205 205 * sets filled in.
↓ open down ↓ |
205 lines elided |
↑ open up ↑ |
206 206 */
207 207 kcred = cralloc();
208 208
209 209 bzero(kcred, crsize);
210 210 kcred->cr_ref = 1;
211 211
212 212 /* kcred is never freed, so we don't need zone_cred_hold here */
213 213 kcred->cr_zone = &zone0;
214 214
215 215 priv_fillset(&CR_LPRIV(kcred));
216 - CR_IPRIV(kcred) = *priv_basic;
216 + CR_IPRIV(kcred) = *priv_default; /* XXX: Really needed here? */
217 217
218 218 /* Not a basic privilege, if chown is not restricted add it to I0 */
219 219 if (!rstchown)
220 220 priv_addset(&CR_IPRIV(kcred), PRIV_FILE_CHOWN_SELF);
221 221
222 222 /* Basic privilege, if link is restricted remove it from I0 */
223 223 if (rstlink)
224 224 priv_delset(&CR_IPRIV(kcred), PRIV_FILE_LINK_ANY);
225 225
226 226 CR_EPRIV(kcred) = CR_PPRIV(kcred) = CR_IPRIV(kcred);
227 227
228 228 CR_FLAGS(kcred) = NET_MAC_AWARE;
229 229
230 230 /*
231 231 * Set up credentials of p0.
232 232 */
233 233 ttoproc(curthread)->p_cred = kcred;
234 234 curthread->t_cred = kcred;
235 235
236 236 ucredsize = UCRED_SIZE;
237 237
238 238 mutex_init(&ephemeral_zone_mutex, NULL, MUTEX_DEFAULT, NULL);
239 239 zone_key_create(&ephemeral_zone_key, NULL, NULL, destroy_ephemeral_zsd);
240 240 }
241 241
242 242 /*
243 243 * Allocate (nearly) uninitialized cred_t.
244 244 */
245 245 static cred_t *
246 246 cralloc_flags(int flgs)
247 247 {
248 248 cred_t *cr = kmem_cache_alloc(cred_cache, flgs);
249 249
250 250 if (cr == NULL)
251 251 return (NULL);
252 252
253 253 cr->cr_ref = 1; /* So we can crfree() */
254 254 cr->cr_zone = NULL;
255 255 cr->cr_label = NULL;
256 256 cr->cr_ksid = NULL;
257 257 cr->cr_klpd = NULL;
258 258 cr->cr_grps = NULL;
259 259 return (cr);
260 260 }
261 261
262 262 cred_t *
263 263 cralloc(void)
264 264 {
265 265 return (cralloc_flags(KM_SLEEP));
266 266 }
267 267
268 268 /*
269 269 * As cralloc but prepared for ksid change (if appropriate).
270 270 */
271 271 cred_t *
272 272 cralloc_ksid(void)
273 273 {
274 274 cred_t *cr = cralloc();
275 275 if (hasephids)
276 276 cr->cr_ksid = kcrsid_alloc();
277 277 return (cr);
278 278 }
279 279
280 280 /*
281 281 * Allocate a initialized cred structure and crhold() it.
282 282 * Initialized means: all ids 0, group count 0, L=Full, E=P=I=I0
283 283 */
284 284 cred_t *
285 285 crget(void)
286 286 {
287 287 cred_t *cr = kmem_cache_alloc(cred_cache, KM_SLEEP);
288 288
289 289 bcopy(kcred, cr, crsize);
290 290 cr->cr_ref = 1;
291 291 zone_cred_hold(cr->cr_zone);
292 292 if (cr->cr_label)
293 293 label_hold(cr->cr_label);
294 294 ASSERT(cr->cr_klpd == NULL);
295 295 ASSERT(cr->cr_grps == NULL);
296 296 return (cr);
297 297 }
298 298
299 299 /*
300 300 * Broadcast the cred to all the threads in the process.
301 301 * The current thread's credentials can be set right away, but other
302 302 * threads must wait until the start of the next system call or trap.
303 303 * This avoids changing the cred in the middle of a system call.
304 304 *
305 305 * The cred has already been held for the process and the thread (2 holds),
306 306 * and p->p_cred set.
307 307 *
308 308 * p->p_crlock shouldn't be held here, since p_lock must be acquired.
309 309 */
310 310 void
311 311 crset(proc_t *p, cred_t *cr)
312 312 {
313 313 kthread_id_t t;
314 314 kthread_id_t first;
315 315 cred_t *oldcr;
316 316
317 317 ASSERT(p == curproc); /* assumes p_lwpcnt can't change */
318 318
319 319 /*
320 320 * DTrace accesses t_cred in probe context. t_cred must always be
321 321 * either NULL, or point to a valid, allocated cred structure.
322 322 */
323 323 t = curthread;
324 324 oldcr = t->t_cred;
325 325 t->t_cred = cr; /* the cred is held by caller for this thread */
326 326 crfree(oldcr); /* free the old cred for the thread */
327 327
328 328 /*
329 329 * Broadcast to other threads, if any.
330 330 */
331 331 if (p->p_lwpcnt > 1) {
332 332 mutex_enter(&p->p_lock); /* to keep thread list safe */
333 333 first = curthread;
334 334 for (t = first->t_forw; t != first; t = t->t_forw)
335 335 t->t_pre_sys = 1; /* so syscall will get new cred */
336 336 mutex_exit(&p->p_lock);
337 337 }
338 338 }
339 339
340 340 /*
341 341 * Put a hold on a cred structure.
342 342 */
343 343 void
344 344 crhold(cred_t *cr)
345 345 {
346 346 ASSERT(cr->cr_ref != 0xdeadbeef && cr->cr_ref != 0);
347 347 atomic_inc_32(&cr->cr_ref);
348 348 }
349 349
350 350 /*
351 351 * Release previous hold on a cred structure. Free it if refcnt == 0.
352 352 * If cred uses label different from zone label, free it.
353 353 */
354 354 void
355 355 crfree(cred_t *cr)
356 356 {
357 357 ASSERT(cr->cr_ref != 0xdeadbeef && cr->cr_ref != 0);
358 358 if (atomic_dec_32_nv(&cr->cr_ref) == 0) {
359 359 ASSERT(cr != kcred);
360 360 if (cr->cr_label)
361 361 label_rele(cr->cr_label);
362 362 if (cr->cr_klpd)
363 363 crklpd_rele(cr->cr_klpd);
364 364 if (cr->cr_zone)
365 365 zone_cred_rele(cr->cr_zone);
366 366 if (cr->cr_ksid)
367 367 kcrsid_rele(cr->cr_ksid);
368 368 if (cr->cr_grps)
369 369 crgrprele(cr->cr_grps);
370 370
371 371 kmem_cache_free(cred_cache, cr);
372 372 }
373 373 }
374 374
375 375 /*
376 376 * Copy a cred structure to a new one and free the old one.
377 377 * The new cred will have two references. One for the calling process,
378 378 * and one for the thread.
379 379 */
380 380 cred_t *
381 381 crcopy(cred_t *cr)
382 382 {
383 383 cred_t *newcr;
384 384
385 385 newcr = cralloc();
386 386 bcopy(cr, newcr, crsize);
387 387 if (newcr->cr_zone)
388 388 zone_cred_hold(newcr->cr_zone);
389 389 if (newcr->cr_label)
390 390 label_hold(newcr->cr_label);
391 391 if (newcr->cr_ksid)
392 392 kcrsid_hold(newcr->cr_ksid);
393 393 if (newcr->cr_klpd)
394 394 crklpd_hold(newcr->cr_klpd);
395 395 if (newcr->cr_grps)
396 396 crgrphold(newcr->cr_grps);
397 397 crfree(cr);
398 398 newcr->cr_ref = 2; /* caller gets two references */
399 399 return (newcr);
400 400 }
401 401
402 402 /*
403 403 * Copy a cred structure to a new one and free the old one.
404 404 * The new cred will have two references. One for the calling process,
405 405 * and one for the thread.
406 406 * This variation on crcopy uses a pre-allocated structure for the
407 407 * "new" cred.
408 408 */
409 409 void
410 410 crcopy_to(cred_t *oldcr, cred_t *newcr)
411 411 {
412 412 credsid_t *nkcr = newcr->cr_ksid;
413 413
414 414 bcopy(oldcr, newcr, crsize);
415 415 if (newcr->cr_zone)
416 416 zone_cred_hold(newcr->cr_zone);
417 417 if (newcr->cr_label)
418 418 label_hold(newcr->cr_label);
419 419 if (newcr->cr_klpd)
420 420 crklpd_hold(newcr->cr_klpd);
421 421 if (newcr->cr_grps)
422 422 crgrphold(newcr->cr_grps);
423 423 if (nkcr) {
424 424 newcr->cr_ksid = nkcr;
425 425 kcrsidcopy_to(oldcr->cr_ksid, newcr->cr_ksid);
426 426 } else if (newcr->cr_ksid)
427 427 kcrsid_hold(newcr->cr_ksid);
428 428 crfree(oldcr);
429 429 newcr->cr_ref = 2; /* caller gets two references */
430 430 }
431 431
432 432 /*
433 433 * Dup a cred struct to a new held one.
434 434 * The old cred is not freed.
435 435 */
436 436 static cred_t *
437 437 crdup_flags(const cred_t *cr, int flgs)
438 438 {
439 439 cred_t *newcr;
440 440
441 441 newcr = cralloc_flags(flgs);
442 442
443 443 if (newcr == NULL)
444 444 return (NULL);
445 445
446 446 bcopy(cr, newcr, crsize);
447 447 if (newcr->cr_zone)
448 448 zone_cred_hold(newcr->cr_zone);
449 449 if (newcr->cr_label)
450 450 label_hold(newcr->cr_label);
451 451 if (newcr->cr_klpd)
452 452 crklpd_hold(newcr->cr_klpd);
453 453 if (newcr->cr_ksid)
454 454 kcrsid_hold(newcr->cr_ksid);
455 455 if (newcr->cr_grps)
456 456 crgrphold(newcr->cr_grps);
457 457 newcr->cr_ref = 1;
458 458 return (newcr);
459 459 }
460 460
461 461 cred_t *
462 462 crdup(cred_t *cr)
463 463 {
464 464 return (crdup_flags(cr, KM_SLEEP));
465 465 }
466 466
467 467 /*
468 468 * Dup a cred struct to a new held one.
469 469 * The old cred is not freed.
470 470 * This variation on crdup uses a pre-allocated structure for the
471 471 * "new" cred.
472 472 */
473 473 void
474 474 crdup_to(cred_t *oldcr, cred_t *newcr)
475 475 {
476 476 credsid_t *nkcr = newcr->cr_ksid;
477 477
478 478 bcopy(oldcr, newcr, crsize);
479 479 if (newcr->cr_zone)
480 480 zone_cred_hold(newcr->cr_zone);
481 481 if (newcr->cr_label)
482 482 label_hold(newcr->cr_label);
483 483 if (newcr->cr_klpd)
484 484 crklpd_hold(newcr->cr_klpd);
485 485 if (newcr->cr_grps)
486 486 crgrphold(newcr->cr_grps);
487 487 if (nkcr) {
488 488 newcr->cr_ksid = nkcr;
489 489 kcrsidcopy_to(oldcr->cr_ksid, newcr->cr_ksid);
490 490 } else if (newcr->cr_ksid)
491 491 kcrsid_hold(newcr->cr_ksid);
492 492 newcr->cr_ref = 1;
493 493 }
494 494
495 495 /*
496 496 * Return the (held) credentials for the current running process.
497 497 */
498 498 cred_t *
499 499 crgetcred(void)
500 500 {
501 501 cred_t *cr;
502 502 proc_t *p;
503 503
504 504 p = ttoproc(curthread);
505 505 mutex_enter(&p->p_crlock);
506 506 crhold(cr = p->p_cred);
507 507 mutex_exit(&p->p_crlock);
508 508 return (cr);
509 509 }
510 510
511 511 /*
512 512 * Backward compatibility check for suser().
513 513 * Accounting flag is now set in the policy functions; auditing is
514 514 * done through use of privilege in the audit trail.
515 515 */
516 516 int
517 517 suser(cred_t *cr)
518 518 {
519 519 return (PRIV_POLICY(cr, PRIV_SYS_SUSER_COMPAT, B_FALSE, EPERM, NULL)
520 520 == 0);
521 521 }
522 522
523 523 /*
524 524 * Determine whether the supplied group id is a member of the group
525 525 * described by the supplied credentials.
526 526 */
527 527 int
528 528 groupmember(gid_t gid, const cred_t *cr)
529 529 {
530 530 if (gid == cr->cr_gid)
531 531 return (1);
532 532 return (supgroupmember(gid, cr));
533 533 }
534 534
535 535 /*
536 536 * As groupmember but only check against the supplemental groups.
537 537 */
538 538 int
539 539 supgroupmember(gid_t gid, const cred_t *cr)
540 540 {
541 541 int hi, lo;
542 542 credgrp_t *grps = cr->cr_grps;
543 543 const gid_t *gp, *endgp;
544 544
545 545 if (grps == NULL)
546 546 return (0);
547 547
548 548 /* For a small number of groups, use sequentials search. */
549 549 if (grps->crg_ngroups <= BIN_GROUP_SEARCH_CUTOFF) {
550 550 endgp = &grps->crg_groups[grps->crg_ngroups];
551 551 for (gp = grps->crg_groups; gp < endgp; gp++)
552 552 if (*gp == gid)
553 553 return (1);
554 554 return (0);
555 555 }
556 556
557 557 /* We use binary search when we have many groups. */
558 558 lo = 0;
559 559 hi = grps->crg_ngroups - 1;
560 560 gp = grps->crg_groups;
561 561
562 562 do {
563 563 int m = (lo + hi) / 2;
564 564
565 565 if (gid > gp[m])
566 566 lo = m + 1;
567 567 else if (gid < gp[m])
568 568 hi = m - 1;
569 569 else
570 570 return (1);
571 571 } while (lo <= hi);
572 572
573 573 return (0);
574 574 }
575 575
576 576 /*
577 577 * This function is called to check whether the credentials set
578 578 * "scrp" has permission to act on credentials set "tcrp". It enforces the
579 579 * permission requirements needed to send a signal to a process.
580 580 * The same requirements are imposed by other system calls, however.
581 581 *
582 582 * The rules are:
583 583 * (1) if the credentials are the same, the check succeeds
584 584 * (2) if the zone ids don't match, and scrp is not in the global zone or
585 585 * does not have the PRIV_PROC_ZONE privilege, the check fails
586 586 * (3) if the real or effective user id of scrp matches the real or saved
587 587 * user id of tcrp or scrp has the PRIV_PROC_OWNER privilege, the check
588 588 * succeeds
589 589 * (4) otherwise, the check fails
590 590 */
591 591 int
592 592 hasprocperm(const cred_t *tcrp, const cred_t *scrp)
593 593 {
594 594 if (scrp == tcrp)
595 595 return (1);
596 596 if (scrp->cr_zone != tcrp->cr_zone &&
597 597 (scrp->cr_zone != global_zone ||
598 598 secpolicy_proc_zone(scrp) != 0))
599 599 return (0);
600 600 if (scrp->cr_uid == tcrp->cr_ruid ||
601 601 scrp->cr_ruid == tcrp->cr_ruid ||
602 602 scrp->cr_uid == tcrp->cr_suid ||
603 603 scrp->cr_ruid == tcrp->cr_suid ||
604 604 !PRIV_POLICY(scrp, PRIV_PROC_OWNER, B_FALSE, EPERM, "hasprocperm"))
605 605 return (1);
606 606 return (0);
607 607 }
608 608
609 609 /*
610 610 * This interface replaces hasprocperm; it works like hasprocperm but
611 611 * additionally returns success if the proc_t's match
612 612 * It is the preferred interface for most uses.
613 613 * And it will acquire p_crlock itself, so it assert's that it shouldn't
614 614 * be held.
615 615 */
616 616 int
617 617 prochasprocperm(proc_t *tp, proc_t *sp, const cred_t *scrp)
618 618 {
619 619 int rets;
620 620 cred_t *tcrp;
621 621
622 622 ASSERT(MUTEX_NOT_HELD(&tp->p_crlock));
623 623
624 624 if (tp == sp)
625 625 return (1);
626 626
627 627 if (tp->p_sessp != sp->p_sessp && secpolicy_basic_proc(scrp) != 0)
628 628 return (0);
629 629
630 630 mutex_enter(&tp->p_crlock);
631 631 crhold(tcrp = tp->p_cred);
632 632 mutex_exit(&tp->p_crlock);
633 633 rets = hasprocperm(tcrp, scrp);
634 634 crfree(tcrp);
635 635
636 636 return (rets);
637 637 }
638 638
639 639 /*
640 640 * This routine is used to compare two credentials to determine if
641 641 * they refer to the same "user". If the pointers are equal, then
642 642 * they must refer to the same user. Otherwise, the contents of
643 643 * the credentials are compared to see whether they are equivalent.
644 644 *
645 645 * This routine returns 0 if the credentials refer to the same user,
646 646 * 1 if they do not.
647 647 */
648 648 int
649 649 crcmp(const cred_t *cr1, const cred_t *cr2)
650 650 {
651 651 credgrp_t *grp1, *grp2;
652 652
653 653 if (cr1 == cr2)
654 654 return (0);
655 655
656 656 if (cr1->cr_uid == cr2->cr_uid &&
657 657 cr1->cr_gid == cr2->cr_gid &&
658 658 cr1->cr_ruid == cr2->cr_ruid &&
659 659 cr1->cr_rgid == cr2->cr_rgid &&
660 660 cr1->cr_zone == cr2->cr_zone &&
661 661 ((grp1 = cr1->cr_grps) == (grp2 = cr2->cr_grps) ||
662 662 (grp1 != NULL && grp2 != NULL &&
663 663 grp1->crg_ngroups == grp2->crg_ngroups &&
664 664 bcmp(grp1->crg_groups, grp2->crg_groups,
665 665 grp1->crg_ngroups * sizeof (gid_t)) == 0))) {
666 666 return (!priv_isequalset(&CR_OEPRIV(cr1), &CR_OEPRIV(cr2)));
667 667 }
668 668 return (1);
669 669 }
670 670
671 671 /*
672 672 * Read access functions to cred_t.
673 673 */
674 674 uid_t
675 675 crgetuid(const cred_t *cr)
676 676 {
677 677 return (cr->cr_uid);
678 678 }
679 679
680 680 uid_t
681 681 crgetruid(const cred_t *cr)
682 682 {
683 683 return (cr->cr_ruid);
684 684 }
685 685
686 686 uid_t
687 687 crgetsuid(const cred_t *cr)
688 688 {
689 689 return (cr->cr_suid);
690 690 }
691 691
692 692 gid_t
693 693 crgetgid(const cred_t *cr)
694 694 {
695 695 return (cr->cr_gid);
696 696 }
697 697
698 698 gid_t
699 699 crgetrgid(const cred_t *cr)
700 700 {
701 701 return (cr->cr_rgid);
702 702 }
703 703
704 704 gid_t
705 705 crgetsgid(const cred_t *cr)
706 706 {
707 707 return (cr->cr_sgid);
708 708 }
709 709
710 710 const auditinfo_addr_t *
711 711 crgetauinfo(const cred_t *cr)
712 712 {
713 713 return ((const auditinfo_addr_t *)CR_AUINFO(cr));
714 714 }
715 715
716 716 auditinfo_addr_t *
717 717 crgetauinfo_modifiable(cred_t *cr)
718 718 {
719 719 return (CR_AUINFO(cr));
720 720 }
721 721
722 722 zoneid_t
723 723 crgetzoneid(const cred_t *cr)
724 724 {
725 725 return (cr->cr_zone == NULL ?
726 726 (cr->cr_uid == -1 ? (zoneid_t)-1 : GLOBAL_ZONEID) :
727 727 cr->cr_zone->zone_id);
728 728 }
729 729
730 730 projid_t
731 731 crgetprojid(const cred_t *cr)
732 732 {
733 733 return (cr->cr_projid);
734 734 }
735 735
736 736 zone_t *
737 737 crgetzone(const cred_t *cr)
738 738 {
739 739 return (cr->cr_zone);
740 740 }
741 741
742 742 struct ts_label_s *
743 743 crgetlabel(const cred_t *cr)
744 744 {
745 745 return (cr->cr_label ?
746 746 cr->cr_label :
747 747 (cr->cr_zone ? cr->cr_zone->zone_slabel : NULL));
748 748 }
749 749
750 750 boolean_t
751 751 crisremote(const cred_t *cr)
752 752 {
753 753 return (REMOTE_PEER_CRED(cr));
754 754 }
755 755
756 756 #define BADUID(x, zn) ((x) != -1 && !VALID_UID((x), (zn)))
757 757 #define BADGID(x, zn) ((x) != -1 && !VALID_GID((x), (zn)))
758 758
759 759 int
760 760 crsetresuid(cred_t *cr, uid_t r, uid_t e, uid_t s)
761 761 {
762 762 zone_t *zone = crgetzone(cr);
763 763
764 764 ASSERT(cr->cr_ref <= 2);
765 765
766 766 if (BADUID(r, zone) || BADUID(e, zone) || BADUID(s, zone))
767 767 return (-1);
768 768
769 769 if (r != -1)
770 770 cr->cr_ruid = r;
771 771 if (e != -1)
772 772 cr->cr_uid = e;
773 773 if (s != -1)
774 774 cr->cr_suid = s;
775 775
776 776 return (0);
777 777 }
778 778
779 779 int
780 780 crsetresgid(cred_t *cr, gid_t r, gid_t e, gid_t s)
781 781 {
782 782 zone_t *zone = crgetzone(cr);
783 783
784 784 ASSERT(cr->cr_ref <= 2);
785 785
786 786 if (BADGID(r, zone) || BADGID(e, zone) || BADGID(s, zone))
787 787 return (-1);
788 788
789 789 if (r != -1)
790 790 cr->cr_rgid = r;
791 791 if (e != -1)
792 792 cr->cr_gid = e;
793 793 if (s != -1)
794 794 cr->cr_sgid = s;
795 795
796 796 return (0);
797 797 }
798 798
799 799 int
800 800 crsetugid(cred_t *cr, uid_t uid, gid_t gid)
801 801 {
802 802 zone_t *zone = crgetzone(cr);
803 803
804 804 ASSERT(cr->cr_ref <= 2);
805 805
806 806 if (!VALID_UID(uid, zone) || !VALID_GID(gid, zone))
807 807 return (-1);
808 808
809 809 cr->cr_uid = cr->cr_ruid = cr->cr_suid = uid;
810 810 cr->cr_gid = cr->cr_rgid = cr->cr_sgid = gid;
811 811
812 812 return (0);
813 813 }
814 814
815 815 static int
816 816 gidcmp(const void *v1, const void *v2)
817 817 {
818 818 gid_t g1 = *(gid_t *)v1;
819 819 gid_t g2 = *(gid_t *)v2;
820 820
821 821 if (g1 < g2)
822 822 return (-1);
823 823 else if (g1 > g2)
824 824 return (1);
825 825 else
826 826 return (0);
827 827 }
828 828
829 829 int
830 830 crsetgroups(cred_t *cr, int n, gid_t *grp)
831 831 {
832 832 ASSERT(cr->cr_ref <= 2);
833 833
834 834 if (n > ngroups_max || n < 0)
835 835 return (-1);
836 836
837 837 if (cr->cr_grps != NULL)
838 838 crgrprele(cr->cr_grps);
839 839
840 840 if (n > 0) {
841 841 cr->cr_grps = kmem_alloc(CREDGRPSZ(n), KM_SLEEP);
842 842 bcopy(grp, cr->cr_grps->crg_groups, n * sizeof (gid_t));
843 843 cr->cr_grps->crg_ref = 1;
844 844 cr->cr_grps->crg_ngroups = n;
845 845 qsort(cr->cr_grps->crg_groups, n, sizeof (gid_t), gidcmp);
846 846 } else {
847 847 cr->cr_grps = NULL;
848 848 }
849 849
850 850 return (0);
851 851 }
852 852
853 853 void
854 854 crsetprojid(cred_t *cr, projid_t projid)
855 855 {
856 856 ASSERT(projid >= 0 && projid <= MAXPROJID);
857 857 cr->cr_projid = projid;
858 858 }
859 859
860 860 /*
861 861 * This routine returns the pointer to the first element of the crg_groups
862 862 * array. It can move around in an implementation defined way.
863 863 * Note that when we have no grouplist, we return one element but the
864 864 * caller should never reference it.
865 865 */
866 866 const gid_t *
867 867 crgetgroups(const cred_t *cr)
868 868 {
869 869 return (cr->cr_grps == NULL ? &cr->cr_gid : cr->cr_grps->crg_groups);
870 870 }
871 871
872 872 int
873 873 crgetngroups(const cred_t *cr)
874 874 {
875 875 return (cr->cr_grps == NULL ? 0 : cr->cr_grps->crg_ngroups);
876 876 }
877 877
878 878 void
879 879 cred2prcred(const cred_t *cr, prcred_t *pcrp)
880 880 {
881 881 pcrp->pr_euid = cr->cr_uid;
882 882 pcrp->pr_ruid = cr->cr_ruid;
883 883 pcrp->pr_suid = cr->cr_suid;
884 884 pcrp->pr_egid = cr->cr_gid;
885 885 pcrp->pr_rgid = cr->cr_rgid;
886 886 pcrp->pr_sgid = cr->cr_sgid;
887 887 pcrp->pr_groups[0] = 0; /* in case ngroups == 0 */
888 888 pcrp->pr_ngroups = cr->cr_grps == NULL ? 0 : cr->cr_grps->crg_ngroups;
889 889
890 890 if (pcrp->pr_ngroups != 0)
891 891 bcopy(cr->cr_grps->crg_groups, pcrp->pr_groups,
892 892 sizeof (gid_t) * pcrp->pr_ngroups);
893 893 }
894 894
895 895 static int
896 896 cred2ucaud(const cred_t *cr, auditinfo64_addr_t *ainfo, const cred_t *rcr)
897 897 {
898 898 auditinfo_addr_t *ai;
899 899 au_tid_addr_t tid;
900 900
901 901 if (secpolicy_audit_getattr(rcr, B_TRUE) != 0)
902 902 return (-1);
903 903
904 904 ai = CR_AUINFO(cr); /* caller makes sure this is non-NULL */
905 905 tid = ai->ai_termid;
906 906
907 907 ainfo->ai_auid = ai->ai_auid;
908 908 ainfo->ai_mask = ai->ai_mask;
909 909 ainfo->ai_asid = ai->ai_asid;
910 910
911 911 ainfo->ai_termid.at_type = tid.at_type;
912 912 bcopy(&tid.at_addr, &ainfo->ai_termid.at_addr, 4 * sizeof (uint_t));
913 913
914 914 ainfo->ai_termid.at_port.at_major = (uint32_t)getmajor(tid.at_port);
915 915 ainfo->ai_termid.at_port.at_minor = (uint32_t)getminor(tid.at_port);
916 916
917 917 return (0);
918 918 }
919 919
920 920 void
921 921 cred2uclabel(const cred_t *cr, bslabel_t *labelp)
922 922 {
923 923 ts_label_t *tslp;
924 924
925 925 if ((tslp = crgetlabel(cr)) != NULL)
926 926 bcopy(&tslp->tsl_label, labelp, sizeof (bslabel_t));
927 927 }
928 928
929 929 /*
930 930 * Convert a credential into a "ucred". Allow the caller to specify
931 931 * and aligned buffer, e.g., in an mblk, so we don't have to allocate
932 932 * memory and copy it twice.
933 933 *
934 934 * This function may call cred2ucaud(), which calls CRED(). Since this
935 935 * can be called from an interrupt thread, receiver's cred (rcr) is needed
936 936 * to determine whether audit info should be included.
937 937 */
938 938 struct ucred_s *
939 939 cred2ucred(const cred_t *cr, pid_t pid, void *buf, const cred_t *rcr)
940 940 {
941 941 struct ucred_s *uc;
942 942 uint32_t realsz = ucredminsize(cr);
943 943 ts_label_t *tslp = is_system_labeled() ? crgetlabel(cr) : NULL;
944 944
945 945 /* The structure isn't always completely filled in, so zero it */
946 946 if (buf == NULL) {
947 947 uc = kmem_zalloc(realsz, KM_SLEEP);
948 948 } else {
949 949 bzero(buf, realsz);
950 950 uc = buf;
951 951 }
952 952 uc->uc_size = realsz;
953 953 uc->uc_pid = pid;
954 954 uc->uc_projid = cr->cr_projid;
955 955 uc->uc_zoneid = crgetzoneid(cr);
956 956
957 957 if (REMOTE_PEER_CRED(cr)) {
958 958 /*
959 959 * Other than label, the rest of cred info about a
960 960 * remote peer isn't available. Copy the label directly
961 961 * after the header where we generally copy the prcred.
962 962 * That's why we use sizeof (struct ucred_s). The other
963 963 * offset fields are initialized to 0.
964 964 */
965 965 uc->uc_labeloff = tslp == NULL ? 0 : sizeof (struct ucred_s);
966 966 } else {
967 967 uc->uc_credoff = UCRED_CRED_OFF;
968 968 uc->uc_privoff = UCRED_PRIV_OFF;
969 969 uc->uc_audoff = UCRED_AUD_OFF;
970 970 uc->uc_labeloff = tslp == NULL ? 0 : UCRED_LABEL_OFF;
971 971
972 972 cred2prcred(cr, UCCRED(uc));
973 973 cred2prpriv(cr, UCPRIV(uc));
974 974
975 975 if (audoff == 0 || cred2ucaud(cr, UCAUD(uc), rcr) != 0)
976 976 uc->uc_audoff = 0;
977 977 }
978 978 if (tslp != NULL)
979 979 bcopy(&tslp->tsl_label, UCLABEL(uc), sizeof (bslabel_t));
980 980
981 981 return (uc);
982 982 }
983 983
984 984 /*
985 985 * Don't allocate the non-needed group entries. Note: this function
986 986 * must match the code in cred2ucred; they must agree about the
987 987 * minimal size of the ucred.
988 988 */
989 989 uint32_t
990 990 ucredminsize(const cred_t *cr)
991 991 {
992 992 int ndiff;
993 993
994 994 if (cr == NULL)
995 995 return (ucredsize);
996 996
997 997 if (REMOTE_PEER_CRED(cr)) {
998 998 if (is_system_labeled())
999 999 return (sizeof (struct ucred_s) + sizeof (bslabel_t));
1000 1000 else
1001 1001 return (sizeof (struct ucred_s));
1002 1002 }
1003 1003
1004 1004 if (cr->cr_grps == NULL)
1005 1005 ndiff = ngroups_max - 1; /* Needs one for prcred_t */
1006 1006 else
1007 1007 ndiff = ngroups_max - cr->cr_grps->crg_ngroups;
1008 1008
1009 1009 return (ucredsize - ndiff * sizeof (gid_t));
1010 1010 }
1011 1011
1012 1012 /*
1013 1013 * Get the "ucred" of a process.
1014 1014 */
1015 1015 struct ucred_s *
1016 1016 pgetucred(proc_t *p)
1017 1017 {
1018 1018 cred_t *cr;
1019 1019 struct ucred_s *uc;
1020 1020
1021 1021 mutex_enter(&p->p_crlock);
1022 1022 cr = p->p_cred;
1023 1023 crhold(cr);
1024 1024 mutex_exit(&p->p_crlock);
1025 1025
1026 1026 uc = cred2ucred(cr, p->p_pid, NULL, CRED());
1027 1027 crfree(cr);
1028 1028
1029 1029 return (uc);
1030 1030 }
1031 1031
1032 1032 /*
1033 1033 * If the reply status is NFSERR_EACCES, it may be because we are
1034 1034 * root (no root net access). Check the real uid, if it isn't root
1035 1035 * make that the uid instead and retry the call.
1036 1036 * Private interface for NFS.
1037 1037 */
1038 1038 cred_t *
1039 1039 crnetadjust(cred_t *cr)
1040 1040 {
1041 1041 if (cr->cr_uid == 0 && cr->cr_ruid != 0) {
1042 1042 cr = crdup(cr);
1043 1043 cr->cr_uid = cr->cr_ruid;
1044 1044 return (cr);
1045 1045 }
1046 1046 return (NULL);
1047 1047 }
1048 1048
1049 1049 /*
1050 1050 * The reference count is of interest when you want to check
1051 1051 * whether it is ok to modify the credential in place.
1052 1052 */
1053 1053 uint_t
1054 1054 crgetref(const cred_t *cr)
1055 1055 {
1056 1056 return (cr->cr_ref);
1057 1057 }
1058 1058
1059 1059 static int
1060 1060 get_c2audit_load(void)
1061 1061 {
1062 1062 static int gotit = 0;
1063 1063 static int c2audit_load;
1064 1064
1065 1065 if (gotit)
1066 1066 return (c2audit_load);
1067 1067 c2audit_load = 1; /* set default value once */
1068 1068 if (mod_sysctl(SYS_CHECK_EXCLUDE, "c2audit") != 0)
1069 1069 c2audit_load = 0;
1070 1070 gotit++;
1071 1071
1072 1072 return (c2audit_load);
1073 1073 }
1074 1074
1075 1075 int
1076 1076 get_audit_ucrsize(void)
1077 1077 {
1078 1078 return (get_c2audit_load() ? sizeof (auditinfo64_addr_t) : 0);
1079 1079 }
1080 1080
1081 1081 /*
1082 1082 * Set zone pointer in credential to indicated value. First adds a
1083 1083 * hold for the new zone, then drops the hold on previous zone (if any).
1084 1084 * This is done in this order in case the old and new zones are the
1085 1085 * same.
1086 1086 */
1087 1087 void
1088 1088 crsetzone(cred_t *cr, zone_t *zptr)
1089 1089 {
1090 1090 zone_t *oldzptr = cr->cr_zone;
1091 1091
1092 1092 ASSERT(cr != kcred);
1093 1093 ASSERT(cr->cr_ref <= 2);
1094 1094 cr->cr_zone = zptr;
1095 1095 zone_cred_hold(zptr);
1096 1096 if (oldzptr)
1097 1097 zone_cred_rele(oldzptr);
1098 1098 }
1099 1099
1100 1100 /*
1101 1101 * Create a new cred based on the supplied label
1102 1102 */
1103 1103 cred_t *
1104 1104 newcred_from_bslabel(bslabel_t *blabel, uint32_t doi, int flags)
1105 1105 {
1106 1106 ts_label_t *lbl = labelalloc(blabel, doi, flags);
1107 1107 cred_t *cr = NULL;
1108 1108
1109 1109 if (lbl != NULL) {
1110 1110 if ((cr = crdup_flags(dummycr, flags)) != NULL) {
1111 1111 cr->cr_label = lbl;
1112 1112 } else {
1113 1113 label_rele(lbl);
1114 1114 }
1115 1115 }
1116 1116
1117 1117 return (cr);
1118 1118 }
1119 1119
1120 1120 /*
1121 1121 * Derive a new cred from the existing cred, but with a different label.
1122 1122 * To be used when a cred is being shared, but the label needs to be changed
1123 1123 * by a caller without affecting other users
1124 1124 */
1125 1125 cred_t *
1126 1126 copycred_from_tslabel(const cred_t *cr, ts_label_t *label, int flags)
1127 1127 {
1128 1128 cred_t *newcr = NULL;
1129 1129
1130 1130 if ((newcr = crdup_flags(cr, flags)) != NULL) {
1131 1131 if (newcr->cr_label != NULL)
1132 1132 label_rele(newcr->cr_label);
1133 1133 label_hold(label);
1134 1134 newcr->cr_label = label;
1135 1135 }
1136 1136
1137 1137 return (newcr);
1138 1138 }
1139 1139
1140 1140 /*
1141 1141 * Derive a new cred from the existing cred, but with a different label.
1142 1142 */
1143 1143 cred_t *
1144 1144 copycred_from_bslabel(const cred_t *cr, bslabel_t *blabel,
1145 1145 uint32_t doi, int flags)
1146 1146 {
1147 1147 ts_label_t *lbl = labelalloc(blabel, doi, flags);
1148 1148 cred_t *newcr = NULL;
1149 1149
1150 1150 if (lbl != NULL) {
1151 1151 newcr = copycred_from_tslabel(cr, lbl, flags);
1152 1152 label_rele(lbl);
1153 1153 }
1154 1154
1155 1155 return (newcr);
1156 1156 }
1157 1157
1158 1158 /*
1159 1159 * This function returns a pointer to the kcred-equivalent in the current zone.
1160 1160 */
1161 1161 cred_t *
1162 1162 zone_kcred(void)
1163 1163 {
1164 1164 zone_t *zone;
1165 1165
1166 1166 if ((zone = CRED()->cr_zone) != NULL)
1167 1167 return (zone->zone_kcred);
1168 1168 else
1169 1169 return (kcred);
1170 1170 }
1171 1171
1172 1172 boolean_t
1173 1173 valid_ephemeral_uid(zone_t *zone, uid_t id)
1174 1174 {
1175 1175 ephemeral_zsd_t *eph_zsd;
1176 1176 if (id <= IDMAP_WK__MAX_UID)
1177 1177 return (B_TRUE);
1178 1178
1179 1179 eph_zsd = get_ephemeral_zsd(zone);
1180 1180 ASSERT(eph_zsd != NULL);
1181 1181 membar_consumer();
1182 1182 return (id > eph_zsd->min_uid && id <= eph_zsd->last_uid);
1183 1183 }
1184 1184
1185 1185 boolean_t
1186 1186 valid_ephemeral_gid(zone_t *zone, gid_t id)
1187 1187 {
1188 1188 ephemeral_zsd_t *eph_zsd;
1189 1189 if (id <= IDMAP_WK__MAX_GID)
1190 1190 return (B_TRUE);
1191 1191
1192 1192 eph_zsd = get_ephemeral_zsd(zone);
1193 1193 ASSERT(eph_zsd != NULL);
1194 1194 membar_consumer();
1195 1195 return (id > eph_zsd->min_gid && id <= eph_zsd->last_gid);
1196 1196 }
1197 1197
1198 1198 int
1199 1199 eph_uid_alloc(zone_t *zone, int flags, uid_t *start, int count)
1200 1200 {
1201 1201 ephemeral_zsd_t *eph_zsd = get_ephemeral_zsd(zone);
1202 1202
1203 1203 ASSERT(eph_zsd != NULL);
1204 1204
1205 1205 mutex_enter(&eph_zsd->eph_lock);
1206 1206
1207 1207 /* Test for unsigned integer wrap around */
1208 1208 if (eph_zsd->last_uid + count < eph_zsd->last_uid) {
1209 1209 mutex_exit(&eph_zsd->eph_lock);
1210 1210 return (-1);
1211 1211 }
1212 1212
1213 1213 /* first call or idmap crashed and state corrupted */
1214 1214 if (flags != 0)
1215 1215 eph_zsd->min_uid = eph_zsd->last_uid;
1216 1216
1217 1217 hasephids = B_TRUE;
1218 1218 *start = eph_zsd->last_uid + 1;
1219 1219 atomic_add_32(&eph_zsd->last_uid, count);
1220 1220 mutex_exit(&eph_zsd->eph_lock);
1221 1221 return (0);
1222 1222 }
1223 1223
1224 1224 int
1225 1225 eph_gid_alloc(zone_t *zone, int flags, gid_t *start, int count)
1226 1226 {
1227 1227 ephemeral_zsd_t *eph_zsd = get_ephemeral_zsd(zone);
1228 1228
1229 1229 ASSERT(eph_zsd != NULL);
1230 1230
1231 1231 mutex_enter(&eph_zsd->eph_lock);
1232 1232
1233 1233 /* Test for unsigned integer wrap around */
1234 1234 if (eph_zsd->last_gid + count < eph_zsd->last_gid) {
1235 1235 mutex_exit(&eph_zsd->eph_lock);
1236 1236 return (-1);
1237 1237 }
1238 1238
1239 1239 /* first call or idmap crashed and state corrupted */
1240 1240 if (flags != 0)
1241 1241 eph_zsd->min_gid = eph_zsd->last_gid;
1242 1242
1243 1243 hasephids = B_TRUE;
1244 1244 *start = eph_zsd->last_gid + 1;
1245 1245 atomic_add_32(&eph_zsd->last_gid, count);
1246 1246 mutex_exit(&eph_zsd->eph_lock);
1247 1247 return (0);
1248 1248 }
1249 1249
1250 1250 /*
1251 1251 * IMPORTANT.The two functions get_ephemeral_data() and set_ephemeral_data()
1252 1252 * are project private functions that are for use of the test system only and
1253 1253 * are not to be used for other purposes.
1254 1254 */
1255 1255
1256 1256 void
1257 1257 get_ephemeral_data(zone_t *zone, uid_t *min_uid, uid_t *last_uid,
1258 1258 gid_t *min_gid, gid_t *last_gid)
1259 1259 {
1260 1260 ephemeral_zsd_t *eph_zsd = get_ephemeral_zsd(zone);
1261 1261
1262 1262 ASSERT(eph_zsd != NULL);
1263 1263
1264 1264 mutex_enter(&eph_zsd->eph_lock);
1265 1265
1266 1266 *min_uid = eph_zsd->min_uid;
1267 1267 *last_uid = eph_zsd->last_uid;
1268 1268 *min_gid = eph_zsd->min_gid;
1269 1269 *last_gid = eph_zsd->last_gid;
1270 1270
1271 1271 mutex_exit(&eph_zsd->eph_lock);
1272 1272 }
1273 1273
1274 1274
1275 1275 void
1276 1276 set_ephemeral_data(zone_t *zone, uid_t min_uid, uid_t last_uid,
1277 1277 gid_t min_gid, gid_t last_gid)
1278 1278 {
1279 1279 ephemeral_zsd_t *eph_zsd = get_ephemeral_zsd(zone);
1280 1280
1281 1281 ASSERT(eph_zsd != NULL);
1282 1282
1283 1283 mutex_enter(&eph_zsd->eph_lock);
1284 1284
1285 1285 if (min_uid != 0)
1286 1286 eph_zsd->min_uid = min_uid;
1287 1287 if (last_uid != 0)
1288 1288 eph_zsd->last_uid = last_uid;
1289 1289 if (min_gid != 0)
1290 1290 eph_zsd->min_gid = min_gid;
1291 1291 if (last_gid != 0)
1292 1292 eph_zsd->last_gid = last_gid;
1293 1293
1294 1294 mutex_exit(&eph_zsd->eph_lock);
1295 1295 }
1296 1296
1297 1297 /*
1298 1298 * If the credential user SID or group SID is mapped to an ephemeral
1299 1299 * ID, map the credential to nobody.
1300 1300 */
1301 1301 cred_t *
1302 1302 crgetmapped(const cred_t *cr)
1303 1303 {
1304 1304 ephemeral_zsd_t *eph_zsd;
1305 1305 /*
1306 1306 * Someone incorrectly passed a NULL cred to a vnode operation
1307 1307 * either on purpose or by calling CRED() in interrupt context.
1308 1308 */
1309 1309 if (cr == NULL)
1310 1310 return (NULL);
1311 1311
1312 1312 if (cr->cr_ksid != NULL) {
1313 1313 if (cr->cr_ksid->kr_sidx[KSID_USER].ks_id > MAXUID) {
1314 1314 eph_zsd = get_ephemeral_zsd(crgetzone(cr));
1315 1315 return (eph_zsd->eph_nobody);
1316 1316 }
1317 1317
1318 1318 if (cr->cr_ksid->kr_sidx[KSID_GROUP].ks_id > MAXUID) {
1319 1319 eph_zsd = get_ephemeral_zsd(crgetzone(cr));
1320 1320 return (eph_zsd->eph_nobody);
1321 1321 }
1322 1322 }
1323 1323
1324 1324 return ((cred_t *)cr);
1325 1325 }
1326 1326
1327 1327 /* index should be in range for a ksidindex_t */
1328 1328 void
1329 1329 crsetsid(cred_t *cr, ksid_t *ksp, int index)
1330 1330 {
1331 1331 ASSERT(cr->cr_ref <= 2);
1332 1332 ASSERT(index >= 0 && index < KSID_COUNT);
1333 1333 if (cr->cr_ksid == NULL && ksp == NULL)
1334 1334 return;
1335 1335 cr->cr_ksid = kcrsid_setsid(cr->cr_ksid, ksp, index);
1336 1336 }
1337 1337
1338 1338 void
1339 1339 crsetsidlist(cred_t *cr, ksidlist_t *ksl)
1340 1340 {
1341 1341 ASSERT(cr->cr_ref <= 2);
1342 1342 if (cr->cr_ksid == NULL && ksl == NULL)
1343 1343 return;
1344 1344 cr->cr_ksid = kcrsid_setsidlist(cr->cr_ksid, ksl);
1345 1345 }
1346 1346
1347 1347 ksid_t *
1348 1348 crgetsid(const cred_t *cr, int i)
1349 1349 {
1350 1350 ASSERT(i >= 0 && i < KSID_COUNT);
1351 1351 if (cr->cr_ksid != NULL && cr->cr_ksid->kr_sidx[i].ks_domain)
1352 1352 return ((ksid_t *)&cr->cr_ksid->kr_sidx[i]);
1353 1353 return (NULL);
1354 1354 }
1355 1355
1356 1356 ksidlist_t *
1357 1357 crgetsidlist(const cred_t *cr)
1358 1358 {
1359 1359 if (cr->cr_ksid != NULL)
1360 1360 return (cr->cr_ksid->kr_sidlist);
1361 1361 return (NULL);
1362 1362 }
1363 1363
1364 1364 /*
1365 1365 * Interface to set the effective and permitted privileges for
1366 1366 * a credential; this interface does no security checks and is
1367 1367 * intended for kernel (file)servers creating credentials with
1368 1368 * specific privileges.
1369 1369 */
1370 1370 int
1371 1371 crsetpriv(cred_t *cr, ...)
1372 1372 {
1373 1373 va_list ap;
1374 1374 const char *privnm;
1375 1375
1376 1376 ASSERT(cr->cr_ref <= 2);
1377 1377
1378 1378 priv_set_PA(cr);
1379 1379
1380 1380 va_start(ap, cr);
1381 1381
1382 1382 while ((privnm = va_arg(ap, const char *)) != NULL) {
1383 1383 int priv = priv_getbyname(privnm, 0);
1384 1384 if (priv < 0)
1385 1385 return (-1);
1386 1386
1387 1387 priv_addset(&CR_PPRIV(cr), priv);
1388 1388 priv_addset(&CR_EPRIV(cr), priv);
1389 1389 }
1390 1390 priv_adjust_PA(cr);
1391 1391 va_end(ap);
1392 1392 return (0);
1393 1393 }
1394 1394
1395 1395 /*
1396 1396 * Interface to effectively set the PRIV_ALL for
1397 1397 * a credential; this interface does no security checks and is
1398 1398 * intended for kernel (file)servers to extend the user credentials
1399 1399 * to be ALL, like either kcred or zcred.
1400 1400 */
1401 1401 void
1402 1402 crset_zone_privall(cred_t *cr)
1403 1403 {
1404 1404 zone_t *zone = crgetzone(cr);
1405 1405
1406 1406 priv_fillset(&CR_LPRIV(cr));
1407 1407 CR_EPRIV(cr) = CR_PPRIV(cr) = CR_IPRIV(cr) = CR_LPRIV(cr);
1408 1408 priv_intersect(zone->zone_privset, &CR_LPRIV(cr));
1409 1409 priv_intersect(zone->zone_privset, &CR_EPRIV(cr));
1410 1410 priv_intersect(zone->zone_privset, &CR_IPRIV(cr));
1411 1411 priv_intersect(zone->zone_privset, &CR_PPRIV(cr));
1412 1412 }
1413 1413
1414 1414 struct credklpd *
1415 1415 crgetcrklpd(const cred_t *cr)
1416 1416 {
1417 1417 return (cr->cr_klpd);
1418 1418 }
1419 1419
1420 1420 void
1421 1421 crsetcrklpd(cred_t *cr, struct credklpd *crklpd)
1422 1422 {
1423 1423 ASSERT(cr->cr_ref <= 2);
1424 1424
1425 1425 if (cr->cr_klpd != NULL)
1426 1426 crklpd_rele(cr->cr_klpd);
1427 1427 cr->cr_klpd = crklpd;
1428 1428 }
1429 1429
1430 1430 credgrp_t *
1431 1431 crgrpcopyin(int n, gid_t *gidset)
1432 1432 {
1433 1433 credgrp_t *mem;
1434 1434 size_t sz = CREDGRPSZ(n);
1435 1435
1436 1436 ASSERT(n > 0);
1437 1437
1438 1438 mem = kmem_alloc(sz, KM_SLEEP);
1439 1439
1440 1440 if (copyin(gidset, mem->crg_groups, sizeof (gid_t) * n)) {
1441 1441 kmem_free(mem, sz);
1442 1442 return (NULL);
1443 1443 }
1444 1444 mem->crg_ref = 1;
1445 1445 mem->crg_ngroups = n;
1446 1446 qsort(mem->crg_groups, n, sizeof (gid_t), gidcmp);
1447 1447 return (mem);
1448 1448 }
1449 1449
1450 1450 const gid_t *
1451 1451 crgetggroups(const credgrp_t *grps)
1452 1452 {
1453 1453 return (grps->crg_groups);
1454 1454 }
1455 1455
1456 1456 void
1457 1457 crsetcredgrp(cred_t *cr, credgrp_t *grps)
1458 1458 {
1459 1459 ASSERT(cr->cr_ref <= 2);
1460 1460
1461 1461 if (cr->cr_grps != NULL)
1462 1462 crgrprele(cr->cr_grps);
1463 1463
1464 1464 cr->cr_grps = grps;
1465 1465 }
1466 1466
1467 1467 void
1468 1468 crgrprele(credgrp_t *grps)
1469 1469 {
1470 1470 if (atomic_dec_32_nv(&grps->crg_ref) == 0)
1471 1471 kmem_free(grps, CREDGRPSZ(grps->crg_ngroups));
1472 1472 }
1473 1473
1474 1474 static void
1475 1475 crgrphold(credgrp_t *grps)
1476 1476 {
1477 1477 atomic_inc_32(&grps->crg_ref);
1478 1478 }
↓ open down ↓ |
1252 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX