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