Mon Aug 9 15:50:13 2010 UTC ()
Return error if we try to mount a file system with block size > MAXBSIZE.

Note: there is a billion ways to make the kernel panic by trying
to mount a garbage file system and I don't imagine we'll ever get
close to fixing even half of them.  However, for this one failing
gracefully is a bonus since Xen DomU only does 32k MAXBSIZE and
the 64k MAXBSIZE file systems are out there (PR port-xen/43727).

Tested by compiling sys/rump with CPPFLAGS+=-DMAXPHYS=32768 (all
tests in tests/fs still pass).  I don't know how we're going to
translate this into an easy regression test, though.  Maybe with
a hacked newfs?


(pooka)
diff -r1.260 -r1.261 src/sys/ufs/ffs/ffs_vfsops.c

cvs diff -r1.260 -r1.261 src/sys/ufs/ffs/ffs_vfsops.c (expand / switch to unified diff)

--- src/sys/ufs/ffs/ffs_vfsops.c 2010/07/21 17:52:13 1.260
+++ src/sys/ufs/ffs/ffs_vfsops.c 2010/08/09 15:50:13 1.261
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: ffs_vfsops.c,v 1.260 2010/07/21 17:52:13 hannken Exp $ */ 1/* $NetBSD: ffs_vfsops.c,v 1.261 2010/08/09 15:50:13 pooka Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc. 4 * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Wasabi Systems, Inc, and by Andrew Doran. 8 * by Wasabi Systems, Inc, and by Andrew Doran.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -51,27 +51,27 @@ @@ -51,27 +51,27 @@
51 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 51 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58 * SUCH DAMAGE. 58 * SUCH DAMAGE.
59 * 59 *
60 * @(#)ffs_vfsops.c 8.31 (Berkeley) 5/20/95 60 * @(#)ffs_vfsops.c 8.31 (Berkeley) 5/20/95
61 */ 61 */
62 62
63#include <sys/cdefs.h> 63#include <sys/cdefs.h>
64__KERNEL_RCSID(0, "$NetBSD: ffs_vfsops.c,v 1.260 2010/07/21 17:52:13 hannken Exp $"); 64__KERNEL_RCSID(0, "$NetBSD: ffs_vfsops.c,v 1.261 2010/08/09 15:50:13 pooka Exp $");
65 65
66#if defined(_KERNEL_OPT) 66#if defined(_KERNEL_OPT)
67#include "opt_ffs.h" 67#include "opt_ffs.h"
68#include "opt_quota.h" 68#include "opt_quota.h"
69#include "opt_wapbl.h" 69#include "opt_wapbl.h"
70#endif 70#endif
71 71
72#include <sys/param.h> 72#include <sys/param.h>
73#include <sys/systm.h> 73#include <sys/systm.h>
74#include <sys/namei.h> 74#include <sys/namei.h>
75#include <sys/proc.h> 75#include <sys/proc.h>
76#include <sys/kernel.h> 76#include <sys/kernel.h>
77#include <sys/vnode.h> 77#include <sys/vnode.h>
@@ -818,26 +818,27 @@ ffs_mountfs(struct vnode *devvp, struct  @@ -818,26 +818,27 @@ ffs_mountfs(struct vnode *devvp, struct
818 struct fs *fs; 818 struct fs *fs;
819 dev_t dev; 819 dev_t dev;
820 struct partinfo dpart; 820 struct partinfo dpart;
821 void *space; 821 void *space;
822 daddr_t sblockloc, fsblockloc; 822 daddr_t sblockloc, fsblockloc;
823 int blks, fstype; 823 int blks, fstype;
824 int error, i, bsize, ronly, bset = 0; 824 int error, i, bsize, ronly, bset = 0;
825#ifdef FFS_EI 825#ifdef FFS_EI
826 int needswap = 0; /* keep gcc happy */ 826 int needswap = 0; /* keep gcc happy */
827#endif 827#endif
828 int32_t *lp; 828 int32_t *lp;
829 kauth_cred_t cred; 829 kauth_cred_t cred;
830 u_int32_t sbsize = 8192; /* keep gcc happy*/ 830 u_int32_t sbsize = 8192; /* keep gcc happy*/
 831 int32_t fsbsize;
831 832
832 dev = devvp->v_rdev; 833 dev = devvp->v_rdev;
833 cred = l ? l->l_cred : NOCRED; 834 cred = l ? l->l_cred : NOCRED;
834 835
835 /* Flush out any old buffers remaining from a previous use. */ 836 /* Flush out any old buffers remaining from a previous use. */
836 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY); 837 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
837 error = vinvalbuf(devvp, V_SAVE, cred, l, 0, 0); 838 error = vinvalbuf(devvp, V_SAVE, cred, l, 0, 0);
838 VOP_UNLOCK(devvp); 839 VOP_UNLOCK(devvp);
839 if (error) 840 if (error)
840 return (error); 841 return (error);
841 842
842 ronly = (mp->mnt_flag & MNT_RDONLY) != 0; 843 ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
843 844
@@ -876,41 +877,45 @@ ffs_mountfs(struct vnode *devvp, struct  @@ -876,41 +877,45 @@ ffs_mountfs(struct vnode *devvp, struct
876 goto out; 877 goto out;
877 } 878 }
878 error = bread(devvp, sblock_try[i] / DEV_BSIZE, SBLOCKSIZE, cred, 879 error = bread(devvp, sblock_try[i] / DEV_BSIZE, SBLOCKSIZE, cred,
879 0, &bp); 880 0, &bp);
880 if (error) { 881 if (error) {
881 fs = NULL; 882 fs = NULL;
882 goto out; 883 goto out;
883 } 884 }
884 fs = (struct fs*)bp->b_data; 885 fs = (struct fs*)bp->b_data;
885 fsblockloc = sblockloc = sblock_try[i]; 886 fsblockloc = sblockloc = sblock_try[i];
886 if (fs->fs_magic == FS_UFS1_MAGIC) { 887 if (fs->fs_magic == FS_UFS1_MAGIC) {
887 sbsize = fs->fs_sbsize; 888 sbsize = fs->fs_sbsize;
888 fstype = UFS1; 889 fstype = UFS1;
 890 fsbsize = fs->fs_bsize;
889#ifdef FFS_EI 891#ifdef FFS_EI
890 needswap = 0; 892 needswap = 0;
891 } else if (fs->fs_magic == bswap32(FS_UFS1_MAGIC)) { 893 } else if (fs->fs_magic == bswap32(FS_UFS1_MAGIC)) {
892 sbsize = bswap32(fs->fs_sbsize); 894 sbsize = bswap32(fs->fs_sbsize);
893 fstype = UFS1; 895 fstype = UFS1;
 896 fsbsize = bswap32(fs->fs_bsize);
894 needswap = 1; 897 needswap = 1;
895#endif 898#endif
896 } else if (fs->fs_magic == FS_UFS2_MAGIC) { 899 } else if (fs->fs_magic == FS_UFS2_MAGIC) {
897 sbsize = fs->fs_sbsize; 900 sbsize = fs->fs_sbsize;
898 fstype = UFS2; 901 fstype = UFS2;
 902 fsbsize = fs->fs_bsize;
899#ifdef FFS_EI 903#ifdef FFS_EI
900 needswap = 0; 904 needswap = 0;
901 } else if (fs->fs_magic == bswap32(FS_UFS2_MAGIC)) { 905 } else if (fs->fs_magic == bswap32(FS_UFS2_MAGIC)) {
902 sbsize = bswap32(fs->fs_sbsize); 906 sbsize = bswap32(fs->fs_sbsize);
903 fstype = UFS2; 907 fstype = UFS2;
 908 fsbsize = bswap32(fs->fs_bsize);
904 needswap = 1; 909 needswap = 1;
905#endif 910#endif
906 } else 911 } else
907 continue; 912 continue;
908 913
909 914
910 /* fs->fs_sblockloc isn't defined for old filesystems */ 915 /* fs->fs_sblockloc isn't defined for old filesystems */
911 if (fstype == UFS1 && !(fs->fs_old_flags & FS_FLAGS_UPDATED)) { 916 if (fstype == UFS1 && !(fs->fs_old_flags & FS_FLAGS_UPDATED)) {
912 if (sblockloc == SBLOCK_UFS2) 917 if (sblockloc == SBLOCK_UFS2)
913 /* 918 /*
914 * This is likely to be the first alternate 919 * This is likely to be the first alternate
915 * in a filesystem with 64k blocks. 920 * in a filesystem with 64k blocks.
916 * Don't use it. 921 * Don't use it.
@@ -923,26 +928,33 @@ ffs_mountfs(struct vnode *devvp, struct  @@ -923,26 +928,33 @@ ffs_mountfs(struct vnode *devvp, struct
923 if (needswap) 928 if (needswap)
924 fsblockloc = bswap64(fsblockloc); 929 fsblockloc = bswap64(fsblockloc);
925#endif 930#endif
926 } 931 }
927 932
928 /* Check we haven't found an alternate superblock */ 933 /* Check we haven't found an alternate superblock */
929 if (fsblockloc != sblockloc) 934 if (fsblockloc != sblockloc)
930 continue; 935 continue;
931 936
932 /* Validate size of superblock */ 937 /* Validate size of superblock */
933 if (sbsize > MAXBSIZE || sbsize < sizeof(struct fs)) 938 if (sbsize > MAXBSIZE || sbsize < sizeof(struct fs))
934 continue; 939 continue;
935 940
 941 /* Check that we can handle the file system blocksize */
 942 if (fsbsize > MAXBSIZE) {
 943 printf("ffs_mountfs: block size (%d) > MAXBSIZE (%d)",
 944 fsbsize, MAXBSIZE);
 945 continue;
 946 }
 947
936 /* Ok seems to be a good superblock */ 948 /* Ok seems to be a good superblock */
937 break; 949 break;
938 } 950 }
939 951
940 fs = malloc((u_long)sbsize, M_UFSMNT, M_WAITOK); 952 fs = malloc((u_long)sbsize, M_UFSMNT, M_WAITOK);
941 memcpy(fs, bp->b_data, sbsize); 953 memcpy(fs, bp->b_data, sbsize);
942 ump->um_fs = fs; 954 ump->um_fs = fs;
943 955
944#ifdef FFS_EI 956#ifdef FFS_EI
945 if (needswap) { 957 if (needswap) {
946 ffs_sb_swap((struct fs*)bp->b_data, fs); 958 ffs_sb_swap((struct fs*)bp->b_data, fs);
947 fs->fs_flags |= FS_SWAPPED; 959 fs->fs_flags |= FS_SWAPPED;
948 } else 960 } else