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