17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5f48205beScasper * Common Development and Distribution License (the "License"). 6f48205beScasper * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 227c478bd9Sstevel@tonic-gate * Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T 23*67dbe2beSCasper H.S. Dik * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate #include <sys/param.h> 297c478bd9Sstevel@tonic-gate #include <sys/types.h> 307c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 317c478bd9Sstevel@tonic-gate #include <sys/systm.h> 32*67dbe2beSCasper H.S. Dik #include <sys/cred.h> 33*67dbe2beSCasper H.S. Dik #include <sys/sid.h> 347c478bd9Sstevel@tonic-gate #include <sys/errno.h> 357c478bd9Sstevel@tonic-gate #include <sys/proc.h> 367c478bd9Sstevel@tonic-gate #include <sys/debug.h> 377c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 387c478bd9Sstevel@tonic-gate #include <sys/policy.h> 397c478bd9Sstevel@tonic-gate 407c478bd9Sstevel@tonic-gate int 417c478bd9Sstevel@tonic-gate setgroups(int gidsetsize, gid_t *gidset) 427c478bd9Sstevel@tonic-gate { 437c478bd9Sstevel@tonic-gate proc_t *p; 447c478bd9Sstevel@tonic-gate cred_t *cr, *newcr; 457c478bd9Sstevel@tonic-gate int i; 467c478bd9Sstevel@tonic-gate int n = gidsetsize; 477c478bd9Sstevel@tonic-gate int error; 48f48205beScasper int scnt = 0; 49f48205beScasper ksidlist_t *ksl = NULL; 50bda89588Sjp151216 zone_t *zone; 51*67dbe2beSCasper H.S. Dik struct credgrp *grps = NULL; 527c478bd9Sstevel@tonic-gate 537c478bd9Sstevel@tonic-gate /* Perform the cheapest tests before grabbing p_crlock */ 547c478bd9Sstevel@tonic-gate if (n > ngroups_max || n < 0) 557c478bd9Sstevel@tonic-gate return (set_errno(EINVAL)); 567c478bd9Sstevel@tonic-gate 57bda89588Sjp151216 zone = crgetzone(CRED()); 587c478bd9Sstevel@tonic-gate if (n != 0) { 59*67dbe2beSCasper H.S. Dik const gid_t *groups; 607c478bd9Sstevel@tonic-gate 61*67dbe2beSCasper H.S. Dik grps = crgrpcopyin(n, gidset); 62*67dbe2beSCasper H.S. Dik 63*67dbe2beSCasper H.S. Dik if (grps == NULL) 647c478bd9Sstevel@tonic-gate return (set_errno(EFAULT)); 65*67dbe2beSCasper H.S. Dik 66*67dbe2beSCasper H.S. Dik groups = crgetggroups(grps); 677c478bd9Sstevel@tonic-gate 687c478bd9Sstevel@tonic-gate for (i = 0; i < n; i++) { 69bda89588Sjp151216 if (!VALID_GID(groups[i], zone)) { 70*67dbe2beSCasper H.S. Dik crgrprele(grps); 71f48205beScasper return (set_errno(EINVAL)); 72f48205beScasper } 73f48205beScasper if (groups[i] > MAXUID) 74f48205beScasper scnt++; 75f48205beScasper } 76f48205beScasper if (scnt > 0) { 77*67dbe2beSCasper H.S. Dik ksl = kcrsid_gidstosids(zone, n, (gid_t *)groups); 78f48205beScasper if (ksl == NULL) { 79*67dbe2beSCasper H.S. Dik crgrprele(grps); 807c478bd9Sstevel@tonic-gate return (set_errno(EINVAL)); 817c478bd9Sstevel@tonic-gate } 827c478bd9Sstevel@tonic-gate } 837c478bd9Sstevel@tonic-gate } 847c478bd9Sstevel@tonic-gate 85f48205beScasper 867c478bd9Sstevel@tonic-gate /* 877c478bd9Sstevel@tonic-gate * Need to pre-allocate the new cred structure before acquiring 887c478bd9Sstevel@tonic-gate * the p_crlock mutex. 897c478bd9Sstevel@tonic-gate */ 90f48205beScasper newcr = cralloc_ksid(); 917c478bd9Sstevel@tonic-gate p = ttoproc(curthread); 927c478bd9Sstevel@tonic-gate mutex_enter(&p->p_crlock); 93ddf7fe95Scasper retry: 947c478bd9Sstevel@tonic-gate cr = p->p_cred; 95ddf7fe95Scasper crhold(cr); 96ddf7fe95Scasper mutex_exit(&p->p_crlock); 977c478bd9Sstevel@tonic-gate 987c478bd9Sstevel@tonic-gate if ((error = secpolicy_allow_setid(cr, -1, B_FALSE)) != 0) { 99*67dbe2beSCasper H.S. Dik if (grps != NULL) 100*67dbe2beSCasper H.S. Dik crgrprele(grps); 101f48205beScasper if (ksl != NULL) 102f48205beScasper ksidlist_rele(ksl); 1037c478bd9Sstevel@tonic-gate crfree(newcr); 104ddf7fe95Scasper crfree(cr); 1057c478bd9Sstevel@tonic-gate return (set_errno(error)); 1067c478bd9Sstevel@tonic-gate } 107ddf7fe95Scasper mutex_enter(&p->p_crlock); 108ddf7fe95Scasper crfree(cr); 109ddf7fe95Scasper if (cr != p->p_cred) 110ddf7fe95Scasper goto retry; 1117c478bd9Sstevel@tonic-gate 1127c478bd9Sstevel@tonic-gate crdup_to(cr, newcr); 113f48205beScasper crsetsidlist(newcr, ksl); 114*67dbe2beSCasper H.S. Dik crsetcredgrp(newcr, grps); 1157c478bd9Sstevel@tonic-gate 1167c478bd9Sstevel@tonic-gate p->p_cred = newcr; 1177c478bd9Sstevel@tonic-gate crhold(newcr); /* hold for the current thread */ 1187c478bd9Sstevel@tonic-gate crfree(cr); /* free the old one */ 1197c478bd9Sstevel@tonic-gate mutex_exit(&p->p_crlock); 1207c478bd9Sstevel@tonic-gate 1217c478bd9Sstevel@tonic-gate /* 1227c478bd9Sstevel@tonic-gate * Broadcast new cred to process threads (including the current one). 1237c478bd9Sstevel@tonic-gate */ 1247c478bd9Sstevel@tonic-gate crset(p, newcr); 1257c478bd9Sstevel@tonic-gate 1267c478bd9Sstevel@tonic-gate return (0); 1277c478bd9Sstevel@tonic-gate } 1287c478bd9Sstevel@tonic-gate 1297c478bd9Sstevel@tonic-gate int 1307c478bd9Sstevel@tonic-gate getgroups(int gidsetsize, gid_t *gidset) 1317c478bd9Sstevel@tonic-gate { 1327c478bd9Sstevel@tonic-gate struct cred *cr; 1337c478bd9Sstevel@tonic-gate int n; 1347c478bd9Sstevel@tonic-gate 1357c478bd9Sstevel@tonic-gate cr = curthread->t_cred; 136*67dbe2beSCasper H.S. Dik n = crgetngroups(cr); 1377c478bd9Sstevel@tonic-gate 1387c478bd9Sstevel@tonic-gate if (gidsetsize != 0) { 1397c478bd9Sstevel@tonic-gate if (gidsetsize < n) 1407c478bd9Sstevel@tonic-gate return (set_errno(EINVAL)); 141*67dbe2beSCasper H.S. Dik if (copyout(crgetgroups(cr), gidset, n * sizeof (gid_t))) 1427c478bd9Sstevel@tonic-gate return (set_errno(EFAULT)); 1437c478bd9Sstevel@tonic-gate } 1447c478bd9Sstevel@tonic-gate 1457c478bd9Sstevel@tonic-gate return (n); 1467c478bd9Sstevel@tonic-gate } 147