9075 Improve ZFS pool import/load process and corrupted pool recovery
[unleashed.git] / usr / src / uts / common / idmap / idmap_kapi.c
blobf77b9a0e9a4a6f70caab5a33702e37a48c8690f7
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
28 * Windows to Solaris Identity Mapping kernel API
29 * This module provides an API to map Windows SIDs to
30 * Solaris UID and GIDs.
34 #include <sys/types.h>
35 #include <sys/ksynch.h>
36 #include <sys/door.h>
37 #include <rpc/rpc_msg.h>
38 #include <rpc/xdr.h>
39 #include <rpc/auth.h>
40 #include <rpc/rpc_sztypes.h>
41 #ifdef DEBUG
42 #include <sys/cmn_err.h>
43 #endif /* DEBUG */
44 #include <sys/proc.h>
45 #include <sys/sunddi.h>
46 #include <sys/param.h>
47 #include <sys/atomic.h>
48 #include <sys/sysmacros.h>
49 #include <sys/disp.h>
50 #include <sys/kidmap.h>
51 #include <sys/zone.h>
52 #include <rpcsvc/idmap_prot.h>
53 #include "kidmap_priv.h"
57 * Defined types
62 * This structure holds pointers for the
63 * batch mapping results.
65 typedef struct idmap_get_res {
66 idmap_id_type idtype;
67 uid_t *uid;
68 gid_t *gid;
69 uid_t *pid;
70 int *is_user;
71 const char **sid_prefix;
72 uint32_t *rid;
73 idmap_stat *stat;
74 } idmap_get_res;
76 /* Batch mapping handle structure */
77 struct idmap_get_handle {
78 struct idmap_zone_specific *zs;
79 int mapping_num;
80 int mapping_size;
81 idmap_mapping *mapping;
82 idmap_get_res *result;
86 /* Zone specific data */
87 typedef struct idmap_zone_specific {
88 zoneid_t zone_id;
89 kmutex_t zone_mutex;
90 idmap_cache_t cache;
91 door_handle_t door_handle;
92 int door_valid;
93 int door_retried;
94 uint32_t message_id;
95 } idmap_zone_specific_t;
100 * Module global data
103 static kmutex_t idmap_zone_mutex;
104 static zone_key_t idmap_zone_key;
108 * Local function definitions
112 static int
113 kidmap_rpc_call(idmap_zone_specific_t *zs, uint32_t op,
114 xdrproc_t xdr_args, caddr_t args, xdrproc_t xdr_res, caddr_t res);
116 static int
117 kidmap_call_door(idmap_zone_specific_t *zs, door_arg_t *arg);
119 static idmap_zone_specific_t *
120 idmap_get_zone_specific(zone_t *zone);
125 idmap_reg_dh(zone_t *zone, door_handle_t dh)
127 idmap_zone_specific_t *zs;
129 zs = idmap_get_zone_specific(zone);
131 mutex_enter(&zs->zone_mutex);
133 if (zs->door_valid)
134 door_ki_rele(zs->door_handle);
136 zs->door_handle = dh;
137 zs->door_valid = 1;
139 mutex_exit(&zs->zone_mutex);
141 return (0);
145 * idmap_unreg_dh
147 * This routine is called by system call idmap_unreg().
148 * idmap_unreg() calls door_ki_rele() on the supplied
149 * door handle after this routine returns. We only
150 * need to perform one door release on zs->door_handle
153 idmap_unreg_dh(zone_t *zone, door_handle_t dh)
155 idmap_zone_specific_t *zs;
157 zs = idmap_get_zone_specific(zone);
159 kidmap_cache_purge(&zs->cache);
161 mutex_enter(&zs->zone_mutex);
163 if (!zs->door_valid || zs->door_handle != dh) {
164 mutex_exit(&zs->zone_mutex);
165 return (EINVAL);
168 door_ki_rele(zs->door_handle);
170 zs->door_valid = 0;
171 zs->door_retried = 0;
172 mutex_exit(&zs->zone_mutex);
174 return (0);
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.
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)
187 idmap_zone_specific_t *zs;
189 zs = idmap_get_zone_specific(zone);
191 kidmap_cache_get_data(&zs->cache, uidbysid, gidbysid,
192 pidbysid, sidbyuid, sidbygid);
195 static int
196 kidmap_call_door(idmap_zone_specific_t *zs, door_arg_t *arg)
198 door_handle_t dh;
199 door_info_t di;
200 int status = 0;
201 int num_retries = 5;
202 int door_retried = 0;
204 retry:
205 mutex_enter(&zs->zone_mutex);
206 if (zs->door_valid) {
207 dh = zs->door_handle;
208 door_ki_hold(dh);
209 } else {
210 dh = NULL;
211 door_retried = zs->door_retried;
213 mutex_exit(&zs->zone_mutex);
215 if (dh == NULL) {
216 /* The door has been retried before so dont wait */
217 if (door_retried)
218 return (-1);
221 * There is no door handle yet. Give
222 * smf a chance to restart idmapd
224 if (num_retries-- > 0) {
225 delay(hz);
226 goto retry;
229 #ifdef DEBUG
230 zcmn_err(zs->zone_id, CE_WARN,
231 "idmap: Error no registered door to call the "
232 "idmap daemon\n");
233 #endif
234 mutex_enter(&zs->zone_mutex);
235 if (!zs->door_valid)
236 zs->door_retried = 1;
237 mutex_exit(&zs->zone_mutex);
239 return (-1);
242 status = door_ki_upcall_limited(dh, arg, NULL, SIZE_MAX, 0);
244 switch (status) {
245 case 0: /* Success */
246 door_ki_rele(dh);
247 return (0);
249 case EINTR:
250 /* If we took an interrupt we have to bail out. */
251 if (ttolwp(curthread) && ISSIG(curthread, JUSTLOOKING)) {
252 door_ki_rele(dh);
253 #ifdef DEBUG
254 zcmn_err(zs->zone_id, CE_WARN,
255 "idmap: Interrupted\n");
256 #endif
257 return (-1);
260 * Just retry and see what happens.
262 /* FALLTHROUGH */
264 case EAGAIN:
265 /* A resouce problem */
266 door_ki_rele(dh);
267 /* Back off before retrying */
268 #ifdef DEBUG
269 zcmn_err(zs->zone_id, CE_WARN,
270 "idmap: Door call returned error %d. Retrying\n", status);
271 #endif /* DEBUG */
272 delay(hz);
273 goto retry;
275 case EBADF:
276 /* Stale door handle. See if smf restarts the daemon. */
277 door_ki_rele(dh);
278 mutex_enter(&zs->zone_mutex);
279 if (zs->door_valid && dh == zs->door_handle) {
280 zs->door_valid = 0;
281 zs->door_retried = 0;
282 door_ki_rele(zs->door_handle);
284 mutex_exit(&zs->zone_mutex);
285 /* Back off before retrying */
286 #ifdef DEBUG
287 zcmn_err(zs->zone_id, CE_WARN,
288 "idmap: Door call returned error %d. Retrying\n", status);
289 #endif /* DEBUG */
290 delay(hz);
291 goto retry;
293 default:
294 /* Unknown error */
295 #ifdef DEBUG
296 zcmn_err(zs->zone_id, CE_WARN,
297 "idmap: Door call returned error %d.\n", status);
298 #endif /* DEBUG */
299 door_ki_rele(dh);
300 return (-1);
305 static idmap_zone_specific_t *
306 idmap_get_zone_specific(zone_t *zone)
308 idmap_zone_specific_t *zs;
310 ASSERT(zone != NULL);
312 zs = zone_getspecific(idmap_zone_key, zone);
313 if (zs != NULL)
314 return (zs);
316 mutex_enter(&idmap_zone_mutex);
317 zs = zone_getspecific(idmap_zone_key, zone);
318 if (zs == NULL) {
319 zs = kmem_zalloc(sizeof (idmap_zone_specific_t), KM_SLEEP);
320 mutex_init(&zs->zone_mutex, NULL, MUTEX_DEFAULT, NULL);
321 kidmap_cache_create(&zs->cache);
322 zs->zone_id = zone->zone_id;
323 (void) zone_setspecific(idmap_zone_key, zone, zs);
324 mutex_exit(&idmap_zone_mutex);
325 return (zs);
327 mutex_exit(&idmap_zone_mutex);
329 return (zs);
333 static void
334 /* ARGSUSED */
335 idmap_zone_destroy(zoneid_t zone_id, void *arg)
337 idmap_zone_specific_t *zs = arg;
338 if (zs != NULL) {
339 kidmap_cache_delete(&zs->cache);
340 if (zs->door_valid) {
341 door_ki_rele(zs->door_handle);
343 mutex_destroy(&zs->zone_mutex);
344 kmem_free(zs, sizeof (idmap_zone_specific_t));
350 kidmap_start(void)
352 mutex_init(&idmap_zone_mutex, NULL, MUTEX_DEFAULT, NULL);
353 zone_key_create(&idmap_zone_key, NULL, NULL, idmap_zone_destroy);
354 kidmap_sid_prefix_store_init();
356 return (0);
361 kidmap_stop(void)
363 return (EBUSY);
368 * idmap_get_door
370 * This is called by the system call allocids() to get the door for the
371 * given zone.
373 door_handle_t
374 idmap_get_door(zone_t *zone)
376 door_handle_t dh = NULL;
377 idmap_zone_specific_t *zs;
379 zs = idmap_get_zone_specific(zone);
381 mutex_enter(&zs->zone_mutex);
382 if (zs->door_valid) {
383 dh = zs->door_handle;
384 door_ki_hold(dh);
386 mutex_exit(&zs->zone_mutex);
387 return (dh);
392 * idmap_purge_cache
394 * This is called by the system call allocids() to purge the cache for the
395 * given zone.
397 void
398 idmap_purge_cache(zone_t *zone)
400 idmap_zone_specific_t *zs;
402 zs = idmap_get_zone_specific(zone);
404 kidmap_cache_purge(&zs->cache);
411 * Given Domain SID and RID, get UID
413 * Input:
414 * sid_prefix - Domain SID in canonical form
415 * rid - RID
417 * Output:
418 * uid - POSIX UID if return == IDMAP_SUCCESS
420 * Return:
421 * Success return IDMAP_SUCCESS else IDMAP error
423 idmap_stat
424 kidmap_getuidbysid(zone_t *zone, const char *sid_prefix, uint32_t rid,
425 uid_t *uid)
427 idmap_zone_specific_t *zs;
428 idmap_mapping_batch args;
429 idmap_mapping mapping;
430 idmap_ids_res results;
431 uint32_t op = IDMAP_GET_MAPPED_IDS;
432 const char *new_sid_prefix;
433 idmap_stat status;
435 if (sid_prefix == NULL || uid == NULL)
436 return (IDMAP_ERR_ARG);
438 zs = idmap_get_zone_specific(zone);
440 if (kidmap_cache_lookup_uidbysid(&zs->cache, sid_prefix, rid, uid)
441 == IDMAP_SUCCESS)
442 return (IDMAP_SUCCESS);
444 bzero(&mapping, sizeof (idmap_mapping));
445 mapping.id1.idtype = IDMAP_SID;
446 mapping.id1.idmap_id_u.sid.prefix = (char *)sid_prefix;
447 mapping.id1.idmap_id_u.sid.rid = rid;
448 mapping.id2.idtype = IDMAP_UID;
450 bzero(&results, sizeof (idmap_ids_res));
452 args.idmap_mapping_batch_len = 1;
453 args.idmap_mapping_batch_val = &mapping;
455 if (kidmap_rpc_call(zs, op, xdr_idmap_mapping_batch,
456 (caddr_t)&args, xdr_idmap_ids_res,
457 (caddr_t)&results) == 0) {
458 /* Door call succeded */
459 if (results.retcode != IDMAP_SUCCESS) {
460 status = results.retcode;
461 *uid = UID_NOBODY;
462 } else if (results.ids.ids_len >= 1 &&
463 results.ids.ids_val[0].id.idtype == IDMAP_UID) {
464 status = results.ids.ids_val[0].retcode;
465 *uid = results.ids.ids_val[0].id.idmap_id_u.uid;
466 if (status == IDMAP_SUCCESS) {
467 new_sid_prefix = kidmap_find_sid_prefix(
468 sid_prefix);
469 kidmap_cache_add_sid2uid(&zs->cache,
470 new_sid_prefix, rid, *uid,
471 results.ids.ids_val[0].direction);
473 } else {
474 status = IDMAP_ERR_NOMAPPING;
475 *uid = UID_NOBODY;
477 xdr_free(xdr_idmap_ids_res, (char *)&results);
478 } else {
479 /* Door call failed */
480 status = IDMAP_ERR_NOMAPPING;
481 *uid = UID_NOBODY;
483 return (status);
488 * Given Domain SID and RID, get GID
490 * Input:
491 * sid_prefix - Domain SID in canonical form
492 * rid - RID
494 * Output:
495 * gid - POSIX UID if return == IDMAP_SUCCESS
497 * Return:
498 * Success return IDMAP_SUCCESS else IDMAP error
500 idmap_stat
501 kidmap_getgidbysid(zone_t *zone, const char *sid_prefix, uint32_t rid,
502 gid_t *gid)
504 idmap_zone_specific_t *zs;
505 idmap_mapping_batch args;
506 idmap_mapping mapping;
507 idmap_ids_res results;
508 uint32_t op = IDMAP_GET_MAPPED_IDS;
509 const char *new_sid_prefix;
510 idmap_stat status;
512 if (sid_prefix == NULL || gid == NULL)
513 return (IDMAP_ERR_ARG);
515 zs = idmap_get_zone_specific(zone);
517 if (kidmap_cache_lookup_gidbysid(&zs->cache, sid_prefix, rid, gid)
518 == IDMAP_SUCCESS)
519 return (IDMAP_SUCCESS);
521 bzero(&mapping, sizeof (idmap_mapping));
522 mapping.id1.idtype = IDMAP_SID;
523 mapping.id1.idmap_id_u.sid.prefix = (char *)sid_prefix;
524 mapping.id1.idmap_id_u.sid.rid = rid;
525 mapping.id2.idtype = IDMAP_GID;
527 bzero(&results, sizeof (idmap_ids_res));
529 args.idmap_mapping_batch_len = 1;
530 args.idmap_mapping_batch_val = &mapping;
532 if (kidmap_rpc_call(zs, op, xdr_idmap_mapping_batch,
533 (caddr_t)&args, xdr_idmap_ids_res,
534 (caddr_t)&results) == 0) {
535 /* Door call succeded */
536 if (results.retcode != IDMAP_SUCCESS) {
537 status = results.retcode;
538 *gid = GID_NOBODY;
539 } else if (results.ids.ids_len >= 1 &&
540 results.ids.ids_val[0].id.idtype == IDMAP_GID) {
541 status = results.ids.ids_val[0].retcode;
542 *gid = results.ids.ids_val[0].id.idmap_id_u.gid;
543 if (status == IDMAP_SUCCESS) {
544 new_sid_prefix = kidmap_find_sid_prefix(
545 sid_prefix);
546 kidmap_cache_add_sid2gid(&zs->cache,
547 new_sid_prefix, rid, *gid,
548 results.ids.ids_val[0].direction);
550 } else {
551 status = IDMAP_ERR_NOMAPPING;
552 *gid = GID_NOBODY;
554 xdr_free(xdr_idmap_ids_res, (char *)&results);
555 } else {
556 /* Door call failed */
557 status = IDMAP_ERR_NOMAPPING;
558 *gid = GID_NOBODY;
560 return (status);
564 * Given Domain SID and RID, get Posix ID
566 * Input:
567 * sid_prefix - Domain SID in canonical form
568 * rid - RID
570 * Output:
571 * pid - POSIX ID if return == IDMAP_SUCCESS
572 * is_user - 1 == UID, 0 == GID if return == IDMAP_SUCCESS
574 * Return:
575 * Success return IDMAP_SUCCESS else IDMAP error
577 idmap_stat
578 kidmap_getpidbysid(zone_t *zone, const char *sid_prefix, uint32_t rid,
579 uid_t *pid, int *is_user)
581 idmap_zone_specific_t *zs;
582 idmap_mapping_batch args;
583 idmap_mapping mapping;
584 idmap_ids_res results;
585 uint32_t op = IDMAP_GET_MAPPED_IDS;
586 const char *new_sid_prefix;
587 idmap_stat status;
589 if (sid_prefix == NULL || pid == NULL || is_user == NULL)
590 return (IDMAP_ERR_ARG);
592 zs = idmap_get_zone_specific(zone);
594 if (kidmap_cache_lookup_pidbysid(&zs->cache, sid_prefix, rid, pid,
595 is_user) == IDMAP_SUCCESS)
596 return (IDMAP_SUCCESS);
598 bzero(&mapping, sizeof (idmap_mapping));
599 mapping.id1.idtype = IDMAP_SID;
600 mapping.id1.idmap_id_u.sid.prefix = (char *)sid_prefix;
601 mapping.id1.idmap_id_u.sid.rid = rid;
602 mapping.id2.idtype = IDMAP_POSIXID;
604 bzero(&results, sizeof (idmap_ids_res));
606 args.idmap_mapping_batch_len = 1;
607 args.idmap_mapping_batch_val = &mapping;
609 if (kidmap_rpc_call(zs, op, xdr_idmap_mapping_batch,
610 (caddr_t)&args, xdr_idmap_ids_res,
611 (caddr_t)&results) == 0) {
612 /* Door call succeded */
613 if (results.retcode != IDMAP_SUCCESS) {
614 status = results.retcode;
615 *is_user = 1;
616 *pid = UID_NOBODY;
617 } else if (results.ids.ids_len >= 1 && (
618 results.ids.ids_val[0].id.idtype == IDMAP_UID ||
619 results.ids.ids_val[0].id.idtype == IDMAP_GID)) {
620 status = results.ids.ids_val[0].retcode;
621 if (results.ids.ids_val[0].id.idtype == IDMAP_UID) {
622 *is_user = 1;
623 *pid = results.ids.ids_val[0].id.idmap_id_u.uid;
624 } else {
625 *is_user = 0;
626 *pid = results.ids.ids_val[0].id.idmap_id_u.gid;
628 if (status == IDMAP_SUCCESS) {
629 new_sid_prefix = kidmap_find_sid_prefix(
630 sid_prefix);
631 kidmap_cache_add_sid2pid(&zs->cache,
632 new_sid_prefix, rid, *pid,
633 *is_user,
634 results.ids.ids_val[0].direction);
636 } else {
637 status = IDMAP_ERR_NOMAPPING;
638 *is_user = 1;
639 *pid = UID_NOBODY;
641 xdr_free(xdr_idmap_ids_res, (char *)&results);
642 } else {
643 /* Door call failed */
644 status = IDMAP_ERR_NOMAPPING;
645 *is_user = 1;
646 *pid = UID_NOBODY;
648 return (status);
653 * Given UID, get Domain SID and RID
655 * Input:
656 * uid - Posix UID
658 * Output:
659 * sid_prefix - Domain SID if return == IDMAP_SUCCESS
660 * rid - RID if return == IDMAP_SUCCESS
662 * Return:
663 * Success return IDMAP_SUCCESS else IDMAP error
665 idmap_stat
666 kidmap_getsidbyuid(zone_t *zone, uid_t uid, const char **sid_prefix,
667 uint32_t *rid)
669 idmap_zone_specific_t *zs;
670 idmap_mapping_batch args;
671 idmap_mapping mapping;
672 idmap_ids_res results;
673 uint32_t op = IDMAP_GET_MAPPED_IDS;
674 idmap_stat status;
675 time_t entry_ttl;
676 idmap_id *id;
678 if (sid_prefix == NULL || rid == NULL)
679 return (IDMAP_ERR_ARG);
681 zs = idmap_get_zone_specific(zone);
683 if (kidmap_cache_lookup_sidbyuid(&zs->cache, sid_prefix, rid, uid)
684 == IDMAP_SUCCESS) {
685 return (IDMAP_SUCCESS);
688 bzero(&mapping, sizeof (idmap_mapping));
689 mapping.id1.idtype = IDMAP_UID;
690 mapping.id1.idmap_id_u.uid = uid;
691 mapping.id2.idtype = IDMAP_SID;
693 bzero(&results, sizeof (idmap_ids_res));
695 args.idmap_mapping_batch_len = 1;
696 args.idmap_mapping_batch_val = &mapping;
698 if (kidmap_rpc_call(zs, op, xdr_idmap_mapping_batch,
699 (caddr_t)&args, xdr_idmap_ids_res,
700 (caddr_t)&results) == 0) {
701 /* Door call succeded */
702 if (results.retcode != IDMAP_SUCCESS) {
703 status = results.retcode;
704 *rid = 0;
705 *sid_prefix = NULL;
706 } else if (results.ids.ids_len >= 1 &&
707 (results.ids.ids_val[0].id.idtype == IDMAP_SID ||
708 results.ids.ids_val[0].id.idtype == IDMAP_USID ||
709 results.ids.ids_val[0].id.idtype == IDMAP_GSID)) {
710 status = results.ids.ids_val[0].retcode;
711 id = &results.ids.ids_val[0].id;
712 *sid_prefix = kidmap_find_sid_prefix(
713 id->idmap_id_u.sid.prefix);
714 *rid = id->idmap_id_u.sid.rid;
715 if (status == IDMAP_SUCCESS) {
716 kidmap_cache_add_sid2uid(&zs->cache,
717 *sid_prefix, *rid, uid,
718 results.ids.ids_val[0].direction);
720 } else {
721 status = IDMAP_ERR_NOMAPPING;
722 *rid = 0;
723 *sid_prefix = NULL;
725 xdr_free(xdr_idmap_ids_res, (char *)&results);
726 } else {
727 /* Door call failed */
728 status = IDMAP_ERR_NOMAPPING;
729 *rid = 0;
730 *sid_prefix = NULL;
732 return (status);
737 * Given GID, get Domain SID and RID
739 * Input:
740 * gid - Posix GID
742 * Output:
743 * sid_prefix - Domain SID if return == IDMAP_SUCCESS
744 * rid - RID if return == IDMAP_SUCCESS
746 * Return:
747 * Success return IDMAP_SUCCESS else IDMAP error
749 idmap_stat
750 kidmap_getsidbygid(zone_t *zone, gid_t gid, const char **sid_prefix,
751 uint32_t *rid)
753 idmap_zone_specific_t *zs;
754 idmap_mapping_batch args;
755 idmap_mapping mapping;
756 idmap_ids_res results;
757 uint32_t op = IDMAP_GET_MAPPED_IDS;
758 idmap_stat status;
759 idmap_id *id;
761 if (sid_prefix == NULL || rid == NULL)
762 return (IDMAP_ERR_ARG);
764 zs = idmap_get_zone_specific(zone);
766 if (kidmap_cache_lookup_sidbygid(&zs->cache, sid_prefix, rid, gid)
767 == IDMAP_SUCCESS) {
768 return (IDMAP_SUCCESS);
771 bzero(&mapping, sizeof (idmap_mapping));
772 mapping.id1.idtype = IDMAP_GID;
773 mapping.id1.idmap_id_u.uid = gid;
774 mapping.id2.idtype = IDMAP_SID;
776 bzero(&results, sizeof (idmap_ids_res));
778 args.idmap_mapping_batch_len = 1;
779 args.idmap_mapping_batch_val = &mapping;
781 if (kidmap_rpc_call(zs, op, xdr_idmap_mapping_batch,
782 (caddr_t)&args, xdr_idmap_ids_res,
783 (caddr_t)&results) == 0) {
784 /* Door call succeded */
785 if (results.retcode != IDMAP_SUCCESS) {
786 status = results.retcode;
787 *rid = 0;
788 *sid_prefix = NULL;
789 } else if (results.ids.ids_len >= 1 &&
790 (results.ids.ids_val[0].id.idtype == IDMAP_SID ||
791 results.ids.ids_val[0].id.idtype == IDMAP_USID ||
792 results.ids.ids_val[0].id.idtype == IDMAP_GSID)) {
793 status = results.ids.ids_val[0].retcode;
794 id = &results.ids.ids_val[0].id;
795 *sid_prefix = kidmap_find_sid_prefix(
796 id->idmap_id_u.sid.prefix);
797 *rid = id->idmap_id_u.sid.rid;
798 if (status == IDMAP_SUCCESS) {
799 kidmap_cache_add_sid2gid(&zs->cache,
800 *sid_prefix, *rid, gid,
801 results.ids.ids_val[0].direction);
803 } else {
804 status = IDMAP_ERR_NOMAPPING;
805 *rid = 0;
806 *sid_prefix = NULL;
808 xdr_free(xdr_idmap_ids_res, (char *)&results);
809 } else {
810 /* Door call failed */
811 status = IDMAP_ERR_NOMAPPING;
812 *rid = 0;
813 *sid_prefix = NULL;
815 return (status);
819 * Create handle to get SID to UID/GID mapping entries
821 * Input:
822 * none
823 * Return:
824 * get_handle
827 idmap_get_handle_t *
828 kidmap_get_create(zone_t *zone)
830 idmap_zone_specific_t *zs;
831 idmap_get_handle_t *handle;
832 #define INIT_MAPPING_SIZE 32
834 zs = idmap_get_zone_specific(zone);
836 handle = kmem_zalloc(sizeof (idmap_get_handle_t), KM_SLEEP);
838 handle->mapping = kmem_zalloc((sizeof (idmap_mapping)) *
839 INIT_MAPPING_SIZE, KM_SLEEP);
841 handle->result = kmem_zalloc((sizeof (idmap_get_res)) *
842 INIT_MAPPING_SIZE, KM_SLEEP);
843 handle->mapping_size = INIT_MAPPING_SIZE;
844 handle->zs = zs;
846 return (handle);
850 * Internal routine to extend a "get_handle"
852 static void
853 kidmap_get_extend(idmap_get_handle_t *get_handle)
855 idmap_mapping *mapping;
856 idmap_get_res *result;
857 int new_size = get_handle->mapping_size + INIT_MAPPING_SIZE;
859 mapping = kmem_zalloc((sizeof (idmap_mapping)) *
860 new_size, KM_SLEEP);
861 (void) memcpy(mapping, get_handle->mapping,
862 (sizeof (idmap_mapping)) * get_handle->mapping_size);
864 result = kmem_zalloc((sizeof (idmap_get_res)) *
865 new_size, KM_SLEEP);
866 (void) memcpy(result, get_handle->result,
867 (sizeof (idmap_get_res)) * get_handle->mapping_size);
869 kmem_free(get_handle->mapping,
870 (sizeof (idmap_mapping)) * get_handle->mapping_size);
871 get_handle->mapping = mapping;
873 kmem_free(get_handle->result,
874 (sizeof (idmap_get_res)) * get_handle->mapping_size);
875 get_handle->result = result;
877 get_handle->mapping_size = new_size;
882 * Given Domain SID and RID, get UID
884 * Input:
885 * sid_prefix - Domain SID in canonical form
886 * rid - RID
888 * Output:
889 * stat - status of the get request
890 * uid - POSIX UID if stat == IDMAP_SUCCESS
892 * Notes:
893 * The output parameters will be set by idmap_get_mappings()
894 * The sid_prefix is copied.
896 idmap_stat
897 kidmap_batch_getuidbysid(idmap_get_handle_t *get_handle, const char *sid_prefix,
898 uint32_t rid, uid_t *uid, idmap_stat *stat)
900 idmap_mapping *mapping;
901 idmap_get_res *result;
903 if (get_handle == NULL || sid_prefix == NULL ||
904 uid == NULL || stat == NULL)
905 return (IDMAP_ERR_ARG);
907 if (kidmap_cache_lookup_uidbysid(&get_handle->zs->cache, sid_prefix,
908 rid, uid) == IDMAP_SUCCESS) {
909 *stat = IDMAP_SUCCESS;
910 return (IDMAP_SUCCESS);
913 /* Get a copy of sid_prefix */
914 sid_prefix = kidmap_find_sid_prefix(sid_prefix);
916 if (get_handle->mapping_num >= get_handle->mapping_size)
917 kidmap_get_extend(get_handle);
919 mapping = &get_handle->mapping[get_handle->mapping_num];
920 mapping->flag = 0;
921 mapping->id1.idtype = IDMAP_SID;
922 mapping->id1.idmap_id_u.sid.prefix = (char *)sid_prefix;
923 mapping->id1.idmap_id_u.sid.rid = rid;
924 mapping->id2.idtype = IDMAP_UID;
926 result = &get_handle->result[get_handle->mapping_num];
927 result->idtype = IDMAP_UID;
928 result->uid = uid;
929 result->gid = NULL;
930 result->pid = NULL;
931 result->sid_prefix = NULL;
932 result->rid = NULL;
933 result->is_user = NULL;
934 result->stat = stat;
936 get_handle->mapping_num++;
938 return (IDMAP_SUCCESS);
943 * Given Domain SID and RID, get GID
945 * Input:
946 * sid_prefix - Domain SID in canonical form
947 * rid - RID
949 * Output:
950 * stat - status of the get request
951 * gid - POSIX GID if stat == IDMAP_SUCCESS
953 * Notes:
954 * The output parameters will be set by idmap_get_mappings()
955 * The sid_prefix is copied.
957 idmap_stat
958 kidmap_batch_getgidbysid(idmap_get_handle_t *get_handle, const char *sid_prefix,
959 uint32_t rid, uid_t *gid, idmap_stat *stat)
961 idmap_mapping *mapping;
962 idmap_get_res *result;
964 if (get_handle == NULL || sid_prefix == NULL ||
965 gid == NULL || stat == NULL)
966 return (IDMAP_ERR_ARG);
968 if (kidmap_cache_lookup_gidbysid(&get_handle->zs->cache, sid_prefix,
969 rid, gid) == IDMAP_SUCCESS) {
970 *stat = IDMAP_SUCCESS;
971 return (IDMAP_SUCCESS);
974 /* Get a copy of sid_prefix */
975 sid_prefix = kidmap_find_sid_prefix(sid_prefix);
977 if (get_handle->mapping_num >= get_handle->mapping_size)
978 kidmap_get_extend(get_handle);
980 mapping = &get_handle->mapping[get_handle->mapping_num];
981 mapping->flag = 0;
982 mapping->id1.idtype = IDMAP_SID;
983 mapping->id1.idmap_id_u.sid.prefix = (char *)sid_prefix;
984 mapping->id1.idmap_id_u.sid.rid = rid;
985 mapping->id2.idtype = IDMAP_GID;
987 result = &get_handle->result[get_handle->mapping_num];
988 result->idtype = IDMAP_GID;
989 result->uid = NULL;
990 result->gid = gid;
991 result->pid = NULL;
992 result->sid_prefix = NULL;
993 result->rid = NULL;
994 result->is_user = NULL;
995 result->stat = stat;
997 get_handle->mapping_num++;
999 return (IDMAP_SUCCESS);
1004 * Given Domain SID and RID, get Posix ID
1006 * Input:
1007 * sid_prefix - Domain SID in canonical form
1008 * rid - RID
1010 * Output:
1011 * stat - status of the get request
1012 * is_user - user or group
1013 * pid - POSIX UID if stat == IDMAP_SUCCESS and is_user == 1
1014 * POSIX GID if stat == IDMAP_SUCCESS and is_user == 0
1016 * Notes:
1017 * The output parameters will be set by idmap_get_mappings()
1018 * The sid_prefix is copied.
1020 idmap_stat
1021 kidmap_batch_getpidbysid(idmap_get_handle_t *get_handle, const char *sid_prefix,
1022 uint32_t rid, uid_t *pid, int *is_user, idmap_stat *stat)
1024 idmap_mapping *mapping;
1025 idmap_get_res *result;
1027 if (get_handle == NULL || sid_prefix == NULL || pid == NULL ||
1028 is_user == NULL || stat == NULL)
1029 return (IDMAP_ERR_ARG);
1031 if (kidmap_cache_lookup_pidbysid(&get_handle->zs->cache, sid_prefix,
1032 rid, pid, is_user) == IDMAP_SUCCESS) {
1033 *stat = IDMAP_SUCCESS;
1034 return (IDMAP_SUCCESS);
1037 /* Get a copy of sid_prefix */
1038 sid_prefix = kidmap_find_sid_prefix(sid_prefix);
1040 if (get_handle->mapping_num >= get_handle->mapping_size)
1041 kidmap_get_extend(get_handle);
1043 mapping = &get_handle->mapping[get_handle->mapping_num];
1044 mapping->flag = 0;
1045 mapping->id1.idtype = IDMAP_SID;
1046 mapping->id1.idmap_id_u.sid.prefix = (char *)sid_prefix;
1047 mapping->id1.idmap_id_u.sid.rid = rid;
1048 mapping->id2.idtype = IDMAP_POSIXID;
1050 result = &get_handle->result[get_handle->mapping_num];
1051 result->idtype = IDMAP_POSIXID;
1052 result->uid = NULL;
1053 result->gid = NULL;
1054 result->pid = pid;
1055 result->sid_prefix = NULL;
1056 result->rid = NULL;
1057 result->is_user = is_user;
1058 result->stat = stat;
1060 get_handle->mapping_num++;
1062 return (IDMAP_SUCCESS);
1067 * Given UID, get SID and RID
1069 * Input:
1070 * uid - POSIX UID
1072 * Output:
1073 * stat - status of the get request
1074 * sid - SID in canonical form (if stat == IDMAP_SUCCESS)
1075 * rid - RID (if stat == IDMAP_SUCCESS)
1077 * Note: The output parameters will be set by idmap_get_mappings()
1079 idmap_stat
1080 kidmap_batch_getsidbyuid(idmap_get_handle_t *get_handle, uid_t uid,
1081 const char **sid_prefix, uint32_t *rid, idmap_stat *stat)
1083 idmap_mapping *mapping;
1084 idmap_get_res *result;
1086 if (get_handle == NULL || sid_prefix == NULL ||
1087 rid == NULL || stat == NULL)
1088 return (IDMAP_ERR_ARG);
1090 if (kidmap_cache_lookup_sidbyuid(&get_handle->zs->cache,
1091 sid_prefix, rid, uid) == IDMAP_SUCCESS) {
1092 *stat = IDMAP_SUCCESS;
1093 return (IDMAP_SUCCESS);
1096 if (get_handle->mapping_num >= get_handle->mapping_size)
1097 kidmap_get_extend(get_handle);
1099 mapping = &get_handle->mapping[get_handle->mapping_num];
1100 mapping->flag = 0;
1101 mapping->id1.idtype = IDMAP_UID;
1102 mapping->id1.idmap_id_u.uid = uid;
1103 mapping->id2.idtype = IDMAP_SID;
1105 result = &get_handle->result[get_handle->mapping_num];
1106 result->idtype = IDMAP_SID;
1107 result->uid = NULL;
1108 result->gid = NULL;
1109 result->pid = NULL;
1110 result->sid_prefix = sid_prefix;
1111 result->rid = rid;
1112 result->is_user = NULL;
1113 result->stat = stat;
1115 get_handle->mapping_num++;
1117 return (IDMAP_SUCCESS);
1122 * Given GID, get SID and RID
1124 * Input:
1125 * gid - POSIX GID
1127 * Output:
1128 * stat - status of the get request
1129 * sid - SID in canonical form (if stat == IDMAP_SUCCESS)
1130 * rid - RID (if stat == IDMAP_SUCCESS)
1132 * Note: The output parameters will be set by idmap_get_mappings()
1134 idmap_stat
1135 kidmap_batch_getsidbygid(idmap_get_handle_t *get_handle, gid_t gid,
1136 const char **sid_prefix, uint32_t *rid, idmap_stat *stat)
1138 idmap_mapping *mapping;
1139 idmap_get_res *result;
1141 if (get_handle == NULL || sid_prefix == NULL ||
1142 rid == NULL || stat == NULL)
1143 return (IDMAP_ERR_ARG);
1145 if (kidmap_cache_lookup_sidbygid(&get_handle->zs->cache,
1146 sid_prefix, rid, gid) == IDMAP_SUCCESS) {
1147 *stat = IDMAP_SUCCESS;
1148 return (IDMAP_SUCCESS);
1151 if (get_handle->mapping_num >= get_handle->mapping_size)
1152 kidmap_get_extend(get_handle);
1154 mapping = &get_handle->mapping[get_handle->mapping_num];
1155 mapping->flag = 0;
1156 mapping->id1.idtype = IDMAP_GID;
1157 mapping->id1.idmap_id_u.gid = gid;
1158 mapping->id2.idtype = IDMAP_SID;
1160 result = &get_handle->result[get_handle->mapping_num];
1161 result->idtype = IDMAP_SID;
1162 result->uid = NULL;
1163 result->gid = NULL;
1164 result->pid = NULL;
1165 result->sid_prefix = sid_prefix;
1166 result->rid = rid;
1167 result->is_user = NULL;
1168 result->stat = stat;
1170 get_handle->mapping_num++;
1172 return (IDMAP_SUCCESS);
1177 * Process the batched "get mapping" requests. The results (i.e.
1178 * status and identity) will be available in the data areas
1179 * provided by individual requests.
1181 * If the door call fails the status IDMAP_ERR_NOMAPPING is
1182 * return and the UID or UID result is set to "nobody"
1185 idmap_stat
1186 kidmap_get_mappings(idmap_get_handle_t *get_handle)
1188 idmap_mapping_batch rpc_args;
1189 idmap_ids_res rpc_res;
1190 uint32_t op = IDMAP_GET_MAPPED_IDS;
1191 idmap_mapping *request;
1192 idmap_get_res *result;
1193 idmap_id *id;
1194 int status;
1195 int i;
1196 const char *sid_prefix;
1197 int is_user;
1198 idmap_cache_t *cache;
1199 int direction;
1201 if (get_handle == NULL)
1202 return (IDMAP_ERR_ARG);
1204 if (get_handle->mapping_num == 0)
1205 return (IDMAP_SUCCESS);
1206 cache = &get_handle->zs->cache;
1208 bzero(&rpc_res, sizeof (idmap_ids_res));
1210 rpc_args.idmap_mapping_batch_len = get_handle->mapping_num;
1211 rpc_args.idmap_mapping_batch_val = get_handle->mapping;
1213 if (kidmap_rpc_call(get_handle->zs, op, xdr_idmap_mapping_batch,
1214 (caddr_t)&rpc_args, xdr_idmap_ids_res,
1215 (caddr_t)&rpc_res) != 0) {
1216 /* Door call failed */
1217 status = IDMAP_ERR_NOMAPPING;
1218 goto error;
1221 status = rpc_res.retcode;
1222 if (status != IDMAP_SUCCESS) {
1223 /* RPC returned idmap error code */
1224 xdr_free(xdr_idmap_ids_res, (char *)&rpc_res);
1225 goto error;
1228 for (i = 0; i < get_handle->mapping_num; i++) {
1229 request = &get_handle->mapping[i];
1230 result = &get_handle->result[i];
1232 if (i >= rpc_res.ids.ids_len) {
1233 *result->stat = IDMAP_ERR_NOMAPPING;
1234 if (result->uid)
1235 *result->uid = UID_NOBODY;
1236 if (result->gid)
1237 *result->gid = GID_NOBODY;
1238 if (result->pid)
1239 *result->pid = UID_NOBODY;
1240 if (result->is_user)
1241 *result->is_user = 1;
1242 if (result->sid_prefix)
1243 *result->sid_prefix = NULL;
1244 if (result->rid)
1245 *result->rid = 0;
1246 continue;
1249 *result->stat = rpc_res.ids.ids_val[i].retcode;
1251 id = &rpc_res.ids.ids_val[i].id;
1252 direction = rpc_res.ids.ids_val[i].direction;
1254 switch (id->idtype) {
1255 case IDMAP_UID:
1256 if (result->uid)
1257 *result->uid = id->idmap_id_u.uid;
1258 if (result->pid)
1259 *result->pid = id->idmap_id_u.uid;
1260 if (result->is_user)
1261 *result->is_user = 1;
1262 sid_prefix = kidmap_find_sid_prefix(
1263 request->id1.idmap_id_u.sid.prefix);
1264 if (*result->stat == IDMAP_SUCCESS && result->uid)
1265 kidmap_cache_add_sid2uid(
1266 cache, sid_prefix,
1267 request->id1.idmap_id_u.sid.rid,
1268 id->idmap_id_u.uid,
1269 direction);
1270 else if (*result->stat == IDMAP_SUCCESS && result->pid)
1271 kidmap_cache_add_sid2pid(
1272 cache, sid_prefix,
1273 request->id1.idmap_id_u.sid.rid,
1274 id->idmap_id_u.uid, 1,
1275 direction);
1276 break;
1278 case IDMAP_GID:
1279 if (result->gid)
1280 *result->gid = id->idmap_id_u.gid;
1281 if (result->pid)
1282 *result->pid = id->idmap_id_u.gid;
1283 if (result->is_user)
1284 *result->is_user = 0;
1285 sid_prefix = kidmap_find_sid_prefix(
1286 request->id1.idmap_id_u.sid.prefix);
1287 if (*result->stat == IDMAP_SUCCESS && result->gid)
1288 kidmap_cache_add_sid2gid(
1289 cache, sid_prefix,
1290 request->id1.idmap_id_u.sid.rid,
1291 id->idmap_id_u.gid,
1292 direction);
1293 else if (*result->stat == IDMAP_SUCCESS && result->pid)
1294 kidmap_cache_add_sid2pid(
1295 cache, sid_prefix,
1296 request->id1.idmap_id_u.sid.rid,
1297 id->idmap_id_u.gid, 0,
1298 direction);
1299 break;
1301 case IDMAP_SID:
1302 case IDMAP_USID:
1303 case IDMAP_GSID:
1304 sid_prefix = kidmap_find_sid_prefix(
1305 id->idmap_id_u.sid.prefix);
1306 if (result->sid_prefix && result->rid) {
1307 *result->sid_prefix = sid_prefix;
1308 *result->rid = id->idmap_id_u.sid.rid;
1310 if (*result->stat == IDMAP_SUCCESS &&
1311 request->id1.idtype == IDMAP_UID)
1312 kidmap_cache_add_sid2uid(
1313 cache, sid_prefix,
1314 id->idmap_id_u.sid.rid,
1315 request->id1.idmap_id_u.uid,
1316 direction);
1317 else if (*result->stat == IDMAP_SUCCESS &&
1318 request->id1.idtype == IDMAP_GID)
1319 kidmap_cache_add_sid2gid(
1320 cache, sid_prefix,
1321 id->idmap_id_u.sid.rid,
1322 request->id1.idmap_id_u.gid,
1323 direction);
1324 break;
1326 default:
1327 *result->stat = IDMAP_ERR_NORESULT;
1328 if (result->uid)
1329 *result->uid = UID_NOBODY;
1330 if (result->gid)
1331 *result->gid = GID_NOBODY;
1332 if (result->pid)
1333 *result->pid = UID_NOBODY;
1334 if (result->is_user)
1335 *result->is_user = 1;
1336 if (result->sid_prefix)
1337 *result->sid_prefix = NULL;
1338 if (result->rid)
1339 *result->rid = 0;
1340 break;
1343 xdr_free(xdr_idmap_ids_res, (char *)&rpc_res);
1345 /* Reset get_handle for new resquests */
1346 get_handle->mapping_num = 0;
1347 return (status);
1349 error:
1350 for (i = 0; i < get_handle->mapping_num; i++) {
1351 result = &get_handle->result[i];
1353 *result->stat = status;
1354 if (result->uid)
1355 *result->uid = UID_NOBODY;
1356 if (result->gid)
1357 *result->gid = GID_NOBODY;
1358 if (result->pid)
1359 *result->pid = UID_NOBODY;
1360 if (result->is_user)
1361 *result->is_user = 1;
1362 if (result->sid_prefix)
1363 *result->sid_prefix = NULL;
1364 if (result->rid)
1365 *result->rid = 0;
1368 /* Reset get_handle for new resquests */
1369 get_handle->mapping_num = 0;
1370 return (status);
1375 * Destroy the "get mapping" handle
1377 void
1378 kidmap_get_destroy(idmap_get_handle_t *get_handle)
1380 if (get_handle == NULL)
1381 return;
1383 kmem_free(get_handle->mapping,
1384 (sizeof (idmap_mapping)) * get_handle->mapping_size);
1385 get_handle->mapping = NULL;
1387 kmem_free(get_handle->result,
1388 (sizeof (idmap_get_res)) * get_handle->mapping_size);
1389 get_handle->result = NULL;
1391 kmem_free(get_handle, sizeof (idmap_get_handle_t));
1395 static int
1396 kidmap_rpc_call(idmap_zone_specific_t *zs, uint32_t op, xdrproc_t xdr_args,
1397 caddr_t args, xdrproc_t xdr_res, caddr_t res)
1399 XDR xdr_ctx;
1400 struct rpc_msg reply_msg;
1401 char *inbuf_ptr = NULL;
1402 size_t inbuf_size = 4096;
1403 char *outbuf_ptr = NULL;
1404 size_t outbuf_size = 4096;
1405 size_t size;
1406 int status = 0;
1407 door_arg_t params;
1408 int retry = 0;
1409 struct rpc_msg call_msg;
1411 params.rbuf = NULL;
1412 params.rsize = 0;
1414 retry:
1415 inbuf_ptr = kmem_alloc(inbuf_size, KM_SLEEP);
1416 outbuf_ptr = kmem_alloc(outbuf_size, KM_SLEEP);
1418 xdrmem_create(&xdr_ctx, inbuf_ptr, inbuf_size, XDR_ENCODE);
1420 call_msg.rm_call.cb_prog = IDMAP_PROG;
1421 call_msg.rm_call.cb_vers = IDMAP_V1;
1422 call_msg.rm_xid = atomic_inc_32_nv(&zs->message_id);
1424 if (!xdr_callhdr(&xdr_ctx, &call_msg)) {
1425 #ifdef DEBUG
1426 zcmn_err(zs->zone_id, CE_WARN,
1427 "idmap: xdr encoding header error");
1428 #endif /* DEBUG */
1429 status = -1;
1430 goto exit;
1433 if (!xdr_uint32(&xdr_ctx, &op) ||
1434 /* Auth none */
1435 !xdr_opaque_auth(&xdr_ctx, &_null_auth) ||
1436 !xdr_opaque_auth(&xdr_ctx, &_null_auth) ||
1437 /* RPC args */
1438 !xdr_args(&xdr_ctx, args)) {
1439 #ifdef DEBUG
1440 zcmn_err(zs->zone_id, CE_WARN, "idmap: xdr encoding error");
1441 #endif /* DEBUG */
1442 if (retry > 2) {
1443 status = -1;
1444 goto exit;
1446 retry++;
1447 if (inbuf_ptr) {
1448 kmem_free(inbuf_ptr, inbuf_size);
1449 inbuf_ptr = NULL;
1451 if (outbuf_ptr) {
1452 kmem_free(outbuf_ptr, outbuf_size);
1453 outbuf_ptr = NULL;
1455 if ((size = xdr_sizeof(xdr_args, args)) == 0) {
1456 #ifdef DEBUG
1457 zcmn_err(zs->zone_id, CE_WARN,
1458 "idmap: xdr_sizeof error");
1459 #endif /* DEBUG */
1460 status = -1;
1461 goto exit;
1463 inbuf_size = size + 1024;
1464 outbuf_size = size + 1024;
1465 goto retry;
1468 params.data_ptr = inbuf_ptr;
1469 params.data_size = XDR_GETPOS(&xdr_ctx);
1470 params.desc_ptr = NULL;
1471 params.desc_num = 0;
1472 params.rbuf = outbuf_ptr;
1473 params.rsize = outbuf_size;
1475 if (kidmap_call_door(zs, &params) != 0) {
1476 status = -1;
1477 goto exit;
1480 reply_msg.acpted_rply.ar_verf = _null_auth;
1481 reply_msg.acpted_rply.ar_results.where = res;
1482 reply_msg.acpted_rply.ar_results.proc = xdr_res;
1483 xdrmem_create(&xdr_ctx, params.data_ptr, params.data_size, XDR_DECODE);
1484 if (xdr_replymsg(&xdr_ctx, &reply_msg)) {
1485 if (reply_msg.rm_reply.rp_stat != MSG_ACCEPTED ||
1486 reply_msg.rm_reply.rp_acpt.ar_stat != SUCCESS) {
1487 status = -1;
1488 goto exit;
1490 } else {
1491 #ifdef DEBUG
1492 zcmn_err(zs->zone_id, CE_WARN,
1493 "idmap: xdr decoding reply message error");
1494 #endif /* DEBUG */
1495 status = -1;
1498 exit:
1499 if (outbuf_ptr != params.rbuf && params.rbuf != NULL)
1500 kmem_free(params.rbuf, params.rsize);
1501 if (inbuf_ptr)
1502 kmem_free(inbuf_ptr, inbuf_size);
1503 if (outbuf_ptr)
1504 kmem_free(outbuf_ptr, outbuf_size);
1505 return (status);