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