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?
16 #include <minix/type.h>
17 #include <minix/type.h>
18 #include <minix/safecopies.h>
20 #include "kernel/system.h"
31 vir_bytes address_Dseg
; /* seg always is D */
42 #define MAX_MAP_INFO 20
43 static struct map_info_s map_info
[MAX_MAP_INFO
];
45 /*===========================================================================*
47 *===========================================================================*/
48 static int add_info(endpoint_t grantor
, endpoint_t grantee
, cp_grant_id_t gid
,
49 vir_bytes offset
, vir_bytes address_Dseg
,
50 int seg
, vir_bytes address
, vir_bytes bytes
)
54 for(i
= 0; i
< MAX_MAP_INFO
; i
++) {
55 if(map_info
[i
].flag
== 0)
62 map_info
[i
].grantor
= grantor
;
63 map_info
[i
].grantee
= grantee
;
64 map_info
[i
].gid
= gid
;
65 map_info
[i
].address_Dseg
= address_Dseg
;
66 map_info
[i
].offset
= offset
;
67 map_info
[i
].seg
= seg
;
68 map_info
[i
].address
= address
;
69 map_info
[i
].bytes
= bytes
;
74 /*===========================================================================*
76 *===========================================================================*/
77 static struct map_info_s
*get_revoke_info(endpoint_t grantor
, int flag
, int arg
)
80 for(i
= 0; i
< MAX_MAP_INFO
; i
++) {
81 if(map_info
[i
].flag
== 1
82 && map_info
[i
].grantor
== grantor
83 && (flag
? (map_info
[i
].gid
== arg
)
84 : (map_info
[i
].address_Dseg
== arg
)))
91 /*===========================================================================*
93 *===========================================================================*/
94 static struct map_info_s
*get_unmap_info(endpoint_t grantee
, int seg
,
98 for(i
= 0; i
< MAX_MAP_INFO
; i
++) {
99 if(map_info
[i
].flag
== 1
100 && map_info
[i
].grantee
== grantee
101 && map_info
[i
].seg
== seg
102 && map_info
[i
].address
== address
)
109 /*===========================================================================*
111 *===========================================================================*/
112 static void clear_info(struct map_info_s
*p
)
117 /*===========================================================================*
119 *===========================================================================*/
120 PUBLIC
int map_invoke_vm(struct proc
* caller
,
121 int req_type
, /* VMPTYPE_... COWMAP, SMAP, SUNMAP */
122 endpoint_t end_d
, int seg_d
, vir_bytes off_d
,
123 endpoint_t end_s
, int seg_s
, vir_bytes off_s
,
124 size_t size
, int flag
)
126 struct proc
*src
, *dst
;
127 phys_bytes lin_src
, lin_dst
;
129 src
= endpoint_lookup(end_s
);
130 dst
= endpoint_lookup(end_d
);
132 lin_src
= umap_local(src
, seg_s
, off_s
, size
);
133 lin_dst
= umap_local(dst
, seg_d
, off_d
, size
);
134 if(lin_src
== 0 || lin_dst
== 0) {
135 printf("map_invoke_vm: error in umap_local.\n");
139 /* Make sure the linear addresses are both page aligned. */
140 if(lin_src
% CLICK_SIZE
!= 0
141 || lin_dst
% CLICK_SIZE
!= 0) {
142 printf("map_invoke_vm: linear addresses not page aligned.\n");
146 assert(!RTS_ISSET(caller
, RTS_VMREQUEST
));
147 assert(!RTS_ISSET(caller
, RTS_VMREQTARGET
));
148 assert(!RTS_ISSET(dst
, RTS_VMREQUEST
));
149 assert(!RTS_ISSET(dst
, RTS_VMREQTARGET
));
150 RTS_SET(caller
, RTS_VMREQUEST
);
151 RTS_SET(dst
, RTS_VMREQTARGET
);
153 /* Map to the destination. */
154 caller
->p_vmrequest
.req_type
= req_type
;
155 caller
->p_vmrequest
.target
= end_d
; /* destination proc */
156 caller
->p_vmrequest
.params
.map
.vir_d
= lin_dst
; /* destination addr */
157 caller
->p_vmrequest
.params
.map
.ep_s
= end_s
; /* source process */
158 caller
->p_vmrequest
.params
.map
.vir_s
= lin_src
; /* source address */
159 caller
->p_vmrequest
.params
.map
.length
= (vir_bytes
) size
;
160 caller
->p_vmrequest
.params
.map
.writeflag
= flag
;
162 caller
->p_vmrequest
.type
= VMSTYPE_MAP
;
164 /* Connect caller on vmrequest wait queue. */
165 if(!(caller
->p_vmrequest
.nextrequestor
= vmrequest
))
166 send_sig(VM_PROC_NR
, SIGKMEM
);
172 /*===========================================================================*
174 *===========================================================================*/
175 PUBLIC
int do_safemap(struct proc
* caller
, message
* m_ptr
)
177 endpoint_t grantor
= m_ptr
->SMAP_EP
;
178 cp_grant_id_t gid
= (cp_grant_id_t
) m_ptr
->SMAP_GID
;
179 vir_bytes offset
= (vir_bytes
) m_ptr
->SMAP_OFFSET
;
180 int seg
= (int) m_ptr
->SMAP_SEG
;
181 vir_bytes address
= (vir_bytes
) m_ptr
->SMAP_ADDRESS
;
182 vir_bytes bytes
= (vir_bytes
) m_ptr
->SMAP_BYTES
;
183 int flag
= m_ptr
->SMAP_FLAG
;
185 vir_bytes offset_result
;
186 endpoint_t new_grantor
;
188 int access
= CPF_MAP
| CPF_READ
;
190 /* Check the grant. We currently support safemap with both direct and
191 * indirect grants, as verify_grant() stores the original grantor
192 * transparently in new_grantor below. However, we maintain the original
193 * semantics associated to indirect grants only here at safemap time.
194 * After the mapping has been set up, if a process part of the chain
195 * of trust crashes or exits without revoking the mapping, the mapping
196 * can no longer be manually or automatically revoked for any of the
197 * processes lower in the chain. This solution reduces complexity but
198 * could be improved if we make the assumption that only one process in
199 * the chain of trust can effectively map the original memory region.
203 r
= verify_grant(grantor
, caller
->p_endpoint
, gid
, bytes
, access
,
204 offset
, &offset_result
, &new_grantor
);
206 printf("verify_grant for gid %d from %d to %d failed: %d\n",
207 gid
, grantor
, caller
->p_endpoint
, r
);
212 r
= add_info(new_grantor
, caller
->p_endpoint
, gid
, offset
,
213 offset_result
, seg
, address
, bytes
);
218 return map_invoke_vm(caller
, VMPTYPE_SMAP
,
219 caller
->p_endpoint
, seg
, address
, new_grantor
, D
, offset_result
, bytes
,flag
);
222 /*===========================================================================*
224 *===========================================================================*/
225 PRIVATE
int safeunmap(struct proc
* caller
, struct map_info_s
*p
)
227 vir_bytes offset_result
;
228 endpoint_t new_grantor
;
231 r
= verify_grant(p
->grantor
, p
->grantee
, p
->gid
, p
->bytes
,
232 CPF_MAP
, p
->offset
, &offset_result
, &new_grantor
);
234 printf("safeunmap: error in verify_grant.\n");
238 r
= map_invoke_vm(caller
, VMPTYPE_SUNMAP
,
239 p
->grantee
, p
->seg
, p
->address
,
240 new_grantor
, D
, offset_result
,
244 printf("safeunmap: error in map_invoke_vm.\n");
250 /*===========================================================================*
252 *===========================================================================*/
253 PUBLIC
int do_saferevmap(struct proc
* caller
, message
* m_ptr
)
255 struct map_info_s
*p
;
256 int flag
= m_ptr
->SMAP_FLAG
;
257 int arg
= m_ptr
->SMAP_GID
; /* gid or address_Dseg */
260 while((p
= get_revoke_info(caller
->p_endpoint
, flag
, arg
)) != NULL
) {
261 if((r
= safeunmap(caller
, p
)) != OK
)
267 /*===========================================================================*
269 *===========================================================================*/
270 PUBLIC
int do_safeunmap(struct proc
* caller
, message
* m_ptr
)
272 vir_bytes address
= (vir_bytes
) m_ptr
->SMAP_ADDRESS
;
273 int seg
= (int)m_ptr
->SMAP_SEG
;
274 struct map_info_s
*p
;
277 while((p
= get_unmap_info(caller
->p_endpoint
, seg
, address
)) != NULL
) {
278 if((r
= safeunmap(caller
, p
)) != OK
)