Tue Mar 3 17:46:39 2015 UTC ()
ffs_reload(): the current implementation blindly guesses critical fields
of the superblock didn't change. Add checks to ensure they didn't change
for real. This prevents several memory corruptions.


(maxv)
diff -r1.319 -r1.320 src/sys/ufs/ffs/ffs_vfsops.c

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

--- src/sys/ufs/ffs/ffs_vfsops.c 2015/02/23 13:38:54 1.319
+++ src/sys/ufs/ffs/ffs_vfsops.c 2015/03/03 17:46:39 1.320
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: ffs_vfsops.c,v 1.319 2015/02/23 13:38:54 maxv Exp $ */ 1/* $NetBSD: ffs_vfsops.c,v 1.320 2015/03/03 17:46:39 maxv 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.319 2015/02/23 13:38:54 maxv Exp $"); 64__KERNEL_RCSID(0, "$NetBSD: ffs_vfsops.c,v 1.320 2015/03/03 17:46:39 maxv 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>
@@ -723,44 +723,52 @@ ffs_reload(struct mount *mp, kauth_cred_ @@ -723,44 +723,52 @@ ffs_reload(struct mount *mp, kauth_cred_
723 if (error) 723 if (error)
724 return (error); 724 return (error);
725 newfs = kmem_alloc(fs_sbsize, KM_SLEEP); 725 newfs = kmem_alloc(fs_sbsize, KM_SLEEP);
726 memcpy(newfs, bp->b_data, fs_sbsize); 726 memcpy(newfs, bp->b_data, fs_sbsize);
727 727
728#ifdef FFS_EI 728#ifdef FFS_EI
729 if (ump->um_flags & UFS_NEEDSWAP) { 729 if (ump->um_flags & UFS_NEEDSWAP) {
730 ffs_sb_swap((struct fs*)bp->b_data, newfs); 730 ffs_sb_swap((struct fs*)bp->b_data, newfs);
731 fs->fs_flags |= FS_SWAPPED; 731 fs->fs_flags |= FS_SWAPPED;
732 } else 732 } else
733#endif 733#endif
734 fs->fs_flags &= ~FS_SWAPPED; 734 fs->fs_flags &= ~FS_SWAPPED;
735 735
736 /* We don't want the superblock size to change. */ 
737 if (newfs->fs_sbsize != fs_sbsize) { 
738 brelse(bp, 0); 
739 kmem_free(newfs, fs_sbsize); 
740 return (EINVAL); 
741 } 
742 if ((newfs->fs_magic != FS_UFS1_MAGIC && 736 if ((newfs->fs_magic != FS_UFS1_MAGIC &&
743 newfs->fs_magic != FS_UFS2_MAGIC)) { 737 newfs->fs_magic != FS_UFS2_MAGIC)) {
744 brelse(bp, 0); 738 brelse(bp, 0);
745 kmem_free(newfs, fs_sbsize); 739 kmem_free(newfs, fs_sbsize);
746 return (EIO); /* XXX needs translation */ 740 return (EIO); /* XXX needs translation */
747 } 741 }
748 if (!ffs_superblock_validate(newfs)) { 742 if (!ffs_superblock_validate(newfs)) {
749 brelse(bp, 0); 743 brelse(bp, 0);
750 kmem_free(newfs, fs_sbsize); 744 kmem_free(newfs, fs_sbsize);
751 return (EINVAL); 745 return (EINVAL);
752 } 746 }
753 747
 748 /*
 749 * The current implementation doesn't handle the possibility that
 750 * these values may have changed.
 751 */
 752 if ((newfs->fs_sbsize != fs_sbsize) ||
 753 (newfs->fs_cssize != fs->fs_cssize) ||
 754 (newfs->fs_contigsumsize != fs->fs_contigsumsize) ||
 755 (newfs->fs_ncg != fs->fs_ncg)) {
 756 brelse(bp, 0);
 757 kmem_free(newfs, fs_sbsize);
 758 return (EINVAL);
 759 }
 760
 761
754 /* Store off old fs_sblockloc for fs_oldfscompat_read. */ 762 /* Store off old fs_sblockloc for fs_oldfscompat_read. */
755 sblockloc = fs->fs_sblockloc; 763 sblockloc = fs->fs_sblockloc;
756 /* 764 /*
757 * Copy pointer fields back into superblock before copying in XXX 765 * Copy pointer fields back into superblock before copying in XXX
758 * new superblock. These should really be in the ufsmount. XXX 766 * new superblock. These should really be in the ufsmount. XXX
759 * Note that important parameters (eg fs_ncg) are unchanged. 767 * Note that important parameters (eg fs_ncg) are unchanged.
760 */ 768 */
761 newfs->fs_csp = fs->fs_csp; 769 newfs->fs_csp = fs->fs_csp;
762 newfs->fs_maxcluster = fs->fs_maxcluster; 770 newfs->fs_maxcluster = fs->fs_maxcluster;
763 newfs->fs_contigdirs = fs->fs_contigdirs; 771 newfs->fs_contigdirs = fs->fs_contigdirs;
764 newfs->fs_ronly = fs->fs_ronly; 772 newfs->fs_ronly = fs->fs_ronly;
765 newfs->fs_active = fs->fs_active; 773 newfs->fs_active = fs->fs_active;
766 memcpy(fs, newfs, (u_int)fs_sbsize); 774 memcpy(fs, newfs, (u_int)fs_sbsize);