Remove building with NOCRYPTO option
[minix3.git] / minix / servers / pm / getset.c
blobf3d2e1202c240332043db9f8d7b87abe7c28a3d7
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"
15 /*===========================================================================*
16 * do_get *
17 *===========================================================================*/
18 int
19 do_get(void)
21 /* Handle PM_GETUID, PM_GETGID, PM_GETGROUPS, PM_GETPID, PM_GETPGRP, PM_GETSID,
22 * PM_ISSETUGID.
24 register struct mproc *rmp = mp;
25 int r;
26 int ngroups;
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);
34 if (ngroups == 0) {
35 r = rmp->mp_ngroups;
36 break;
39 if (ngroups < rmp->mp_ngroups)
40 /* Asking for less groups than available */
41 return(EINVAL);
43 r = sys_datacopy(SELF, (vir_bytes) rmp->mp_sgroups, who_e,
44 m_in.m_lc_pm_groups.ptr, ngroups * sizeof(gid_t));
46 if (r != OK)
47 return(r);
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;
56 case PM_GETGID:
57 r = rmp->mp_realgid;
58 rmp->mp_reply.m_pm_lc_getgid.egid = rmp->mp_effgid;
59 break;
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;
66 case PM_GETPGRP:
67 r = rmp->mp_procgrp;
68 break;
70 case PM_GETSID:
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;
80 case PM_ISSETUGID:
81 r = !!(rmp->mp_flags & TAINTED);
82 break;
84 default:
85 r = EINVAL;
86 break;
88 return(r);
91 /*===========================================================================*
92 * do_set *
93 *===========================================================================*/
94 int
95 do_set(void)
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.
101 register struct mproc *rmp = mp;
102 message m;
103 int r, i;
104 int ngroups;
105 uid_t uid;
106 gid_t gid;
108 memset(&m, 0, sizeof(m));
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;
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;
126 break;
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;
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;
141 break;
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;
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;
156 break;
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;
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;
170 break;
172 case PM_SETGROUPS:
173 if (rmp->mp_effuid != SUPER_USER)
174 return(EPERM);
176 ngroups = m_in.m_lc_pm_groups.num;
178 if (ngroups > NGROUPS_MAX || ngroups < 0)
179 return(EINVAL);
181 if (ngroups > 0 && m_in.m_lc_pm_groups.ptr == 0)
182 return(EFAULT);
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);
190 for (i = 0; i < ngroups; i++) {
191 if (rmp->mp_sgroups[i] > GID_MAX)
192 return(EINVAL);
194 for (i = ngroups; i < NGROUPS_MAX; i++) {
195 rmp->mp_sgroups[i] = 0;
197 rmp->mp_ngroups = ngroups;
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;
204 break;
205 case PM_SETSID:
206 if (rmp->mp_procgrp == rmp->mp_pid) return(EPERM);
207 rmp->mp_procgrp = rmp->mp_pid;
209 m.m_type = VFS_PM_SETSID;
210 m.VFS_PM_ENDPT = rmp->mp_endpoint;
212 break;
214 default:
215 return(EINVAL);
218 /* Send the request to VFS */
219 tell_vfs(rmp, &m);
221 /* Do not reply until VFS has processed the request */
222 return(SUSPEND);