1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * Windows to Solaris Identity Mapping kernel API 29 * This module provides an API to map Windows SIDs to 30 * Solaris UID and GIDs. 31 */ 32 33 #pragma ident "%Z%%M% %I% %E% SMI" 34 35 #include <sys/types.h> 36 #include <sys/ksynch.h> 37 #include <sys/door.h> 38 #include <rpc/rpc_msg.h> 39 #include <rpc/xdr.h> 40 #include <rpc/auth.h> 41 #include <rpc/rpc_sztypes.h> 42 #ifdef DEBUG 43 #include <sys/cmn_err.h> 44 #endif /* DEBUG */ 45 #include <sys/proc.h> 46 #include <sys/sunddi.h> 47 #include <sys/param.h> 48 #include <sys/atomic.h> 49 #include <sys/sysmacros.h> 50 #include <sys/disp.h> 51 #include <sys/kidmap.h> 52 #include <sys/zone.h> 53 #include "idmap_prot.h" 54 #include "kidmap_priv.h" 55 56 57 /* 58 * Defined types 59 */ 60 61 62 /* 63 * This structure holds pointers for the 64 * batch mapping results. 65 */ 66 typedef struct idmap_get_res { 67 idmap_id_type idtype; 68 uid_t *uid; 69 gid_t *gid; 70 uid_t *pid; 71 int *is_user; 72 const char **sid_prefix; 73 uint32_t *rid; 74 idmap_stat *stat; 75 } idmap_get_res; 76 77 /* Batch mapping handle structure */ 78 struct idmap_get_handle { 79 struct idmap_zone_specific *zs; 80 int mapping_num; 81 int mapping_size; 82 idmap_mapping *mapping; 83 idmap_get_res *result; 84 }; 85 86 87 /* Zone specific data */ 88 typedef struct idmap_zone_specific { 89 zoneid_t zone_id; 90 kmutex_t zone_mutex; 91 idmap_cache_t cache; 92 door_handle_t door_handle; 93 int door_valid; 94 uint32_t message_id; 95 } idmap_zone_specific_t; 96 97 98 99 /* 100 * Module global data 101 */ 102 103 static kmutex_t idmap_zone_mutex; 104 static zone_key_t idmap_zone_key; 105 106 107 /* 108 * Local function definitions 109 */ 110 111 112 static int 113 kidmap_rpc_call(idmap_zone_specific_t *zs, uint32_t op, 114 xdrproc_t xdr_args, caddr_t args, 115 xdrproc_t xdr_res, caddr_t res); 116 117 static int 118 kidmap_call_door(idmap_zone_specific_t *zs, door_arg_t *arg); 119 120 static idmap_zone_specific_t * 121 idmap_get_zone_specific(zone_t *zone); 122 123 124 125 int 126 idmap_reg_dh(zone_t *zone, door_handle_t dh) 127 { 128 idmap_zone_specific_t *zs; 129 130 zs = idmap_get_zone_specific(zone); 131 132 mutex_enter(&zs->zone_mutex); 133 134 if (zs->door_valid) 135 door_ki_rele(zs->door_handle); 136 137 zs->door_handle = dh; 138 zs->door_valid = 1; 139 140 mutex_exit(&zs->zone_mutex); 141 142 return (0); 143 } 144 145 /* 146 * idmap_unreg_dh 147 * 148 * This routine is called by system call idmap_unreg(). 149 * idmap_unreg() calls door_ki_rele() on the supplied 150 * door handle after this routine returns. We only 151 * need to perform one door release on zs->door_handle 152 */ 153 int 154 idmap_unreg_dh(zone_t *zone, door_handle_t dh) 155 { 156 idmap_zone_specific_t *zs; 157 158 zs = idmap_get_zone_specific(zone); 159 160 kidmap_cache_purge(&zs->cache); 161 162 mutex_enter(&zs->zone_mutex); 163 164 if (!zs->door_valid || zs->door_handle != dh) { 165 mutex_exit(&zs->zone_mutex); 166 return (EINVAL); 167 } 168 169 door_ki_rele(zs->door_handle); 170 171 zs->door_valid = 0; 172 mutex_exit(&zs->zone_mutex); 173 174 return (0); 175 } 176 177 178 /* 179 * IMPORTANT. This function idmap_get_cache_data() is project 180 * private and is for use of the test system only and should 181 * not be used for other purposes. 182 */ 183 void 184 idmap_get_cache_data(zone_t *zone, size_t *uidbysid, size_t *gidbysid, 185 size_t *pidbysid, size_t *sidbyuid, size_t *sidbygid) 186 { 187 idmap_zone_specific_t *zs; 188 189 zs = idmap_get_zone_specific(zone); 190 191 kidmap_cache_get_data(&zs->cache, uidbysid, gidbysid, 192 pidbysid, sidbyuid, sidbygid); 193 } 194 195 static int 196 kidmap_call_door(idmap_zone_specific_t *zs, door_arg_t *arg) 197 { 198 door_handle_t dh; 199 door_info_t di; 200 int status = 0; 201 int nretries = 0; 202 203 retry: 204 dh = NULL; 205 mutex_enter(&zs->zone_mutex); 206 if (zs->door_valid) { 207 dh = zs->door_handle; 208 door_ki_hold(dh); 209 } 210 mutex_exit(&zs->zone_mutex); 211 212 if (dh == NULL) { 213 /* 214 * There is no door handle yet. Give 215 * smf a chance to restarts the idmap daemon 216 */ 217 if (nretries++ < 5) { 218 delay(hz); 219 goto retry; 220 } 221 #ifdef DEBUG 222 zcmn_err(zs->zone_id, CE_WARN, 223 "idmap: Error no registered door to call the " 224 "idmap daemon\n"); 225 #endif 226 return (-1); 227 } 228 229 status = door_ki_upcall_limited(dh, arg, NULL, SIZE_MAX, 0); 230 231 switch (status) { 232 case 0: /* Success */ 233 door_ki_rele(dh); 234 return (0); 235 236 case EINTR: 237 /* If we took an interrupt we have to bail out. */ 238 if (ttolwp(curthread) && ISSIG(curthread, JUSTLOOKING)) { 239 door_ki_rele(dh); 240 zcmn_err(zs->zone_id, CE_WARN, 241 "idmap: Interrupted\n"); 242 return (-1); 243 } 244 /* 245 * Just retry and see what happens. 246 */ 247 /* FALLTHROUGH */ 248 249 case EAGAIN: 250 /* A resouce problem */ 251 door_ki_rele(dh); 252 /* Back off before retrying */ 253 #ifdef DEBUG 254 zcmn_err(zs->zone_id, CE_WARN, 255 "idmap: Door call returned error %d. Retrying\n", status); 256 #endif /* DEBUG */ 257 delay(hz); 258 goto retry; 259 260 case EBADF: 261 /* Stale door handle. See if smf restarts the daemon. */ 262 door_ki_rele(dh); 263 mutex_enter(&zs->zone_mutex); 264 if (zs->door_valid && dh == zs->door_handle) { 265 zs->door_valid = 0; 266 door_ki_rele(zs->door_handle); 267 } 268 mutex_exit(&zs->zone_mutex); 269 /* Back off before retrying */ 270 #ifdef DEBUG 271 zcmn_err(zs->zone_id, CE_WARN, 272 "idmap: Door call returned error %d. Retrying\n", status); 273 #endif /* DEBUG */ 274 delay(hz); 275 goto retry; 276 277 default: 278 /* Unknown error */ 279 #ifdef DEBUG 280 zcmn_err(zs->zone_id, CE_WARN, 281 "idmap: Door call returned error %d.\n", status); 282 #endif /* DEBUG */ 283 door_ki_rele(dh); 284 return (-1); 285 } 286 } 287 288 289 static idmap_zone_specific_t * 290 idmap_get_zone_specific(zone_t *zone) 291 { 292 idmap_zone_specific_t *zs; 293 294 ASSERT(zone != NULL); 295 296 zs = zone_getspecific(idmap_zone_key, zone); 297 if (zs != NULL) 298 return (zs); 299 300 mutex_enter(&idmap_zone_mutex); 301 zs = zone_getspecific(idmap_zone_key, zone); 302 if (zs == NULL) { 303 zs = kmem_zalloc(sizeof (idmap_zone_specific_t), KM_SLEEP); 304 mutex_init(&zs->zone_mutex, NULL, MUTEX_DEFAULT, NULL); 305 kidmap_cache_create(&zs->cache); 306 zs->zone_id = zone->zone_id; 307 (void) zone_setspecific(idmap_zone_key, zone, zs); 308 mutex_exit(&idmap_zone_mutex); 309 return (zs); 310 } 311 mutex_exit(&idmap_zone_mutex); 312 313 return (zs); 314 } 315 316 317 static void 318 /* ARGSUSED */ 319 idmap_zone_destroy(zoneid_t zone_id, void *arg) 320 { 321 idmap_zone_specific_t *zs = arg; 322 if (zs != NULL) { 323 kidmap_cache_delete(&zs->cache); 324 if (zs->door_valid) { 325 door_ki_rele(zs->door_handle); 326 } 327 mutex_destroy(&zs->zone_mutex); 328 kmem_free(zs, sizeof (idmap_zone_specific_t)); 329 } 330 } 331 332 333 int 334 kidmap_start(void) 335 { 336 mutex_init(&idmap_zone_mutex, NULL, MUTEX_DEFAULT, NULL); 337 zone_key_create(&idmap_zone_key, NULL, NULL, idmap_zone_destroy); 338 kidmap_sid_prefix_store_init(); 339 340 return (0); 341 } 342 343 344 int 345 kidmap_stop(void) 346 { 347 return (EBUSY); 348 } 349 350 351 /* 352 * idmap_get_door 353 * 354 * This is called by the system call allocids() to get the door for the 355 * given zone. 356 */ 357 door_handle_t 358 idmap_get_door(zone_t *zone) 359 { 360 door_handle_t dh = NULL; 361 idmap_zone_specific_t *zs; 362 363 zs = idmap_get_zone_specific(zone); 364 365 mutex_enter(&zs->zone_mutex); 366 if (zs->door_valid) { 367 dh = zs->door_handle; 368 door_ki_hold(dh); 369 } 370 mutex_exit(&zs->zone_mutex); 371 return (dh); 372 } 373 374 375 /* 376 * idmap_purge_cache 377 * 378 * This is called by the system call allocids() to purge the cache for the 379 * given zone. 380 */ 381 void 382 idmap_purge_cache(zone_t *zone) 383 { 384 idmap_zone_specific_t *zs; 385 386 zs = idmap_get_zone_specific(zone); 387 388 kidmap_cache_purge(&zs->cache); 389 } 390 391 392 393 394 /* 395 * Given Domain SID and RID, get UID 396 * 397 * Input: 398 * sid_prefix - Domain SID in canonical form 399 * rid - RID 400 * 401 * Output: 402 * uid - POSIX UID if return == IDMAP_SUCCESS 403 * 404 * Return: 405 * Success return IDMAP_SUCCESS else IDMAP error 406 */ 407 idmap_stat 408 kidmap_getuidbysid(zone_t *zone, const char *sid_prefix, uint32_t rid, 409 uid_t *uid) 410 { 411 idmap_zone_specific_t *zs; 412 idmap_mapping_batch args; 413 idmap_mapping mapping; 414 idmap_ids_res results; 415 uint32_t op = IDMAP_GET_MAPPED_IDS; 416 const char *new_sid_prefix; 417 idmap_stat status; 418 419 if (sid_prefix == NULL || uid == NULL) 420 return (IDMAP_ERR_ARG); 421 422 zs = idmap_get_zone_specific(zone); 423 424 if (kidmap_cache_lookup_uidbysid(&zs->cache, sid_prefix, rid, uid) 425 == IDMAP_SUCCESS) 426 return (IDMAP_SUCCESS); 427 428 bzero(&mapping, sizeof (idmap_mapping)); 429 mapping.id1.idtype = IDMAP_SID; 430 mapping.id1.idmap_id_u.sid.prefix = (char *)sid_prefix; 431 mapping.id1.idmap_id_u.sid.rid = rid; 432 mapping.id2.idtype = IDMAP_UID; 433 434 bzero(&results, sizeof (idmap_ids_res)); 435 436 args.idmap_mapping_batch_len = 1; 437 args.idmap_mapping_batch_val = &mapping; 438 439 if (kidmap_rpc_call(zs, op, xdr_idmap_mapping_batch, 440 (caddr_t)&args, xdr_idmap_ids_res, 441 (caddr_t)&results) == 0) { 442 /* Door call succeded */ 443 if (results.retcode != IDMAP_SUCCESS) { 444 status = results.retcode; 445 *uid = UID_NOBODY; 446 } else if (results.ids.ids_len >= 1 && 447 results.ids.ids_val[0].id.idtype == IDMAP_UID) { 448 status = results.ids.ids_val[0].retcode; 449 *uid = results.ids.ids_val[0].id.idmap_id_u.uid; 450 if (status == IDMAP_SUCCESS) { 451 new_sid_prefix = kidmap_find_sid_prefix( 452 sid_prefix); 453 kidmap_cache_add_uidbysid(&zs->cache, 454 new_sid_prefix, rid, *uid); 455 } 456 } else { 457 status = IDMAP_ERR_NOMAPPING; 458 *uid = UID_NOBODY; 459 } 460 xdr_free(xdr_idmap_ids_res, (char *)&results); 461 } else { 462 /* Door call failed */ 463 status = IDMAP_ERR_NOMAPPING; 464 *uid = UID_NOBODY; 465 } 466 return (status); 467 } 468 469 470 /* 471 * Given Domain SID and RID, get GID 472 * 473 * Input: 474 * sid_prefix - Domain SID in canonical form 475 * rid - RID 476 * 477 * Output: 478 * gid - POSIX UID if return == IDMAP_SUCCESS 479 * 480 * Return: 481 * Success return IDMAP_SUCCESS else IDMAP error 482 */ 483 idmap_stat 484 kidmap_getgidbysid(zone_t *zone, const char *sid_prefix, uint32_t rid, 485 gid_t *gid) 486 { 487 idmap_zone_specific_t *zs; 488 idmap_mapping_batch args; 489 idmap_mapping mapping; 490 idmap_ids_res results; 491 uint32_t op = IDMAP_GET_MAPPED_IDS; 492 const char *new_sid_prefix; 493 idmap_stat status; 494 495 if (sid_prefix == NULL || gid == NULL) 496 return (IDMAP_ERR_ARG); 497 498 zs = idmap_get_zone_specific(zone); 499 500 if (kidmap_cache_lookup_gidbysid(&zs->cache, sid_prefix, rid, gid) 501 == IDMAP_SUCCESS) 502 return (IDMAP_SUCCESS); 503 504 bzero(&mapping, sizeof (idmap_mapping)); 505 mapping.id1.idtype = IDMAP_SID; 506 mapping.id1.idmap_id_u.sid.prefix = (char *)sid_prefix; 507 mapping.id1.idmap_id_u.sid.rid = rid; 508 mapping.id2.idtype = IDMAP_GID; 509 510 bzero(&results, sizeof (idmap_ids_res)); 511 512 args.idmap_mapping_batch_len = 1; 513 args.idmap_mapping_batch_val = &mapping; 514 515 if (kidmap_rpc_call(zs, op, xdr_idmap_mapping_batch, 516 (caddr_t)&args, xdr_idmap_ids_res, 517 (caddr_t)&results) == 0) { 518 /* Door call succeded */ 519 if (results.retcode != IDMAP_SUCCESS) { 520 status = results.retcode; 521 *gid = GID_NOBODY; 522 } else if (results.ids.ids_len >= 1 && 523 results.ids.ids_val[0].id.idtype == IDMAP_GID) { 524 status = results.ids.ids_val[0].retcode; 525 *gid = results.ids.ids_val[0].id.idmap_id_u.gid; 526 if (status == IDMAP_SUCCESS) { 527 new_sid_prefix = kidmap_find_sid_prefix( 528 sid_prefix); 529 kidmap_cache_add_gidbysid(&zs->cache, 530 new_sid_prefix, rid, *gid); 531 } 532 } else { 533 status = IDMAP_ERR_NOMAPPING; 534 *gid = GID_NOBODY; 535 } 536 xdr_free(xdr_idmap_ids_res, (char *)&results); 537 } else { 538 /* Door call failed */ 539 status = IDMAP_ERR_NOMAPPING; 540 *gid = GID_NOBODY; 541 } 542 return (status); 543 } 544 545 /* 546 * Given Domain SID and RID, get Posix ID 547 * 548 * Input: 549 * sid_prefix - Domain SID in canonical form 550 * rid - RID 551 * 552 * Output: 553 * pid - POSIX ID if return == IDMAP_SUCCESS 554 * is_user - 1 == UID, 0 == GID if return == IDMAP_SUCCESS 555 * 556 * Return: 557 * Success return IDMAP_SUCCESS else IDMAP error 558 */ 559 idmap_stat 560 kidmap_getpidbysid(zone_t *zone, const char *sid_prefix, uint32_t rid, 561 uid_t *pid, int *is_user) 562 { 563 idmap_zone_specific_t *zs; 564 idmap_mapping_batch args; 565 idmap_mapping mapping; 566 idmap_ids_res results; 567 uint32_t op = IDMAP_GET_MAPPED_IDS; 568 const char *new_sid_prefix; 569 idmap_stat status; 570 571 if (sid_prefix == NULL || pid == NULL || is_user == NULL) 572 return (IDMAP_ERR_ARG); 573 574 zs = idmap_get_zone_specific(zone); 575 576 if (kidmap_cache_lookup_pidbysid(&zs->cache, sid_prefix, rid, pid, 577 is_user) == IDMAP_SUCCESS) 578 return (IDMAP_SUCCESS); 579 580 bzero(&mapping, sizeof (idmap_mapping)); 581 mapping.id1.idtype = IDMAP_SID; 582 mapping.id1.idmap_id_u.sid.prefix = (char *)sid_prefix; 583 mapping.id1.idmap_id_u.sid.rid = rid; 584 mapping.id2.idtype = IDMAP_POSIXID; 585 586 bzero(&results, sizeof (idmap_ids_res)); 587 588 args.idmap_mapping_batch_len = 1; 589 args.idmap_mapping_batch_val = &mapping; 590 591 if (kidmap_rpc_call(zs, op, xdr_idmap_mapping_batch, 592 (caddr_t)&args, xdr_idmap_ids_res, 593 (caddr_t)&results) == 0) { 594 /* Door call succeded */ 595 if (results.retcode != IDMAP_SUCCESS) { 596 status = results.retcode; 597 *is_user = 1; 598 *pid = UID_NOBODY; 599 } else if (results.ids.ids_len >= 1 && ( 600 results.ids.ids_val[0].id.idtype == IDMAP_UID || 601 results.ids.ids_val[0].id.idtype == IDMAP_GID)) { 602 status = results.ids.ids_val[0].retcode; 603 if (results.ids.ids_val[0].id.idtype == IDMAP_UID) { 604 *is_user = 1; 605 *pid = results.ids.ids_val[0].id.idmap_id_u.uid; 606 } else { 607 *is_user = 0; 608 *pid = results.ids.ids_val[0].id.idmap_id_u.gid; 609 } 610 if (status == IDMAP_SUCCESS) { 611 new_sid_prefix = kidmap_find_sid_prefix( 612 sid_prefix); 613 kidmap_cache_add_pidbysid(&zs->cache, 614 new_sid_prefix, rid, *pid, 615 *is_user); 616 } 617 } else { 618 status = IDMAP_ERR_NOMAPPING; 619 *is_user = 1; 620 *pid = UID_NOBODY; 621 } 622 xdr_free(xdr_idmap_ids_res, (char *)&results); 623 } else { 624 /* Door call failed */ 625 status = IDMAP_ERR_NOMAPPING; 626 *is_user = 1; 627 *pid = UID_NOBODY; 628 } 629 return (status); 630 } 631 632 633 /* 634 * Given UID, get Domain SID and RID 635 * 636 * Input: 637 * uid - Posix UID 638 * 639 * Output: 640 * sid_prefix - Domain SID if return == IDMAP_SUCCESS 641 * rid - RID if return == IDMAP_SUCCESS 642 * 643 * Return: 644 * Success return IDMAP_SUCCESS else IDMAP error 645 */ 646 idmap_stat 647 kidmap_getsidbyuid(zone_t *zone, uid_t uid, const char **sid_prefix, 648 uint32_t *rid) 649 { 650 idmap_zone_specific_t *zs; 651 idmap_mapping_batch args; 652 idmap_mapping mapping; 653 idmap_ids_res results; 654 uint32_t op = IDMAP_GET_MAPPED_IDS; 655 idmap_stat status; 656 time_t entry_ttl; 657 idmap_id *id; 658 659 if (sid_prefix == NULL || rid == NULL) 660 return (IDMAP_ERR_ARG); 661 662 zs = idmap_get_zone_specific(zone); 663 664 if (kidmap_cache_lookup_sidbyuid(&zs->cache, sid_prefix, rid, uid) 665 == IDMAP_SUCCESS) { 666 return (IDMAP_SUCCESS); 667 } 668 669 bzero(&mapping, sizeof (idmap_mapping)); 670 mapping.id1.idtype = IDMAP_UID; 671 mapping.id1.idmap_id_u.uid = uid; 672 mapping.id2.idtype = IDMAP_SID; 673 674 bzero(&results, sizeof (idmap_ids_res)); 675 676 args.idmap_mapping_batch_len = 1; 677 args.idmap_mapping_batch_val = &mapping; 678 679 if (kidmap_rpc_call(zs, op, xdr_idmap_mapping_batch, 680 (caddr_t)&args, xdr_idmap_ids_res, 681 (caddr_t)&results) == 0) { 682 /* Door call succeded */ 683 if (results.retcode != IDMAP_SUCCESS) { 684 status = results.retcode; 685 *rid = 0; 686 *sid_prefix = NULL; 687 } else if (results.ids.ids_len >= 1 && 688 (results.ids.ids_val[0].id.idtype == IDMAP_SID || 689 results.ids.ids_val[0].id.idtype == IDMAP_USID || 690 results.ids.ids_val[0].id.idtype == IDMAP_GSID)) { 691 status = results.ids.ids_val[0].retcode; 692 id = &results.ids.ids_val[0].id; 693 *sid_prefix = kidmap_find_sid_prefix( 694 id->idmap_id_u.sid.prefix); 695 *rid = id->idmap_id_u.sid.rid; 696 if (status == IDMAP_SUCCESS) { 697 kidmap_cache_add_sidbyuid(&zs->cache, 698 *sid_prefix, *rid, uid); 699 } 700 } else { 701 status = IDMAP_ERR_NOMAPPING; 702 *rid = 0; 703 *sid_prefix = NULL; 704 } 705 xdr_free(xdr_idmap_ids_res, (char *)&results); 706 } else { 707 /* Door call failed */ 708 status = IDMAP_ERR_NOMAPPING; 709 *rid = 0; 710 *sid_prefix = NULL; 711 } 712 return (status); 713 } 714 715 716 /* 717 * Given GID, get Domain SID and RID 718 * 719 * Input: 720 * gid - Posix GID 721 * 722 * Output: 723 * sid_prefix - Domain SID if return == IDMAP_SUCCESS 724 * rid - RID if return == IDMAP_SUCCESS 725 * 726 * Return: 727 * Success return IDMAP_SUCCESS else IDMAP error 728 */ 729 idmap_stat 730 kidmap_getsidbygid(zone_t *zone, gid_t gid, const char **sid_prefix, 731 uint32_t *rid) 732 { 733 idmap_zone_specific_t *zs; 734 idmap_mapping_batch args; 735 idmap_mapping mapping; 736 idmap_ids_res results; 737 uint32_t op = IDMAP_GET_MAPPED_IDS; 738 idmap_stat status; 739 idmap_id *id; 740 741 if (sid_prefix == NULL || rid == NULL) 742 return (IDMAP_ERR_ARG); 743 744 zs = idmap_get_zone_specific(zone); 745 746 if (kidmap_cache_lookup_sidbygid(&zs->cache, sid_prefix, rid, gid) 747 == IDMAP_SUCCESS) { 748 return (IDMAP_SUCCESS); 749 } 750 751 bzero(&mapping, sizeof (idmap_mapping)); 752 mapping.id1.idtype = IDMAP_GID; 753 mapping.id1.idmap_id_u.uid = gid; 754 mapping.id2.idtype = IDMAP_SID; 755 756 bzero(&results, sizeof (idmap_ids_res)); 757 758 args.idmap_mapping_batch_len = 1; 759 args.idmap_mapping_batch_val = &mapping; 760 761 if (kidmap_rpc_call(zs, op, xdr_idmap_mapping_batch, 762 (caddr_t)&args, xdr_idmap_ids_res, 763 (caddr_t)&results) == 0) { 764 /* Door call succeded */ 765 if (results.retcode != IDMAP_SUCCESS) { 766 status = results.retcode; 767 *rid = 0; 768 *sid_prefix = NULL; 769 } else if (results.ids.ids_len >= 1 && 770 (results.ids.ids_val[0].id.idtype == IDMAP_SID || 771 results.ids.ids_val[0].id.idtype == IDMAP_USID || 772 results.ids.ids_val[0].id.idtype == IDMAP_GSID)) { 773 status = results.ids.ids_val[0].retcode; 774 id = &results.ids.ids_val[0].id; 775 *sid_prefix = kidmap_find_sid_prefix( 776 id->idmap_id_u.sid.prefix); 777 *rid = id->idmap_id_u.sid.rid; 778 if (status == IDMAP_SUCCESS) { 779 kidmap_cache_add_sidbygid(&zs->cache, 780 *sid_prefix, *rid, gid); 781 } 782 } else { 783 status = IDMAP_ERR_NOMAPPING; 784 *rid = 0; 785 *sid_prefix = NULL; 786 } 787 xdr_free(xdr_idmap_ids_res, (char *)&results); 788 } else { 789 /* Door call failed */ 790 status = IDMAP_ERR_NOMAPPING; 791 *rid = 0; 792 *sid_prefix = NULL; 793 } 794 return (status); 795 } 796 797 /* 798 * Create handle to get SID to UID/GID mapping entries 799 * 800 * Input: 801 * none 802 * Return: 803 * get_handle 804 * 805 */ 806 idmap_get_handle_t * 807 kidmap_get_create(zone_t *zone) 808 { 809 idmap_zone_specific_t *zs; 810 idmap_get_handle_t *handle; 811 #define INIT_MAPPING_SIZE 32 812 813 zs = idmap_get_zone_specific(zone); 814 815 handle = kmem_zalloc(sizeof (idmap_get_handle_t), KM_SLEEP); 816 817 handle->mapping = kmem_zalloc((sizeof (idmap_mapping)) * 818 INIT_MAPPING_SIZE, KM_SLEEP); 819 820 handle->result = kmem_zalloc((sizeof (idmap_get_res)) * 821 INIT_MAPPING_SIZE, KM_SLEEP); 822 handle->mapping_size = INIT_MAPPING_SIZE; 823 handle->zs = zs; 824 825 return (handle); 826 } 827 828 /* 829 * Internal routine to extend a "get_handle" 830 */ 831 static void 832 kidmap_get_extend(idmap_get_handle_t *get_handle) 833 { 834 idmap_mapping *mapping; 835 idmap_get_res *result; 836 int new_size = get_handle->mapping_size + INIT_MAPPING_SIZE; 837 838 mapping = kmem_zalloc((sizeof (idmap_mapping)) * 839 new_size, KM_SLEEP); 840 (void) memcpy(mapping, get_handle->mapping, 841 (sizeof (idmap_mapping)) * get_handle->mapping_size); 842 843 result = kmem_zalloc((sizeof (idmap_get_res)) * 844 new_size, KM_SLEEP); 845 (void) memcpy(result, get_handle->result, 846 (sizeof (idmap_get_res)) * get_handle->mapping_size); 847 848 kmem_free(get_handle->mapping, 849 (sizeof (idmap_mapping)) * get_handle->mapping_size); 850 get_handle->mapping = mapping; 851 852 kmem_free(get_handle->result, 853 (sizeof (idmap_get_res)) * get_handle->mapping_size); 854 get_handle->result = result; 855 856 get_handle->mapping_size = new_size; 857 } 858 859 860 /* 861 * Given Domain SID and RID, get UID 862 * 863 * Input: 864 * sid_prefix - Domain SID in canonical form 865 * rid - RID 866 * 867 * Output: 868 * stat - status of the get request 869 * uid - POSIX UID if stat == IDMAP_SUCCESS 870 * 871 * Note: The output parameters will be set by idmap_get_mappings() 872 */ 873 idmap_stat 874 kidmap_batch_getuidbysid(idmap_get_handle_t *get_handle, const char *sid_prefix, 875 uint32_t rid, uid_t *uid, idmap_stat *stat) 876 { 877 idmap_mapping *mapping; 878 idmap_get_res *result; 879 880 if (get_handle == NULL || sid_prefix == NULL || 881 uid == NULL || stat == NULL) 882 return (IDMAP_ERR_ARG); 883 884 if (kidmap_cache_lookup_uidbysid(&get_handle->zs->cache, sid_prefix, 885 rid, uid) == IDMAP_SUCCESS) { 886 *stat = IDMAP_SUCCESS; 887 return (IDMAP_SUCCESS); 888 } 889 890 if (get_handle->mapping_num >= get_handle->mapping_size) 891 kidmap_get_extend(get_handle); 892 893 mapping = &get_handle->mapping[get_handle->mapping_num]; 894 mapping->flag = 0; 895 mapping->id1.idtype = IDMAP_SID; 896 mapping->id1.idmap_id_u.sid.prefix = (char *)sid_prefix; 897 mapping->id1.idmap_id_u.sid.rid = rid; 898 mapping->id2.idtype = IDMAP_UID; 899 900 result = &get_handle->result[get_handle->mapping_num]; 901 result->idtype = IDMAP_UID; 902 result->uid = uid; 903 result->gid = NULL; 904 result->pid = NULL; 905 result->sid_prefix = NULL; 906 result->rid = NULL; 907 result->is_user = NULL; 908 result->stat = stat; 909 910 get_handle->mapping_num++; 911 912 return (IDMAP_SUCCESS); 913 } 914 915 916 /* 917 * Given Domain SID and RID, get GID 918 * 919 * Input: 920 * sid_prefix - Domain SID in canonical form 921 * rid - RID 922 * 923 * Output: 924 * stat - status of the get request 925 * gid - POSIX GID if stat == IDMAP_SUCCESS 926 * 927 * Note: The output parameters will be set by idmap_get_mappings() 928 */ 929 idmap_stat 930 kidmap_batch_getgidbysid(idmap_get_handle_t *get_handle, const char *sid_prefix, 931 uint32_t rid, uid_t *gid, idmap_stat *stat) 932 { 933 idmap_mapping *mapping; 934 idmap_get_res *result; 935 936 if (get_handle == NULL || sid_prefix == NULL || 937 gid == NULL || stat == NULL) 938 return (IDMAP_ERR_ARG); 939 940 if (kidmap_cache_lookup_gidbysid(&get_handle->zs->cache, sid_prefix, 941 rid, gid) == IDMAP_SUCCESS) { 942 *stat = IDMAP_SUCCESS; 943 return (IDMAP_SUCCESS); 944 } 945 946 if (get_handle->mapping_num >= get_handle->mapping_size) 947 kidmap_get_extend(get_handle); 948 949 mapping = &get_handle->mapping[get_handle->mapping_num]; 950 mapping->flag = 0; 951 mapping->id1.idtype = IDMAP_SID; 952 mapping->id1.idmap_id_u.sid.prefix = (char *)sid_prefix; 953 mapping->id1.idmap_id_u.sid.rid = rid; 954 mapping->id2.idtype = IDMAP_GID; 955 956 result = &get_handle->result[get_handle->mapping_num]; 957 result->idtype = IDMAP_GID; 958 result->uid = NULL; 959 result->gid = gid; 960 result->pid = NULL; 961 result->sid_prefix = NULL; 962 result->rid = NULL; 963 result->is_user = NULL; 964 result->stat = stat; 965 966 get_handle->mapping_num++; 967 968 return (IDMAP_SUCCESS); 969 } 970 971 972 /* 973 * Given Domain SID and RID, get Posix ID 974 * 975 * Input: 976 * sid_prefix - Domain SID in canonical form 977 * rid - RID 978 * 979 * Output: 980 * stat - status of the get request 981 * is_user - user or group 982 * pid - POSIX UID if stat == IDMAP_SUCCESS and is_user == 1 983 * POSIX GID if stat == IDMAP_SUCCESS and is_user == 0 984 * 985 * Note: The output parameters will be set by idmap_get_mappings() 986 */ 987 idmap_stat 988 kidmap_batch_getpidbysid(idmap_get_handle_t *get_handle, const char *sid_prefix, 989 uint32_t rid, uid_t *pid, int *is_user, idmap_stat *stat) 990 { 991 idmap_mapping *mapping; 992 idmap_get_res *result; 993 994 if (get_handle == NULL || sid_prefix == NULL || pid == NULL || 995 is_user == NULL || stat == NULL) 996 return (IDMAP_ERR_ARG); 997 998 if (kidmap_cache_lookup_pidbysid(&get_handle->zs->cache, sid_prefix, 999 rid, pid, is_user) == IDMAP_SUCCESS) { 1000 *stat = IDMAP_SUCCESS; 1001 return (IDMAP_SUCCESS); 1002 } 1003 1004 1005 if (get_handle->mapping_num >= get_handle->mapping_size) 1006 kidmap_get_extend(get_handle); 1007 1008 mapping = &get_handle->mapping[get_handle->mapping_num]; 1009 mapping->flag = 0; 1010 mapping->id1.idtype = IDMAP_SID; 1011 mapping->id1.idmap_id_u.sid.prefix = (char *)sid_prefix; 1012 mapping->id1.idmap_id_u.sid.rid = rid; 1013 mapping->id2.idtype = IDMAP_POSIXID; 1014 1015 result = &get_handle->result[get_handle->mapping_num]; 1016 result->idtype = IDMAP_POSIXID; 1017 result->uid = NULL; 1018 result->gid = NULL; 1019 result->pid = pid; 1020 result->sid_prefix = NULL; 1021 result->rid = NULL; 1022 result->is_user = is_user; 1023 result->stat = stat; 1024 1025 get_handle->mapping_num++; 1026 1027 return (IDMAP_SUCCESS); 1028 } 1029 1030 1031 /* 1032 * Given UID, get SID and RID 1033 * 1034 * Input: 1035 * uid - POSIX UID 1036 * 1037 * Output: 1038 * stat - status of the get request 1039 * sid - SID in canonical form (if stat == IDMAP_SUCCESS) 1040 * rid - RID (if stat == IDMAP_SUCCESS) 1041 * 1042 * Note: The output parameters will be set by idmap_get_mappings() 1043 */ 1044 idmap_stat 1045 kidmap_batch_getsidbyuid(idmap_get_handle_t *get_handle, uid_t uid, 1046 const char **sid_prefix, uint32_t *rid, idmap_stat *stat) 1047 { 1048 idmap_mapping *mapping; 1049 idmap_get_res *result; 1050 1051 if (get_handle == NULL || sid_prefix == NULL || 1052 rid == NULL || stat == NULL) 1053 return (IDMAP_ERR_ARG); 1054 1055 if (kidmap_cache_lookup_sidbyuid(&get_handle->zs->cache, 1056 sid_prefix, rid, uid) == IDMAP_SUCCESS) { 1057 *stat = IDMAP_SUCCESS; 1058 return (IDMAP_SUCCESS); 1059 } 1060 1061 if (get_handle->mapping_num >= get_handle->mapping_size) 1062 kidmap_get_extend(get_handle); 1063 1064 mapping = &get_handle->mapping[get_handle->mapping_num]; 1065 mapping->flag = 0; 1066 mapping->id1.idtype = IDMAP_UID; 1067 mapping->id1.idmap_id_u.uid = uid; 1068 mapping->id2.idtype = IDMAP_SID; 1069 1070 result = &get_handle->result[get_handle->mapping_num]; 1071 result->idtype = IDMAP_SID; 1072 result->uid = NULL; 1073 result->gid = NULL; 1074 result->pid = NULL; 1075 result->sid_prefix = sid_prefix; 1076 result->rid = rid; 1077 result->is_user = NULL; 1078 result->stat = stat; 1079 1080 get_handle->mapping_num++; 1081 1082 return (IDMAP_SUCCESS); 1083 } 1084 1085 1086 /* 1087 * Given GID, get SID and RID 1088 * 1089 * Input: 1090 * gid - POSIX GID 1091 * 1092 * Output: 1093 * stat - status of the get request 1094 * sid - SID in canonical form (if stat == IDMAP_SUCCESS) 1095 * rid - RID (if stat == IDMAP_SUCCESS) 1096 * 1097 * Note: The output parameters will be set by idmap_get_mappings() 1098 */ 1099 idmap_stat 1100 kidmap_batch_getsidbygid(idmap_get_handle_t *get_handle, gid_t gid, 1101 const char **sid_prefix, uint32_t *rid, idmap_stat *stat) 1102 { 1103 idmap_mapping *mapping; 1104 idmap_get_res *result; 1105 1106 if (get_handle == NULL || sid_prefix == NULL || 1107 rid == NULL || stat == NULL) 1108 return (IDMAP_ERR_ARG); 1109 1110 if (kidmap_cache_lookup_sidbygid(&get_handle->zs->cache, 1111 sid_prefix, rid, gid) == IDMAP_SUCCESS) { 1112 *stat = IDMAP_SUCCESS; 1113 return (IDMAP_SUCCESS); 1114 } 1115 1116 if (get_handle->mapping_num >= get_handle->mapping_size) 1117 kidmap_get_extend(get_handle); 1118 1119 mapping = &get_handle->mapping[get_handle->mapping_num]; 1120 mapping->flag = 0; 1121 mapping->id1.idtype = IDMAP_GID; 1122 mapping->id1.idmap_id_u.gid = gid; 1123 mapping->id2.idtype = IDMAP_SID; 1124 1125 result = &get_handle->result[get_handle->mapping_num]; 1126 result->idtype = IDMAP_SID; 1127 result->uid = NULL; 1128 result->gid = NULL; 1129 result->pid = NULL; 1130 result->sid_prefix = sid_prefix; 1131 result->rid = rid; 1132 result->is_user = NULL; 1133 result->stat = stat; 1134 1135 get_handle->mapping_num++; 1136 1137 return (IDMAP_SUCCESS); 1138 } 1139 1140 1141 /* 1142 * Process the batched "get mapping" requests. The results (i.e. 1143 * status and identity) will be available in the data areas 1144 * provided by individual requests. 1145 * 1146 * If the door call fails the status IDMAP_ERR_NOMAPPING is 1147 * return and the UID or UID result is set to "nobody" 1148 */ 1149 1150 idmap_stat 1151 kidmap_get_mappings(idmap_get_handle_t *get_handle) 1152 { 1153 idmap_mapping_batch rpc_args; 1154 idmap_ids_res rpc_res; 1155 uint32_t op = IDMAP_GET_MAPPED_IDS; 1156 idmap_mapping *mapping; 1157 idmap_get_res *result; 1158 idmap_id *id; 1159 int status; 1160 int i; 1161 const char *sid_prefix; 1162 int is_user; 1163 idmap_cache_t *cache; 1164 1165 if (get_handle == NULL) 1166 return (IDMAP_ERR_ARG); 1167 1168 if (get_handle->mapping_num == 0) 1169 return (IDMAP_SUCCESS); 1170 cache = &get_handle->zs->cache; 1171 1172 bzero(&rpc_res, sizeof (idmap_ids_res)); 1173 1174 rpc_args.idmap_mapping_batch_len = get_handle->mapping_num; 1175 rpc_args.idmap_mapping_batch_val = get_handle->mapping; 1176 1177 if (kidmap_rpc_call(get_handle->zs, op, xdr_idmap_mapping_batch, 1178 (caddr_t)&rpc_args, xdr_idmap_ids_res, 1179 (caddr_t)&rpc_res) != 0) { 1180 /* Door call failed */ 1181 status = IDMAP_ERR_NOMAPPING; 1182 goto error; 1183 } 1184 1185 status = rpc_res.retcode; 1186 if (status != IDMAP_SUCCESS) { 1187 /* RPC returned idmap error code */ 1188 xdr_free(xdr_idmap_ids_res, (char *)&rpc_res); 1189 goto error; 1190 } 1191 1192 for (i = 0; i < get_handle->mapping_num; i++) { 1193 mapping = &get_handle->mapping[i]; 1194 result = &get_handle->result[i]; 1195 1196 if (i >= rpc_res.ids.ids_len) { 1197 *result->stat = IDMAP_ERR_NOMAPPING; 1198 if (result->uid) 1199 *result->uid = UID_NOBODY; 1200 if (result->gid) 1201 *result->gid = GID_NOBODY; 1202 if (result->pid) 1203 *result->pid = UID_NOBODY; 1204 if (result->is_user) 1205 *result->is_user = 1; 1206 if (result->sid_prefix) 1207 *result->sid_prefix = NULL; 1208 if (result->rid) 1209 *result->rid = 0; 1210 continue; 1211 } 1212 1213 *result->stat = rpc_res.ids.ids_val[i].retcode; 1214 1215 id = &rpc_res.ids.ids_val[i].id; 1216 switch (id->idtype) { 1217 case IDMAP_UID: 1218 if (result->uid) 1219 *result->uid = id->idmap_id_u.uid; 1220 if (result->pid) 1221 *result->pid = id->idmap_id_u.uid; 1222 if (result->is_user) 1223 *result->is_user = 1; 1224 sid_prefix = kidmap_find_sid_prefix( 1225 mapping->id1.idmap_id_u.sid.prefix); 1226 if (*result->stat == IDMAP_SUCCESS && result->uid) 1227 kidmap_cache_add_uidbysid( 1228 cache, sid_prefix, 1229 mapping->id1.idmap_id_u.sid.rid, 1230 id->idmap_id_u.uid); 1231 else if (*result->stat == IDMAP_SUCCESS && result->pid) 1232 kidmap_cache_add_pidbysid( 1233 cache, sid_prefix, 1234 mapping->id1.idmap_id_u.sid.rid, 1235 id->idmap_id_u.uid, 1); 1236 break; 1237 1238 case IDMAP_GID: 1239 if (result->gid) 1240 *result->gid = id->idmap_id_u.gid; 1241 if (result->pid) 1242 *result->pid = id->idmap_id_u.gid; 1243 if (result->is_user) 1244 *result->is_user = 0; 1245 sid_prefix = kidmap_find_sid_prefix( 1246 mapping->id1.idmap_id_u.sid.prefix); 1247 if (*result->stat == IDMAP_SUCCESS && result->gid) 1248 kidmap_cache_add_gidbysid( 1249 cache, sid_prefix, 1250 mapping->id1.idmap_id_u.sid.rid, 1251 id->idmap_id_u.gid); 1252 else if (*result->stat == IDMAP_SUCCESS && result->pid) 1253 kidmap_cache_add_pidbysid( 1254 cache, sid_prefix, 1255 mapping->id1.idmap_id_u.sid.rid, 1256 id->idmap_id_u.gid, 0); 1257 break; 1258 1259 case IDMAP_SID: 1260 case IDMAP_USID: 1261 case IDMAP_GSID: 1262 sid_prefix = kidmap_find_sid_prefix( 1263 id->idmap_id_u.sid.prefix); 1264 if (result->sid_prefix && result->rid) { 1265 *result->sid_prefix = sid_prefix; 1266 *result->rid = id->idmap_id_u.sid.rid; 1267 } 1268 if (*result->stat == IDMAP_SUCCESS && 1269 mapping->id1.idtype == IDMAP_UID) 1270 kidmap_cache_add_sidbyuid( 1271 cache, sid_prefix, 1272 id->idmap_id_u.sid.rid, 1273 mapping->id1.idmap_id_u.uid); 1274 else if (*result->stat == IDMAP_SUCCESS && 1275 mapping->id1.idtype == IDMAP_GID) 1276 kidmap_cache_add_sidbygid( 1277 cache, sid_prefix, 1278 id->idmap_id_u.sid.rid, 1279 mapping->id1.idmap_id_u.gid); 1280 break; 1281 1282 default: 1283 *result->stat = IDMAP_ERR_NORESULT; 1284 if (result->uid) 1285 *result->uid = UID_NOBODY; 1286 if (result->gid) 1287 *result->gid = GID_NOBODY; 1288 if (result->pid) 1289 *result->pid = UID_NOBODY; 1290 if (result->is_user) 1291 *result->is_user = 1; 1292 if (result->sid_prefix) 1293 *result->sid_prefix = NULL; 1294 if (result->rid) 1295 *result->rid = 0; 1296 break; 1297 } 1298 } 1299 xdr_free(xdr_idmap_ids_res, (char *)&rpc_res); 1300 1301 /* Reset get_handle for new resquests */ 1302 get_handle->mapping_num = 0; 1303 return (status); 1304 1305 error: 1306 for (i = 0; i < get_handle->mapping_num; i++) { 1307 result = &get_handle->result[i]; 1308 1309 *result->stat = status; 1310 if (result->uid) 1311 *result->uid = UID_NOBODY; 1312 if (result->gid) 1313 *result->gid = GID_NOBODY; 1314 if (result->pid) 1315 *result->pid = UID_NOBODY; 1316 if (result->is_user) 1317 *result->is_user = 1; 1318 if (result->sid_prefix) 1319 *result->sid_prefix = NULL; 1320 if (result->rid) 1321 *result->rid = 0; 1322 } 1323 1324 /* Reset get_handle for new resquests */ 1325 get_handle->mapping_num = 0; 1326 return (status); 1327 } 1328 1329 1330 /* 1331 * Destroy the "get mapping" handle 1332 */ 1333 void 1334 kidmap_get_destroy(idmap_get_handle_t *get_handle) 1335 { 1336 if (get_handle == NULL) 1337 return; 1338 1339 kmem_free(get_handle->mapping, 1340 (sizeof (idmap_mapping)) * get_handle->mapping_size); 1341 get_handle->mapping = NULL; 1342 1343 kmem_free(get_handle->result, 1344 (sizeof (idmap_get_res)) * get_handle->mapping_size); 1345 get_handle->result = NULL; 1346 1347 kmem_free(get_handle, sizeof (idmap_get_handle_t)); 1348 } 1349 1350 1351 static int 1352 kidmap_rpc_call(idmap_zone_specific_t *zs, uint32_t op, xdrproc_t xdr_args, 1353 caddr_t args, xdrproc_t xdr_res, caddr_t res) 1354 { 1355 XDR xdr_ctx; 1356 struct rpc_msg reply_msg; 1357 char *inbuf_ptr = NULL; 1358 size_t inbuf_size = 4096; 1359 char *outbuf_ptr = NULL; 1360 size_t outbuf_size = 4096; 1361 size_t size; 1362 int status = 0; 1363 door_arg_t params; 1364 int retry = 0; 1365 struct rpc_msg call_msg; 1366 1367 params.rbuf = NULL; 1368 params.rsize = 0; 1369 1370 retry: 1371 inbuf_ptr = kmem_alloc(inbuf_size, KM_SLEEP); 1372 outbuf_ptr = kmem_alloc(outbuf_size, KM_SLEEP); 1373 1374 xdrmem_create(&xdr_ctx, inbuf_ptr, inbuf_size, XDR_ENCODE); 1375 1376 call_msg.rm_call.cb_prog = IDMAP_PROG; 1377 call_msg.rm_call.cb_vers = IDMAP_V1; 1378 call_msg.rm_xid = atomic_inc_32_nv(&zs->message_id); 1379 1380 if (!xdr_callhdr(&xdr_ctx, &call_msg)) { 1381 #ifdef DEBUG 1382 zcmn_err(zs->zone_id, CE_WARN, 1383 "idmap: xdr encoding header error"); 1384 #endif /* DEBUG */ 1385 status = -1; 1386 goto exit; 1387 } 1388 1389 if (!xdr_uint32(&xdr_ctx, &op) || 1390 /* Auth none */ 1391 !xdr_opaque_auth(&xdr_ctx, &_null_auth) || 1392 !xdr_opaque_auth(&xdr_ctx, &_null_auth) || 1393 /* RPC args */ 1394 !xdr_args(&xdr_ctx, args)) { 1395 #ifdef DEBUG 1396 zcmn_err(zs->zone_id, CE_WARN, "idmap: xdr encoding error"); 1397 #endif /* DEBUG */ 1398 if (retry > 2) { 1399 status = -1; 1400 goto exit; 1401 } 1402 retry++; 1403 if (inbuf_ptr) { 1404 kmem_free(inbuf_ptr, inbuf_size); 1405 inbuf_ptr = NULL; 1406 } 1407 if (outbuf_ptr) { 1408 kmem_free(outbuf_ptr, outbuf_size); 1409 outbuf_ptr = NULL; 1410 } 1411 if ((size = xdr_sizeof(xdr_args, args)) == 0) { 1412 #ifdef DEBUG 1413 zcmn_err(zs->zone_id, CE_WARN, 1414 "idmap: xdr_sizeof error"); 1415 #endif /* DEBUG */ 1416 status = -1; 1417 goto exit; 1418 } 1419 inbuf_size = size + 1024; 1420 outbuf_size = size + 1024; 1421 goto retry; 1422 } 1423 1424 params.data_ptr = inbuf_ptr; 1425 params.data_size = XDR_GETPOS(&xdr_ctx); 1426 params.desc_ptr = NULL; 1427 params.desc_num = 0; 1428 params.rbuf = outbuf_ptr; 1429 params.rsize = outbuf_size; 1430 1431 if (kidmap_call_door(zs, ¶ms) != 0) { 1432 status = -1; 1433 goto exit; 1434 } 1435 1436 reply_msg.acpted_rply.ar_verf = _null_auth; 1437 reply_msg.acpted_rply.ar_results.where = res; 1438 reply_msg.acpted_rply.ar_results.proc = xdr_res; 1439 xdrmem_create(&xdr_ctx, params.data_ptr, params.data_size, XDR_DECODE); 1440 if (xdr_replymsg(&xdr_ctx, &reply_msg)) { 1441 if (reply_msg.rm_reply.rp_stat != MSG_ACCEPTED || 1442 reply_msg.rm_reply.rp_acpt.ar_stat != SUCCESS) { 1443 status = -1; 1444 goto exit; 1445 } 1446 } else { 1447 #ifdef DEBUG 1448 zcmn_err(zs->zone_id, CE_WARN, 1449 "idmap: xdr decoding reply message error"); 1450 #endif /* DEBUG */ 1451 status = -1; 1452 } 1453 1454 exit: 1455 if (outbuf_ptr != params.rbuf && params.rbuf != NULL) 1456 kmem_free(params.rbuf, params.rsize); 1457 if (inbuf_ptr) 1458 kmem_free(inbuf_ptr, inbuf_size); 1459 if (outbuf_ptr) 1460 kmem_free(outbuf_ptr, outbuf_size); 1461 return (status); 1462 } 1463