1433d6423SLionel Sambuc /* This file handles the 6 system calls that get and set uids and gids.
2433d6423SLionel Sambuc * It also handles getpid(), setsid(), and getpgrp(). The code for each
3433d6423SLionel Sambuc * one is so tiny that it hardly seemed worthwhile to make each a separate
4433d6423SLionel Sambuc * function.
5433d6423SLionel Sambuc */
6433d6423SLionel Sambuc
7433d6423SLionel Sambuc #include "pm.h"
8433d6423SLionel Sambuc #include <minix/callnr.h>
9433d6423SLionel Sambuc #include <minix/endpoint.h>
10433d6423SLionel Sambuc #include <limits.h>
11433d6423SLionel Sambuc #include <minix/com.h>
12433d6423SLionel Sambuc #include <signal.h>
13433d6423SLionel Sambuc #include "mproc.h"
14433d6423SLionel Sambuc
15433d6423SLionel Sambuc /*===========================================================================*
16433d6423SLionel Sambuc * do_get *
17433d6423SLionel Sambuc *===========================================================================*/
18*637f688fSRichard Sailer int
do_get(void)19*637f688fSRichard Sailer do_get(void)
20433d6423SLionel Sambuc {
21433d6423SLionel Sambuc /* Handle PM_GETUID, PM_GETGID, PM_GETGROUPS, PM_GETPID, PM_GETPGRP, PM_GETSID,
22433d6423SLionel Sambuc * PM_ISSETUGID.
23433d6423SLionel Sambuc */
24433d6423SLionel Sambuc register struct mproc *rmp = mp;
25433d6423SLionel Sambuc int r;
26433d6423SLionel Sambuc int ngroups;
27433d6423SLionel Sambuc
28433d6423SLionel Sambuc switch(call_nr) {
29433d6423SLionel Sambuc case PM_GETGROUPS:
30433d6423SLionel Sambuc ngroups = m_in.m_lc_pm_groups.num;
31433d6423SLionel Sambuc if (ngroups > NGROUPS_MAX || ngroups < 0)
32433d6423SLionel Sambuc return(EINVAL);
33433d6423SLionel Sambuc
34433d6423SLionel Sambuc if (ngroups == 0) {
35433d6423SLionel Sambuc r = rmp->mp_ngroups;
36433d6423SLionel Sambuc break;
37433d6423SLionel Sambuc }
38433d6423SLionel Sambuc
39433d6423SLionel Sambuc if (ngroups < rmp->mp_ngroups)
40433d6423SLionel Sambuc /* Asking for less groups than available */
41433d6423SLionel Sambuc return(EINVAL);
42433d6423SLionel Sambuc
43433d6423SLionel Sambuc r = sys_datacopy(SELF, (vir_bytes) rmp->mp_sgroups, who_e,
44433d6423SLionel Sambuc m_in.m_lc_pm_groups.ptr, ngroups * sizeof(gid_t));
45433d6423SLionel Sambuc
46433d6423SLionel Sambuc if (r != OK)
47433d6423SLionel Sambuc return(r);
48433d6423SLionel Sambuc
49433d6423SLionel Sambuc r = rmp->mp_ngroups;
50433d6423SLionel Sambuc break;
51433d6423SLionel Sambuc case PM_GETUID:
52433d6423SLionel Sambuc r = rmp->mp_realuid;
53433d6423SLionel Sambuc rmp->mp_reply.m_pm_lc_getuid.euid = rmp->mp_effuid;
54433d6423SLionel Sambuc break;
55433d6423SLionel Sambuc
56433d6423SLionel Sambuc case PM_GETGID:
57433d6423SLionel Sambuc r = rmp->mp_realgid;
58433d6423SLionel Sambuc rmp->mp_reply.m_pm_lc_getgid.egid = rmp->mp_effgid;
59433d6423SLionel Sambuc break;
60433d6423SLionel Sambuc
61433d6423SLionel Sambuc case PM_GETPID:
62433d6423SLionel Sambuc r = mproc[who_p].mp_pid;
63433d6423SLionel Sambuc rmp->mp_reply.m_pm_lc_getpid.parent_pid = mproc[rmp->mp_parent].mp_pid;
64433d6423SLionel Sambuc break;
65433d6423SLionel Sambuc
66433d6423SLionel Sambuc case PM_GETPGRP:
67433d6423SLionel Sambuc r = rmp->mp_procgrp;
68433d6423SLionel Sambuc break;
69433d6423SLionel Sambuc
70433d6423SLionel Sambuc case PM_GETSID:
71433d6423SLionel Sambuc {
72433d6423SLionel Sambuc struct mproc *target;
73433d6423SLionel Sambuc pid_t p = m_in.m_lc_pm_getsid.pid;
74433d6423SLionel Sambuc target = p ? find_proc(p) : &mproc[who_p];
75433d6423SLionel Sambuc r = ESRCH;
76433d6423SLionel Sambuc if(target)
77433d6423SLionel Sambuc r = target->mp_procgrp;
78433d6423SLionel Sambuc break;
79433d6423SLionel Sambuc }
80433d6423SLionel Sambuc case PM_ISSETUGID:
81433d6423SLionel Sambuc r = !!(rmp->mp_flags & TAINTED);
82433d6423SLionel Sambuc break;
83433d6423SLionel Sambuc
84433d6423SLionel Sambuc default:
85433d6423SLionel Sambuc r = EINVAL;
86433d6423SLionel Sambuc break;
87433d6423SLionel Sambuc }
88433d6423SLionel Sambuc return(r);
89433d6423SLionel Sambuc }
90433d6423SLionel Sambuc
91433d6423SLionel Sambuc /*===========================================================================*
92433d6423SLionel Sambuc * do_set *
93433d6423SLionel Sambuc *===========================================================================*/
94*637f688fSRichard Sailer int
do_set(void)95*637f688fSRichard Sailer do_set(void)
96433d6423SLionel Sambuc {
97433d6423SLionel Sambuc /* Handle PM_SETUID, PM_SETEUID, PM_SETGID, PM_SETGROUPS, PM_SETEGID, and
98433d6423SLionel Sambuc * SETSID. These calls have in common that, if successful, they will be
99433d6423SLionel Sambuc * forwarded to VFS as well.
100433d6423SLionel Sambuc */
101433d6423SLionel Sambuc register struct mproc *rmp = mp;
102433d6423SLionel Sambuc message m;
103433d6423SLionel Sambuc int r, i;
104433d6423SLionel Sambuc int ngroups;
105433d6423SLionel Sambuc uid_t uid;
106433d6423SLionel Sambuc gid_t gid;
107433d6423SLionel Sambuc
108433d6423SLionel Sambuc memset(&m, 0, sizeof(m));
109433d6423SLionel Sambuc
110433d6423SLionel Sambuc switch(call_nr) {
111433d6423SLionel Sambuc case PM_SETUID:
112433d6423SLionel Sambuc uid = m_in.m_lc_pm_setuid.uid;
1131122b286SDavid van Moolenbroek /* NetBSD specific semantics: setuid(geteuid()) may fail. */
114433d6423SLionel Sambuc if (rmp->mp_realuid != uid && rmp->mp_effuid != SUPER_USER)
115433d6423SLionel Sambuc return(EPERM);
1161122b286SDavid van Moolenbroek /* BSD semantics: always update all three fields. */
1171122b286SDavid van Moolenbroek rmp->mp_realuid = uid;
1181122b286SDavid van Moolenbroek rmp->mp_effuid = uid;
1191122b286SDavid van Moolenbroek rmp->mp_svuid = uid;
1201122b286SDavid van Moolenbroek
1211122b286SDavid van Moolenbroek m.m_type = VFS_PM_SETUID;
1221122b286SDavid van Moolenbroek m.VFS_PM_ENDPT = rmp->mp_endpoint;
1231122b286SDavid van Moolenbroek m.VFS_PM_EID = rmp->mp_effuid;
1241122b286SDavid van Moolenbroek m.VFS_PM_RID = rmp->mp_realuid;
1251122b286SDavid van Moolenbroek
1261122b286SDavid van Moolenbroek break;
1271122b286SDavid van Moolenbroek
1281122b286SDavid van Moolenbroek case PM_SETEUID:
1291122b286SDavid van Moolenbroek uid = m_in.m_lc_pm_setuid.uid;
1301122b286SDavid van Moolenbroek /* BSD semantics: seteuid(geteuid()) may fail. */
1311122b286SDavid van Moolenbroek if (rmp->mp_realuid != uid && rmp->mp_svuid != uid &&
1321122b286SDavid van Moolenbroek rmp->mp_effuid != SUPER_USER)
1331122b286SDavid van Moolenbroek return(EPERM);
134433d6423SLionel Sambuc rmp->mp_effuid = uid;
135433d6423SLionel Sambuc
136433d6423SLionel Sambuc m.m_type = VFS_PM_SETUID;
137433d6423SLionel Sambuc m.VFS_PM_ENDPT = rmp->mp_endpoint;
138433d6423SLionel Sambuc m.VFS_PM_EID = rmp->mp_effuid;
139433d6423SLionel Sambuc m.VFS_PM_RID = rmp->mp_realuid;
140433d6423SLionel Sambuc
141433d6423SLionel Sambuc break;
142433d6423SLionel Sambuc
143433d6423SLionel Sambuc case PM_SETGID:
144433d6423SLionel Sambuc gid = m_in.m_lc_pm_setgid.gid;
145433d6423SLionel Sambuc if (rmp->mp_realgid != gid && rmp->mp_effuid != SUPER_USER)
146433d6423SLionel Sambuc return(EPERM);
1471122b286SDavid van Moolenbroek rmp->mp_realgid = gid;
1481122b286SDavid van Moolenbroek rmp->mp_effgid = gid;
1491122b286SDavid van Moolenbroek rmp->mp_svgid = gid;
1501122b286SDavid van Moolenbroek
1511122b286SDavid van Moolenbroek m.m_type = VFS_PM_SETGID;
1521122b286SDavid van Moolenbroek m.VFS_PM_ENDPT = rmp->mp_endpoint;
1531122b286SDavid van Moolenbroek m.VFS_PM_EID = rmp->mp_effgid;
1541122b286SDavid van Moolenbroek m.VFS_PM_RID = rmp->mp_realgid;
1551122b286SDavid van Moolenbroek
1561122b286SDavid van Moolenbroek break;
1571122b286SDavid van Moolenbroek
1581122b286SDavid van Moolenbroek case PM_SETEGID:
1591122b286SDavid van Moolenbroek gid = m_in.m_lc_pm_setgid.gid;
1601122b286SDavid van Moolenbroek if (rmp->mp_realgid != gid && rmp->mp_svgid != gid &&
1611122b286SDavid van Moolenbroek rmp->mp_effuid != SUPER_USER)
1621122b286SDavid van Moolenbroek return(EPERM);
163433d6423SLionel Sambuc rmp->mp_effgid = gid;
164433d6423SLionel Sambuc
165433d6423SLionel Sambuc m.m_type = VFS_PM_SETGID;
166433d6423SLionel Sambuc m.VFS_PM_ENDPT = rmp->mp_endpoint;
167433d6423SLionel Sambuc m.VFS_PM_EID = rmp->mp_effgid;
168433d6423SLionel Sambuc m.VFS_PM_RID = rmp->mp_realgid;
169433d6423SLionel Sambuc
170433d6423SLionel Sambuc break;
1711122b286SDavid van Moolenbroek
172433d6423SLionel Sambuc case PM_SETGROUPS:
173433d6423SLionel Sambuc if (rmp->mp_effuid != SUPER_USER)
174433d6423SLionel Sambuc return(EPERM);
175433d6423SLionel Sambuc
176433d6423SLionel Sambuc ngroups = m_in.m_lc_pm_groups.num;
177433d6423SLionel Sambuc
178433d6423SLionel Sambuc if (ngroups > NGROUPS_MAX || ngroups < 0)
179433d6423SLionel Sambuc return(EINVAL);
180433d6423SLionel Sambuc
181433d6423SLionel Sambuc if (ngroups > 0 && m_in.m_lc_pm_groups.ptr == 0)
182433d6423SLionel Sambuc return(EFAULT);
183433d6423SLionel Sambuc
184433d6423SLionel Sambuc r = sys_datacopy(who_e, m_in.m_lc_pm_groups.ptr, SELF,
185433d6423SLionel Sambuc (vir_bytes) rmp->mp_sgroups,
186433d6423SLionel Sambuc ngroups * sizeof(gid_t));
187433d6423SLionel Sambuc if (r != OK)
188433d6423SLionel Sambuc return(r);
189433d6423SLionel Sambuc
190433d6423SLionel Sambuc for (i = 0; i < ngroups; i++) {
191433d6423SLionel Sambuc if (rmp->mp_sgroups[i] > GID_MAX)
192433d6423SLionel Sambuc return(EINVAL);
193433d6423SLionel Sambuc }
194433d6423SLionel Sambuc for (i = ngroups; i < NGROUPS_MAX; i++) {
195433d6423SLionel Sambuc rmp->mp_sgroups[i] = 0;
196433d6423SLionel Sambuc }
197433d6423SLionel Sambuc rmp->mp_ngroups = ngroups;
198433d6423SLionel Sambuc
199433d6423SLionel Sambuc m.m_type = VFS_PM_SETGROUPS;
200433d6423SLionel Sambuc m.VFS_PM_ENDPT = rmp->mp_endpoint;
201433d6423SLionel Sambuc m.VFS_PM_GROUP_NO = rmp->mp_ngroups;
202433d6423SLionel Sambuc m.VFS_PM_GROUP_ADDR = (char *) rmp->mp_sgroups;
203433d6423SLionel Sambuc
204433d6423SLionel Sambuc break;
205433d6423SLionel Sambuc case PM_SETSID:
206433d6423SLionel Sambuc if (rmp->mp_procgrp == rmp->mp_pid) return(EPERM);
207433d6423SLionel Sambuc rmp->mp_procgrp = rmp->mp_pid;
208433d6423SLionel Sambuc
209433d6423SLionel Sambuc m.m_type = VFS_PM_SETSID;
210433d6423SLionel Sambuc m.VFS_PM_ENDPT = rmp->mp_endpoint;
211433d6423SLionel Sambuc
212433d6423SLionel Sambuc break;
213433d6423SLionel Sambuc
214433d6423SLionel Sambuc default:
215433d6423SLionel Sambuc return(EINVAL);
216433d6423SLionel Sambuc }
217433d6423SLionel Sambuc
218433d6423SLionel Sambuc /* Send the request to VFS */
219433d6423SLionel Sambuc tell_vfs(rmp, &m);
220433d6423SLionel Sambuc
221433d6423SLionel Sambuc /* Do not reply until VFS has processed the request */
222433d6423SLionel Sambuc return(SUSPEND);
223433d6423SLionel Sambuc }
224