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
7 * SMAP_OFFSET offset of the grant space
9 * SMAP_BYTES bytes to be copied
10 * SMAP_FLAG access, writable map or not?
15 #include "kernel/system.h"
18 #include <minix/safecopies.h>
29 vir_bytes address_Dseg
; /* seg always is D */
39 #define MAX_MAP_INFO 20
40 static struct map_info_s map_info
[MAX_MAP_INFO
];
42 /*===========================================================================*
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
)
51 for(i
= 0; i
< MAX_MAP_INFO
; i
++) {
52 if(map_info
[i
].flag
== 0)
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
;
70 /*===========================================================================*
72 *===========================================================================*/
73 static struct map_info_s
*get_revoke_info(endpoint_t grantor
, int flag
, int arg
)
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
)))
87 /*===========================================================================*
89 *===========================================================================*/
90 static struct map_info_s
*get_unmap_info(endpoint_t grantee
,
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
)
104 /*===========================================================================*
106 *===========================================================================*/
107 static void clear_info(struct map_info_s
*p
)
112 /*===========================================================================*
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
)
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");
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");
158 /*===========================================================================*
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
;
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.
188 r
= verify_grant(grantor
, caller
->p_endpoint
, gid
, bytes
, access
,
189 offset
, &offset_result
, &new_grantor
);
191 printf("verify_grant for gid %d from %d to %d failed: %d\n",
192 gid
, grantor
, caller
->p_endpoint
, r
);
197 r
= add_info(new_grantor
, caller
->p_endpoint
, gid
, offset
,
198 offset_result
, address
, bytes
);
203 return map_invoke_vm(caller
, VMPTYPE_SMAP
,
204 caller
->p_endpoint
, address
, new_grantor
, offset_result
, bytes
,flag
);
207 /*===========================================================================*
209 *===========================================================================*/
210 static int safeunmap(struct proc
* caller
, struct map_info_s
*p
)
212 vir_bytes offset_result
;
213 endpoint_t new_grantor
;
216 r
= verify_grant(p
->grantor
, p
->grantee
, p
->gid
, p
->bytes
,
217 CPF_MAP
, p
->offset
, &offset_result
, &new_grantor
);
219 printf("safeunmap: error in verify_grant.\n");
223 r
= map_invoke_vm(caller
, VMPTYPE_SUNMAP
,
224 p
->grantee
, p
->address
,
225 new_grantor
, offset_result
,
229 printf("safeunmap: error in map_invoke_vm.\n");
235 /*===========================================================================*
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 */
245 while((p
= get_revoke_info(caller
->p_endpoint
, flag
, arg
)) != NULL
) {
246 if((r
= safeunmap(caller
, p
)) != OK
)
252 /*===========================================================================*
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
;
261 while((p
= get_unmap_info(caller
->p_endpoint
, address
)) != NULL
) {
262 if((r
= safeunmap(caller
, p
)) != OK
)