From 3f686532c9b4fd603d4ad2d3392232cff24188f4 Mon Sep 17 00:00:00 2001 From: Austin Shafer Date: Fri, 21 Apr 2023 09:56:50 +0200 Subject: [PATCH] linuxkpi: Fix __sg_alloc_table_from_pages loop Commit 3e0856b63fe0e375a0951e05c2ef98bb2ebd9421 updated __sg_alloc_table_from_pages to use the same API as linux, but modified the loop condition when going over the pages in a sg list. Part of the change included moving the sg_next call out of the for loop and into the body, which causes an off by one error when traversing the list. Since sg_next is called before the loop body it will skip the first element and read one past the last element. This caused panics when running PRIME with nvidia-drm as the off-by-one issue causes a NULL dereference. Reviewed by: bz, hselasky Differential Revision: https://reviews.freebsd.org/D39628 Fixes: 3e0856b63fe0 ("linuxkpi: Fix `sg_alloc_table_from_pages()` to have the same API as Linux") --- sys/compat/linuxkpi/common/include/linux/scatterlist.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/compat/linuxkpi/common/include/linux/scatterlist.h b/sys/compat/linuxkpi/common/include/linux/scatterlist.h index fe4bce06819d..b448262f3497 100644 --- a/sys/compat/linuxkpi/common/include/linux/scatterlist.h +++ b/sys/compat/linuxkpi/common/include/linux/scatterlist.h @@ -383,8 +383,6 @@ __sg_alloc_table_from_pages(struct sg_table *sgt, unsigned long seg_size; unsigned int j; - s = sg_next(s); - len = 0; for (j = cur + 1; j < count; ++j) { len += PAGE_SIZE; @@ -398,6 +396,8 @@ __sg_alloc_table_from_pages(struct sg_table *sgt, size -= seg_size; off = 0; cur = j; + + s = sg_next(s); } KASSERT(s != NULL, ("s is NULL after loop in __sg_alloc_table_from_pages()"));