1 /* 2 * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC. 3 * Copyright (C) 2007 The Regents of the University of California. 4 * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). 5 * Written by Brian Behlendorf <behlendorf1@llnl.gov>. 6 * UCRL-CODE-235197 7 * 8 * This file is part of the SPL, Solaris Porting Layer. 9 * For details, see <http://zfsonlinux.org/>. 10 * 11 * The SPL is free software; you can redistribute it and/or modify it 12 * under the terms of the GNU General Public License as published by the 13 * Free Software Foundation; either version 2 of the License, or (at your 14 * option) any later version. 15 * 16 * The SPL is distributed in the hope that it will be useful, but WITHOUT 17 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 18 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 19 * for more details. 20 * 21 * You should have received a copy of the GNU General Public License along 22 * with the SPL. If not, see <http://www.gnu.org/licenses/>. 23 * 24 * Solaris Porting Layer (SPL) Credential Implementation. 25 */ 26 27 #include <sys/cred.h> 28 29 static int 30 cr_groups_search(const struct group_info *group_info, kgid_t grp) 31 { 32 unsigned int left, right, mid; 33 int cmp; 34 35 if (!group_info) 36 return (0); 37 38 left = 0; 39 right = group_info->ngroups; 40 while (left < right) { 41 mid = (left + right) / 2; 42 cmp = KGID_TO_SGID(grp) - 43 KGID_TO_SGID(GROUP_AT(group_info, mid)); 44 45 if (cmp > 0) 46 left = mid + 1; 47 else if (cmp < 0) 48 right = mid; 49 else 50 return (1); 51 } 52 return (0); 53 } 54 55 /* Hold a reference on the credential */ 56 void 57 crhold(cred_t *cr) 58 { 59 (void) get_cred((const cred_t *)cr); 60 } 61 62 /* Free a reference on the credential */ 63 void 64 crfree(cred_t *cr) 65 { 66 put_cred((const cred_t *)cr); 67 } 68 69 /* Return the number of supplemental groups */ 70 int 71 crgetngroups(const cred_t *cr) 72 { 73 struct group_info *gi; 74 int rc; 75 76 gi = cr->group_info; 77 rc = gi->ngroups; 78 #ifndef HAVE_GROUP_INFO_GID 79 /* 80 * For Linux <= 4.8, 81 * crgetgroups will only returns gi->blocks[0], which contains only 82 * the first NGROUPS_PER_BLOCK groups. 83 */ 84 if (rc > NGROUPS_PER_BLOCK) { 85 WARN_ON_ONCE(1); 86 rc = NGROUPS_PER_BLOCK; 87 } 88 #endif 89 return (rc); 90 } 91 92 /* 93 * Return an array of supplemental gids. The returned address is safe 94 * to use as long as the caller has taken a reference with crhold(). 95 * 96 * Linux 4.9 API change, group_info changed from 2d array via ->blocks to 1d 97 * array via ->gid. 98 */ 99 gid_t * 100 crgetgroups(const cred_t *cr) 101 { 102 struct group_info *gi; 103 gid_t *gids = NULL; 104 105 gi = cr->group_info; 106 #ifdef HAVE_GROUP_INFO_GID 107 gids = KGIDP_TO_SGIDP(gi->gid); 108 #else 109 if (gi->nblocks > 0) 110 gids = KGIDP_TO_SGIDP(gi->blocks[0]); 111 #endif 112 return (gids); 113 } 114 115 /* Check if the passed gid is available in supplied credential. */ 116 int 117 groupmember(gid_t gid, const cred_t *cr) 118 { 119 struct group_info *gi; 120 int rc; 121 122 gi = cr->group_info; 123 rc = cr_groups_search(gi, SGID_TO_KGID(gid)); 124 125 return (rc); 126 } 127 128 /* Return the effective user id */ 129 uid_t 130 crgetuid(const cred_t *cr) 131 { 132 return (KUID_TO_SUID(cr->euid)); 133 } 134 135 /* Return the real user id */ 136 uid_t 137 crgetruid(const cred_t *cr) 138 { 139 return (KUID_TO_SUID(cr->uid)); 140 } 141 142 /* Return the saved user id */ 143 uid_t 144 crgetsuid(const cred_t *cr) 145 { 146 return (KUID_TO_SUID(cr->suid)); 147 } 148 149 /* Return the filesystem user id */ 150 uid_t 151 crgetfsuid(const cred_t *cr) 152 { 153 return (KUID_TO_SUID(cr->fsuid)); 154 } 155 156 /* Return the effective group id */ 157 gid_t 158 crgetgid(const cred_t *cr) 159 { 160 return (KGID_TO_SGID(cr->egid)); 161 } 162 163 /* Return the real group id */ 164 gid_t 165 crgetrgid(const cred_t *cr) 166 { 167 return (KGID_TO_SGID(cr->gid)); 168 } 169 170 /* Return the saved group id */ 171 gid_t 172 crgetsgid(const cred_t *cr) 173 { 174 return (KGID_TO_SGID(cr->sgid)); 175 } 176 177 /* Return the filesystem group id */ 178 gid_t 179 crgetfsgid(const cred_t *cr) 180 { 181 return (KGID_TO_SGID(cr->fsgid)); 182 } 183 184 EXPORT_SYMBOL(crhold); 185 EXPORT_SYMBOL(crfree); 186 EXPORT_SYMBOL(crgetuid); 187 EXPORT_SYMBOL(crgetruid); 188 EXPORT_SYMBOL(crgetsuid); 189 EXPORT_SYMBOL(crgetfsuid); 190 EXPORT_SYMBOL(crgetgid); 191 EXPORT_SYMBOL(crgetrgid); 192 EXPORT_SYMBOL(crgetsgid); 193 EXPORT_SYMBOL(crgetfsgid); 194 EXPORT_SYMBOL(crgetngroups); 195 EXPORT_SYMBOL(crgetgroups); 196 EXPORT_SYMBOL(groupmember); 197