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_sid2uid(&zs->cache, 454 new_sid_prefix, rid, *uid, 455 results.ids.ids_val[0].direction); 456 } 457 } else { 458 status = IDMAP_ERR_NOMAPPING; 459 *uid = UID_NOBODY; 460 } 461 xdr_free(xdr_idmap_ids_res, (char *)&results); 462 } else { 463 /* Door call failed */ 464 status = IDMAP_ERR_NOMAPPING; 465 *uid = UID_NOBODY; 466 } 467 return (status); 468 } 469 470 471 /* 472 * Given Domain SID and RID, get GID 473 * 474 * Input: 475 * sid_prefix - Domain SID in canonical form 476 * rid - RID 477 * 478 * Output: 479 * gid - POSIX UID if return == IDMAP_SUCCESS 480 * 481 * Return: 482 * Success return IDMAP_SUCCESS else IDMAP error 483 */ 484 idmap_stat 485 kidmap_getgidbysid(zone_t *zone, const char *sid_prefix, uint32_t rid, 486 gid_t *gid) 487 { 488 idmap_zone_specific_t *zs; 489 idmap_mapping_batch args; 490 idmap_mapping mapping; 491 idmap_ids_res results; 492 uint32_t op = IDMAP_GET_MAPPED_IDS; 493 const char *new_sid_prefix; 494 idmap_stat status; 495 496 if (sid_prefix == NULL || gid == NULL) 497 return (IDMAP_ERR_ARG); 498 499 zs = idmap_get_zone_specific(zone); 500 501 if (kidmap_cache_lookup_gidbysid(&zs->cache, sid_prefix, rid, gid) 502 == IDMAP_SUCCESS) 503 return (IDMAP_SUCCESS); 504 505 bzero(&mapping, sizeof (idmap_mapping)); 506 mapping.id1.idtype = IDMAP_SID; 507 mapping.id1.idmap_id_u.sid.prefix = (char *)sid_prefix; 508 mapping.id1.idmap_id_u.sid.rid = rid; 509 mapping.id2.idtype = IDMAP_GID; 510 511 bzero(&results, sizeof (idmap_ids_res)); 512 513 args.idmap_mapping_batch_len = 1; 514 args.idmap_mapping_batch_val = &mapping; 515 516 if (kidmap_rpc_call(zs, op, xdr_idmap_mapping_batch, 517 (caddr_t)&args, xdr_idmap_ids_res, 518 (caddr_t)&results) == 0) { 519 /* Door call succeded */ 520 if (results.retcode != IDMAP_SUCCESS) { 521 status = results.retcode; 522 *gid = GID_NOBODY; 523 } else if (results.ids.ids_len >= 1 && 524 results.ids.ids_val[0].id.idtype == IDMAP_GID) { 525 status = results.ids.ids_val[0].retcode; 526 *gid = results.ids.ids_val[0].id.idmap_id_u.gid; 527 if (status == IDMAP_SUCCESS) { 528 new_sid_prefix = kidmap_find_sid_prefix( 529 sid_prefix); 530 kidmap_cache_add_sid2gid(&zs->cache, 531 new_sid_prefix, rid, *gid, 532 results.ids.ids_val[0].direction); 533 } 534 } else { 535 status = IDMAP_ERR_NOMAPPING; 536 *gid = GID_NOBODY; 537 } 538 xdr_free(xdr_idmap_ids_res, (char *)&results); 539 } else { 540 /* Door call failed */ 541 status = IDMAP_ERR_NOMAPPING; 542 *gid = GID_NOBODY; 543 } 544 return (status); 545 } 546 547 /* 548 * Given Domain SID and RID, get Posix ID 549 * 550 * Input: 551 * sid_prefix - Domain SID in canonical form 552 * rid - RID 553 * 554 * Output: 555 * pid - POSIX ID if return == IDMAP_SUCCESS 556 * is_user - 1 == UID, 0 == GID if return == IDMAP_SUCCESS 557 * 558 * Return: 559 * Success return IDMAP_SUCCESS else IDMAP error 560 */ 561 idmap_stat 562 kidmap_getpidbysid(zone_t *zone, const char *sid_prefix, uint32_t rid, 563 uid_t *pid, int *is_user) 564 { 565 idmap_zone_specific_t *zs; 566 idmap_mapping_batch args; 567 idmap_mapping mapping; 568 idmap_ids_res results; 569 uint32_t op = IDMAP_GET_MAPPED_IDS; 570 const char *new_sid_prefix; 571 idmap_stat status; 572 573 if (sid_prefix == NULL || pid == NULL || is_user == NULL) 574 return (IDMAP_ERR_ARG); 575 576 zs = idmap_get_zone_specific(zone); 577 578 if (kidmap_cache_lookup_pidbysid(&zs->cache, sid_prefix, rid, pid, 579 is_user) == IDMAP_SUCCESS) 580 return (IDMAP_SUCCESS); 581 582 bzero(&mapping, sizeof (idmap_mapping)); 583 mapping.id1.idtype = IDMAP_SID; 584 mapping.id1.idmap_id_u.sid.prefix = (char *)sid_prefix; 585 mapping.id1.idmap_id_u.sid.rid = rid; 586 mapping.id2.idtype = IDMAP_POSIXID; 587 588 bzero(&results, sizeof (idmap_ids_res)); 589 590 args.idmap_mapping_batch_len = 1; 591 args.idmap_mapping_batch_val = &mapping; 592 593 if (kidmap_rpc_call(zs, op, xdr_idmap_mapping_batch, 594 (caddr_t)&args, xdr_idmap_ids_res, 595 (caddr_t)&results) == 0) { 596 /* Door call succeded */ 597 if (results.retcode != IDMAP_SUCCESS) { 598 status = results.retcode; 599 *is_user = 1; 600 *pid = UID_NOBODY; 601 } else if (results.ids.ids_len >= 1 && ( 602 results.ids.ids_val[0].id.idtype == IDMAP_UID || 603 results.ids.ids_val[0].id.idtype == IDMAP_GID)) { 604 status = results.ids.ids_val[0].retcode; 605 if (results.ids.ids_val[0].id.idtype == IDMAP_UID) { 606 *is_user = 1; 607 *pid = results.ids.ids_val[0].id.idmap_id_u.uid; 608 } else { 609 *is_user = 0; 610 *pid = results.ids.ids_val[0].id.idmap_id_u.gid; 611 } 612 if (status == IDMAP_SUCCESS) { 613 new_sid_prefix = kidmap_find_sid_prefix( 614 sid_prefix); 615 kidmap_cache_add_sid2pid(&zs->cache, 616 new_sid_prefix, rid, *pid, 617 *is_user, 618 results.ids.ids_val[0].direction); 619 } 620 } else { 621 status = IDMAP_ERR_NOMAPPING; 622 *is_user = 1; 623 *pid = UID_NOBODY; 624 } 625 xdr_free(xdr_idmap_ids_res, (char *)&results); 626 } else { 627 /* Door call failed */ 628 status = IDMAP_ERR_NOMAPPING; 629 *is_user = 1; 630 *pid = UID_NOBODY; 631 } 632 return (status); 633 } 634 635 636 /* 637 * Given UID, get Domain SID and RID 638 * 639 * Input: 640 * uid - Posix UID 641 * 642 * Output: 643 * sid_prefix - Domain SID if return == IDMAP_SUCCESS 644 * rid - RID if return == IDMAP_SUCCESS 645 * 646 * Return: 647 * Success return IDMAP_SUCCESS else IDMAP error 648 */ 649 idmap_stat 650 kidmap_getsidbyuid(zone_t *zone, uid_t uid, const char **sid_prefix, 651 uint32_t *rid) 652 { 653 idmap_zone_specific_t *zs; 654 idmap_mapping_batch args; 655 idmap_mapping mapping; 656 idmap_ids_res results; 657 uint32_t op = IDMAP_GET_MAPPED_IDS; 658 idmap_stat status; 659 time_t entry_ttl; 660 idmap_id *id; 661 662 if (sid_prefix == NULL || rid == NULL) 663 return (IDMAP_ERR_ARG); 664 665 zs = idmap_get_zone_specific(zone); 666 667 if (kidmap_cache_lookup_sidbyuid(&zs->cache, sid_prefix, rid, uid) 668 == IDMAP_SUCCESS) { 669 return (IDMAP_SUCCESS); 670 } 671 672 bzero(&mapping, sizeof (idmap_mapping)); 673 mapping.id1.idtype = IDMAP_UID; 674 mapping.id1.idmap_id_u.uid = uid; 675 mapping.id2.idtype = IDMAP_SID; 676 677 bzero(&results, sizeof (idmap_ids_res)); 678 679 args.idmap_mapping_batch_len = 1; 680 args.idmap_mapping_batch_val = &mapping; 681 682 if (kidmap_rpc_call(zs, op, xdr_idmap_mapping_batch, 683 (caddr_t)&args, xdr_idmap_ids_res, 684 (caddr_t)&results) == 0) { 685 /* Door call succeded */ 686 if (results.retcode != IDMAP_SUCCESS) { 687 status = results.retcode; 688 *rid = 0; 689 *sid_prefix = NULL; 690 } else if (results.ids.ids_len >= 1 && 691 (results.ids.ids_val[0].id.idtype == IDMAP_SID || 692 results.ids.ids_val[0].id.idtype == IDMAP_USID || 693 results.ids.ids_val[0].id.idtype == IDMAP_GSID)) { 694 status = results.ids.ids_val[0].retcode; 695 id = &results.ids.ids_val[0].id; 696 *sid_prefix = kidmap_find_sid_prefix( 697 id->idmap_id_u.sid.prefix); 698 *rid = id->idmap_id_u.sid.rid; 699 if (status == IDMAP_SUCCESS) { 700 kidmap_cache_add_sid2uid(&zs->cache, 701 *sid_prefix, *rid, uid, 702 results.ids.ids_val[0].direction); 703 } 704 } else { 705 status = IDMAP_ERR_NOMAPPING; 706 *rid = 0; 707 *sid_prefix = NULL; 708 } 709 xdr_free(xdr_idmap_ids_res, (char *)&results); 710 } else { 711 /* Door call failed */ 712 status = IDMAP_ERR_NOMAPPING; 713 *rid = 0; 714 *sid_prefix = NULL; 715 } 716 return (status); 717 } 718 719 720 /* 721 * Given GID, get Domain SID and RID 722 * 723 * Input: 724 * gid - Posix GID 725 * 726 * Output: 727 * sid_prefix - Domain SID if return == IDMAP_SUCCESS 728 * rid - RID if return == IDMAP_SUCCESS 729 * 730 * Return: 731 * Success return IDMAP_SUCCESS else IDMAP error 732 */ 733 idmap_stat 734 kidmap_getsidbygid(zone_t *zone, gid_t gid, const char **sid_prefix, 735 uint32_t *rid) 736 { 737 idmap_zone_specific_t *zs; 738 idmap_mapping_batch args; 739 idmap_mapping mapping; 740 idmap_ids_res results; 741 uint32_t op = IDMAP_GET_MAPPED_IDS; 742 idmap_stat status; 743 idmap_id *id; 744 745 if (sid_prefix == NULL || rid == NULL) 746 return (IDMAP_ERR_ARG); 747 748 zs = idmap_get_zone_specific(zone); 749 750 if (kidmap_cache_lookup_sidbygid(&zs->cache, sid_prefix, rid, gid) 751 == IDMAP_SUCCESS) { 752 return (IDMAP_SUCCESS); 753 } 754 755 bzero(&mapping, sizeof (idmap_mapping)); 756 mapping.id1.idtype = IDMAP_GID; 757 mapping.id1.idmap_id_u.uid = gid; 758 mapping.id2.idtype = IDMAP_SID; 759 760 bzero(&results, sizeof (idmap_ids_res)); 761 762 args.idmap_mapping_batch_len = 1; 763 args.idmap_mapping_batch_val = &mapping; 764 765 if (kidmap_rpc_call(zs, op, xdr_idmap_mapping_batch, 766 (caddr_t)&args, xdr_idmap_ids_res, 767 (caddr_t)&results) == 0) { 768 /* Door call succeded */ 769 if (results.retcode != IDMAP_SUCCESS) { 770 status = results.retcode; 771 *rid = 0; 772 *sid_prefix = NULL; 773 } else if (results.ids.ids_len >= 1 && 774 (results.ids.ids_val[0].id.idtype == IDMAP_SID || 775 results.ids.ids_val[0].id.idtype == IDMAP_USID || 776 results.ids.ids_val[0].id.idtype == IDMAP_GSID)) { 777 status = results.ids.ids_val[0].retcode; 778 id = &results.ids.ids_val[0].id; 779 *sid_prefix = kidmap_find_sid_prefix( 780 id->idmap_id_u.sid.prefix); 781 *rid = id->idmap_id_u.sid.rid; 782 if (status == IDMAP_SUCCESS) { 783 kidmap_cache_add_sid2gid(&zs->cache, 784 *sid_prefix, *rid, gid, 785 results.ids.ids_val[0].direction); 786 } 787 } else { 788 status = IDMAP_ERR_NOMAPPING; 789 *rid = 0; 790 *sid_prefix = NULL; 791 } 792 xdr_free(xdr_idmap_ids_res, (char *)&results); 793 } else { 794 /* Door call failed */ 795 status = IDMAP_ERR_NOMAPPING; 796 *rid = 0; 797 *sid_prefix = NULL; 798 } 799 return (status); 800 } 801 802 /* 803 * Create handle to get SID to UID/GID mapping entries 804 * 805 * Input: 806 * none 807 * Return: 808 * get_handle 809 * 810 */ 811 idmap_get_handle_t * 812 kidmap_get_create(zone_t *zone) 813 { 814 idmap_zone_specific_t *zs; 815 idmap_get_handle_t *handle; 816 #define INIT_MAPPING_SIZE 32 817 818 zs = idmap_get_zone_specific(zone); 819 820 handle = kmem_zalloc(sizeof (idmap_get_handle_t), KM_SLEEP); 821 822 handle->mapping = kmem_zalloc((sizeof (idmap_mapping)) * 823 INIT_MAPPING_SIZE, KM_SLEEP); 824 825 handle->result = kmem_zalloc((sizeof (idmap_get_res)) * 826 INIT_MAPPING_SIZE, KM_SLEEP); 827 handle->mapping_size = INIT_MAPPING_SIZE; 828 handle->zs = zs; 829 830 return (handle); 831 } 832 833 /* 834 * Internal routine to extend a "get_handle" 835 */ 836 static void 837 kidmap_get_extend(idmap_get_handle_t *get_handle) 838 { 839 idmap_mapping *mapping; 840 idmap_get_res *result; 841 int new_size = get_handle->mapping_size + INIT_MAPPING_SIZE; 842 843 mapping = kmem_zalloc((sizeof (idmap_mapping)) * 844 new_size, KM_SLEEP); 845 (void) memcpy(mapping, get_handle->mapping, 846 (sizeof (idmap_mapping)) * get_handle->mapping_size); 847 848 result = kmem_zalloc((sizeof (idmap_get_res)) * 849 new_size, KM_SLEEP); 850 (void) memcpy(result, get_handle->result, 851 (sizeof (idmap_get_res)) * get_handle->mapping_size); 852 853 kmem_free(get_handle->mapping, 854 (sizeof (idmap_mapping)) * get_handle->mapping_size); 855 get_handle->mapping = mapping; 856 857 kmem_free(get_handle->result, 858 (sizeof (idmap_get_res)) * get_handle->mapping_size); 859 get_handle->result = result; 860 861 get_handle->mapping_size = new_size; 862 } 863 864 865 /* 866 * Given Domain SID and RID, get UID 867 * 868 * Input: 869 * sid_prefix - Domain SID in canonical form 870 * rid - RID 871 * 872 * Output: 873 * stat - status of the get request 874 * uid - POSIX UID if stat == IDMAP_SUCCESS 875 * 876 * Note: The output parameters will be set by idmap_get_mappings() 877 */ 878 idmap_stat 879 kidmap_batch_getuidbysid(idmap_get_handle_t *get_handle, const char *sid_prefix, 880 uint32_t rid, uid_t *uid, idmap_stat *stat) 881 { 882 idmap_mapping *mapping; 883 idmap_get_res *result; 884 885 if (get_handle == NULL || sid_prefix == NULL || 886 uid == NULL || stat == NULL) 887 return (IDMAP_ERR_ARG); 888 889 if (kidmap_cache_lookup_uidbysid(&get_handle->zs->cache, sid_prefix, 890 rid, uid) == IDMAP_SUCCESS) { 891 *stat = IDMAP_SUCCESS; 892 return (IDMAP_SUCCESS); 893 } 894 895 if (get_handle->mapping_num >= get_handle->mapping_size) 896 kidmap_get_extend(get_handle); 897 898 mapping = &get_handle->mapping[get_handle->mapping_num]; 899 mapping->flag = 0; 900 mapping->id1.idtype = IDMAP_SID; 901 mapping->id1.idmap_id_u.sid.prefix = (char *)sid_prefix; 902 mapping->id1.idmap_id_u.sid.rid = rid; 903 mapping->id2.idtype = IDMAP_UID; 904 905 result = &get_handle->result[get_handle->mapping_num]; 906 result->idtype = IDMAP_UID; 907 result->uid = uid; 908 result->gid = NULL; 909 result->pid = NULL; 910 result->sid_prefix = NULL; 911 result->rid = NULL; 912 result->is_user = NULL; 913 result->stat = stat; 914 915 get_handle->mapping_num++; 916 917 return (IDMAP_SUCCESS); 918 } 919 920 921 /* 922 * Given Domain SID and RID, get GID 923 * 924 * Input: 925 * sid_prefix - Domain SID in canonical form 926 * rid - RID 927 * 928 * Output: 929 * stat - status of the get request 930 * gid - POSIX GID if stat == IDMAP_SUCCESS 931 * 932 * Note: The output parameters will be set by idmap_get_mappings() 933 */ 934 idmap_stat 935 kidmap_batch_getgidbysid(idmap_get_handle_t *get_handle, const char *sid_prefix, 936 uint32_t rid, uid_t *gid, idmap_stat *stat) 937 { 938 idmap_mapping *mapping; 939 idmap_get_res *result; 940 941 if (get_handle == NULL || sid_prefix == NULL || 942 gid == NULL || stat == NULL) 943 return (IDMAP_ERR_ARG); 944 945 if (kidmap_cache_lookup_gidbysid(&get_handle->zs->cache, sid_prefix, 946 rid, gid) == IDMAP_SUCCESS) { 947 *stat = IDMAP_SUCCESS; 948 return (IDMAP_SUCCESS); 949 } 950 951 if (get_handle->mapping_num >= get_handle->mapping_size) 952 kidmap_get_extend(get_handle); 953 954 mapping = &get_handle->mapping[get_handle->mapping_num]; 955 mapping->flag = 0; 956 mapping->id1.idtype = IDMAP_SID; 957 mapping->id1.idmap_id_u.sid.prefix = (char *)sid_prefix; 958 mapping->id1.idmap_id_u.sid.rid = rid; 959 mapping->id2.idtype = IDMAP_GID; 960 961 result = &get_handle->result[get_handle->mapping_num]; 962 result->idtype = IDMAP_GID; 963 result->uid = NULL; 964 result->gid = gid; 965 result->pid = NULL; 966 result->sid_prefix = NULL; 967 result->rid = NULL; 968 result->is_user = NULL; 969 result->stat = stat; 970 971 get_handle->mapping_num++; 972 973 return (IDMAP_SUCCESS); 974 } 975 976 977 /* 978 * Given Domain SID and RID, get Posix ID 979 * 980 * Input: 981 * sid_prefix - Domain SID in canonical form 982 * rid - RID 983 * 984 * Output: 985 * stat - status of the get request 986 * is_user - user or group 987 * pid - POSIX UID if stat == IDMAP_SUCCESS and is_user == 1 988 * POSIX GID if stat == IDMAP_SUCCESS and is_user == 0 989 * 990 * Note: The output parameters will be set by idmap_get_mappings() 991 */ 992 idmap_stat 993 kidmap_batch_getpidbysid(idmap_get_handle_t *get_handle, const char *sid_prefix, 994 uint32_t rid, uid_t *pid, int *is_user, idmap_stat *stat) 995 { 996 idmap_mapping *mapping; 997 idmap_get_res *result; 998 999 if (get_handle == NULL || sid_prefix == NULL || pid == NULL || 1000 is_user == NULL || stat == NULL) 1001 return (IDMAP_ERR_ARG); 1002 1003 if (kidmap_cache_lookup_pidbysid(&get_handle->zs->cache, sid_prefix, 1004 rid, pid, is_user) == IDMAP_SUCCESS) { 1005 *stat = IDMAP_SUCCESS; 1006 return (IDMAP_SUCCESS); 1007 } 1008 1009 1010 if (get_handle->mapping_num >= get_handle->mapping_size) 1011 kidmap_get_extend(get_handle); 1012 1013 mapping = &get_handle->mapping[get_handle->mapping_num]; 1014 mapping->flag = 0; 1015 mapping->id1.idtype = IDMAP_SID; 1016 mapping->id1.idmap_id_u.sid.prefix = (char *)sid_prefix; 1017 mapping->id1.idmap_id_u.sid.rid = rid; 1018 mapping->id2.idtype = IDMAP_POSIXID; 1019 1020 result = &get_handle->result[get_handle->mapping_num]; 1021 result->idtype = IDMAP_POSIXID; 1022 result->uid = NULL; 1023 result->gid = NULL; 1024 result->pid = pid; 1025 result->sid_prefix = NULL; 1026 result->rid = NULL; 1027 result->is_user = is_user; 1028 result->stat = stat; 1029 1030 get_handle->mapping_num++; 1031 1032 return (IDMAP_SUCCESS); 1033 } 1034 1035 1036 /* 1037 * Given UID, get SID and RID 1038 * 1039 * Input: 1040 * uid - POSIX UID 1041 * 1042 * Output: 1043 * stat - status of the get request 1044 * sid - SID in canonical form (if stat == IDMAP_SUCCESS) 1045 * rid - RID (if stat == IDMAP_SUCCESS) 1046 * 1047 * Note: The output parameters will be set by idmap_get_mappings() 1048 */ 1049 idmap_stat 1050 kidmap_batch_getsidbyuid(idmap_get_handle_t *get_handle, uid_t uid, 1051 const char **sid_prefix, uint32_t *rid, idmap_stat *stat) 1052 { 1053 idmap_mapping *mapping; 1054 idmap_get_res *result; 1055 1056 if (get_handle == NULL || sid_prefix == NULL || 1057 rid == NULL || stat == NULL) 1058 return (IDMAP_ERR_ARG); 1059 1060 if (kidmap_cache_lookup_sidbyuid(&get_handle->zs->cache, 1061 sid_prefix, rid, uid) == IDMAP_SUCCESS) { 1062 *stat = IDMAP_SUCCESS; 1063 return (IDMAP_SUCCESS); 1064 } 1065 1066 if (get_handle->mapping_num >= get_handle->mapping_size) 1067 kidmap_get_extend(get_handle); 1068 1069 mapping = &get_handle->mapping[get_handle->mapping_num]; 1070 mapping->flag = 0; 1071 mapping->id1.idtype = IDMAP_UID; 1072 mapping->id1.idmap_id_u.uid = uid; 1073 mapping->id2.idtype = IDMAP_SID; 1074 1075 result = &get_handle->result[get_handle->mapping_num]; 1076 result->idtype = IDMAP_SID; 1077 result->uid = NULL; 1078 result->gid = NULL; 1079 result->pid = NULL; 1080 result->sid_prefix = sid_prefix; 1081 result->rid = rid; 1082 result->is_user = NULL; 1083 result->stat = stat; 1084 1085 get_handle->mapping_num++; 1086 1087 return (IDMAP_SUCCESS); 1088 } 1089 1090 1091 /* 1092 * Given GID, get SID and RID 1093 * 1094 * Input: 1095 * gid - POSIX GID 1096 * 1097 * Output: 1098 * stat - status of the get request 1099 * sid - SID in canonical form (if stat == IDMAP_SUCCESS) 1100 * rid - RID (if stat == IDMAP_SUCCESS) 1101 * 1102 * Note: The output parameters will be set by idmap_get_mappings() 1103 */ 1104 idmap_stat 1105 kidmap_batch_getsidbygid(idmap_get_handle_t *get_handle, gid_t gid, 1106 const char **sid_prefix, uint32_t *rid, idmap_stat *stat) 1107 { 1108 idmap_mapping *mapping; 1109 idmap_get_res *result; 1110 1111 if (get_handle == NULL || sid_prefix == NULL || 1112 rid == NULL || stat == NULL) 1113 return (IDMAP_ERR_ARG); 1114 1115 if (kidmap_cache_lookup_sidbygid(&get_handle->zs->cache, 1116 sid_prefix, rid, gid) == IDMAP_SUCCESS) { 1117 *stat = IDMAP_SUCCESS; 1118 return (IDMAP_SUCCESS); 1119 } 1120 1121 if (get_handle->mapping_num >= get_handle->mapping_size) 1122 kidmap_get_extend(get_handle); 1123 1124 mapping = &get_handle->mapping[get_handle->mapping_num]; 1125 mapping->flag = 0; 1126 mapping->id1.idtype = IDMAP_GID; 1127 mapping->id1.idmap_id_u.gid = gid; 1128 mapping->id2.idtype = IDMAP_SID; 1129 1130 result = &get_handle->result[get_handle->mapping_num]; 1131 result->idtype = IDMAP_SID; 1132 result->uid = NULL; 1133 result->gid = NULL; 1134 result->pid = NULL; 1135 result->sid_prefix = sid_prefix; 1136 result->rid = rid; 1137 result->is_user = NULL; 1138 result->stat = stat; 1139 1140 get_handle->mapping_num++; 1141 1142 return (IDMAP_SUCCESS); 1143 } 1144 1145 1146 /* 1147 * Process the batched "get mapping" requests. The results (i.e. 1148 * status and identity) will be available in the data areas 1149 * provided by individual requests. 1150 * 1151 * If the door call fails the status IDMAP_ERR_NOMAPPING is 1152 * return and the UID or UID result is set to "nobody" 1153 */ 1154 1155 idmap_stat 1156 kidmap_get_mappings(idmap_get_handle_t *get_handle) 1157 { 1158 idmap_mapping_batch rpc_args; 1159 idmap_ids_res rpc_res; 1160 uint32_t op = IDMAP_GET_MAPPED_IDS; 1161 idmap_mapping *request; 1162 idmap_get_res *result; 1163 idmap_id *id; 1164 int status; 1165 int i; 1166 const char *sid_prefix; 1167 int is_user; 1168 idmap_cache_t *cache; 1169 int direction; 1170 1171 if (get_handle == NULL) 1172 return (IDMAP_ERR_ARG); 1173 1174 if (get_handle->mapping_num == 0) 1175 return (IDMAP_SUCCESS); 1176 cache = &get_handle->zs->cache; 1177 1178 bzero(&rpc_res, sizeof (idmap_ids_res)); 1179 1180 rpc_args.idmap_mapping_batch_len = get_handle->mapping_num; 1181 rpc_args.idmap_mapping_batch_val = get_handle->mapping; 1182 1183 if (kidmap_rpc_call(get_handle->zs, op, xdr_idmap_mapping_batch, 1184 (caddr_t)&rpc_args, xdr_idmap_ids_res, 1185 (caddr_t)&rpc_res) != 0) { 1186 /* Door call failed */ 1187 status = IDMAP_ERR_NOMAPPING; 1188 goto error; 1189 } 1190 1191 status = rpc_res.retcode; 1192 if (status != IDMAP_SUCCESS) { 1193 /* RPC returned idmap error code */ 1194 xdr_free(xdr_idmap_ids_res, (char *)&rpc_res); 1195 goto error; 1196 } 1197 1198 for (i = 0; i < get_handle->mapping_num; i++) { 1199 request = &get_handle->mapping[i]; 1200 result = &get_handle->result[i]; 1201 1202 if (i >= rpc_res.ids.ids_len) { 1203 *result->stat = IDMAP_ERR_NOMAPPING; 1204 if (result->uid) 1205 *result->uid = UID_NOBODY; 1206 if (result->gid) 1207 *result->gid = GID_NOBODY; 1208 if (result->pid) 1209 *result->pid = UID_NOBODY; 1210 if (result->is_user) 1211 *result->is_user = 1; 1212 if (result->sid_prefix) 1213 *result->sid_prefix = NULL; 1214 if (result->rid) 1215 *result->rid = 0; 1216 continue; 1217 } 1218 1219 *result->stat = rpc_res.ids.ids_val[i].retcode; 1220 1221 id = &rpc_res.ids.ids_val[i].id; 1222 direction = rpc_res.ids.ids_val[i].direction; 1223 1224 switch (id->idtype) { 1225 case IDMAP_UID: 1226 if (result->uid) 1227 *result->uid = id->idmap_id_u.uid; 1228 if (result->pid) 1229 *result->pid = id->idmap_id_u.uid; 1230 if (result->is_user) 1231 *result->is_user = 1; 1232 sid_prefix = kidmap_find_sid_prefix( 1233 request->id1.idmap_id_u.sid.prefix); 1234 if (*result->stat == IDMAP_SUCCESS && result->uid) 1235 kidmap_cache_add_sid2uid( 1236 cache, sid_prefix, 1237 request->id1.idmap_id_u.sid.rid, 1238 id->idmap_id_u.uid, 1239 direction); 1240 else if (*result->stat == IDMAP_SUCCESS && result->pid) 1241 kidmap_cache_add_sid2pid( 1242 cache, sid_prefix, 1243 request->id1.idmap_id_u.sid.rid, 1244 id->idmap_id_u.uid, 1, 1245 direction); 1246 break; 1247 1248 case IDMAP_GID: 1249 if (result->gid) 1250 *result->gid = id->idmap_id_u.gid; 1251 if (result->pid) 1252 *result->pid = id->idmap_id_u.gid; 1253 if (result->is_user) 1254 *result->is_user = 0; 1255 sid_prefix = kidmap_find_sid_prefix( 1256 request->id1.idmap_id_u.sid.prefix); 1257 if (*result->stat == IDMAP_SUCCESS && result->gid) 1258 kidmap_cache_add_sid2gid( 1259 cache, sid_prefix, 1260 request->id1.idmap_id_u.sid.rid, 1261 id->idmap_id_u.gid, 1262 direction); 1263 else if (*result->stat == IDMAP_SUCCESS && result->pid) 1264 kidmap_cache_add_sid2pid( 1265 cache, sid_prefix, 1266 request->id1.idmap_id_u.sid.rid, 1267 id->idmap_id_u.gid, 0, 1268 direction); 1269 break; 1270 1271 case IDMAP_SID: 1272 case IDMAP_USID: 1273 case IDMAP_GSID: 1274 sid_prefix = kidmap_find_sid_prefix( 1275 id->idmap_id_u.sid.prefix); 1276 if (result->sid_prefix && result->rid) { 1277 *result->sid_prefix = sid_prefix; 1278 *result->rid = id->idmap_id_u.sid.rid; 1279 } 1280 if (*result->stat == IDMAP_SUCCESS && 1281 request->id1.idtype == IDMAP_UID) 1282 kidmap_cache_add_sid2uid( 1283 cache, sid_prefix, 1284 id->idmap_id_u.sid.rid, 1285 request->id1.idmap_id_u.uid, 1286 direction); 1287 else if (*result->stat == IDMAP_SUCCESS && 1288 request->id1.idtype == IDMAP_GID) 1289 kidmap_cache_add_sid2gid( 1290 cache, sid_prefix, 1291 id->idmap_id_u.sid.rid, 1292 request->id1.idmap_id_u.gid, 1293 direction); 1294 break; 1295 1296 default: 1297 *result->stat = IDMAP_ERR_NORESULT; 1298 if (result->uid) 1299 *result->uid = UID_NOBODY; 1300 if (result->gid) 1301 *result->gid = GID_NOBODY; 1302 if (result->pid) 1303 *result->pid = UID_NOBODY; 1304 if (result->is_user) 1305 *result->is_user = 1; 1306 if (result->sid_prefix) 1307 *result->sid_prefix = NULL; 1308 if (result->rid) 1309 *result->rid = 0; 1310 break; 1311 } 1312 } 1313 xdr_free(xdr_idmap_ids_res, (char *)&rpc_res); 1314 1315 /* Reset get_handle for new resquests */ 1316 get_handle->mapping_num = 0; 1317 return (status); 1318 1319 error: 1320 for (i = 0; i < get_handle->mapping_num; i++) { 1321 result = &get_handle->result[i]; 1322 1323 *result->stat = status; 1324 if (result->uid) 1325 *result->uid = UID_NOBODY; 1326 if (result->gid) 1327 *result->gid = GID_NOBODY; 1328 if (result->pid) 1329 *result->pid = UID_NOBODY; 1330 if (result->is_user) 1331 *result->is_user = 1; 1332 if (result->sid_prefix) 1333 *result->sid_prefix = NULL; 1334 if (result->rid) 1335 *result->rid = 0; 1336 } 1337 1338 /* Reset get_handle for new resquests */ 1339 get_handle->mapping_num = 0; 1340 return (status); 1341 } 1342 1343 1344 /* 1345 * Destroy the "get mapping" handle 1346 */ 1347 void 1348 kidmap_get_destroy(idmap_get_handle_t *get_handle) 1349 { 1350 if (get_handle == NULL) 1351 return; 1352 1353 kmem_free(get_handle->mapping, 1354 (sizeof (idmap_mapping)) * get_handle->mapping_size); 1355 get_handle->mapping = NULL; 1356 1357 kmem_free(get_handle->result, 1358 (sizeof (idmap_get_res)) * get_handle->mapping_size); 1359 get_handle->result = NULL; 1360 1361 kmem_free(get_handle, sizeof (idmap_get_handle_t)); 1362 } 1363 1364 1365 static int 1366 kidmap_rpc_call(idmap_zone_specific_t *zs, uint32_t op, xdrproc_t xdr_args, 1367 caddr_t args, xdrproc_t xdr_res, caddr_t res) 1368 { 1369 XDR xdr_ctx; 1370 struct rpc_msg reply_msg; 1371 char *inbuf_ptr = NULL; 1372 size_t inbuf_size = 4096; 1373 char *outbuf_ptr = NULL; 1374 size_t outbuf_size = 4096; 1375 size_t size; 1376 int status = 0; 1377 door_arg_t params; 1378 int retry = 0; 1379 struct rpc_msg call_msg; 1380 1381 params.rbuf = NULL; 1382 params.rsize = 0; 1383 1384 retry: 1385 inbuf_ptr = kmem_alloc(inbuf_size, KM_SLEEP); 1386 outbuf_ptr = kmem_alloc(outbuf_size, KM_SLEEP); 1387 1388 xdrmem_create(&xdr_ctx, inbuf_ptr, inbuf_size, XDR_ENCODE); 1389 1390 call_msg.rm_call.cb_prog = IDMAP_PROG; 1391 call_msg.rm_call.cb_vers = IDMAP_V1; 1392 call_msg.rm_xid = atomic_inc_32_nv(&zs->message_id); 1393 1394 if (!xdr_callhdr(&xdr_ctx, &call_msg)) { 1395 #ifdef DEBUG 1396 zcmn_err(zs->zone_id, CE_WARN, 1397 "idmap: xdr encoding header error"); 1398 #endif /* DEBUG */ 1399 status = -1; 1400 goto exit; 1401 } 1402 1403 if (!xdr_uint32(&xdr_ctx, &op) || 1404 /* Auth none */ 1405 !xdr_opaque_auth(&xdr_ctx, &_null_auth) || 1406 !xdr_opaque_auth(&xdr_ctx, &_null_auth) || 1407 /* RPC args */ 1408 !xdr_args(&xdr_ctx, args)) { 1409 #ifdef DEBUG 1410 zcmn_err(zs->zone_id, CE_WARN, "idmap: xdr encoding error"); 1411 #endif /* DEBUG */ 1412 if (retry > 2) { 1413 status = -1; 1414 goto exit; 1415 } 1416 retry++; 1417 if (inbuf_ptr) { 1418 kmem_free(inbuf_ptr, inbuf_size); 1419 inbuf_ptr = NULL; 1420 } 1421 if (outbuf_ptr) { 1422 kmem_free(outbuf_ptr, outbuf_size); 1423 outbuf_ptr = NULL; 1424 } 1425 if ((size = xdr_sizeof(xdr_args, args)) == 0) { 1426 #ifdef DEBUG 1427 zcmn_err(zs->zone_id, CE_WARN, 1428 "idmap: xdr_sizeof error"); 1429 #endif /* DEBUG */ 1430 status = -1; 1431 goto exit; 1432 } 1433 inbuf_size = size + 1024; 1434 outbuf_size = size + 1024; 1435 goto retry; 1436 } 1437 1438 params.data_ptr = inbuf_ptr; 1439 params.data_size = XDR_GETPOS(&xdr_ctx); 1440 params.desc_ptr = NULL; 1441 params.desc_num = 0; 1442 params.rbuf = outbuf_ptr; 1443 params.rsize = outbuf_size; 1444 1445 if (kidmap_call_door(zs, ¶ms) != 0) { 1446 status = -1; 1447 goto exit; 1448 } 1449 1450 reply_msg.acpted_rply.ar_verf = _null_auth; 1451 reply_msg.acpted_rply.ar_results.where = res; 1452 reply_msg.acpted_rply.ar_results.proc = xdr_res; 1453 xdrmem_create(&xdr_ctx, params.data_ptr, params.data_size, XDR_DECODE); 1454 if (xdr_replymsg(&xdr_ctx, &reply_msg)) { 1455 if (reply_msg.rm_reply.rp_stat != MSG_ACCEPTED || 1456 reply_msg.rm_reply.rp_acpt.ar_stat != SUCCESS) { 1457 status = -1; 1458 goto exit; 1459 } 1460 } else { 1461 #ifdef DEBUG 1462 zcmn_err(zs->zone_id, CE_WARN, 1463 "idmap: xdr decoding reply message error"); 1464 #endif /* DEBUG */ 1465 status = -1; 1466 } 1467 1468 exit: 1469 if (outbuf_ptr != params.rbuf && params.rbuf != NULL) 1470 kmem_free(params.rbuf, params.rsize); 1471 if (inbuf_ptr) 1472 kmem_free(inbuf_ptr, inbuf_size); 1473 if (outbuf_ptr) 1474 kmem_free(outbuf_ptr, outbuf_size); 1475 return (status); 1476 } 1477