/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * SID system call. */ #include #include #include #include #include #include #include #include static uint64_t allocids(int flag, int nuids, int ngids) { rval_t r; uid_t su = 0; gid_t sg = 0; struct door_info di; door_handle_t dh; int err; zone_t *zone = crgetzone(CRED()); dh = idmap_get_door(zone); if (dh == NULL) return (set_errno(EPERM)); if ((err = door_ki_info(dh, &di)) != 0) { door_ki_rele(dh); return (set_errno(err)); } door_ki_rele(dh); if (curproc->p_pid != di.di_target) return (set_errno(EPERM)); if (flag) idmap_purge_cache(zone); if (nuids < 0 || ngids < 0) return (set_errno(EINVAL)); if (flag != 0 || nuids > 0) err = eph_uid_alloc(zone, flag, &su, nuids); if (err == 0 && (flag != 0 || ngids > 0)) err = eph_gid_alloc(zone, flag, &sg, ngids); if (err != 0) return (set_errno(EOVERFLOW)); r.r_val1 = su; r.r_val2 = sg; return (r.r_vals); } static int idmap_reg(int did) { door_handle_t dh; int err; cred_t *cr = CRED(); if ((err = secpolicy_idmap(cr)) != 0) return (set_errno(err)); dh = door_ki_lookup(did); if (dh == NULL) return (set_errno(EBADF)); if ((err = idmap_reg_dh(crgetzone(cr), dh)) != 0) return (set_errno(err)); return (0); } static int idmap_unreg(int did) { door_handle_t dh = door_ki_lookup(did); int res; zone_t *zone; if (dh == NULL) return (set_errno(EINVAL)); zone = crgetzone(CRED()); res = idmap_unreg_dh(zone, dh); door_ki_rele(dh); if (res != 0) return (set_errno(res)); return (0); } static uint64_t idmap_flush_kcache(void) { struct door_info di; door_handle_t dh; int err; zone_t *zone = crgetzone(CRED()); dh = idmap_get_door(zone); if (dh == NULL) return (set_errno(EPERM)); if ((err = door_ki_info(dh, &di)) != 0) { door_ki_rele(dh); return (set_errno(err)); } door_ki_rele(dh); if (curproc->p_pid != di.di_target) return (set_errno(EPERM)); idmap_purge_cache(zone); return (0); } uint64_t sidsys(int op, int flag, int nuids, int ngids) { switch (op) { case SIDSYS_ALLOC_IDS: return (allocids(flag, nuids, ngids)); case SIDSYS_IDMAP_REG: return (idmap_reg(flag)); case SIDSYS_IDMAP_UNREG: return (idmap_unreg(flag)); case SIDSYS_IDMAP_FLUSH_KCACHE: return (idmap_flush_kcache()); default: return (set_errno(EINVAL)); } }