diff options
Diffstat (limited to 'meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2023-1252.patch')
-rw-r--r-- | meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2023-1252.patch | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2023-1252.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2023-1252.patch new file mode 100644 index 000000000..89a7f7949 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2023-1252.patch @@ -0,0 +1,89 @@ +From 9a254403760041528bc8f69fe2f5e1ef86950991 Mon Sep 17 00:00:00 2001 +From: yangerkun <yangerkun@huawei.com> +Date: Thu, 30 Sep 2021 11:22:28 +0800 +Subject: [PATCH] ovl: fix use after free in struct ovl_aio_req + +Example for triggering use after free in a overlay on ext4 setup: + +aio_read + ovl_read_iter + vfs_iter_read + ext4_file_read_iter + ext4_dio_read_iter + iomap_dio_rw -> -EIOCBQUEUED + /* + * Here IO is completed in a separate thread, + * ovl_aio_cleanup_handler() frees aio_req which has iocb embedded + */ + file_accessed(iocb->ki_filp); /**BOOM**/ + +Fix by introducing a refcount in ovl_aio_req similarly to aio_kiocb. This +guarantees that iocb is only freed after vfs_read/write_iter() returns on +underlying fs. + +Fixes: 2406a307ac7d ("ovl: implement async IO routines") +Signed-off-by: yangerkun <yangerkun@huawei.com> +Link: https://lore.kernel.org/r/20210930032228.3199690-3-yangerkun@huawei.com/ +Cc: <stable@vger.kernel.org> # v5.6 +Signed-off-by: Miklos Szeredi <mszeredi@redhat.com> +--- + fs/overlayfs/file.c | 16 ++++++++++++++-- + 1 file changed, 14 insertions(+), 2 deletions(-) + +diff --git a/fs/overlayfs/file.c b/fs/overlayfs/file.c +index c88ac571593dc1..44fea16751f1db 100644 +--- a/fs/overlayfs/file.c ++++ b/fs/overlayfs/file.c +@@ -17,6 +17,7 @@ + + struct ovl_aio_req { + struct kiocb iocb; ++ refcount_t ref; + struct kiocb *orig_iocb; + struct fd fd; + }; +@@ -252,6 +253,14 @@ static rwf_t ovl_iocb_to_rwf(int ifl) + return flags; + } + ++static inline void ovl_aio_put(struct ovl_aio_req *aio_req) ++{ ++ if (refcount_dec_and_test(&aio_req->ref)) { ++ fdput(aio_req->fd); ++ kmem_cache_free(ovl_aio_request_cachep, aio_req); ++ } ++} ++ + static void ovl_aio_cleanup_handler(struct ovl_aio_req *aio_req) + { + struct kiocb *iocb = &aio_req->iocb; +@@ -268,8 +277,7 @@ static void ovl_aio_cleanup_handler(struct ovl_aio_req *aio_req) + } + + orig_iocb->ki_pos = iocb->ki_pos; +- fdput(aio_req->fd); +- kmem_cache_free(ovl_aio_request_cachep, aio_req); ++ ovl_aio_put(aio_req); + } + + static void ovl_aio_rw_complete(struct kiocb *iocb, long res, long res2) +@@ -319,7 +327,9 @@ static ssize_t ovl_read_iter(struct kiocb *iocb, struct iov_iter *iter) + aio_req->orig_iocb = iocb; + kiocb_clone(&aio_req->iocb, iocb, real.file); + aio_req->iocb.ki_complete = ovl_aio_rw_complete; ++ refcount_set(&aio_req->ref, 2); + ret = vfs_iocb_iter_read(real.file, &aio_req->iocb, iter); ++ ovl_aio_put(aio_req); + if (ret != -EIOCBQUEUED) + ovl_aio_cleanup_handler(aio_req); + } +@@ -390,7 +400,9 @@ static ssize_t ovl_write_iter(struct kiocb *iocb, struct iov_iter *iter) + kiocb_clone(&aio_req->iocb, iocb, real.file); + aio_req->iocb.ki_flags = ifl; + aio_req->iocb.ki_complete = ovl_aio_rw_complete; ++ refcount_set(&aio_req->ref, 2); + ret = vfs_iocb_iter_write(real.file, &aio_req->iocb, iter); ++ ovl_aio_put(aio_req); + if (ret != -EIOCBQUEUED) + ovl_aio_cleanup_handler(aio_req); + } |