From: Sumit Garg sumit.garg@oss.qualcomm.com
Earlier TEE subsystem assumed to refcount all the memory pages to be shared with TEE implementation to be refcounted. However, the slab allocations within the kernel don't allow refcounting kernel pages.
It is rather better to trust the kernel clients to not free pages while being shared with TEE implementation. Hence, remove refcounting of kernel pages from register_shm_helper() API.
Fixes: b9c0e49abfca ("mm: decline to manipulate the refcount on a slab page") Reported-by: Marco Felsch m.felsch@pengutronix.de Reported-by: Sven Püschel s.pueschel@pengutronix.de Suggested-by: Matthew Wilcox willy@infradead.org Signed-off-by: Sumit Garg sumit.garg@oss.qualcomm.com --- drivers/tee/tee_shm.c | 29 +---------------------------- 1 file changed, 1 insertion(+), 28 deletions(-)
diff --git a/drivers/tee/tee_shm.c b/drivers/tee/tee_shm.c index 4a47de4bb2e5..54e2ba3afb25 100644 --- a/drivers/tee/tee_shm.c +++ b/drivers/tee/tee_shm.c @@ -23,29 +23,11 @@ struct tee_shm_dma_mem { struct page *page; };
-static void shm_put_kernel_pages(struct page **pages, size_t page_count) -{ - size_t n; - - for (n = 0; n < page_count; n++) - put_page(pages[n]); -} - -static void shm_get_kernel_pages(struct page **pages, size_t page_count) -{ - size_t n; - - for (n = 0; n < page_count; n++) - get_page(pages[n]); -} - static void release_registered_pages(struct tee_shm *shm) { if (shm->pages) { if (shm->flags & TEE_SHM_USER_MAPPED) unpin_user_pages(shm->pages, shm->num_pages); - else - shm_put_kernel_pages(shm->pages, shm->num_pages);
kfree(shm->pages); } @@ -477,13 +459,6 @@ register_shm_helper(struct tee_context *ctx, struct iov_iter *iter, u32 flags, goto err_put_shm_pages; }
- /* - * iov_iter_extract_kvec_pages does not get reference on the pages, - * get a reference on them. - */ - if (iov_iter_is_kvec(iter)) - shm_get_kernel_pages(shm->pages, num_pages); - shm->offset = off; shm->size = len; shm->num_pages = num_pages; @@ -497,10 +472,8 @@ register_shm_helper(struct tee_context *ctx, struct iov_iter *iter, u32 flags,
return shm; err_put_shm_pages: - if (!iov_iter_is_kvec(iter)) + if (iter_is_uvec(iter)) unpin_user_pages(shm->pages, shm->num_pages); - else - shm_put_kernel_pages(shm->pages, shm->num_pages); err_free_shm_pages: kfree(shm->pages); err_free_shm:
On Fri, Feb 13, 2026 at 05:03:17PM +0530, Sumit Garg wrote:
From: Sumit Garg sumit.garg@oss.qualcomm.com
Um, this patch is exactly the patch I sent. You're stealing my authorship! This patch should have my From: and Signed-off-by: lines. Your role in this is "handling and transporting the patch" (see Documentation/process/submitting-patches.rst). By all means take credit for writing the commit message.
Earlier TEE subsystem assumed to refcount all the memory pages to be shared with TEE implementation to be refcounted. However, the slab allocations within the kernel don't allow refcounting kernel pages.
It is rather better to trust the kernel clients to not free pages while being shared with TEE implementation. Hence, remove refcounting of kernel pages from register_shm_helper() API.
Fixes: b9c0e49abfca ("mm: decline to manipulate the refcount on a slab page") Reported-by: Marco Felsch m.felsch@pengutronix.de Reported-by: Sven Püschel s.pueschel@pengutronix.de Suggested-by: Matthew Wilcox willy@infradead.org Signed-off-by: Sumit Garg sumit.garg@oss.qualcomm.com
drivers/tee/tee_shm.c | 29 +---------------------------- 1 file changed, 1 insertion(+), 28 deletions(-)
diff --git a/drivers/tee/tee_shm.c b/drivers/tee/tee_shm.c index 4a47de4bb2e5..54e2ba3afb25 100644 --- a/drivers/tee/tee_shm.c +++ b/drivers/tee/tee_shm.c @@ -23,29 +23,11 @@ struct tee_shm_dma_mem { struct page *page; }; -static void shm_put_kernel_pages(struct page **pages, size_t page_count) -{
- size_t n;
- for (n = 0; n < page_count; n++)
put_page(pages[n]);-}
-static void shm_get_kernel_pages(struct page **pages, size_t page_count) -{
- size_t n;
- for (n = 0; n < page_count; n++)
get_page(pages[n]);-}
static void release_registered_pages(struct tee_shm *shm) { if (shm->pages) { if (shm->flags & TEE_SHM_USER_MAPPED) unpin_user_pages(shm->pages, shm->num_pages);
elseshm_put_kernel_pages(shm->pages, shm->num_pages);kfree(shm->pages); } @@ -477,13 +459,6 @@ register_shm_helper(struct tee_context *ctx, struct iov_iter *iter, u32 flags, goto err_put_shm_pages; }
- /*
* iov_iter_extract_kvec_pages does not get reference on the pages,* get a reference on them.*/- if (iov_iter_is_kvec(iter))
shm_get_kernel_pages(shm->pages, num_pages);- shm->offset = off; shm->size = len; shm->num_pages = num_pages;
@@ -497,10 +472,8 @@ register_shm_helper(struct tee_context *ctx, struct iov_iter *iter, u32 flags, return shm; err_put_shm_pages:
- if (!iov_iter_is_kvec(iter))
- if (iter_is_uvec(iter)) unpin_user_pages(shm->pages, shm->num_pages);
- else
shm_put_kernel_pages(shm->pages, shm->num_pages);err_free_shm_pages: kfree(shm->pages); err_free_shm: -- 2.51.0
On Fri, Feb 13, 2026 at 04:08:57PM +0000, Matthew Wilcox wrote:
On Fri, Feb 13, 2026 at 05:03:17PM +0530, Sumit Garg wrote:
From: Sumit Garg sumit.garg@oss.qualcomm.com
Um, this patch is exactly the patch I sent. You're stealing my authorship! This patch should have my From: and Signed-off-by: lines. Your role in this is "handling and transporting the patch" (see Documentation/process/submitting-patches.rst). By all means take credit for writing the commit message.
Not sure how I can consider that diff from you a proper patch but surely I tried to give your suggestion attributes. However, it's fine with me to keep your authorship if you really want to vet this patch. Will send a v2 with the authorship updated.
-Sumit
Earlier TEE subsystem assumed to refcount all the memory pages to be shared with TEE implementation to be refcounted. However, the slab allocations within the kernel don't allow refcounting kernel pages.
It is rather better to trust the kernel clients to not free pages while being shared with TEE implementation. Hence, remove refcounting of kernel pages from register_shm_helper() API.
Fixes: b9c0e49abfca ("mm: decline to manipulate the refcount on a slab page") Reported-by: Marco Felsch m.felsch@pengutronix.de Reported-by: Sven Püschel s.pueschel@pengutronix.de Suggested-by: Matthew Wilcox willy@infradead.org Signed-off-by: Sumit Garg sumit.garg@oss.qualcomm.com
drivers/tee/tee_shm.c | 29 +---------------------------- 1 file changed, 1 insertion(+), 28 deletions(-)
diff --git a/drivers/tee/tee_shm.c b/drivers/tee/tee_shm.c index 4a47de4bb2e5..54e2ba3afb25 100644 --- a/drivers/tee/tee_shm.c +++ b/drivers/tee/tee_shm.c @@ -23,29 +23,11 @@ struct tee_shm_dma_mem { struct page *page; }; -static void shm_put_kernel_pages(struct page **pages, size_t page_count) -{
- size_t n;
- for (n = 0; n < page_count; n++)
put_page(pages[n]);-}
-static void shm_get_kernel_pages(struct page **pages, size_t page_count) -{
- size_t n;
- for (n = 0; n < page_count; n++)
get_page(pages[n]);-}
static void release_registered_pages(struct tee_shm *shm) { if (shm->pages) { if (shm->flags & TEE_SHM_USER_MAPPED) unpin_user_pages(shm->pages, shm->num_pages);
elseshm_put_kernel_pages(shm->pages, shm->num_pages);kfree(shm->pages); } @@ -477,13 +459,6 @@ register_shm_helper(struct tee_context *ctx, struct iov_iter *iter, u32 flags, goto err_put_shm_pages; }
- /*
* iov_iter_extract_kvec_pages does not get reference on the pages,* get a reference on them.*/- if (iov_iter_is_kvec(iter))
shm_get_kernel_pages(shm->pages, num_pages);- shm->offset = off; shm->size = len; shm->num_pages = num_pages;
@@ -497,10 +472,8 @@ register_shm_helper(struct tee_context *ctx, struct iov_iter *iter, u32 flags, return shm; err_put_shm_pages:
- if (!iov_iter_is_kvec(iter))
- if (iter_is_uvec(iter)) unpin_user_pages(shm->pages, shm->num_pages);
- else
shm_put_kernel_pages(shm->pages, shm->num_pages);err_free_shm_pages: kfree(shm->pages); err_free_shm: -- 2.51.0
Hi Sumit,
kernel test robot noticed the following build errors:
[auto build test ERROR on akpm-mm/mm-everything] [also build test ERROR on linus/master v6.19 next-20260213] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Sumit-Garg/tee-shm-Remove-ref... base: https://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm.git mm-everything patch link: https://lore.kernel.org/r/20260213113317.1728769-1-sumit.garg%40kernel.org patch subject: [RFT PATCH] tee: shm: Remove refcounting of kernel pages config: x86_64-randconfig-r073-20260214 (https://download.01.org/0day-ci/archive/20260214/202602142012.snNfstpn-lkp@i...) compiler: gcc-14 (Debian 14.2.0-19) 14.2.0 smatch version: v0.5.0-8994-gd50c5a4c reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260214/202602142012.snNfstpn-lkp@i...)
If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot lkp@intel.com | Closes: https://lore.kernel.org/oe-kbuild-all/202602142012.snNfstpn-lkp@intel.com/
All errors (new ones prefixed by >>):
drivers/tee/tee_shm.c: In function 'register_shm_helper':
drivers/tee/tee_shm.c:475:13: error: implicit declaration of function 'iter_is_uvec'; did you mean 'iter_is_iovec'? [-Wimplicit-function-declaration]
475 | if (iter_is_uvec(iter)) | ^~~~~~~~~~~~ | iter_is_iovec
vim +475 drivers/tee/tee_shm.c
399 400 static struct tee_shm * 401 register_shm_helper(struct tee_context *ctx, struct iov_iter *iter, u32 flags, 402 int id) 403 { 404 struct tee_device *teedev = ctx->teedev; 405 struct tee_shm *shm; 406 unsigned long start, addr; 407 size_t num_pages, off; 408 ssize_t len; 409 void *ret; 410 int rc; 411 412 if (!tee_device_get(teedev)) 413 return ERR_PTR(-EINVAL); 414 415 if (!teedev->desc->ops->shm_register || 416 !teedev->desc->ops->shm_unregister) { 417 ret = ERR_PTR(-ENOTSUPP); 418 goto err_dev_put; 419 } 420 421 teedev_ctx_get(ctx); 422 423 shm = kzalloc(sizeof(*shm), GFP_KERNEL); 424 if (!shm) { 425 ret = ERR_PTR(-ENOMEM); 426 goto err_ctx_put; 427 } 428 429 refcount_set(&shm->refcount, 1); 430 shm->flags = flags; 431 shm->ctx = ctx; 432 shm->id = id; 433 addr = untagged_addr((unsigned long)iter_iov_addr(iter)); 434 start = rounddown(addr, PAGE_SIZE); 435 num_pages = iov_iter_npages(iter, INT_MAX); 436 if (!num_pages) { 437 ret = ERR_PTR(-ENOMEM); 438 goto err_ctx_put; 439 } 440 441 shm->pages = kcalloc(num_pages, sizeof(*shm->pages), GFP_KERNEL); 442 if (!shm->pages) { 443 ret = ERR_PTR(-ENOMEM); 444 goto err_free_shm; 445 } 446 447 len = iov_iter_extract_pages(iter, &shm->pages, LONG_MAX, num_pages, 0, 448 &off); 449 if (unlikely(len <= 0)) { 450 ret = len ? ERR_PTR(len) : ERR_PTR(-ENOMEM); 451 goto err_free_shm_pages; 452 } else if (DIV_ROUND_UP(len + off, PAGE_SIZE) != num_pages) { 453 /* 454 * If we only got a few pages, update to release the 455 * correct amount below. 456 */ 457 shm->num_pages = len / PAGE_SIZE; 458 ret = ERR_PTR(-ENOMEM); 459 goto err_put_shm_pages; 460 } 461 462 shm->offset = off; 463 shm->size = len; 464 shm->num_pages = num_pages; 465 466 rc = teedev->desc->ops->shm_register(ctx, shm, shm->pages, 467 shm->num_pages, start); 468 if (rc) { 469 ret = ERR_PTR(rc); 470 goto err_put_shm_pages; 471 } 472 473 return shm; 474 err_put_shm_pages:
475 if (iter_is_uvec(iter))
476 unpin_user_pages(shm->pages, shm->num_pages); 477 err_free_shm_pages: 478 kfree(shm->pages); 479 err_free_shm: 480 kfree(shm); 481 err_ctx_put: 482 teedev_ctx_put(ctx); 483 err_dev_put: 484 tee_device_put(teedev); 485 return ret; 486 } 487
Hi Sumit,
kernel test robot noticed the following build errors:
[auto build test ERROR on akpm-mm/mm-everything] [also build test ERROR on linus/master v6.19 next-20260213] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Sumit-Garg/tee-shm-Remove-ref... base: https://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm.git mm-everything patch link: https://lore.kernel.org/r/20260213113317.1728769-1-sumit.garg%40kernel.org patch subject: [RFT PATCH] tee: shm: Remove refcounting of kernel pages config: loongarch-randconfig-r071-20260214 (https://download.01.org/0day-ci/archive/20260216/202602160147.pGHOLa5U-lkp@i...) compiler: clang version 18.1.8 (https://github.com/llvm/llvm-project 3b5b5c1ec4a3095ab096dd780e84d7ab81f3d7ff) rustc: rustc 1.88.0 (6b00bc388 2025-06-23) smatch version: v0.5.0-8994-gd50c5a4c reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260216/202602160147.pGHOLa5U-lkp@i...)
If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot lkp@intel.com | Closes: https://lore.kernel.org/oe-kbuild-all/202602160147.pGHOLa5U-lkp@intel.com/
All errors (new ones prefixed by >>):
drivers/tee/tee_shm.c:475:6: error: call to undeclared function 'iter_is_uvec'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
475 | if (iter_is_uvec(iter)) | ^ drivers/tee/tee_shm.c:475:6: note: did you mean 'iter_is_iovec'? include/linux/uio.h:128:20: note: 'iter_is_iovec' declared here 128 | static inline bool iter_is_iovec(const struct iov_iter *i) | ^ 1 error generated.
vim +/iter_is_uvec +475 drivers/tee/tee_shm.c
399 400 static struct tee_shm * 401 register_shm_helper(struct tee_context *ctx, struct iov_iter *iter, u32 flags, 402 int id) 403 { 404 struct tee_device *teedev = ctx->teedev; 405 struct tee_shm *shm; 406 unsigned long start, addr; 407 size_t num_pages, off; 408 ssize_t len; 409 void *ret; 410 int rc; 411 412 if (!tee_device_get(teedev)) 413 return ERR_PTR(-EINVAL); 414 415 if (!teedev->desc->ops->shm_register || 416 !teedev->desc->ops->shm_unregister) { 417 ret = ERR_PTR(-ENOTSUPP); 418 goto err_dev_put; 419 } 420 421 teedev_ctx_get(ctx); 422 423 shm = kzalloc(sizeof(*shm), GFP_KERNEL); 424 if (!shm) { 425 ret = ERR_PTR(-ENOMEM); 426 goto err_ctx_put; 427 } 428 429 refcount_set(&shm->refcount, 1); 430 shm->flags = flags; 431 shm->ctx = ctx; 432 shm->id = id; 433 addr = untagged_addr((unsigned long)iter_iov_addr(iter)); 434 start = rounddown(addr, PAGE_SIZE); 435 num_pages = iov_iter_npages(iter, INT_MAX); 436 if (!num_pages) { 437 ret = ERR_PTR(-ENOMEM); 438 goto err_ctx_put; 439 } 440 441 shm->pages = kcalloc(num_pages, sizeof(*shm->pages), GFP_KERNEL); 442 if (!shm->pages) { 443 ret = ERR_PTR(-ENOMEM); 444 goto err_free_shm; 445 } 446 447 len = iov_iter_extract_pages(iter, &shm->pages, LONG_MAX, num_pages, 0, 448 &off); 449 if (unlikely(len <= 0)) { 450 ret = len ? ERR_PTR(len) : ERR_PTR(-ENOMEM); 451 goto err_free_shm_pages; 452 } else if (DIV_ROUND_UP(len + off, PAGE_SIZE) != num_pages) { 453 /* 454 * If we only got a few pages, update to release the 455 * correct amount below. 456 */ 457 shm->num_pages = len / PAGE_SIZE; 458 ret = ERR_PTR(-ENOMEM); 459 goto err_put_shm_pages; 460 } 461 462 shm->offset = off; 463 shm->size = len; 464 shm->num_pages = num_pages; 465 466 rc = teedev->desc->ops->shm_register(ctx, shm, shm->pages, 467 shm->num_pages, start); 468 if (rc) { 469 ret = ERR_PTR(rc); 470 goto err_put_shm_pages; 471 } 472 473 return shm; 474 err_put_shm_pages:
475 if (iter_is_uvec(iter))
476 unpin_user_pages(shm->pages, shm->num_pages); 477 err_free_shm_pages: 478 kfree(shm->pages); 479 err_free_shm: 480 kfree(shm); 481 err_ctx_put: 482 teedev_ctx_put(ctx); 483 err_dev_put: 484 tee_device_put(teedev); 485 return ret; 486 } 487
Hi Sumit,
On 2/13/26 12:33 PM, Sumit Garg wrote:
From: Sumit Garg sumit.garg@oss.qualcomm.com
Earlier TEE subsystem assumed to refcount all the memory pages to be shared with TEE implementation to be refcounted. However, the slab allocations within the kernel don't allow refcounting kernel pages.
It is rather better to trust the kernel clients to not free pages while being shared with TEE implementation. Hence, remove refcounting of kernel pages from register_shm_helper() API.
Fixes: b9c0e49abfca ("mm: decline to manipulate the refcount on a slab page") Reported-by: Marco Felsch m.felsch@pengutronix.de Reported-by: Sven Püschel s.pueschel@pengutronix.de Suggested-by: Matthew Wilcox willy@infradead.org Signed-off-by: Sumit Garg sumit.garg@oss.qualcomm.com
drivers/tee/tee_shm.c | 29 +---------------------------- 1 file changed, 1 insertion(+), 28 deletions(-)
diff --git a/drivers/tee/tee_shm.c b/drivers/tee/tee_shm.c index 4a47de4bb2e5..54e2ba3afb25 100644 --- a/drivers/tee/tee_shm.c +++ b/drivers/tee/tee_shm.c @@ -23,29 +23,11 @@ struct tee_shm_dma_mem { struct page *page; }; -static void shm_put_kernel_pages(struct page **pages, size_t page_count) -{
- size_t n;
- for (n = 0; n < page_count; n++)
put_page(pages[n]);-}
-static void shm_get_kernel_pages(struct page **pages, size_t page_count) -{
- size_t n;
- for (n = 0; n < page_count; n++)
get_page(pages[n]);-}
- static void release_registered_pages(struct tee_shm *shm) { if (shm->pages) { if (shm->flags & TEE_SHM_USER_MAPPED) unpin_user_pages(shm->pages, shm->num_pages);
elseshm_put_kernel_pages(shm->pages, shm->num_pages);kfree(shm->pages); } @@ -477,13 +459,6 @@ register_shm_helper(struct tee_context *ctx, struct iov_iter *iter, u32 flags, goto err_put_shm_pages; }
- /*
* iov_iter_extract_kvec_pages does not get reference on the pages,* get a reference on them.*/- if (iov_iter_is_kvec(iter))
shm_get_kernel_pages(shm->pages, num_pages);- shm->offset = off; shm->size = len; shm->num_pages = num_pages;
@@ -497,10 +472,8 @@ register_shm_helper(struct tee_context *ctx, struct iov_iter *iter, u32 flags, return shm; err_put_shm_pages:
- if (!iov_iter_is_kvec(iter))
- if (iter_is_uvec(iter))
I've replaced (due to compile failures noted by the kernel test robot) this with the compiler suggested iter_is_iovec . I haven't checked, if this is the correct fix.
With this patch applied (on the upstream commit 970296997869), my reported stacktrace/warning doesn't occur anymore. I didn't do any extensive testing, but creating and using a trusted key with keyctl worked fine in my short test.
Sincerely Sven
unpin_user_pages(shm->pages, shm->num_pages);
- else
err_free_shm_pages: kfree(shm->pages); err_free_shm:shm_put_kernel_pages(shm->pages, shm->num_pages);
op-tee@lists.trustedfirmware.org