Commit 9f6c1333938c5d93da8be8f29f3b5469a3c00f95
Committed by
Linus Torvalds
1 parent
532f649f14
Exists in
master
and in
4 other branches
V3 minixfs: add missing directory type checking
There are a few places in the Minix FS code where the "inode" field of a minix_dir_entry is used without checking first to see if the dirent is really a minix3_dir_entry. The inode number in a V1/V2 dirent is 16 bits, whereas that in a V3 dirent is 32 bits. Accessing it as a 16 bit field when it really should be accessed as a 32 bit field probably kinda sorta works on a little-endian machine, but leads to some rather odd behaviour on big-endian machines. [akpm@linux-foundation.org: coding-style fixes] Signed-off-by: Doug Graham <dgraham@nortel.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Showing 1 changed file with 18 additions and 4 deletions Side-by-side Diff
fs/minix/dir.c
... | ... | @@ -308,14 +308,18 @@ |
308 | 308 | struct inode *inode = (struct inode*)mapping->host; |
309 | 309 | char *kaddr = page_address(page); |
310 | 310 | loff_t pos = page_offset(page) + (char*)de - kaddr; |
311 | - unsigned len = minix_sb(inode->i_sb)->s_dirsize; | |
311 | + struct minix_sb_info *sbi = minix_sb(inode->i_sb); | |
312 | + unsigned len = sbi->s_dirsize; | |
312 | 313 | int err; |
313 | 314 | |
314 | 315 | lock_page(page); |
315 | 316 | err = __minix_write_begin(NULL, mapping, pos, len, |
316 | 317 | AOP_FLAG_UNINTERRUPTIBLE, &page, NULL); |
317 | 318 | if (err == 0) { |
318 | - de->inode = 0; | |
319 | + if (sbi->s_version == MINIX_V3) | |
320 | + ((minix3_dirent *) de)->inode = 0; | |
321 | + else | |
322 | + de->inode = 0; | |
319 | 323 | err = dir_commit_chunk(page, pos, len); |
320 | 324 | } else { |
321 | 325 | unlock_page(page); |
... | ... | @@ -440,7 +444,10 @@ |
440 | 444 | err = __minix_write_begin(NULL, mapping, pos, sbi->s_dirsize, |
441 | 445 | AOP_FLAG_UNINTERRUPTIBLE, &page, NULL); |
442 | 446 | if (err == 0) { |
443 | - de->inode = inode->i_ino; | |
447 | + if (sbi->s_version == MINIX_V3) | |
448 | + ((minix3_dirent *) de)->inode = inode->i_ino; | |
449 | + else | |
450 | + de->inode = inode->i_ino; | |
444 | 451 | err = dir_commit_chunk(page, pos, sbi->s_dirsize); |
445 | 452 | } else { |
446 | 453 | unlock_page(page); |
... | ... | @@ -470,7 +477,14 @@ |
470 | 477 | ino_t res = 0; |
471 | 478 | |
472 | 479 | if (de) { |
473 | - res = de->inode; | |
480 | + struct address_space *mapping = page->mapping; | |
481 | + struct inode *inode = mapping->host; | |
482 | + struct minix_sb_info *sbi = minix_sb(inode->i_sb); | |
483 | + | |
484 | + if (sbi->s_version == MINIX_V3) | |
485 | + res = ((minix3_dirent *) de)->inode; | |
486 | + else | |
487 | + res = de->inode; | |
474 | 488 | dir_put_page(page); |
475 | 489 | } |
476 | 490 | return res; |