1 /* This file handles the 6 system calls that get and set uids and gids. 2 * It also handles getpid(), setsid(), and getpgrp(). The code for each 3 * one is so tiny that it hardly seemed worthwhile to make each a separate 4 * function. 5 */ 6 7 #include "pm.h" 8 #include <minix/callnr.h> 9 #include <minix/endpoint.h> 10 #include <limits.h> 11 #include <minix/com.h> 12 #include <signal.h> 13 #include "mproc.h" 14 15 /*===========================================================================* 16 * do_get * 17 *===========================================================================*/ 18 int 19 do_get(void) 20 { 21 /* Handle PM_GETUID, PM_GETGID, PM_GETGROUPS, PM_GETPID, PM_GETPGRP, PM_GETSID, 22 * PM_ISSETUGID. 23 */ 24 register struct mproc *rmp = mp; 25 int r; 26 int ngroups; 27 28 switch(call_nr) { 29 case PM_GETGROUPS: 30 ngroups = m_in.m_lc_pm_groups.num; 31 if (ngroups > NGROUPS_MAX || ngroups < 0) 32 return(EINVAL); 33 34 if (ngroups == 0) { 35 r = rmp->mp_ngroups; 36 break; 37 } 38 39 if (ngroups < rmp->mp_ngroups) 40 /* Asking for less groups than available */ 41 return(EINVAL); 42 43 r = sys_datacopy(SELF, (vir_bytes) rmp->mp_sgroups, who_e, 44 m_in.m_lc_pm_groups.ptr, ngroups * sizeof(gid_t)); 45 46 if (r != OK) 47 return(r); 48 49 r = rmp->mp_ngroups; 50 break; 51 case PM_GETUID: 52 r = rmp->mp_realuid; 53 rmp->mp_reply.m_pm_lc_getuid.euid = rmp->mp_effuid; 54 break; 55 56 case PM_GETGID: 57 r = rmp->mp_realgid; 58 rmp->mp_reply.m_pm_lc_getgid.egid = rmp->mp_effgid; 59 break; 60 61 case PM_GETPID: 62 r = mproc[who_p].mp_pid; 63 rmp->mp_reply.m_pm_lc_getpid.parent_pid = mproc[rmp->mp_parent].mp_pid; 64 break; 65 66 case PM_GETPGRP: 67 r = rmp->mp_procgrp; 68 break; 69 70 case PM_GETSID: 71 { 72 struct mproc *target; 73 pid_t p = m_in.m_lc_pm_getsid.pid; 74 target = p ? find_proc(p) : &mproc[who_p]; 75 r = ESRCH; 76 if(target) 77 r = target->mp_procgrp; 78 break; 79 } 80 case PM_ISSETUGID: 81 r = !!(rmp->mp_flags & TAINTED); 82 break; 83 84 default: 85 r = EINVAL; 86 break; 87 } 88 return(r); 89 } 90 91 /*===========================================================================* 92 * do_set * 93 *===========================================================================*/ 94 int 95 do_set(void) 96 { 97 /* Handle PM_SETUID, PM_SETEUID, PM_SETGID, PM_SETGROUPS, PM_SETEGID, and 98 * SETSID. These calls have in common that, if successful, they will be 99 * forwarded to VFS as well. 100 */ 101 register struct mproc *rmp = mp; 102 message m; 103 int r, i; 104 int ngroups; 105 uid_t uid; 106 gid_t gid; 107 108 memset(&m, 0, sizeof(m)); 109 110 switch(call_nr) { 111 case PM_SETUID: 112 uid = m_in.m_lc_pm_setuid.uid; 113 /* NetBSD specific semantics: setuid(geteuid()) may fail. */ 114 if (rmp->mp_realuid != uid && rmp->mp_effuid != SUPER_USER) 115 return(EPERM); 116 /* BSD semantics: always update all three fields. */ 117 rmp->mp_realuid = uid; 118 rmp->mp_effuid = uid; 119 rmp->mp_svuid = uid; 120 121 m.m_type = VFS_PM_SETUID; 122 m.VFS_PM_ENDPT = rmp->mp_endpoint; 123 m.VFS_PM_EID = rmp->mp_effuid; 124 m.VFS_PM_RID = rmp->mp_realuid; 125 126 break; 127 128 case PM_SETEUID: 129 uid = m_in.m_lc_pm_setuid.uid; 130 /* BSD semantics: seteuid(geteuid()) may fail. */ 131 if (rmp->mp_realuid != uid && rmp->mp_svuid != uid && 132 rmp->mp_effuid != SUPER_USER) 133 return(EPERM); 134 rmp->mp_effuid = uid; 135 136 m.m_type = VFS_PM_SETUID; 137 m.VFS_PM_ENDPT = rmp->mp_endpoint; 138 m.VFS_PM_EID = rmp->mp_effuid; 139 m.VFS_PM_RID = rmp->mp_realuid; 140 141 break; 142 143 case PM_SETGID: 144 gid = m_in.m_lc_pm_setgid.gid; 145 if (rmp->mp_realgid != gid && rmp->mp_effuid != SUPER_USER) 146 return(EPERM); 147 rmp->mp_realgid = gid; 148 rmp->mp_effgid = gid; 149 rmp->mp_svgid = gid; 150 151 m.m_type = VFS_PM_SETGID; 152 m.VFS_PM_ENDPT = rmp->mp_endpoint; 153 m.VFS_PM_EID = rmp->mp_effgid; 154 m.VFS_PM_RID = rmp->mp_realgid; 155 156 break; 157 158 case PM_SETEGID: 159 gid = m_in.m_lc_pm_setgid.gid; 160 if (rmp->mp_realgid != gid && rmp->mp_svgid != gid && 161 rmp->mp_effuid != SUPER_USER) 162 return(EPERM); 163 rmp->mp_effgid = gid; 164 165 m.m_type = VFS_PM_SETGID; 166 m.VFS_PM_ENDPT = rmp->mp_endpoint; 167 m.VFS_PM_EID = rmp->mp_effgid; 168 m.VFS_PM_RID = rmp->mp_realgid; 169 170 break; 171 172 case PM_SETGROUPS: 173 if (rmp->mp_effuid != SUPER_USER) 174 return(EPERM); 175 176 ngroups = m_in.m_lc_pm_groups.num; 177 178 if (ngroups > NGROUPS_MAX || ngroups < 0) 179 return(EINVAL); 180 181 if (ngroups > 0 && m_in.m_lc_pm_groups.ptr == 0) 182 return(EFAULT); 183 184 r = sys_datacopy(who_e, m_in.m_lc_pm_groups.ptr, SELF, 185 (vir_bytes) rmp->mp_sgroups, 186 ngroups * sizeof(gid_t)); 187 if (r != OK) 188 return(r); 189 190 for (i = 0; i < ngroups; i++) { 191 if (rmp->mp_sgroups[i] > GID_MAX) 192 return(EINVAL); 193 } 194 for (i = ngroups; i < NGROUPS_MAX; i++) { 195 rmp->mp_sgroups[i] = 0; 196 } 197 rmp->mp_ngroups = ngroups; 198 199 m.m_type = VFS_PM_SETGROUPS; 200 m.VFS_PM_ENDPT = rmp->mp_endpoint; 201 m.VFS_PM_GROUP_NO = rmp->mp_ngroups; 202 m.VFS_PM_GROUP_ADDR = (char *) rmp->mp_sgroups; 203 204 break; 205 case PM_SETSID: 206 if (rmp->mp_procgrp == rmp->mp_pid) return(EPERM); 207 rmp->mp_procgrp = rmp->mp_pid; 208 209 m.m_type = VFS_PM_SETSID; 210 m.VFS_PM_ENDPT = rmp->mp_endpoint; 211 212 break; 213 214 default: 215 return(EINVAL); 216 } 217 218 /* Send the request to VFS */ 219 tell_vfs(rmp, &m); 220 221 /* Do not reply until VFS has processed the request */ 222 return(SUSPEND); 223 } 224