iov_iter_extract_pages() returns the number of bytes extracted and sets off to the offset into the first page. For the iterator, the number of pages pinned is therefore DIV_ROUND_UP(len + off, PAGE_SIZE).
The partial-extraction error path instead records len / PAGE_SIZE. For an unaligned buffer this can undercount by one, causing unpin_user_pages() to leave a page pinned.
Fixes: d5cf5b37064b ("tee: fix register_shm_helper()") Cc: stable@vger.kernel.org Co-developed-by: Jo Van Bulck jo.vanbulck@cs.kuleuven.be Signed-off-by: Jo Van Bulck jo.vanbulck@cs.kuleuven.be Signed-off-by: Shukai Ni shukai.ni@kuleuven.be --- drivers/tee/tee_shm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/tee/tee_shm.c b/drivers/tee/tee_shm.c index 6742b35..fa446e4 100644 --- a/drivers/tee/tee_shm.c +++ b/drivers/tee/tee_shm.c @@ -454,7 +454,7 @@ register_shm_helper(struct tee_context *ctx, struct iov_iter *iter, u32 flags, * If we only got a few pages, update to release the * correct amount below. */ - shm->num_pages = len / PAGE_SIZE; + shm->num_pages = DIV_ROUND_UP(len + off, PAGE_SIZE); ret = ERR_PTR(-ENOMEM); goto err_put_shm_pages; }