VM: static data structure for mem allocation
[minix3.git] / servers / pm / getset.c
blob5354339df6d6f71b3e6a5fb4c6770ce0de6ce4fe
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 */
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 #include "param.h"
16 /*===========================================================================*
17 * do_get *
18 *===========================================================================*/
19 int do_get()
21 /* Handle GETUID, GETGID, GETGROUPS, GETGROUPS_O, GETPID, GETPGRP, GETSID,
22 ISSETUGID.
25 register struct mproc *rmp = mp;
26 int r, i;
27 int ngroups;
28 char sgroups[NGROUPS_MAX]; /* XXX: Temp storage for GETGROUPS_O */
30 switch(call_nr) {
31 case GETGROUPS_O:
32 ngroups = m_in.grp_no;
33 if (ngroups > NGROUPS_MAX || ngroups < 0)
34 return(EINVAL);
36 if (ngroups == 0) {
37 r = rmp->mp_ngroups;
38 break;
41 if (ngroups < rmp->mp_ngroups)
42 /* Asking for less groups than available */
43 return(EINVAL);
45 for (i = 0; i < ngroups; i++)
46 sgroups[i] = (char) rmp->mp_sgroups[i];
48 r = sys_datacopy(SELF, (vir_bytes) &sgroups, who_e,
49 (vir_bytes) m_in.groupsp, ngroups * sizeof(char));
51 if (r != OK)
52 return(r);
54 r = rmp->mp_ngroups;
55 break;
56 case GETGROUPS:
57 ngroups = m_in.grp_no;
58 if (ngroups > NGROUPS_MAX || ngroups < 0)
59 return(EINVAL);
61 if (ngroups == 0) {
62 r = rmp->mp_ngroups;
63 break;
66 if (ngroups < rmp->mp_ngroups)
67 /* Asking for less groups than available */
68 return(EINVAL);
70 r = sys_datacopy(SELF, (vir_bytes) rmp->mp_sgroups, who_e,
71 (vir_bytes) m_in.groupsp, ngroups * sizeof(gid_t));
73 if (r != OK)
74 return(r);
76 r = rmp->mp_ngroups;
77 break;
78 case GETUID:
79 r = rmp->mp_realuid;
80 rmp->mp_reply.reply_res2 = rmp->mp_effuid;
81 break;
83 case GETGID:
84 r = rmp->mp_realgid;
85 rmp->mp_reply.reply_res2 = rmp->mp_effgid;
86 break;
88 case MINIX_GETPID:
89 r = mproc[who_p].mp_pid;
90 rmp->mp_reply.reply_res2 = mproc[rmp->mp_parent].mp_pid;
91 break;
93 case GETPGRP:
94 r = rmp->mp_procgrp;
95 break;
97 case PM_GETSID:
99 struct mproc *target;
100 pid_t p = m_in.PM_GETSID_PID;
101 target = p ? find_proc(p) : &mproc[who_p];
102 r = ESRCH;
103 if(target)
104 r = target->mp_procgrp;
105 break;
107 case ISSETUGID:
108 r = !!(rmp->mp_flags & TAINTED);
109 break;
111 default:
112 r = EINVAL;
113 break;
115 return(r);
118 /*===========================================================================*
119 * do_set *
120 *===========================================================================*/
121 int do_set()
123 /* Handle SETUID, SETEUID, SETGID, SETEGID, SETSID. These calls have in common
124 * that, if successful, they will be forwarded to VFS as well.
126 register struct mproc *rmp = mp;
127 message m;
128 int r, i;
129 int ngroups;
130 char sgroups[NGROUPS_MAX]; /* XXX: Temp storage for SETGROUPS_O */
133 switch(call_nr) {
134 case SETUID:
135 case SETEUID:
136 if (rmp->mp_realuid != (uid_t) m_in.usr_id &&
137 rmp->mp_effuid != SUPER_USER)
138 return(EPERM);
139 if(call_nr == SETUID) rmp->mp_realuid = (uid_t) m_in.usr_id;
140 rmp->mp_effuid = (uid_t) m_in.usr_id;
142 m.m_type = PM_SETUID;
143 m.PM_PROC = rmp->mp_endpoint;
144 m.PM_EID = rmp->mp_effuid;
145 m.PM_RID = rmp->mp_realuid;
147 break;
149 case SETGID:
150 case SETEGID:
151 if (rmp->mp_realgid != (gid_t) m_in.grp_id &&
152 rmp->mp_effuid != SUPER_USER)
153 return(EPERM);
154 if(call_nr == SETGID) rmp->mp_realgid = (gid_t) m_in.grp_id;
155 rmp->mp_effgid = (gid_t) m_in.grp_id;
157 m.m_type = PM_SETGID;
158 m.PM_PROC = rmp->mp_endpoint;
159 m.PM_EID = rmp->mp_effgid;
160 m.PM_RID = rmp->mp_realgid;
162 break;
163 case SETGROUPS:
164 if (rmp->mp_effuid != SUPER_USER)
165 return(EPERM);
167 ngroups = m_in.grp_no;
169 if (ngroups > NGROUPS_MAX || ngroups < 0)
170 return(EINVAL);
172 if (m_in.groupsp == NULL)
173 return(EFAULT);
175 r = sys_datacopy(who_e, (vir_bytes) m_in.groupsp, SELF,
176 (vir_bytes) rmp->mp_sgroups,
177 ngroups * sizeof(gid_t));
178 if (r != OK)
179 return(r);
181 for (i = 0; i < ngroups; i++) {
182 if (rmp->mp_sgroups[i] > GID_MAX)
183 return(EINVAL);
185 for (i = ngroups; i < NGROUPS_MAX; i++) {
186 rmp->mp_sgroups[i] = 0;
188 rmp->mp_ngroups = ngroups;
190 m.m_type = PM_SETGROUPS;
191 m.PM_PROC = rmp->mp_endpoint;
192 m.PM_GROUP_NO = rmp->mp_ngroups;
193 m.PM_GROUP_ADDR = (char *) rmp->mp_sgroups;
195 break;
196 case SETGROUPS_O:
197 if (rmp->mp_effuid != SUPER_USER)
198 return(EPERM);
200 ngroups = m_in.grp_no;
202 if (ngroups > NGROUPS_MAX || ngroups < 0)
203 return(EINVAL);
205 if (m_in.groupsp == NULL)
206 return(EFAULT);
208 r = sys_datacopy(who_e, (vir_bytes) m_in.groupsp, SELF,
209 (vir_bytes) &sgroups, ngroups * sizeof(char));
210 if (r != OK)
211 return(r);
213 for (i = 0; i < ngroups; i++)
214 rmp->mp_sgroups[i] = (gid_t) sgroups[i];
215 for (i = ngroups; i < NGROUPS_MAX; i++)
216 rmp->mp_sgroups[i] = 0;
217 rmp->mp_ngroups = ngroups;
219 m.m_type = PM_SETGROUPS;
220 m.PM_PROC = rmp->mp_endpoint;
221 m.PM_GROUP_NO = rmp->mp_ngroups;
222 m.PM_GROUP_ADDR = (char *) rmp->mp_sgroups;
224 break;
225 case SETSID:
226 if (rmp->mp_procgrp == rmp->mp_pid) return(EPERM);
227 rmp->mp_procgrp = rmp->mp_pid;
229 m.m_type = PM_SETSID;
230 m.PM_PROC = rmp->mp_endpoint;
232 break;
234 default:
235 return(EINVAL);
238 /* Send the request to VFS */
239 tell_vfs(rmp, &m);
241 /* Do not reply until VFS has processed the request */
242 return(SUSPEND);