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
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"
27 vir_bytes address_Dseg
; /* seg always is D */
38 #define MAX_MAP_INFO 20
39 static struct map_info_s map_info
[MAX_MAP_INFO
];
41 /*===========================================================================*
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
)
50 for(i
= 0; i
< MAX_MAP_INFO
; i
++) {
51 if(map_info
[i
].flag
== 0)
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
;
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
, int seg
,
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
)
105 /*===========================================================================*
107 *===========================================================================*/
108 static void clear_info(struct map_info_s
*p
)
113 /*===========================================================================*
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");
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");
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
);
168 /*===========================================================================*
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
;
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.
199 r
= verify_grant(grantor
, caller
->p_endpoint
, gid
, bytes
, access
,
200 offset
, &offset_result
, &new_grantor
);
202 printf("verify_grant for gid %d from %d to %d failed: %d\n",
203 gid
, grantor
, caller
->p_endpoint
, r
);
208 r
= add_info(new_grantor
, caller
->p_endpoint
, gid
, offset
,
209 offset_result
, seg
, address
, bytes
);
214 return map_invoke_vm(caller
, VMPTYPE_SMAP
,
215 caller
->p_endpoint
, seg
, address
, new_grantor
, D
, offset_result
, bytes
,flag
);
218 /*===========================================================================*
220 *===========================================================================*/
221 PRIVATE
int safeunmap(struct proc
* caller
, struct map_info_s
*p
)
223 vir_bytes offset_result
;
224 endpoint_t new_grantor
;
227 r
= verify_grant(p
->grantor
, p
->grantee
, p
->gid
, p
->bytes
,
228 CPF_MAP
, p
->offset
, &offset_result
, &new_grantor
);
230 printf("safeunmap: error in verify_grant.\n");
234 r
= map_invoke_vm(caller
, VMPTYPE_SUNMAP
,
235 p
->grantee
, p
->seg
, p
->address
,
236 new_grantor
, D
, offset_result
,
240 printf("safeunmap: error in map_invoke_vm.\n");
246 /*===========================================================================*
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 */
256 while((p
= get_revoke_info(caller
->p_endpoint
, flag
, arg
)) != NULL
) {
257 if((r
= safeunmap(caller
, p
)) != OK
)
263 /*===========================================================================*
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
;
273 while((p
= get_unmap_info(caller
->p_endpoint
, seg
, address
)) != NULL
) {
274 if((r
= safeunmap(caller
, p
)) != OK
)