From 19326174e264802b91fb4dfc0c1ea16d8bf3ef7e Mon Sep 17 00:00:00 2001 From: Bobi Jam Date: Fri, 18 Apr 2014 13:58:36 +0800 Subject: [PATCH] LU-4619 llite: prevent buffer overflow in fiemap lov_fiemap() does not take consider its @vallen parameter, which is the max buffer size the caller can hold for the fiemap extents. This patch fixes this and limits the max mapped fiemap extent count to fit in the preallocted buffer. This patch also fixes a memory out of bound write issue when the fiemap call is only for detecting the number of existing extent. Signed-off-by: Bobi Jam Change-Id: I3a786837fbfec7d5b3f848c5d357b28b9967be85 Reviewed-on: http://review.whamcloud.com/9834 Reviewed-by: Fan Yong Tested-by: Jenkins Reviewed-by: Patrick Farrell Tested-by: Maloo Reviewed-by: Oleg Drokin --- lustre/llite/file.c | 25 ++++++++++++++----------- lustre/lov/lov_obd.c | 11 ++++++----- 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/lustre/llite/file.c b/lustre/llite/file.c index e0019c3..99d866a 100644 --- a/lustre/llite/file.c +++ b/lustre/llite/file.c @@ -1822,12 +1822,12 @@ out: * Make the FIEMAP get_info call and returns the result. */ static int ll_do_fiemap(struct inode *inode, struct ll_user_fiemap *fiemap, - int num_bytes) + size_t num_bytes) { struct obd_export *exp = ll_i2dtexp(inode); struct lov_stripe_md *lsm = NULL; struct ll_fiemap_info_key fm_key = { .name = KEY_FIEMAP, }; - int vallen = num_bytes; + __u32 vallen = num_bytes; int rc; ENTRY; @@ -3425,18 +3425,21 @@ static int ll_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, fiemap->fm_extent_count = fieinfo->fi_extents_max; fiemap->fm_start = start; fiemap->fm_length = len; - memcpy(&fiemap->fm_extents[0], fieinfo->fi_extents_start, - sizeof(struct ll_fiemap_extent)); + if (extent_count > 0) + memcpy(&fiemap->fm_extents[0], fieinfo->fi_extents_start, + sizeof(struct ll_fiemap_extent)); - rc = ll_do_fiemap(inode, fiemap, num_bytes); + rc = ll_do_fiemap(inode, fiemap, num_bytes); - fieinfo->fi_flags = fiemap->fm_flags; - fieinfo->fi_extents_mapped = fiemap->fm_mapped_extents; - memcpy(fieinfo->fi_extents_start, &fiemap->fm_extents[0], - fiemap->fm_mapped_extents * sizeof(struct ll_fiemap_extent)); + fieinfo->fi_flags = fiemap->fm_flags; + fieinfo->fi_extents_mapped = fiemap->fm_mapped_extents; + if (extent_count > 0) + memcpy(fieinfo->fi_extents_start, &fiemap->fm_extents[0], + fiemap->fm_mapped_extents * + sizeof(struct ll_fiemap_extent)); - OBD_FREE_LARGE(fiemap, num_bytes); - return rc; + OBD_FREE_LARGE(fiemap, num_bytes); + return rc; } struct posix_acl *ll_get_acl(struct inode *inode, int type) diff --git a/lustre/lov/lov_obd.c b/lustre/lov/lov_obd.c index 7d35c05..8cdc3f1 100644 --- a/lustre/lov/lov_obd.c +++ b/lustre/lov/lov_obd.c @@ -1862,11 +1862,12 @@ static int lov_fiemap(struct lov_obd *lov, __u32 keylen, void *key, if (fm_end_offset == -EINVAL) GOTO(out, rc = -EINVAL); - if (fiemap->fm_extent_count == 0) { - get_num_extents = 1; - count_local = 0; - } - + if (fiemap_count_to_size(fiemap->fm_extent_count) > *vallen) + fiemap->fm_extent_count = fiemap_size_to_count(*vallen); + if (fiemap->fm_extent_count == 0) { + get_num_extents = 1; + count_local = 0; + } /* Check each stripe */ for (cur_stripe = start_stripe, i = 0; i < stripe_count; i++, cur_stripe = (cur_stripe + 1) % lsm->lsm_stripe_count) { -- 1.8.3.1