Fri Jan 21 20:36:53 2011 UTC ()
Split out the raw to indexed partitioning code protecting against roque
implementations that use `ramdom' numbers for the physical partitions breaking
lots of implementations. Known curlpit is MicroSoft Windows 7.

Not only the partition mappings need to be protected against this but also the metadata partition files.


(reinoud)
diff -r1.110 -r1.111 src/sys/fs/udf/udf_subr.c

cvs diff -r1.110 -r1.111 src/sys/fs/udf/udf_subr.c (expand / switch to unified diff)

--- src/sys/fs/udf/udf_subr.c 2011/01/13 13:13:31 1.110
+++ src/sys/fs/udf/udf_subr.c 2011/01/21 20:36:53 1.111
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: udf_subr.c,v 1.110 2011/01/13 13:13:31 reinoud Exp $ */ 1/* $NetBSD: udf_subr.c,v 1.111 2011/01/21 20:36:53 reinoud Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2006, 2008 Reinoud Zandijk 4 * Copyright (c) 2006, 2008 Reinoud Zandijk
5 * All rights reserved. 5 * All rights reserved.
6 *  6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
@@ -19,27 +19,27 @@ @@ -19,27 +19,27 @@
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 *  26 *
27 */ 27 */
28 28
29 29
30#include <sys/cdefs.h> 30#include <sys/cdefs.h>
31#ifndef lint 31#ifndef lint
32__KERNEL_RCSID(0, "$NetBSD: udf_subr.c,v 1.110 2011/01/13 13:13:31 reinoud Exp $"); 32__KERNEL_RCSID(0, "$NetBSD: udf_subr.c,v 1.111 2011/01/21 20:36:53 reinoud Exp $");
33#endif /* not lint */ 33#endif /* not lint */
34 34
35 35
36#if defined(_KERNEL_OPT) 36#if defined(_KERNEL_OPT)
37#include "opt_compat_netbsd.h" 37#include "opt_compat_netbsd.h"
38#endif 38#endif
39 39
40#include <sys/param.h> 40#include <sys/param.h>
41#include <sys/systm.h> 41#include <sys/systm.h>
42#include <sys/sysctl.h> 42#include <sys/sysctl.h>
43#include <sys/namei.h> 43#include <sys/namei.h>
44#include <sys/proc.h> 44#include <sys/proc.h>
45#include <sys/kernel.h> 45#include <sys/kernel.h>
@@ -973,38 +973,59 @@ int @@ -973,38 +973,59 @@ int
973udf_get_record_vpart(struct udf_mount *ump, int udf_c_type) 973udf_get_record_vpart(struct udf_mount *ump, int udf_c_type)
974{ 974{
975 int vpart_num; 975 int vpart_num;
976 976
977 vpart_num = ump->data_part; 977 vpart_num = ump->data_part;
978 if (udf_c_type == UDF_C_NODE) 978 if (udf_c_type == UDF_C_NODE)
979 vpart_num = ump->node_part; 979 vpart_num = ump->node_part;
980 if (udf_c_type == UDF_C_FIDS) 980 if (udf_c_type == UDF_C_FIDS)
981 vpart_num = ump->fids_part; 981 vpart_num = ump->fids_part;
982 982
983 return vpart_num; 983 return vpart_num;
984} 984}
985 985
 986
 987/*
 988 * BUGALERT: some rogue implementations use random physical partition
 989 * numbers to break other implementations so lookup the number.
 990 */
 991
 992static uint16_t
 993udf_find_raw_phys(struct udf_mount *ump, uint16_t raw_phys_part)
 994{
 995 struct part_desc *part;
 996 uint16_t phys_part;
 997
 998 for (phys_part = 0; phys_part < UDF_PARTITIONS; phys_part++) {
 999 part = ump->partitions[phys_part];
 1000 if (part == NULL)
 1001 break;
 1002 if (udf_rw16(part->part_num) == raw_phys_part)
 1003 break;
 1004 }
 1005 return phys_part;
 1006}
 1007
986/* --------------------------------------------------------------------- */ 1008/* --------------------------------------------------------------------- */
987 1009
988/* we dont try to be smart; we just record the parts */ 1010/* we dont try to be smart; we just record the parts */
989#define UDF_UPDATE_DSCR(name, dscr) \ 1011#define UDF_UPDATE_DSCR(name, dscr) \
990 if (name) \ 1012 if (name) \
991 free(name, M_UDFVOLD); \ 1013 free(name, M_UDFVOLD); \
992 name = dscr; 1014 name = dscr;
993 1015
994static int 1016static int
995udf_process_vds_descriptor(struct udf_mount *ump, union dscrptr *dscr) 1017udf_process_vds_descriptor(struct udf_mount *ump, union dscrptr *dscr)
996{ 1018{
997 struct part_desc *part; 
998 uint16_t phys_part, raw_phys_part; 1019 uint16_t phys_part, raw_phys_part;
999 1020
1000 DPRINTF(VOLUMES, ("\tprocessing VDS descr %d\n", 1021 DPRINTF(VOLUMES, ("\tprocessing VDS descr %d\n",
1001 udf_rw16(dscr->tag.id))); 1022 udf_rw16(dscr->tag.id)));
1002 switch (udf_rw16(dscr->tag.id)) { 1023 switch (udf_rw16(dscr->tag.id)) {
1003 case TAGID_PRI_VOL : /* primary partition */ 1024 case TAGID_PRI_VOL : /* primary partition */
1004 UDF_UPDATE_DSCR(ump->primary_vol, &dscr->pvd); 1025 UDF_UPDATE_DSCR(ump->primary_vol, &dscr->pvd);
1005 break; 1026 break;
1006 case TAGID_LOGVOL : /* logical volume */ 1027 case TAGID_LOGVOL : /* logical volume */
1007 UDF_UPDATE_DSCR(ump->logical_vol, &dscr->lvd); 1028 UDF_UPDATE_DSCR(ump->logical_vol, &dscr->lvd);
1008 break; 1029 break;
1009 case TAGID_UNALLOC_SPACE : /* unallocated space */ 1030 case TAGID_UNALLOC_SPACE : /* unallocated space */
1010 UDF_UPDATE_DSCR(ump->unallocated, &dscr->usd); 1031 UDF_UPDATE_DSCR(ump->unallocated, &dscr->usd);
@@ -1016,33 +1037,28 @@ udf_process_vds_descriptor(struct udf_mo @@ -1016,33 +1037,28 @@ udf_process_vds_descriptor(struct udf_mo
1016 case TAGID_PARTITION : /* physical partition */ 1037 case TAGID_PARTITION : /* physical partition */
1017 /* not much use if its not allocated */ 1038 /* not much use if its not allocated */
1018 if ((udf_rw16(dscr->pd.flags) & UDF_PART_FLAG_ALLOCATED) == 0) { 1039 if ((udf_rw16(dscr->pd.flags) & UDF_PART_FLAG_ALLOCATED) == 0) {
1019 free(dscr, M_UDFVOLD); 1040 free(dscr, M_UDFVOLD);
1020 break; 1041 break;
1021 } 1042 }
1022 1043
1023 /* 1044 /*
1024 * BUGALERT: some rogue implementations use random physical 1045 * BUGALERT: some rogue implementations use random physical
1025 * partition numbers to break other implementations so lookup 1046 * partition numbers to break other implementations so lookup
1026 * the number. 1047 * the number.
1027 */ 1048 */
1028 raw_phys_part = udf_rw16(dscr->pd.part_num); 1049 raw_phys_part = udf_rw16(dscr->pd.part_num);
1029 for (phys_part = 0; phys_part < UDF_PARTITIONS; phys_part++) { 1050 phys_part = udf_find_raw_phys(ump, raw_phys_part);
1030 part = ump->partitions[phys_part]; 1051
1031 if (part == NULL) 
1032 break; 
1033 if (udf_rw16(part->part_num) == raw_phys_part) 
1034 break; 
1035 } 
1036 if (phys_part == UDF_PARTITIONS) { 1052 if (phys_part == UDF_PARTITIONS) {
1037 free(dscr, M_UDFVOLD); 1053 free(dscr, M_UDFVOLD);
1038 return EINVAL; 1054 return EINVAL;
1039 } 1055 }
1040 1056
1041 UDF_UPDATE_DSCR(ump->partitions[phys_part], &dscr->pd); 1057 UDF_UPDATE_DSCR(ump->partitions[phys_part], &dscr->pd);
1042 break; 1058 break;
1043 case TAGID_VOL : /* volume space extender; rare */ 1059 case TAGID_VOL : /* volume space extender; rare */
1044 DPRINTF(VOLUMES, ("VDS extender ignored\n")); 1060 DPRINTF(VOLUMES, ("VDS extender ignored\n"));
1045 free(dscr, M_UDFVOLD); 1061 free(dscr, M_UDFVOLD);
1046 break; 1062 break;
1047 default : 1063 default :
1048 DPRINTF(VOLUMES, ("Unhandled VDS type %d\n", 1064 DPRINTF(VOLUMES, ("Unhandled VDS type %d\n",
@@ -1829,27 +1845,26 @@ udf_write_metadata_partition_spacetable( @@ -1829,27 +1845,26 @@ udf_write_metadata_partition_spacetable(
1829 1845
1830/* --------------------------------------------------------------------- */ 1846/* --------------------------------------------------------------------- */
1831 1847
1832/* 1848/*
1833 * Checks if ump's vds information is correct and complete 1849 * Checks if ump's vds information is correct and complete
1834 */ 1850 */
1835 1851
1836int 1852int
1837udf_process_vds(struct udf_mount *ump) { 1853udf_process_vds(struct udf_mount *ump) {
1838 union udf_pmap *mapping; 1854 union udf_pmap *mapping;
1839 /* struct udf_args *args = &ump->mount_args; */ 1855 /* struct udf_args *args = &ump->mount_args; */
1840 struct logvol_int_desc *lvint; 1856 struct logvol_int_desc *lvint;
1841 struct udf_logvol_info *lvinfo; 1857 struct udf_logvol_info *lvinfo;
1842 struct part_desc *part; 
1843 uint32_t n_pm, mt_l; 1858 uint32_t n_pm, mt_l;
1844 uint8_t *pmap_pos; 1859 uint8_t *pmap_pos;
1845 char *domain_name, *map_name; 1860 char *domain_name, *map_name;
1846 const char *check_name; 1861 const char *check_name;
1847 char bits[128]; 1862 char bits[128];
1848 int pmap_stype, pmap_size; 1863 int pmap_stype, pmap_size;
1849 int pmap_type, log_part, phys_part, raw_phys_part, maps_on; 1864 int pmap_type, log_part, phys_part, raw_phys_part, maps_on;
1850 int n_phys, n_virt, n_spar, n_meta; 1865 int n_phys, n_virt, n_spar, n_meta;
1851 int len, error; 1866 int len, error;
1852 1867
1853 if (ump == NULL) 1868 if (ump == NULL)
1854 return ENOENT; 1869 return ENOENT;
1855 1870
@@ -1960,33 +1975,27 @@ udf_process_vds(struct udf_mount *ump) { @@ -1960,33 +1975,27 @@ udf_process_vds(struct udf_mount *ump) {
1960 ump->fids_part = log_part; 1975 ump->fids_part = log_part;
1961 break; 1976 break;
1962 } 1977 }
1963 break; 1978 break;
1964 default: 1979 default:
1965 return EINVAL; 1980 return EINVAL;
1966 } 1981 }
1967 1982
1968 /* 1983 /*
1969 * BUGALERT: some rogue implementations use random physical 1984 * BUGALERT: some rogue implementations use random physical
1970 * partition numbers to break other implementations so lookup 1985 * partition numbers to break other implementations so lookup
1971 * the number. 1986 * the number.
1972 */ 1987 */
1973 for (phys_part = 0; phys_part < UDF_PARTITIONS; phys_part++) { 1988 phys_part = udf_find_raw_phys(ump, raw_phys_part);
1974 part = ump->partitions[phys_part]; 
1975 if (part == NULL) 
1976 continue; 
1977 if (udf_rw16(part->part_num) == raw_phys_part) 
1978 break; 
1979 } 
1980 1989
1981 DPRINTF(VOLUMES, ("\t%d -> %d(%d) type %d\n", log_part, 1990 DPRINTF(VOLUMES, ("\t%d -> %d(%d) type %d\n", log_part,
1982 raw_phys_part, phys_part, pmap_type)); 1991 raw_phys_part, phys_part, pmap_type));
1983  1992
1984 if (phys_part == UDF_PARTITIONS) 1993 if (phys_part == UDF_PARTITIONS)
1985 return EINVAL; 1994 return EINVAL;
1986 if (pmap_type == UDF_VTOP_TYPE_UNKNOWN) 1995 if (pmap_type == UDF_VTOP_TYPE_UNKNOWN)
1987 return EINVAL; 1996 return EINVAL;
1988 1997
1989 ump->vtop [log_part] = phys_part; 1998 ump->vtop [log_part] = phys_part;
1990 ump->vtop_tp[log_part] = pmap_type; 1999 ump->vtop_tp[log_part] = pmap_type;
1991 2000
1992 pmap_pos += pmap_size; 2001 pmap_pos += pmap_size;
@@ -3106,37 +3115,48 @@ udf_read_sparables(struct udf_mount *ump @@ -3106,37 +3115,48 @@ udf_read_sparables(struct udf_mount *ump
3106 return 0; 3115 return 0;
3107 3116
3108 return ENOENT; 3117 return ENOENT;
3109} 3118}
3110 3119
3111/* --------------------------------------------------------------------- */ 3120/* --------------------------------------------------------------------- */
3112 3121
3113static int 3122static int
3114udf_read_metadata_nodes(struct udf_mount *ump, union udf_pmap *mapping) 3123udf_read_metadata_nodes(struct udf_mount *ump, union udf_pmap *mapping)
3115{ 3124{
3116 struct part_map_meta *pmm = &mapping->pmm; 3125 struct part_map_meta *pmm = &mapping->pmm;
3117 struct long_ad icb_loc; 3126 struct long_ad icb_loc;
3118 struct vnode *vp; 3127 struct vnode *vp;
 3128 uint16_t raw_phys_part, phys_part;
3119 int error; 3129 int error;
3120 3130
 3131 /*
 3132 * BUGALERT: some rogue implementations use random physical
 3133 * partition numbers to break other implementations so lookup
 3134 * the number.
 3135 */
 3136
3121 /* extract our allocation parameters set up on format */ 3137 /* extract our allocation parameters set up on format */
3122 ump->metadata_alloc_unit_size = udf_rw32(mapping->pmm.alloc_unit_size); 3138 ump->metadata_alloc_unit_size = udf_rw32(mapping->pmm.alloc_unit_size);
3123 ump->metadata_alignment_unit_size = udf_rw16(mapping->pmm.alignment_unit_size); 3139 ump->metadata_alignment_unit_size = udf_rw16(mapping->pmm.alignment_unit_size);
3124 ump->metadata_flags = mapping->pmm.flags; 3140 ump->metadata_flags = mapping->pmm.flags;
3125 3141
3126 DPRINTF(VOLUMES, ("Reading in Metadata files\n")); 3142 DPRINTF(VOLUMES, ("Reading in Metadata files\n"));
3127 icb_loc.loc.part_num = pmm->part_num; 3143 raw_phys_part = udf_rw16(pmm->part_num);
3128 icb_loc.loc.lb_num = pmm->meta_file_lbn; 3144 phys_part = udf_find_raw_phys(ump, raw_phys_part);
 3145
 3146 icb_loc.loc.part_num = udf_rw16(phys_part);
 3147
3129 DPRINTF(VOLUMES, ("Metadata file\n")); 3148 DPRINTF(VOLUMES, ("Metadata file\n"));
 3149 icb_loc.loc.lb_num = pmm->meta_file_lbn;
3130 error = udf_get_node(ump, &icb_loc, &ump->metadata_node); 3150 error = udf_get_node(ump, &icb_loc, &ump->metadata_node);
3131 if (ump->metadata_node) { 3151 if (ump->metadata_node) {
3132 vp = ump->metadata_node->vnode; 3152 vp = ump->metadata_node->vnode;
3133 UDF_SET_SYSTEMFILE(vp); 3153 UDF_SET_SYSTEMFILE(vp);
3134 } 3154 }
3135 3155
3136 icb_loc.loc.lb_num = pmm->meta_mirror_file_lbn; 3156 icb_loc.loc.lb_num = pmm->meta_mirror_file_lbn;
3137 if (icb_loc.loc.lb_num != -1) { 3157 if (icb_loc.loc.lb_num != -1) {
3138 DPRINTF(VOLUMES, ("Metadata copy file\n")); 3158 DPRINTF(VOLUMES, ("Metadata copy file\n"));
3139 error = udf_get_node(ump, &icb_loc, &ump->metadatamirror_node); 3159 error = udf_get_node(ump, &icb_loc, &ump->metadatamirror_node);
3140 if (ump->metadatamirror_node) { 3160 if (ump->metadatamirror_node) {
3141 vp = ump->metadatamirror_node->vnode; 3161 vp = ump->metadatamirror_node->vnode;
3142 UDF_SET_SYSTEMFILE(vp); 3162 UDF_SET_SYSTEMFILE(vp);
@@ -5299,26 +5319,27 @@ udf_get_node(struct udf_mount *ump, stru @@ -5299,26 +5319,27 @@ udf_get_node(struct udf_mount *ump, stru
5299 assert(node_icb_loc); 5319 assert(node_icb_loc);
5300 udf_node = udf_node_lookup(ump, node_icb_loc); 5320 udf_node = udf_node_lookup(ump, node_icb_loc);
5301 if (udf_node) { 5321 if (udf_node) {
5302 DPRINTF(NODE, ("\tgot it from the hash!\n")); 5322 DPRINTF(NODE, ("\tgot it from the hash!\n"));
5303 /* vnode is returned locked */ 5323 /* vnode is returned locked */
5304 *udf_noderes = udf_node; 5324 *udf_noderes = udf_node;
5305 mutex_exit(&ump->get_node_lock); 5325 mutex_exit(&ump->get_node_lock);
5306 return 0; 5326 return 0;
5307 } 5327 }
5308 5328
5309 /* garbage check: translate udf_node_icb_loc to sectornr */ 5329 /* garbage check: translate udf_node_icb_loc to sectornr */
5310 error = udf_translate_vtop(ump, node_icb_loc, &sector, &dummy); 5330 error = udf_translate_vtop(ump, node_icb_loc, &sector, &dummy);
5311 if (error) { 5331 if (error) {
 5332 DPRINTF(NODE, ("\tcan't translate icb address!\n"));
5312 /* no use, this will fail anyway */ 5333 /* no use, this will fail anyway */
5313 mutex_exit(&ump->get_node_lock); 5334 mutex_exit(&ump->get_node_lock);
5314 return EINVAL; 5335 return EINVAL;
5315 } 5336 }
5316 5337
5317 /* build udf_node (do initialise!) */ 5338 /* build udf_node (do initialise!) */
5318 udf_node = pool_get(&udf_node_pool, PR_WAITOK); 5339 udf_node = pool_get(&udf_node_pool, PR_WAITOK);
5319 memset(udf_node, 0, sizeof(struct udf_node)); 5340 memset(udf_node, 0, sizeof(struct udf_node));
5320 5341
5321 DPRINTF(NODE, ("\tget new vnode\n")); 5342 DPRINTF(NODE, ("\tget new vnode\n"));
5322 /* give it a vnode */ 5343 /* give it a vnode */
5323 error = getnewvnode(VT_UDF, ump->vfs_mountp, udf_vnodeop_p, &nvp); 5344 error = getnewvnode(VT_UDF, ump->vfs_mountp, udf_vnodeop_p, &nvp);
5324 if (error) { 5345 if (error) {