Commit ec81aecb29668ad71f699f4e7b96ec46691895b6
hfs: fix a potential buffer overflow
A specially-crafted Hierarchical File System (HFS) filesystem could cause a buffer overflow to occur in a process's kernel stack during a memcpy() call within the hfs_bnode_read() function (at fs/hfs/bnode.c:24). The attacker can provide the source buffer and length, and the destination buffer is a local variable of a fixed length. This local variable (passed as "&entry" from fs/hfs/dir.c:112 and allocated on line 60) is stored in the stack frame of hfs_bnode_read()'s caller, which is hfs_readdir(). Because the hfs_readdir() function executes upon any attempt to read a directory on the filesystem, it gets called whenever a user attempts to inspect any filesystem contents. [amwang@redhat.com: modify this patch and fix coding style problems] Signed-off-by: WANG Cong <amwang@redhat.com> Cc: Eugene Teo <eteo@redhat.com> Cc: Roman Zippel <zippel@linux-m68k.org> Cc: Al Viro <viro@zeniv.linux.org.uk> Cc: Christoph Hellwig <hch@lst.de> Cc: Alexey Dobriyan <adobriyan@gmail.com> Cc: Dave Anderson <anderson@redhat.com> Cc: <stable@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Showing 3 changed files with 21 additions and 1 deletions Side-by-side Diff
... | ... | @@ -289,6 +289,10 @@ |
289 | 289 | err = hfs_brec_find(&src_fd); |
290 | 290 | if (err) |
291 | 291 | goto out; |
292 | + if (src_fd.entrylength > sizeof(entry) || src_fd.entrylength < 0) { | |
293 | + err = -EIO; | |
294 | + goto out; | |
295 | + } | |
292 | 296 | |
293 | 297 | hfs_bnode_read(src_fd.bnode, &entry, src_fd.entryoffset, |
294 | 298 | src_fd.entrylength); |
... | ... | @@ -79,6 +79,11 @@ |
79 | 79 | filp->f_pos++; |
80 | 80 | /* fall through */ |
81 | 81 | case 1: |
82 | + if (fd.entrylength > sizeof(entry) || fd.entrylength < 0) { | |
83 | + err = -EIO; | |
84 | + goto out; | |
85 | + } | |
86 | + | |
82 | 87 | hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, fd.entrylength); |
83 | 88 | if (entry.type != HFS_CDR_THD) { |
84 | 89 | printk(KERN_ERR "hfs: bad catalog folder thread\n"); |
... | ... | @@ -109,6 +114,12 @@ |
109 | 114 | err = -EIO; |
110 | 115 | goto out; |
111 | 116 | } |
117 | + | |
118 | + if (fd.entrylength > sizeof(entry) || fd.entrylength < 0) { | |
119 | + err = -EIO; | |
120 | + goto out; | |
121 | + } | |
122 | + | |
112 | 123 | hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, fd.entrylength); |
113 | 124 | type = entry.type; |
114 | 125 | len = hfs_mac2asc(sb, strbuf, &fd.key->cat.CName); |
... | ... | @@ -409,8 +409,13 @@ |
409 | 409 | /* try to get the root inode */ |
410 | 410 | hfs_find_init(HFS_SB(sb)->cat_tree, &fd); |
411 | 411 | res = hfs_cat_find_brec(sb, HFS_ROOT_CNID, &fd); |
412 | - if (!res) | |
412 | + if (!res) { | |
413 | + if (fd.entrylength > sizeof(rec) || fd.entrylength < 0) { | |
414 | + res = -EIO; | |
415 | + goto bail; | |
416 | + } | |
413 | 417 | hfs_bnode_read(fd.bnode, &rec, fd.entryoffset, fd.entrylength); |
418 | + } | |
414 | 419 | if (res) { |
415 | 420 | hfs_find_exit(&fd); |
416 | 421 | goto bail_no_root; |
-
mentioned in commit 879295
-
mentioned in commit 6f24f8
-
mentioned in commit 6f24f8
-
mentioned in commit 6f24f8
-
mentioned in commit 6f24f8
-
mentioned in commit 6f24f8
-
mentioned in commit 6f24f8
-
mentioned in commit 6f24f8
-
mentioned in commit 6f24f8
-
mentioned in commit 6f24f8
-
mentioned in commit 6f24f8
-
mentioned in commit 6f24f8
-
mentioned in commit 6f24f8
-
mentioned in commit 6f24f8
-
mentioned in commit 6f24f8
-
mentioned in commit 6f24f8
-
mentioned in commit 6f24f8
-
mentioned in commit 6f24f8
-
mentioned in commit 6f24f8
-
mentioned in commit 6f24f8
-
mentioned in commit 6f24f8
-
mentioned in commit 6f24f8
-
mentioned in commit 6f24f8
-
mentioned in commit 6f24f8
-
mentioned in commit 6f24f8
-
mentioned in commit 6f24f8
-
mentioned in commit 6f24f8
-
mentioned in commit 6f24f8
-
mentioned in commit 6f24f8
-
mentioned in commit 6f24f8
-
mentioned in commit 6f24f8
-
mentioned in commit 6f24f8
-
mentioned in commit 6f24f8
-
mentioned in commit 6f24f8
-
mentioned in commit 6f24f8
-
mentioned in commit 6f24f8
-
mentioned in commit 6f24f8
-
mentioned in commit 6f24f8
-
mentioned in commit 6f24f8
-
mentioned in commit 6f24f8
-
mentioned in commit 6f24f8
-
mentioned in commit 6f24f8
-
mentioned in commit 6f24f8
-
mentioned in commit 6f24f8
-
mentioned in commit 6f24f8