no more kprintf - kernel uses libsys printf now, only kputc is special
[minix.git] / kernel / system / do_safemap.c
blob65555949c459b079986818d3ad3f76867d00a2c9
1 /* The kernel call implemented in this file:
2 * m_type: SYS_SAFEMAP or SYS_SAFEREVMAP or SYS_SAFEUNMAP
4 * The parameters for this kernel call are:
5 * SMAP_EP endpoint of the grantor
6 * SMAP_GID grant id
7 * SMAP_OFFSET offset of the grant space
8 * SMAP_SEG segment
9 * SMAP_ADDRESS address
10 * SMAP_BYTES bytes to be copied
11 * SMAP_FLAG access, writable map or not?
14 #include <minix/type.h>
15 #include <minix/safecopies.h>
17 #include "../system.h"
20 struct map_info_s {
21 int flag;
23 /* Grantor. */
24 endpoint_t grantor;
25 cp_grant_id_t gid;
26 vir_bytes offset;
27 vir_bytes address_Dseg; /* seg always is D */
29 /* Grantee. */
30 endpoint_t grantee;
31 int seg;
32 vir_bytes address;
34 /* Length. */
35 vir_bytes bytes;
38 #define MAX_MAP_INFO 20
39 static struct map_info_s map_info[MAX_MAP_INFO];
41 /*===========================================================================*
42 * add_info *
43 *===========================================================================*/
44 static int add_info(endpoint_t grantor, endpoint_t grantee, cp_grant_id_t gid,
45 vir_bytes offset, vir_bytes address_Dseg,
46 int seg, vir_bytes address, vir_bytes bytes)
48 int i;
50 for(i = 0; i < MAX_MAP_INFO; i++) {
51 if(map_info[i].flag == 0)
52 break;
54 if(i == MAX_MAP_INFO)
55 return EBUSY;
57 map_info[i].flag = 1;
58 map_info[i].grantor = grantor;
59 map_info[i].grantee = grantee;
60 map_info[i].gid = gid;
61 map_info[i].address_Dseg = address_Dseg;
62 map_info[i].offset = offset;
63 map_info[i].seg = seg;
64 map_info[i].address = address;
65 map_info[i].bytes = bytes;
67 return OK;
70 /*===========================================================================*
71 * get_revoke_info *
72 *===========================================================================*/
73 static struct map_info_s *get_revoke_info(endpoint_t grantor, int flag, int arg)
75 int i;
76 for(i = 0; i < MAX_MAP_INFO; i++) {
77 if(map_info[i].flag == 1
78 && map_info[i].grantor == grantor
79 && (flag ? (map_info[i].gid == arg)
80 : (map_info[i].address_Dseg == arg)))
81 return &map_info[i];
84 return NULL;
87 /*===========================================================================*
88 * get_unmap_info *
89 *===========================================================================*/
90 static struct map_info_s *get_unmap_info(endpoint_t grantee, int seg,
91 vir_bytes address)
93 int i;
94 for(i = 0; i < MAX_MAP_INFO; i++) {
95 if(map_info[i].flag == 1
96 && map_info[i].grantee == grantee
97 && map_info[i].seg == seg
98 && map_info[i].address == address)
99 return &map_info[i];
102 return NULL;
105 /*===========================================================================*
106 * clear_info *
107 *===========================================================================*/
108 static void clear_info(struct map_info_s *p)
110 p->flag = 0;
113 /*===========================================================================*
114 * map_invoke_vm *
115 *===========================================================================*/
116 PUBLIC int map_invoke_vm(struct proc * caller,
117 int req_type, /* VMPTYPE_... COWMAP, SMAP, SUNMAP */
118 endpoint_t end_d, int seg_d, vir_bytes off_d,
119 endpoint_t end_s, int seg_s, vir_bytes off_s,
120 size_t size, int flag)
122 struct proc *src, *dst;
123 phys_bytes lin_src, lin_dst;
125 src = endpoint_lookup(end_s);
126 dst = endpoint_lookup(end_d);
128 lin_src = umap_local(src, seg_s, off_s, size);
129 lin_dst = umap_local(dst, seg_d, off_d, size);
130 if(lin_src == 0 || lin_dst == 0) {
131 printf("map_invoke_vm: error in umap_local.\n");
132 return EINVAL;
135 /* Make sure the linear addresses are both page aligned. */
136 if(lin_src % CLICK_SIZE != 0
137 || lin_dst % CLICK_SIZE != 0) {
138 printf("map_invoke_vm: linear addresses not page aligned.\n");
139 return EINVAL;
142 vmassert(!RTS_ISSET(caller, RTS_VMREQUEST));
143 vmassert(!RTS_ISSET(caller, RTS_VMREQTARGET));
144 vmassert(!RTS_ISSET(dst, RTS_VMREQUEST));
145 vmassert(!RTS_ISSET(dst, RTS_VMREQTARGET));
146 RTS_SET(caller, RTS_VMREQUEST);
147 RTS_SET(dst, RTS_VMREQTARGET);
149 /* Map to the destination. */
150 caller->p_vmrequest.req_type = req_type;
151 caller->p_vmrequest.target = end_d; /* destination proc */
152 caller->p_vmrequest.params.map.vir_d = lin_dst; /* destination addr */
153 caller->p_vmrequest.params.map.ep_s = end_s; /* source process */
154 caller->p_vmrequest.params.map.vir_s = lin_src; /* source address */
155 caller->p_vmrequest.params.map.length = (vir_bytes) size;
156 caller->p_vmrequest.params.map.writeflag = flag;
158 caller->p_vmrequest.type = VMSTYPE_MAP;
160 /* Connect caller on vmrequest wait queue. */
161 if(!(caller->p_vmrequest.nextrequestor = vmrequest))
162 mini_notify(proc_addr(SYSTEM), VM_PROC_NR);
163 vmrequest = caller;
165 return OK;
168 /*===========================================================================*
169 * do_safemap *
170 *===========================================================================*/
171 PUBLIC int do_safemap(struct proc * caller, message * m_ptr)
173 endpoint_t grantor = m_ptr->SMAP_EP;
174 cp_grant_id_t gid = (cp_grant_id_t) m_ptr->SMAP_GID;
175 vir_bytes offset = (vir_bytes) m_ptr->SMAP_OFFSET;
176 int seg = (int) m_ptr->SMAP_SEG;
177 vir_bytes address = (vir_bytes) m_ptr->SMAP_ADDRESS;
178 vir_bytes bytes = (vir_bytes) m_ptr->SMAP_BYTES;
179 int flag = m_ptr->SMAP_FLAG;
181 vir_bytes offset_result;
182 endpoint_t new_grantor;
183 int r;
184 int access = CPF_MAP | CPF_READ;
186 /* Check the grant. We currently support safemap with both direct and
187 * indirect grants, as verify_grant() stores the original grantor
188 * transparently in new_grantor below. However, we maintain the original
189 * semantics associated to indirect grants only here at safemap time.
190 * After the mapping has been set up, if a process part of the chain
191 * of trust crashes or exits without revoking the mapping, the mapping
192 * can no longer be manually or automatically revoked for any of the
193 * processes lower in the chain. This solution reduces complexity but
194 * could be improved if we make the assumption that only one process in
195 * the chain of trust can effectively map the original memory region.
197 if(flag != 0)
198 access |= CPF_WRITE;
199 r = verify_grant(grantor, caller->p_endpoint, gid, bytes, access,
200 offset, &offset_result, &new_grantor);
201 if(r != OK) {
202 printf("verify_grant for gid %d from %d to %d failed: %d\n",
203 gid, grantor, caller->p_endpoint, r);
204 return r;
207 /* Add map info. */
208 r = add_info(new_grantor, caller->p_endpoint, gid, offset,
209 offset_result, seg, address, bytes);
210 if(r != OK)
211 return r;
213 /* Invoke VM. */
214 return map_invoke_vm(caller, VMPTYPE_SMAP,
215 caller->p_endpoint, seg, address, new_grantor, D, offset_result, bytes,flag);
218 /*===========================================================================*
219 * safeunmap *
220 *===========================================================================*/
221 PRIVATE int safeunmap(struct proc * caller, struct map_info_s *p)
223 vir_bytes offset_result;
224 endpoint_t new_grantor;
225 int r;
227 r = verify_grant(p->grantor, p->grantee, p->gid, p->bytes,
228 CPF_MAP, p->offset, &offset_result, &new_grantor);
229 if(r != OK) {
230 printf("safeunmap: error in verify_grant.\n");
231 return r;
234 r = map_invoke_vm(caller, VMPTYPE_SUNMAP,
235 p->grantee, p->seg, p->address,
236 new_grantor, D, offset_result,
237 p->bytes, 0);
238 clear_info(p);
239 if(r != OK) {
240 printf("safeunmap: error in map_invoke_vm.\n");
241 return r;
243 return OK;
246 /*===========================================================================*
247 * do_saferevmap *
248 *===========================================================================*/
249 PUBLIC int do_saferevmap(struct proc * caller, message * m_ptr)
251 struct map_info_s *p;
252 int flag = m_ptr->SMAP_FLAG;
253 int arg = m_ptr->SMAP_GID; /* gid or address_Dseg */
254 int r;
256 while((p = get_revoke_info(caller->p_endpoint, flag, arg)) != NULL) {
257 if((r = safeunmap(caller, p)) != OK)
258 return r;
260 return OK;
263 /*===========================================================================*
264 * do_safeunmap *
265 *===========================================================================*/
266 PUBLIC int do_safeunmap(struct proc * caller, message * m_ptr)
268 vir_bytes address = (vir_bytes) m_ptr->SMAP_ADDRESS;
269 int seg = (int)m_ptr->SMAP_SEG;
270 struct map_info_s *p;
271 int r;
273 while((p = get_unmap_info(caller->p_endpoint, seg, address)) != NULL) {
274 if((r = safeunmap(caller, p)) != OK)
275 return r;
277 return OK;