testsh2.sh: change output to new cksum util
[minix.git] / kernel / system / do_safemap.c
blob12fa93dfff5c92b48166d74da9d50695ad77e873
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_ADDRESS address
9 * SMAP_BYTES bytes to be copied
10 * SMAP_FLAG access, writable map or not?
13 #include <assert.h>
15 #include "kernel/system.h"
16 #include "kernel.h"
18 #include <minix/safecopies.h>
20 #include <signal.h>
22 struct map_info_s {
23 int flag;
25 /* Grantor. */
26 endpoint_t grantor;
27 cp_grant_id_t gid;
28 vir_bytes offset;
29 vir_bytes address_Dseg; /* seg always is D */
31 /* Grantee. */
32 endpoint_t grantee;
33 vir_bytes address;
35 /* Length. */
36 vir_bytes bytes;
39 #define MAX_MAP_INFO 20
40 static struct map_info_s map_info[MAX_MAP_INFO];
42 /*===========================================================================*
43 * add_info *
44 *===========================================================================*/
45 static int add_info(endpoint_t grantor, endpoint_t grantee, cp_grant_id_t gid,
46 vir_bytes offset, vir_bytes address_Dseg,
47 vir_bytes address, vir_bytes bytes)
49 int i;
51 for(i = 0; i < MAX_MAP_INFO; i++) {
52 if(map_info[i].flag == 0)
53 break;
55 if(i == MAX_MAP_INFO)
56 return EBUSY;
58 map_info[i].flag = 1;
59 map_info[i].grantor = grantor;
60 map_info[i].grantee = grantee;
61 map_info[i].gid = gid;
62 map_info[i].address_Dseg = address_Dseg;
63 map_info[i].offset = offset;
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,
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].address == address)
98 return &map_info[i];
101 return NULL;
104 /*===========================================================================*
105 * clear_info *
106 *===========================================================================*/
107 static void clear_info(struct map_info_s *p)
109 p->flag = 0;
112 /*===========================================================================*
113 * map_invoke_vm *
114 *===========================================================================*/
115 int map_invoke_vm(struct proc * caller,
116 int req_type, /* VMPTYPE_... COWMAP, SMAP, SUNMAP */
117 endpoint_t end_d, vir_bytes off_d,
118 endpoint_t end_s, vir_bytes off_s,
119 size_t size, int flag)
121 struct proc *dst;
123 dst = endpoint_lookup(end_d);
125 /* Make sure the linear addresses are both page aligned. */
126 if(off_s % CLICK_SIZE != 0 || off_d % CLICK_SIZE != 0) {
127 printf("map_invoke_vm: linear addresses not page aligned.\n");
128 return EINVAL;
131 assert(!RTS_ISSET(caller, RTS_VMREQUEST));
132 assert(!RTS_ISSET(caller, RTS_VMREQTARGET));
133 assert(!RTS_ISSET(dst, RTS_VMREQUEST));
134 assert(!RTS_ISSET(dst, RTS_VMREQTARGET));
135 RTS_SET(caller, RTS_VMREQUEST);
136 RTS_SET(dst, RTS_VMREQTARGET);
138 /* Map to the destination. */
139 caller->p_vmrequest.req_type = req_type;
140 caller->p_vmrequest.target = end_d; /* destination proc */
141 caller->p_vmrequest.params.map.vir_d = off_d; /* destination addr */
142 caller->p_vmrequest.params.map.ep_s = end_s; /* source process */
143 caller->p_vmrequest.params.map.vir_s = off_s; /* source address */
144 caller->p_vmrequest.params.map.length = (vir_bytes) size;
145 caller->p_vmrequest.params.map.writeflag = flag;
147 caller->p_vmrequest.type = VMSTYPE_MAP;
149 /* Connect caller on vmrequest wait queue. */
150 if(!(caller->p_vmrequest.nextrequestor = vmrequest))
151 if(OK != send_sig(VM_PROC_NR, SIGKMEM))
152 panic("send_sig failed");
153 vmrequest = caller;
155 return OK;
158 /*===========================================================================*
159 * do_safemap *
160 *===========================================================================*/
161 int do_safemap(struct proc * caller, message * m_ptr)
163 endpoint_t grantor = m_ptr->SMAP_EP;
164 cp_grant_id_t gid = (cp_grant_id_t) m_ptr->SMAP_GID;
165 vir_bytes offset = (vir_bytes) m_ptr->SMAP_OFFSET;
166 vir_bytes address = (vir_bytes) m_ptr->SMAP_ADDRESS;
167 vir_bytes bytes = (vir_bytes) m_ptr->SMAP_BYTES;
168 int flag = m_ptr->SMAP_FLAG;
170 vir_bytes offset_result;
171 endpoint_t new_grantor;
172 int r;
173 int access = CPF_MAP | CPF_READ;
175 /* Check the grant. We currently support safemap with both direct and
176 * indirect grants, as verify_grant() stores the original grantor
177 * transparently in new_grantor below. However, we maintain the original
178 * semantics associated to indirect grants only here at safemap time.
179 * After the mapping has been set up, if a process part of the chain
180 * of trust crashes or exits without revoking the mapping, the mapping
181 * can no longer be manually or automatically revoked for any of the
182 * processes lower in the chain. This solution reduces complexity but
183 * could be improved if we make the assumption that only one process in
184 * the chain of trust can effectively map the original memory region.
186 if(flag != 0)
187 access |= CPF_WRITE;
188 r = verify_grant(grantor, caller->p_endpoint, gid, bytes, access,
189 offset, &offset_result, &new_grantor);
190 if(r != OK) {
191 printf("verify_grant for gid %d from %d to %d failed: %d\n",
192 gid, grantor, caller->p_endpoint, r);
193 return r;
196 /* Add map info. */
197 r = add_info(new_grantor, caller->p_endpoint, gid, offset,
198 offset_result, address, bytes);
199 if(r != OK)
200 return r;
202 /* Invoke VM. */
203 return map_invoke_vm(caller, VMPTYPE_SMAP,
204 caller->p_endpoint, address, new_grantor, offset_result, bytes,flag);
207 /*===========================================================================*
208 * safeunmap *
209 *===========================================================================*/
210 static int safeunmap(struct proc * caller, struct map_info_s *p)
212 vir_bytes offset_result;
213 endpoint_t new_grantor;
214 int r;
216 r = verify_grant(p->grantor, p->grantee, p->gid, p->bytes,
217 CPF_MAP, p->offset, &offset_result, &new_grantor);
218 if(r != OK) {
219 printf("safeunmap: error in verify_grant.\n");
220 return r;
223 r = map_invoke_vm(caller, VMPTYPE_SUNMAP,
224 p->grantee, p->address,
225 new_grantor, offset_result,
226 p->bytes, 0);
227 clear_info(p);
228 if(r != OK) {
229 printf("safeunmap: error in map_invoke_vm.\n");
230 return r;
232 return OK;
235 /*===========================================================================*
236 * do_saferevmap *
237 *===========================================================================*/
238 int do_saferevmap(struct proc * caller, message * m_ptr)
240 struct map_info_s *p;
241 int flag = m_ptr->SMAP_FLAG;
242 int arg = m_ptr->SMAP_GID; /* gid or address_Dseg */
243 int r;
245 while((p = get_revoke_info(caller->p_endpoint, flag, arg)) != NULL) {
246 if((r = safeunmap(caller, p)) != OK)
247 return r;
249 return OK;
252 /*===========================================================================*
253 * do_safeunmap *
254 *===========================================================================*/
255 int do_safeunmap(struct proc * caller, message * m_ptr)
257 vir_bytes address = (vir_bytes) m_ptr->SMAP_ADDRESS;
258 struct map_info_s *p;
259 int r;
261 while((p = get_unmap_info(caller->p_endpoint, address)) != NULL) {
262 if((r = safeunmap(caller, p)) != OK)
263 return r;
265 return OK;