@@ -22,23 +22,12 @@ static void shm_put_kernel_pages(struct page **pages, size_t page_count)
2222 put_page (pages [n ]);
2323}
2424
25- static int shm_get_kernel_pages (unsigned long start , size_t page_count ,
26- struct page * * pages )
25+ static void shm_get_kernel_pages (struct page * * pages , size_t page_count )
2726{
28- struct page * page ;
2927 size_t n ;
3028
31- if (WARN_ON_ONCE (is_vmalloc_addr ((void * )start ) ||
32- is_kmap_addr ((void * )start )))
33- return - EINVAL ;
34-
35- page = virt_to_page ((void * )start );
36- for (n = 0 ; n < page_count ; n ++ ) {
37- pages [n ] = page + n ;
29+ for (n = 0 ; n < page_count ; n ++ )
3830 get_page (pages [n ]);
39- }
40-
41- return page_count ;
4231}
4332
4433static void release_registered_pages (struct tee_shm * shm )
@@ -214,13 +203,14 @@ struct tee_shm *tee_shm_alloc_priv_buf(struct tee_context *ctx, size_t size)
214203EXPORT_SYMBOL_GPL (tee_shm_alloc_priv_buf );
215204
216205static struct tee_shm *
217- register_shm_helper (struct tee_context * ctx , unsigned long addr ,
218- size_t length , u32 flags , int id )
206+ register_shm_helper (struct tee_context * ctx , struct iov_iter * iter , u32 flags ,
207+ int id )
219208{
220209 struct tee_device * teedev = ctx -> teedev ;
221210 struct tee_shm * shm ;
222- unsigned long start ;
223- size_t num_pages ;
211+ unsigned long start , addr ;
212+ size_t num_pages , off ;
213+ ssize_t len ;
224214 void * ret ;
225215 int rc ;
226216
@@ -245,31 +235,38 @@ register_shm_helper(struct tee_context *ctx, unsigned long addr,
245235 shm -> flags = flags ;
246236 shm -> ctx = ctx ;
247237 shm -> id = id ;
248- addr = untagged_addr (addr );
238+ addr = untagged_addr (( unsigned long ) iter_iov_addr ( iter ) );
249239 start = rounddown (addr , PAGE_SIZE );
250- shm -> offset = addr - start ;
251- shm -> size = length ;
252- num_pages = (roundup (addr + length , PAGE_SIZE ) - start ) / PAGE_SIZE ;
240+ num_pages = iov_iter_npages (iter , INT_MAX );
241+ if (!num_pages ) {
242+ ret = ERR_PTR (- ENOMEM );
243+ goto err_ctx_put ;
244+ }
245+
253246 shm -> pages = kcalloc (num_pages , sizeof (* shm -> pages ), GFP_KERNEL );
254247 if (!shm -> pages ) {
255248 ret = ERR_PTR (- ENOMEM );
256249 goto err_free_shm ;
257250 }
258251
259- if (flags & TEE_SHM_USER_MAPPED )
260- rc = pin_user_pages_fast (start , num_pages , FOLL_WRITE ,
261- shm -> pages );
262- else
263- rc = shm_get_kernel_pages (start , num_pages , shm -> pages );
264- if (rc > 0 )
265- shm -> num_pages = rc ;
266- if (rc != num_pages ) {
267- if (rc >= 0 )
268- rc = - ENOMEM ;
269- ret = ERR_PTR (rc );
270- goto err_put_shm_pages ;
252+ len = iov_iter_extract_pages (iter , & shm -> pages , LONG_MAX , num_pages , 0 ,
253+ & off );
254+ if (unlikely (len <= 0 )) {
255+ ret = len ? ERR_PTR (len ) : ERR_PTR (- ENOMEM );
256+ goto err_free_shm_pages ;
271257 }
272258
259+ /*
260+ * iov_iter_extract_kvec_pages does not get reference on the pages,
261+ * get a reference on them.
262+ */
263+ if (iov_iter_is_kvec (iter ))
264+ shm_get_kernel_pages (shm -> pages , num_pages );
265+
266+ shm -> offset = off ;
267+ shm -> size = len ;
268+ shm -> num_pages = num_pages ;
269+
273270 rc = teedev -> desc -> ops -> shm_register (ctx , shm , shm -> pages ,
274271 shm -> num_pages , start );
275272 if (rc ) {
@@ -279,10 +276,11 @@ register_shm_helper(struct tee_context *ctx, unsigned long addr,
279276
280277 return shm ;
281278err_put_shm_pages :
282- if (flags & TEE_SHM_USER_MAPPED )
279+ if (! iov_iter_is_kvec ( iter ) )
283280 unpin_user_pages (shm -> pages , shm -> num_pages );
284281 else
285282 shm_put_kernel_pages (shm -> pages , shm -> num_pages );
283+ err_free_shm_pages :
286284 kfree (shm -> pages );
287285err_free_shm :
288286 kfree (shm );
@@ -307,6 +305,7 @@ struct tee_shm *tee_shm_register_user_buf(struct tee_context *ctx,
307305 u32 flags = TEE_SHM_USER_MAPPED | TEE_SHM_DYNAMIC ;
308306 struct tee_device * teedev = ctx -> teedev ;
309307 struct tee_shm * shm ;
308+ struct iov_iter iter ;
310309 void * ret ;
311310 int id ;
312311
@@ -319,7 +318,8 @@ struct tee_shm *tee_shm_register_user_buf(struct tee_context *ctx,
319318 if (id < 0 )
320319 return ERR_PTR (id );
321320
322- shm = register_shm_helper (ctx , addr , length , flags , id );
321+ iov_iter_ubuf (& iter , ITER_DEST , (void __user * )addr , length );
322+ shm = register_shm_helper (ctx , & iter , flags , id );
323323 if (IS_ERR (shm )) {
324324 mutex_lock (& teedev -> mutex );
325325 idr_remove (& teedev -> idr , id );
@@ -352,8 +352,14 @@ struct tee_shm *tee_shm_register_kernel_buf(struct tee_context *ctx,
352352 void * addr , size_t length )
353353{
354354 u32 flags = TEE_SHM_DYNAMIC ;
355+ struct kvec kvec ;
356+ struct iov_iter iter ;
357+
358+ kvec .iov_base = addr ;
359+ kvec .iov_len = length ;
360+ iov_iter_kvec (& iter , ITER_DEST , & kvec , 1 , length );
355361
356- return register_shm_helper (ctx , ( unsigned long ) addr , length , flags , -1 );
362+ return register_shm_helper (ctx , & iter , flags , -1 );
357363}
358364EXPORT_SYMBOL_GPL (tee_shm_register_kernel_buf );
359365
0 commit comments