• R/O
  • HTTP
  • SSH
  • HTTPS

linux-2.4.36: 提交

2.4.36-stable kernel tree


Commit MetaInfo

修訂b85ad79e46390c2774a7dc2056a2a719ae97a5ac (tree)
時間2008-11-09 23:26:51
作者Eric Sandeen <sandeen@redh...>
CommiterWilly Tarreau

Log Message

ext: Avoid printk floods in the face of directory

This is a trivial backport of the following upstream commits:

- bd39597cbd42a784105a04010100e27267481c67 (ext2)
- cdbf6dba28e8e6268c8420857696309470009fd9 (ext3)

This addresses CVE-2008-3528

ext[23]: Avoid printk floods in the face of directory corruption

Note: some people thinks this represents a security bug, since it
might make the system go away while it is printing a large number of
console messages, especially if a serial console is involved. Hence,
it has been assigned CVE-2008-3528, but it requires that the attacker
either has physical access to your machine to insert a USB disk with a
corrupted filesystem image (at which point why not just hit the power
button), or is otherwise able to convince the system administrator to
mount an arbitrary filesystem image (at which point why not just
include a setuid shell or world-writable hard disk device file or some
such). Me, I think they're just being silly. --tytso

Signed-off-by: Eric Sandeen <sandeen@redhat.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Cc: linux-ext4@vger.kernel.org
Cc: Eugene Teo <eugeneteo@kernel.sg>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
[w@1wt.eu: backport from 2.6-stable to 2.4. Removed all ext4 references]
Signed-off-by: Willy Tarreau <w@1wt.eu>

Change Summary

差異

--- a/fs/ext2/dir.c
+++ b/fs/ext2/dir.c
@@ -63,7 +63,7 @@ static int ext2_commit_chunk(struct page *page, unsigned from, unsigned to)
6363 return err;
6464 }
6565
66-static void ext2_check_page(struct page *page)
66+static void ext2_check_page(struct page *page, int quiet)
6767 {
6868 struct inode *dir = page->mapping->host;
6969 struct super_block *sb = dir->i_sb;
@@ -110,10 +110,10 @@ out:
110110 /* Too bad, we had an error */
111111
112112 Ebadsize:
113- ext2_error(sb, "ext2_check_page",
114- "size of directory #%lu is not a multiple of chunk size",
115- dir->i_ino
116- );
113+ if (!quiet)
114+ ext2_error(sb, __func__,
115+ "size of directory #%lu is not a multiple "
116+ "of chunk size", dir->i_ino);
117117 goto fail;
118118 Eshort:
119119 error = "rec_len is smaller than minimal";
@@ -130,25 +130,29 @@ Espan:
130130 Einumber:
131131 error = "inode out of bounds";
132132 bad_entry:
133- ext2_error (sb, "ext2_check_page", "bad entry in directory #%lu: %s - "
134- "offset=%lu, inode=%lu, rec_len=%d, name_len=%d",
135- dir->i_ino, error, (page->index<<PAGE_CACHE_SHIFT)+offs,
136- (unsigned long) le32_to_cpu(p->inode),
137- rec_len, p->name_len);
133+ if (!quiet)
134+ ext2_error(sb, __func__, "bad entry in directory #%lu: : %s - "
135+ "offset=%lu, inode=%lu, rec_len=%d, name_len=%d",
136+ dir->i_ino, error, (page->index<<PAGE_CACHE_SHIFT)+offs,
137+ (unsigned long) le32_to_cpu(p->inode),
138+ rec_len, p->name_len);
138139 goto fail;
139140 Eend:
140- p = (ext2_dirent *)(kaddr + offs);
141- ext2_error (sb, "ext2_check_page",
142- "entry in directory #%lu spans the page boundary"
143- "offset=%lu, inode=%lu",
144- dir->i_ino, (page->index<<PAGE_CACHE_SHIFT)+offs,
145- (unsigned long) le32_to_cpu(p->inode));
141+ if (!quiet) {
142+ p = (ext2_dirent *)(kaddr + offs);
143+ ext2_error(sb, "ext2_check_page",
144+ "entry in directory #%lu spans the page boundary"
145+ "offset=%lu, inode=%lu",
146+ dir->i_ino, (page->index<<PAGE_CACHE_SHIFT)+offs,
147+ (unsigned long) le32_to_cpu(p->inode));
148+ }
146149 fail:
147150 SetPageChecked(page);
148151 SetPageError(page);
149152 }
150153
151-static struct page * ext2_get_page(struct inode *dir, unsigned long n)
154+static struct page * ext2_get_page(struct inode *dir, unsigned long n,
155+ int quiet)
152156 {
153157 struct address_space *mapping = dir->i_mapping;
154158 struct page *page = read_cache_page(mapping, n,
@@ -159,7 +163,7 @@ static struct page * ext2_get_page(struct inode *dir, unsigned long n)
159163 if (!Page_Uptodate(page))
160164 goto fail;
161165 if (!PageChecked(page))
162- ext2_check_page(page);
166+ ext2_check_page(page, quiet);
163167 if (PageError(page))
164168 goto fail;
165169 }
@@ -257,7 +261,7 @@ ext2_readdir (struct file * filp, void * dirent, filldir_t filldir)
257261 for ( ; n < npages; n++, offset = 0) {
258262 char *kaddr, *limit;
259263 ext2_dirent *de;
260- struct page *page = ext2_get_page(inode, n);
264+ struct page *page = ext2_get_page(inode, n, 0);
261265
262266 if (IS_ERR(page)) {
263267 ext2_error(sb, __FUNCTION__,
@@ -320,6 +324,7 @@ struct ext2_dir_entry_2 * ext2_find_entry (struct inode * dir,
320324 unsigned long npages = dir_pages(dir);
321325 struct page *page = NULL;
322326 ext2_dirent * de;
327+ int dir_has_error = 0;
323328
324329 /* OFFSET_CACHE */
325330 *res_page = NULL;
@@ -330,7 +335,7 @@ struct ext2_dir_entry_2 * ext2_find_entry (struct inode * dir,
330335 n = start;
331336 do {
332337 char *kaddr;
333- page = ext2_get_page(dir, n);
338+ page = ext2_get_page(dir, n, dir_has_error);
334339 if (!IS_ERR(page)) {
335340 kaddr = page_address(page);
336341 de = (ext2_dirent *) kaddr;
@@ -341,7 +346,9 @@ struct ext2_dir_entry_2 * ext2_find_entry (struct inode * dir,
341346 de = ext2_next_entry(de);
342347 }
343348 ext2_put_page(page);
344- }
349+ } else
350+ dir_has_error = 1;
351+
345352 if (++n >= npages)
346353 n = 0;
347354 /* next page is past the blocks we've got */
@@ -364,7 +371,7 @@ found:
364371
365372 struct ext2_dir_entry_2 * ext2_dotdot (struct inode *dir, struct page **p)
366373 {
367- struct page *page = ext2_get_page(dir, 0);
374+ struct page *page = ext2_get_page(dir, 0, 0);
368375 ext2_dirent *de = NULL;
369376
370377 if (!IS_ERR(page)) {
@@ -431,7 +438,7 @@ int ext2_add_link (struct dentry *dentry, struct inode *inode)
431438
432439 /* We take care of directory expansion in the same loop */
433440 for (n = 0; n <= npages; n++) {
434- page = ext2_get_page(dir, n);
441+ page = ext2_get_page(dir, n, 0);
435442 err = PTR_ERR(page);
436443 if (IS_ERR(page))
437444 goto out;
@@ -571,14 +578,17 @@ int ext2_empty_dir (struct inode * inode)
571578 {
572579 struct page *page = NULL;
573580 unsigned long i, npages = dir_pages(inode);
581+ int dir_has_error = 0;
574582
575583 for (i = 0; i < npages; i++) {
576584 char *kaddr;
577585 ext2_dirent * de;
578- page = ext2_get_page(inode, i);
586+ page = ext2_get_page(inode, i, dir_has_error);
579587
580- if (IS_ERR(page))
588+ if (IS_ERR(page)) {
589+ dir_has_error = 1;
581590 continue;
591+ }
582592
583593 kaddr = page_address(page);
584594 de = (ext2_dirent *)kaddr;
--- a/fs/ext3/dir.c
+++ b/fs/ext3/dir.c
@@ -76,6 +76,7 @@ static int ext3_readdir(struct file * filp,
7676 struct super_block * sb;
7777 int err;
7878 struct inode *inode = filp->f_dentry->d_inode;
79+ int dir_has_error = 0;
7980
8081 sb = inode->i_sb;
8182
@@ -87,9 +88,12 @@ static int ext3_readdir(struct file * filp,
8788 blk = (filp->f_pos) >> EXT3_BLOCK_SIZE_BITS(sb);
8889 bh = ext3_bread (0, inode, blk, 0, &err);
8990 if (!bh) {
90- ext3_error (sb, "ext3_readdir",
91- "directory #%lu contains a hole at offset %lu",
92- inode->i_ino, (unsigned long)filp->f_pos);
91+ if (!dir_has_error) {
92+ ext3_error (sb, __func__, "directory #%lu "
93+ "contains a hole at offset %lld",
94+ inode->i_ino, filp->f_pos);
95+ dir_has_error = 1;
96+ }
9397 filp->f_pos += sb->s_blocksize - offset;
9498 continue;
9599 }
Show on old repository browser