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 case PM_SETEUID: 111 uid = m_in.m_lc_pm_setuid.uid; 112 if (rmp->mp_realuid != uid && rmp->mp_effuid != SUPER_USER) 113 return(EPERM); 114 if(call_nr == PM_SETUID) rmp->mp_realuid = uid; 115 rmp->mp_effuid = uid; 116 117 m.m_type = VFS_PM_SETUID; 118 m.VFS_PM_ENDPT = rmp->mp_endpoint; 119 m.VFS_PM_EID = rmp->mp_effuid; 120 m.VFS_PM_RID = rmp->mp_realuid; 121 122 break; 123 124 case PM_SETGID: 125 case PM_SETEGID: 126 gid = m_in.m_lc_pm_setgid.gid; 127 if (rmp->mp_realgid != gid && rmp->mp_effuid != SUPER_USER) 128 return(EPERM); 129 if(call_nr == PM_SETGID) rmp->mp_realgid = gid; 130 rmp->mp_effgid = gid; 131 132 m.m_type = VFS_PM_SETGID; 133 m.VFS_PM_ENDPT = rmp->mp_endpoint; 134 m.VFS_PM_EID = rmp->mp_effgid; 135 m.VFS_PM_RID = rmp->mp_realgid; 136 137 break; 138 case PM_SETGROUPS: 139 if (rmp->mp_effuid != SUPER_USER) 140 return(EPERM); 141 142 ngroups = m_in.m_lc_pm_groups.num; 143 144 if (ngroups > NGROUPS_MAX || ngroups < 0) 145 return(EINVAL); 146 147 if (ngroups > 0 && m_in.m_lc_pm_groups.ptr == 0) 148 return(EFAULT); 149 150 r = sys_datacopy(who_e, m_in.m_lc_pm_groups.ptr, SELF, 151 (vir_bytes) rmp->mp_sgroups, 152 ngroups * sizeof(gid_t)); 153 if (r != OK) 154 return(r); 155 156 for (i = 0; i < ngroups; i++) { 157 if (rmp->mp_sgroups[i] > GID_MAX) 158 return(EINVAL); 159 } 160 for (i = ngroups; i < NGROUPS_MAX; i++) { 161 rmp->mp_sgroups[i] = 0; 162 } 163 rmp->mp_ngroups = ngroups; 164 165 m.m_type = VFS_PM_SETGROUPS; 166 m.VFS_PM_ENDPT = rmp->mp_endpoint; 167 m.VFS_PM_GROUP_NO = rmp->mp_ngroups; 168 m.VFS_PM_GROUP_ADDR = (char *) rmp->mp_sgroups; 169 170 break; 171 case PM_SETSID: 172 if (rmp->mp_procgrp == rmp->mp_pid) return(EPERM); 173 rmp->mp_procgrp = rmp->mp_pid; 174 175 m.m_type = VFS_PM_SETSID; 176 m.VFS_PM_ENDPT = rmp->mp_endpoint; 177 178 break; 179 180 default: 181 return(EINVAL); 182 } 183 184 /* Send the request to VFS */ 185 tell_vfs(rmp, &m); 186 187 /* Do not reply until VFS has processed the request */ 188 return(SUSPEND); 189 } 190