xref: /minix3/minix/servers/pm/getset.c (revision 637f688f0d4ccff0fa8a6ddafcd1d89fdfbc462d)
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