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 2006 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 #pragma ident   "%Z%%M% %I%     %E% SMI"
  28 
  29 #include <sys/types.h>
  30 #include <sys/systm.h>
  31 #include <sys/errno.h>
  32 #include <sys/zone.h>
  33 #include <sys/lx_types.h>
  34 #include <sys/lx_syscall.h>
  35 #include <sys/cred_impl.h>
  36 #include <sys/policy.h>
  37 #include <sys/ucred.h>
  38 #include <sys/syscall.h>
  39 #include <alloca.h>
  40 #include <errno.h>
  41 #include <ucred.h>
  42 #include <unistd.h>
  43 #include <errno.h>
  44 #include <string.h>
  45 #include <sys/lx_misc.h>
  46 
  47 int
  48 lx_setuid16(uintptr_t uid)
  49 {
  50         return ((setuid(LX_UID16_TO_UID32((lx_uid16_t)uid))) ? -errno : 0);
  51 }
  52 
  53 int
  54 lx_getuid16(void)
  55 {
  56         return ((int)LX_UID32_TO_UID16(getuid()));
  57 }
  58 
  59 int
  60 lx_setgid16(uintptr_t gid)
  61 {
  62         return ((setgid(LX_GID16_TO_GID32((lx_gid16_t)gid))) ? -errno : 0);
  63 }
  64 
  65 int
  66 lx_getgid16(void)
  67 {
  68         return ((int)LX_GID32_TO_GID16(getgid()));
  69 }
  70 
  71 int
  72 lx_geteuid16(void)
  73 {
  74         return ((int)LX_UID32_TO_UID16(geteuid()));
  75 }
  76 
  77 int
  78 lx_getegid16(void)
  79 {
  80         return ((int)LX_GID32_TO_GID16(getegid()));
  81 }
  82 
  83 int
  84 lx_geteuid(void)
  85 {
  86         return ((int)geteuid());
  87 }
  88 
  89 int
  90 lx_getegid(void)
  91 {
  92         return ((int)getegid());
  93 }
  94 
  95 int
  96 lx_getresuid(uintptr_t ruid, uintptr_t euid, uintptr_t suid)
  97 {
  98         lx_uid_t lx_ruid, lx_euid, lx_suid;
  99         ucred_t *cr;
 100         size_t sz;
 101 
 102         /*
 103          * We allocate a ucred_t ourselves rather than call ucred_get(3C)
 104          * because ucred_get() calls malloc(3C), which the brand library cannot
 105          * use.  Because we allocate the space with SAFE_ALLOCA(), there's
 106          * no need to free it when we're done.
 107          */
 108         sz = ucred_size();
 109         cr = (ucred_t *)SAFE_ALLOCA(sz);
 110         if (cr == NULL)
 111                 return (-ENOMEM);
 112 
 113         if (syscall(SYS_ucredsys, UCREDSYS_UCREDGET, P_MYID, cr) != 0)
 114                 return (-errno);
 115 
 116         if (((lx_ruid = (lx_uid_t)ucred_getruid(cr)) == (lx_uid_t)-1) ||
 117             ((lx_euid = (lx_uid_t)ucred_geteuid(cr)) == (lx_uid_t)-1) ||
 118             ((lx_suid = (lx_uid_t)ucred_getsuid(cr)) == (lx_uid_t)-1)) {
 119                 return (-errno);
 120         }
 121 
 122         if (uucopy(&lx_ruid, (void *)ruid, sizeof (lx_uid_t)) != 0)
 123                 return (-errno);
 124 
 125         if (uucopy(&lx_euid, (void *)euid, sizeof (lx_uid_t)) != 0)
 126                 return (-errno);
 127 
 128         return ((uucopy(&lx_suid, (void *)suid, sizeof (lx_uid_t)) != 0)
 129             ? -errno : 0);
 130 }
 131 
 132 int
 133 lx_getresuid16(uintptr_t ruid16, uintptr_t euid16, uintptr_t suid16)
 134 {
 135         lx_uid_t lx_ruid, lx_euid, lx_suid;
 136         lx_uid16_t lx_ruid16, lx_euid16, lx_suid16;
 137         int rv;
 138 
 139         if ((rv = lx_getresuid((uintptr_t)&lx_ruid, (uintptr_t)&lx_euid,
 140             (uintptr_t)&lx_suid)) != 0)
 141                 return (rv);
 142 
 143         lx_ruid16 = LX_UID32_TO_UID16(lx_ruid);
 144         lx_euid16 = LX_UID32_TO_UID16(lx_euid);
 145         lx_suid16 = LX_UID32_TO_UID16(lx_suid);
 146 
 147         if (uucopy(&lx_ruid16, (void *)ruid16, sizeof (lx_uid16_t)) != 0)
 148                 return (-errno);
 149 
 150         if (uucopy(&lx_euid16, (void *)euid16, sizeof (lx_uid16_t)) != 0)
 151                 return (-errno);
 152 
 153         return ((uucopy(&lx_suid16, (void *)suid16, sizeof (lx_uid16_t)) != 0)
 154             ? -errno : 0);
 155 }
 156 
 157 int
 158 lx_getresgid(uintptr_t rgid, uintptr_t egid, uintptr_t sgid)
 159 {
 160         ucred_t *cr;
 161         lx_gid_t lx_rgid, lx_egid, lx_sgid;
 162         size_t sz;
 163 
 164         /*
 165          * We allocate a ucred_t ourselves rather than call ucred_get(3C)
 166          * because ucred_get() calls malloc(3C), which the brand library cannot
 167          * use.  Because we allocate the space with SAFE_ALLOCA(), there's
 168          * no need to free it when we're done.
 169          */
 170         sz = ucred_size();
 171         cr = (ucred_t *)SAFE_ALLOCA(sz);
 172         if (cr == NULL)
 173                 return (-ENOMEM);
 174 
 175         if (syscall(SYS_ucredsys, UCREDSYS_UCREDGET, P_MYID, cr) != 0)
 176                 return (-errno);
 177 
 178         if (((lx_rgid = (lx_gid_t)ucred_getrgid(cr)) == (lx_gid_t)-1) ||
 179             ((lx_egid = (lx_gid_t)ucred_getegid(cr)) == (lx_gid_t)-1) ||
 180             ((lx_sgid = (lx_gid_t)ucred_getsgid(cr)) == (lx_gid_t)-1)) {
 181                 return (-errno);
 182         }
 183 
 184         if (uucopy(&lx_rgid, (void *)rgid, sizeof (lx_gid_t)) != 0)
 185                 return (-errno);
 186 
 187         if (uucopy(&lx_egid, (void *)egid, sizeof (lx_gid_t)) != 0)
 188                 return (-errno);
 189 
 190         return ((uucopy(&lx_sgid, (void *)sgid, sizeof (lx_gid_t)) != 0)
 191             ? -errno : 0);
 192 }
 193 
 194 int
 195 lx_getresgid16(uintptr_t rgid16, uintptr_t egid16, uintptr_t sgid16)
 196 {
 197         lx_gid_t lx_rgid, lx_egid, lx_sgid;
 198         lx_gid16_t lx_rgid16, lx_egid16, lx_sgid16;
 199         int rv;
 200 
 201         if ((rv = lx_getresgid((uintptr_t)&lx_rgid, (uintptr_t)&lx_egid,
 202             (uintptr_t)&lx_sgid)) != 0)
 203                 return (rv);
 204 
 205         lx_rgid16 = LX_UID32_TO_UID16(lx_rgid);
 206         lx_egid16 = LX_UID32_TO_UID16(lx_egid);
 207         lx_sgid16 = LX_UID32_TO_UID16(lx_sgid);
 208 
 209         if (uucopy(&lx_rgid16, (void *)rgid16, sizeof (lx_gid16_t)) != 0)
 210                 return (-errno);
 211 
 212         if (uucopy(&lx_egid16, (void *)egid16, sizeof (lx_gid16_t)) != 0)
 213                 return (-errno);
 214 
 215         return ((uucopy(&lx_sgid16, (void *)sgid16, sizeof (lx_gid16_t)) != 0)
 216             ? -errno : 0);
 217 }
 218 
 219 int
 220 lx_setreuid16(uintptr_t ruid, uintptr_t euid)
 221 {
 222         return ((setreuid(LX_UID16_TO_UID32((lx_uid16_t)ruid),
 223             LX_UID16_TO_UID32((lx_uid16_t)euid))) ? -errno : 0);
 224 }
 225 
 226 int
 227 lx_setregid16(uintptr_t rgid, uintptr_t egid)
 228 {
 229         return ((setregid(LX_UID16_TO_UID32((lx_gid16_t)rgid),
 230             LX_UID16_TO_UID32((lx_gid16_t)egid))) ? -errno : 0);
 231 }
 232 
 233 /*
 234  * The lx brand cannot support the setfs[ug]id16/setfs[ug]id calls as that
 235  * would require significant rework of Solaris' privilege mechanisms, so
 236  * instead return the current effective [ug]id.
 237  *
 238  * In Linux, fsids track effective IDs, so returning the effective IDs works
 239  * as a substitute; returning the current value also denotes failure of the
 240  * call if the caller had specified something different.  We don't need to
 241  * worry about setting error codes because the Linux calls don't set any.
 242  */
 243 /*ARGSUSED*/
 244 int
 245 lx_setfsuid16(uintptr_t fsuid16)
 246 {
 247         return (lx_geteuid16());
 248 }
 249 
 250 /*ARGSUSED*/
 251 int
 252 lx_setfsgid16(uintptr_t fsgid16)
 253 {
 254         return (lx_getegid16());
 255 }
 256 
 257 /*ARGSUSED*/
 258 int
 259 lx_setfsuid(uintptr_t fsuid)
 260 {
 261         return (geteuid());
 262 }
 263 
 264 /*ARGSUSED*/
 265 int
 266 lx_setfsgid(uintptr_t fsgid)
 267 {
 268         return (getegid());
 269 }