From: Anton Arapov <aarapov@redhat.com> Date: Thu, 13 Nov 2008 16:08:48 +0100 Subject: [fs] hfsplus: check read_mapping_page return value Message-id: 20081113150846.GC10438@redhat.com O-Subject: [RHEL5.4 PATCH] BZ469645: CVE-2008-4934 kernel: hfsplus: check read_mapping_page() return value Bugzilla: 469645 RH-Acked-by: Jiri Pirko <jpirko@redhat.com> RH-Acked-by: Eugene Teo <eteo@redhat.com> RH-Acked-by: John Feeney <jfeeney@redhat.com> CVE: CVE-2008-4934 Bugzilla: 469645 Description: Return value of read_mapping_page() is passed on to kmap unchecked. The bug is triggered after the first read_mapping_page() in hfsplus_block_allocate(), this patch fixes all three usages in this functions but leaves the ones further down in the file unchanged. Upstream status: commit# 649f1ee6c705aab644035a7998d7b574193a598a Test status: patched kernel has been successfuly built, tested for boot. hfsplus module successfully inserts and removes in/from kernel. https://brewweb.devel.redhat.com/taskinfo?taskID=1572109 Notice: CVE-2008-4934 BZ469643 clone of this bug for RHEL4.8 == diff --git a/fs/hfsplus/bitmap.c b/fs/hfsplus/bitmap.c index d128a25..ea30afc 100644 --- a/fs/hfsplus/bitmap.c +++ b/fs/hfsplus/bitmap.c @@ -32,6 +32,10 @@ int hfsplus_block_allocate(struct super_block *sb, u32 size, u32 offset, u32 *ma mutex_lock(&HFSPLUS_SB(sb).alloc_file->i_mutex); mapping = HFSPLUS_SB(sb).alloc_file->i_mapping; page = read_mapping_page(mapping, offset / PAGE_CACHE_BITS, NULL); + if (IS_ERR(page)) { + start = size; + goto out; + } pptr = kmap(page); curr = pptr + (offset & (PAGE_CACHE_BITS - 1)) / 32; i = offset % 32; @@ -73,6 +77,10 @@ int hfsplus_block_allocate(struct super_block *sb, u32 size, u32 offset, u32 *ma break; page = read_mapping_page(mapping, offset / PAGE_CACHE_BITS, NULL); + if (IS_ERR(page)) { + start = size; + goto out; + } curr = pptr = kmap(page); if ((size ^ offset) / PAGE_CACHE_BITS) end = pptr + PAGE_CACHE_BITS / 32; @@ -120,6 +128,10 @@ found: offset += PAGE_CACHE_BITS; page = read_mapping_page(mapping, offset / PAGE_CACHE_BITS, NULL); + if (IS_ERR(page)) { + start = size; + goto out; + } pptr = kmap(page); curr = pptr; end = pptr + PAGE_CACHE_BITS / 32;