Hi Jens,
This one-patch series fixes a page-pin leak in register_shm_helper() after iov_iter_extract_pages() partially extracts an unaligned user buffer. The cleanup path undercounts the pinned pages by one and loses the final pin when it frees the page array.
The issue was reproduced on an x86_64 7.0.0-29-generic kernel with 4 KiB pages. On the unpatched kernel, each failing registration increased nr_foll_pin_acquired - nr_foll_pin_released by one.
The faulty code is also present in current mainline, linux-next, the TEE maintainer's next branch, and the supported 7.2.y, 7.1.y, 6.18.y, and 6.12.y branches.
Regards, Shukai
Shukai Ni (1): tee: fix page count in register_shm_helper() error path
drivers/tee/tee_shm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
base-commit: cee9395acd8043be0644b25c34bfa86623f2b935
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; }
op-tee@lists.trustedfirmware.org