aboutsummaryrefslogtreecommitdiffstats
path: root/fs/sysv/super.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/sysv/super.c')
-rw-r--r--fs/sysv/super.c75
1 files changed, 52 insertions, 23 deletions
diff --git a/fs/sysv/super.c b/fs/sysv/super.c
index 5a903da54551..85359a8df605 100644
--- a/fs/sysv/super.c
+++ b/fs/sysv/super.c
@@ -24,6 +24,7 @@
24#include <linux/init.h> 24#include <linux/init.h>
25#include <linux/slab.h> 25#include <linux/slab.h>
26#include <linux/buffer_head.h> 26#include <linux/buffer_head.h>
27#include <linux/parser.h>
27#include "sysv.h" 28#include "sysv.h"
28 29
29/* 30/*
@@ -347,7 +348,6 @@ static int complete_read_super(struct super_block *sb, int silent, int size)
347 sb->s_flags |= MS_RDONLY; 348 sb->s_flags |= MS_RDONLY;
348 if (sbi->s_truncate) 349 if (sbi->s_truncate)
349 sb->s_root->d_op = &sysv_dentry_operations; 350 sb->s_root->d_op = &sysv_dentry_operations;
350 sb->s_dirt = 1;
351 return 1; 351 return 1;
352} 352}
353 353
@@ -435,12 +435,46 @@ Ebadsize:
435 goto failed; 435 goto failed;
436} 436}
437 437
438static int v7_fill_super(struct super_block *sb, void *data, int silent) 438static int v7_sanity_check(struct super_block *sb, struct buffer_head *bh)
439{ 439{
440 struct sysv_sb_info *sbi;
441 struct buffer_head *bh, *bh2 = NULL;
442 struct v7_super_block *v7sb; 440 struct v7_super_block *v7sb;
443 struct sysv_inode *v7i; 441 struct sysv_inode *v7i;
442 struct buffer_head *bh2;
443 struct sysv_sb_info *sbi;
444
445 sbi = sb->s_fs_info;
446
447 /* plausibility check on superblock */
448 v7sb = (struct v7_super_block *) bh->b_data;
449 if (fs16_to_cpu(sbi, v7sb->s_nfree) > V7_NICFREE ||
450 fs16_to_cpu(sbi, v7sb->s_ninode) > V7_NICINOD ||
451 fs32_to_cpu(sbi, v7sb->s_fsize) > V7_MAXSIZE)
452 return 0;
453
454 /* plausibility check on root inode: it is a directory,
455 with a nonzero size that is a multiple of 16 */
456 bh2 = sb_bread(sb, 2);
457 if (bh2 == NULL)
458 return 0;
459
460 v7i = (struct sysv_inode *)(bh2->b_data + 64);
461 if ((fs16_to_cpu(sbi, v7i->i_mode) & ~0777) != S_IFDIR ||
462 (fs32_to_cpu(sbi, v7i->i_size) == 0) ||
463 (fs32_to_cpu(sbi, v7i->i_size) & 017) ||
464 (fs32_to_cpu(sbi, v7i->i_size) > V7_NFILES *
465 sizeof(struct sysv_dir_entry))) {
466 brelse(bh2);
467 return 0;
468 }
469
470 brelse(bh2);
471 return 1;
472}
473
474static int v7_fill_super(struct super_block *sb, void *data, int silent)
475{
476 struct sysv_sb_info *sbi;
477 struct buffer_head *bh;
444 478
445 if (440 != sizeof (struct v7_super_block)) 479 if (440 != sizeof (struct v7_super_block))
446 panic("V7 FS: bad super-block size"); 480 panic("V7 FS: bad super-block size");
@@ -454,7 +488,6 @@ static int v7_fill_super(struct super_block *sb, void *data, int silent)
454 sbi->s_sb = sb; 488 sbi->s_sb = sb;
455 sbi->s_block_base = 0; 489 sbi->s_block_base = 0;
456 sbi->s_type = FSTYPE_V7; 490 sbi->s_type = FSTYPE_V7;
457 sbi->s_bytesex = BYTESEX_PDP;
458 sb->s_fs_info = sbi; 491 sb->s_fs_info = sbi;
459 492
460 sb_set_blocksize(sb, 512); 493 sb_set_blocksize(sb, 512);
@@ -466,32 +499,27 @@ static int v7_fill_super(struct super_block *sb, void *data, int silent)
466 goto failed; 499 goto failed;
467 } 500 }
468 501
469 /* plausibility check on superblock */ 502 /* Try PDP-11 UNIX */
470 v7sb = (struct v7_super_block *) bh->b_data; 503 sbi->s_bytesex = BYTESEX_PDP;
471 if (fs16_to_cpu(sbi, v7sb->s_nfree) > V7_NICFREE || 504 if (v7_sanity_check(sb, bh))
472 fs16_to_cpu(sbi, v7sb->s_ninode) > V7_NICINOD || 505 goto detected;
473 fs32_to_cpu(sbi, v7sb->s_time) == 0)
474 goto failed;
475 506
476 /* plausibility check on root inode: it is a directory, 507 /* Try PC/IX, v7/x86 */
477 with a nonzero size that is a multiple of 16 */ 508 sbi->s_bytesex = BYTESEX_LE;
478 if ((bh2 = sb_bread(sb, 2)) == NULL) 509 if (v7_sanity_check(sb, bh))
479 goto failed; 510 goto detected;
480 v7i = (struct sysv_inode *)(bh2->b_data + 64);
481 if ((fs16_to_cpu(sbi, v7i->i_mode) & ~0777) != S_IFDIR ||
482 (fs32_to_cpu(sbi, v7i->i_size) == 0) ||
483 (fs32_to_cpu(sbi, v7i->i_size) & 017) != 0)
484 goto failed;
485 brelse(bh2);
486 bh2 = NULL;
487 511
512 goto failed;
513
514detected:
488 sbi->s_bh1 = bh; 515 sbi->s_bh1 = bh;
489 sbi->s_bh2 = bh; 516 sbi->s_bh2 = bh;
490 if (complete_read_super(sb, silent, 1)) 517 if (complete_read_super(sb, silent, 1))
491 return 0; 518 return 0;
492 519
493failed: 520failed:
494 brelse(bh2); 521 printk(KERN_ERR "VFS: could not find a valid V7 on %s.\n",
522 sb->s_id);
495 brelse(bh); 523 brelse(bh);
496 kfree(sbi); 524 kfree(sbi);
497 return -EINVAL; 525 return -EINVAL;
@@ -560,4 +588,5 @@ static void __exit exit_sysv_fs(void)
560 588
561module_init(init_sysv_fs) 589module_init(init_sysv_fs)
562module_exit(exit_sysv_fs) 590module_exit(exit_sysv_fs)
591MODULE_ALIAS("v7");
563MODULE_LICENSE("GPL"); 592MODULE_LICENSE("GPL");