Commit a1ca8e71 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'fs_for_v5.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs

Pull UDF and isofs updates from Jan Kara:
 "Several smaller fixes and cleanups in UDF and isofs"

* tag 'fs_for_v5.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs:
  udf_get_extendedattr() had no boundary checks.
  isofs: joliet: Fix iocharset=utf8 mount option
  udf: Fix iocharset=utf8 mount option
  udf: Get rid of 0-length arrays in struct fileIdentDesc
  udf: Get rid of 0-length arrays
  udf: Remove unused declaration
  udf: Check LVID earlier
parents 63b0c403 58bc6d1b
...@@ -155,7 +155,6 @@ struct iso9660_options{ ...@@ -155,7 +155,6 @@ struct iso9660_options{
unsigned int overriderockperm:1; unsigned int overriderockperm:1;
unsigned int uid_set:1; unsigned int uid_set:1;
unsigned int gid_set:1; unsigned int gid_set:1;
unsigned int utf8:1;
unsigned char map; unsigned char map;
unsigned char check; unsigned char check;
unsigned int blocksize; unsigned int blocksize;
...@@ -356,7 +355,6 @@ static int parse_options(char *options, struct iso9660_options *popt) ...@@ -356,7 +355,6 @@ static int parse_options(char *options, struct iso9660_options *popt)
popt->gid = GLOBAL_ROOT_GID; popt->gid = GLOBAL_ROOT_GID;
popt->uid = GLOBAL_ROOT_UID; popt->uid = GLOBAL_ROOT_UID;
popt->iocharset = NULL; popt->iocharset = NULL;
popt->utf8 = 0;
popt->overriderockperm = 0; popt->overriderockperm = 0;
popt->session=-1; popt->session=-1;
popt->sbsector=-1; popt->sbsector=-1;
...@@ -389,10 +387,13 @@ static int parse_options(char *options, struct iso9660_options *popt) ...@@ -389,10 +387,13 @@ static int parse_options(char *options, struct iso9660_options *popt)
case Opt_cruft: case Opt_cruft:
popt->cruft = 1; popt->cruft = 1;
break; break;
#ifdef CONFIG_JOLIET
case Opt_utf8: case Opt_utf8:
popt->utf8 = 1; kfree(popt->iocharset);
popt->iocharset = kstrdup("utf8", GFP_KERNEL);
if (!popt->iocharset)
return 0;
break; break;
#ifdef CONFIG_JOLIET
case Opt_iocharset: case Opt_iocharset:
kfree(popt->iocharset); kfree(popt->iocharset);
popt->iocharset = match_strdup(&args[0]); popt->iocharset = match_strdup(&args[0]);
...@@ -495,7 +496,6 @@ static int isofs_show_options(struct seq_file *m, struct dentry *root) ...@@ -495,7 +496,6 @@ static int isofs_show_options(struct seq_file *m, struct dentry *root)
if (sbi->s_nocompress) seq_puts(m, ",nocompress"); if (sbi->s_nocompress) seq_puts(m, ",nocompress");
if (sbi->s_overriderockperm) seq_puts(m, ",overriderockperm"); if (sbi->s_overriderockperm) seq_puts(m, ",overriderockperm");
if (sbi->s_showassoc) seq_puts(m, ",showassoc"); if (sbi->s_showassoc) seq_puts(m, ",showassoc");
if (sbi->s_utf8) seq_puts(m, ",utf8");
if (sbi->s_check) seq_printf(m, ",check=%c", sbi->s_check); if (sbi->s_check) seq_printf(m, ",check=%c", sbi->s_check);
if (sbi->s_mapping) seq_printf(m, ",map=%c", sbi->s_mapping); if (sbi->s_mapping) seq_printf(m, ",map=%c", sbi->s_mapping);
...@@ -518,9 +518,10 @@ static int isofs_show_options(struct seq_file *m, struct dentry *root) ...@@ -518,9 +518,10 @@ static int isofs_show_options(struct seq_file *m, struct dentry *root)
seq_printf(m, ",fmode=%o", sbi->s_fmode); seq_printf(m, ",fmode=%o", sbi->s_fmode);
#ifdef CONFIG_JOLIET #ifdef CONFIG_JOLIET
if (sbi->s_nls_iocharset && if (sbi->s_nls_iocharset)
strcmp(sbi->s_nls_iocharset->charset, CONFIG_NLS_DEFAULT) != 0)
seq_printf(m, ",iocharset=%s", sbi->s_nls_iocharset->charset); seq_printf(m, ",iocharset=%s", sbi->s_nls_iocharset->charset);
else
seq_puts(m, ",iocharset=utf8");
#endif #endif
return 0; return 0;
} }
...@@ -863,14 +864,13 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent) ...@@ -863,14 +864,13 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent)
sbi->s_nls_iocharset = NULL; sbi->s_nls_iocharset = NULL;
#ifdef CONFIG_JOLIET #ifdef CONFIG_JOLIET
if (joliet_level && opt.utf8 == 0) { if (joliet_level) {
char *p = opt.iocharset ? opt.iocharset : CONFIG_NLS_DEFAULT; char *p = opt.iocharset ? opt.iocharset : CONFIG_NLS_DEFAULT;
sbi->s_nls_iocharset = load_nls(p); if (strcmp(p, "utf8") != 0) {
if (! sbi->s_nls_iocharset) { sbi->s_nls_iocharset = opt.iocharset ?
/* Fail only if explicit charset specified */ load_nls(opt.iocharset) : load_nls_default();
if (opt.iocharset) if (!sbi->s_nls_iocharset)
goto out_freesbi; goto out_freesbi;
sbi->s_nls_iocharset = load_nls_default();
} }
} }
#endif #endif
...@@ -886,7 +886,6 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent) ...@@ -886,7 +886,6 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent)
sbi->s_gid = opt.gid; sbi->s_gid = opt.gid;
sbi->s_uid_set = opt.uid_set; sbi->s_uid_set = opt.uid_set;
sbi->s_gid_set = opt.gid_set; sbi->s_gid_set = opt.gid_set;
sbi->s_utf8 = opt.utf8;
sbi->s_nocompress = opt.nocompress; sbi->s_nocompress = opt.nocompress;
sbi->s_overriderockperm = opt.overriderockperm; sbi->s_overriderockperm = opt.overriderockperm;
/* /*
......
...@@ -44,7 +44,6 @@ struct isofs_sb_info { ...@@ -44,7 +44,6 @@ struct isofs_sb_info {
unsigned char s_session; unsigned char s_session;
unsigned int s_high_sierra:1; unsigned int s_high_sierra:1;
unsigned int s_rock:2; unsigned int s_rock:2;
unsigned int s_utf8:1;
unsigned int s_cruft:1; /* Broken disks with high byte of length unsigned int s_cruft:1; /* Broken disks with high byte of length
* containing junk */ * containing junk */
unsigned int s_nocompress:1; unsigned int s_nocompress:1;
......
...@@ -41,14 +41,12 @@ uni16_to_x8(unsigned char *ascii, __be16 *uni, int len, struct nls_table *nls) ...@@ -41,14 +41,12 @@ uni16_to_x8(unsigned char *ascii, __be16 *uni, int len, struct nls_table *nls)
int int
get_joliet_filename(struct iso_directory_record * de, unsigned char *outname, struct inode * inode) get_joliet_filename(struct iso_directory_record * de, unsigned char *outname, struct inode * inode)
{ {
unsigned char utf8;
struct nls_table *nls; struct nls_table *nls;
unsigned char len = 0; unsigned char len = 0;
utf8 = ISOFS_SB(inode->i_sb)->s_utf8;
nls = ISOFS_SB(inode->i_sb)->s_nls_iocharset; nls = ISOFS_SB(inode->i_sb)->s_nls_iocharset;
if (utf8) { if (!nls) {
len = utf16s_to_utf8s((const wchar_t *) de->name, len = utf16s_to_utf8s((const wchar_t *) de->name,
de->name_len[0] >> 1, UTF16_BIG_ENDIAN, de->name_len[0] >> 1, UTF16_BIG_ENDIAN,
outname, PAGE_SIZE); outname, PAGE_SIZE);
......
...@@ -35,7 +35,6 @@ ...@@ -35,7 +35,6 @@
#include "udf_i.h" #include "udf_i.h"
#include "udf_sb.h" #include "udf_sb.h"
static int udf_readdir(struct file *file, struct dir_context *ctx) static int udf_readdir(struct file *file, struct dir_context *ctx)
{ {
struct inode *dir = file_inode(file); struct inode *dir = file_inode(file);
...@@ -135,7 +134,7 @@ static int udf_readdir(struct file *file, struct dir_context *ctx) ...@@ -135,7 +134,7 @@ static int udf_readdir(struct file *file, struct dir_context *ctx)
lfi = cfi.lengthFileIdent; lfi = cfi.lengthFileIdent;
if (fibh.sbh == fibh.ebh) { if (fibh.sbh == fibh.ebh) {
nameptr = fi->fileIdent + liu; nameptr = udf_get_fi_ident(fi);
} else { } else {
int poffset; /* Unpaded ending offset */ int poffset; /* Unpaded ending offset */
...@@ -153,7 +152,7 @@ static int udf_readdir(struct file *file, struct dir_context *ctx) ...@@ -153,7 +152,7 @@ static int udf_readdir(struct file *file, struct dir_context *ctx)
} }
} }
nameptr = copy_name; nameptr = copy_name;
memcpy(nameptr, fi->fileIdent + liu, memcpy(nameptr, udf_get_fi_ident(fi),
lfi - poffset); lfi - poffset);
memcpy(nameptr + lfi - poffset, memcpy(nameptr + lfi - poffset,
fibh.ebh->b_data, poffset); fibh.ebh->b_data, poffset);
......
...@@ -307,14 +307,14 @@ struct logicalVolDesc { ...@@ -307,14 +307,14 @@ struct logicalVolDesc {
struct regid impIdent; struct regid impIdent;
uint8_t impUse[128]; uint8_t impUse[128];
struct extent_ad integritySeqExt; struct extent_ad integritySeqExt;
uint8_t partitionMaps[0]; uint8_t partitionMaps[];
} __packed; } __packed;
/* Generic Partition Map (ECMA 167r3 3/10.7.1) */ /* Generic Partition Map (ECMA 167r3 3/10.7.1) */
struct genericPartitionMap { struct genericPartitionMap {
uint8_t partitionMapType; uint8_t partitionMapType;
uint8_t partitionMapLength; uint8_t partitionMapLength;
uint8_t partitionMapping[0]; uint8_t partitionMapping[];
} __packed; } __packed;
/* Partition Map Type (ECMA 167r3 3/10.7.1.1) */ /* Partition Map Type (ECMA 167r3 3/10.7.1.1) */
...@@ -342,7 +342,7 @@ struct unallocSpaceDesc { ...@@ -342,7 +342,7 @@ struct unallocSpaceDesc {
struct tag descTag; struct tag descTag;
__le32 volDescSeqNum; __le32 volDescSeqNum;
__le32 numAllocDescs; __le32 numAllocDescs;
struct extent_ad allocDescs[0]; struct extent_ad allocDescs[];
} __packed; } __packed;
/* Terminating Descriptor (ECMA 167r3 3/10.9) */ /* Terminating Descriptor (ECMA 167r3 3/10.9) */
...@@ -360,9 +360,9 @@ struct logicalVolIntegrityDesc { ...@@ -360,9 +360,9 @@ struct logicalVolIntegrityDesc {
uint8_t logicalVolContentsUse[32]; uint8_t logicalVolContentsUse[32];
__le32 numOfPartitions; __le32 numOfPartitions;
__le32 lengthOfImpUse; __le32 lengthOfImpUse;
__le32 freeSpaceTable[0]; __le32 freeSpaceTable[];
__le32 sizeTable[0]; /* __le32 sizeTable[]; */
uint8_t impUse[0]; /* uint8_t impUse[]; */
} __packed; } __packed;
/* Integrity Type (ECMA 167r3 3/10.10.3) */ /* Integrity Type (ECMA 167r3 3/10.10.3) */
...@@ -471,9 +471,9 @@ struct fileIdentDesc { ...@@ -471,9 +471,9 @@ struct fileIdentDesc {
uint8_t lengthFileIdent; uint8_t lengthFileIdent;
struct long_ad icb; struct long_ad icb;
__le16 lengthOfImpUse; __le16 lengthOfImpUse;
uint8_t impUse[0]; uint8_t impUse[];
uint8_t fileIdent[0]; /* uint8_t fileIdent[]; */
uint8_t padding[0]; /* uint8_t padding[]; */
} __packed; } __packed;
/* File Characteristics (ECMA 167r3 4/14.4.3) */ /* File Characteristics (ECMA 167r3 4/14.4.3) */
...@@ -578,8 +578,8 @@ struct fileEntry { ...@@ -578,8 +578,8 @@ struct fileEntry {
__le64 uniqueID; __le64 uniqueID;
__le32 lengthExtendedAttr; __le32 lengthExtendedAttr;
__le32 lengthAllocDescs; __le32 lengthAllocDescs;
uint8_t extendedAttr[0]; uint8_t extendedAttr[];
uint8_t allocDescs[0]; /* uint8_t allocDescs[]; */
} __packed; } __packed;
/* Permissions (ECMA 167r3 4/14.9.5) */ /* Permissions (ECMA 167r3 4/14.9.5) */
...@@ -632,7 +632,7 @@ struct genericFormat { ...@@ -632,7 +632,7 @@ struct genericFormat {
uint8_t attrSubtype; uint8_t attrSubtype;
uint8_t reserved[3]; uint8_t reserved[3];
__le32 attrLength; __le32 attrLength;
uint8_t attrData[0]; uint8_t attrData[];
} __packed; } __packed;
/* Character Set Information (ECMA 167r3 4/14.10.3) */ /* Character Set Information (ECMA 167r3 4/14.10.3) */
...@@ -643,7 +643,7 @@ struct charSetInfo { ...@@ -643,7 +643,7 @@ struct charSetInfo {
__le32 attrLength; __le32 attrLength;
__le32 escapeSeqLength; __le32 escapeSeqLength;
uint8_t charSetType; uint8_t charSetType;
uint8_t escapeSeq[0]; uint8_t escapeSeq[];
} __packed; } __packed;
/* Alternate Permissions (ECMA 167r3 4/14.10.4) */ /* Alternate Permissions (ECMA 167r3 4/14.10.4) */
...@@ -682,7 +682,7 @@ struct infoTimesExtAttr { ...@@ -682,7 +682,7 @@ struct infoTimesExtAttr {
__le32 attrLength; __le32 attrLength;
__le32 dataLength; __le32 dataLength;
__le32 infoTimeExistence; __le32 infoTimeExistence;
uint8_t infoTimes[0]; uint8_t infoTimes[];
} __packed; } __packed;
/* Device Specification (ECMA 167r3 4/14.10.7) */ /* Device Specification (ECMA 167r3 4/14.10.7) */
...@@ -694,7 +694,7 @@ struct deviceSpec { ...@@ -694,7 +694,7 @@ struct deviceSpec {
__le32 impUseLength; __le32 impUseLength;
__le32 majorDeviceIdent; __le32 majorDeviceIdent;
__le32 minorDeviceIdent; __le32 minorDeviceIdent;
uint8_t impUse[0]; uint8_t impUse[];
} __packed; } __packed;
/* Implementation Use Extended Attr (ECMA 167r3 4/14.10.8) */ /* Implementation Use Extended Attr (ECMA 167r3 4/14.10.8) */
...@@ -705,7 +705,7 @@ struct impUseExtAttr { ...@@ -705,7 +705,7 @@ struct impUseExtAttr {
__le32 attrLength; __le32 attrLength;
__le32 impUseLength; __le32 impUseLength;
struct regid impIdent; struct regid impIdent;
uint8_t impUse[0]; uint8_t impUse[];
} __packed; } __packed;
/* Application Use Extended Attribute (ECMA 167r3 4/14.10.9) */ /* Application Use Extended Attribute (ECMA 167r3 4/14.10.9) */
...@@ -716,7 +716,7 @@ struct appUseExtAttr { ...@@ -716,7 +716,7 @@ struct appUseExtAttr {
__le32 attrLength; __le32 attrLength;
__le32 appUseLength; __le32 appUseLength;
struct regid appIdent; struct regid appIdent;
uint8_t appUse[0]; uint8_t appUse[];
} __packed; } __packed;
#define EXTATTR_CHAR_SET 1 #define EXTATTR_CHAR_SET 1
...@@ -733,7 +733,7 @@ struct unallocSpaceEntry { ...@@ -733,7 +733,7 @@ struct unallocSpaceEntry {
struct tag descTag; struct tag descTag;
struct icbtag icbTag; struct icbtag icbTag;
__le32 lengthAllocDescs; __le32 lengthAllocDescs;
uint8_t allocDescs[0]; uint8_t allocDescs[];
} __packed; } __packed;
/* Space Bitmap Descriptor (ECMA 167r3 4/14.12) */ /* Space Bitmap Descriptor (ECMA 167r3 4/14.12) */
...@@ -741,7 +741,7 @@ struct spaceBitmapDesc { ...@@ -741,7 +741,7 @@ struct spaceBitmapDesc {
struct tag descTag; struct tag descTag;
__le32 numOfBits; __le32 numOfBits;
__le32 numOfBytes; __le32 numOfBytes;
uint8_t bitmap[0]; uint8_t bitmap[];
} __packed; } __packed;
/* Partition Integrity Entry (ECMA 167r3 4/14.13) */ /* Partition Integrity Entry (ECMA 167r3 4/14.13) */
...@@ -780,7 +780,7 @@ struct pathComponent { ...@@ -780,7 +780,7 @@ struct pathComponent {
uint8_t componentType; uint8_t componentType;
uint8_t lengthComponentIdent; uint8_t lengthComponentIdent;
__le16 componentFileVersionNum; __le16 componentFileVersionNum;
dchars componentIdent[0]; dchars componentIdent[];
} __packed; } __packed;
/* File Entry (ECMA 167r3 4/14.17) */ /* File Entry (ECMA 167r3 4/14.17) */
...@@ -809,8 +809,8 @@ struct extendedFileEntry { ...@@ -809,8 +809,8 @@ struct extendedFileEntry {
__le64 uniqueID; __le64 uniqueID;
__le32 lengthExtendedAttr; __le32 lengthExtendedAttr;
__le32 lengthAllocDescs; __le32 lengthAllocDescs;
uint8_t extendedAttr[0]; uint8_t extendedAttr[];
uint8_t allocDescs[0]; /* uint8_t allocDescs[]; */
} __packed; } __packed;
#endif /* _ECMA_167_H */ #endif /* _ECMA_167_H */
...@@ -390,8 +390,7 @@ struct buffer_head *udf_expand_dir_adinicb(struct inode *inode, ...@@ -390,8 +390,7 @@ struct buffer_head *udf_expand_dir_adinicb(struct inode *inode,
dfibh.eoffset += (sfibh.eoffset - sfibh.soffset); dfibh.eoffset += (sfibh.eoffset - sfibh.soffset);
dfi = (struct fileIdentDesc *)(dbh->b_data + dfibh.soffset); dfi = (struct fileIdentDesc *)(dbh->b_data + dfibh.soffset);
if (udf_write_fi(inode, sfi, dfi, &dfibh, sfi->impUse, if (udf_write_fi(inode, sfi, dfi, &dfibh, sfi->impUse,
sfi->fileIdent + udf_get_fi_ident(sfi))) {
le16_to_cpu(sfi->lengthOfImpUse))) {
iinfo->i_alloc_type = ICBTAG_FLAG_AD_IN_ICB; iinfo->i_alloc_type = ICBTAG_FLAG_AD_IN_ICB;
brelse(dbh); brelse(dbh);
return NULL; return NULL;
......
...@@ -173,13 +173,22 @@ struct genericFormat *udf_get_extendedattr(struct inode *inode, uint32_t type, ...@@ -173,13 +173,22 @@ struct genericFormat *udf_get_extendedattr(struct inode *inode, uint32_t type,
else else
offset = le32_to_cpu(eahd->appAttrLocation); offset = le32_to_cpu(eahd->appAttrLocation);
while (offset < iinfo->i_lenEAttr) { while (offset + sizeof(*gaf) < iinfo->i_lenEAttr) {
uint32_t attrLength;
gaf = (struct genericFormat *)&ea[offset]; gaf = (struct genericFormat *)&ea[offset];
attrLength = le32_to_cpu(gaf->attrLength);
/* Detect undersized elements and buffer overflows */
if ((attrLength < sizeof(*gaf)) ||
(attrLength > (iinfo->i_lenEAttr - offset)))
break;
if (le32_to_cpu(gaf->attrType) == type && if (le32_to_cpu(gaf->attrType) == type &&
gaf->attrSubtype == subtype) gaf->attrSubtype == subtype)
return gaf; return gaf;
else else
offset += le32_to_cpu(gaf->attrLength); offset += attrLength;
} }
} }
......
...@@ -74,12 +74,11 @@ int udf_write_fi(struct inode *inode, struct fileIdentDesc *cfi, ...@@ -74,12 +74,11 @@ int udf_write_fi(struct inode *inode, struct fileIdentDesc *cfi,
if (fileident) { if (fileident) {
if (adinicb || (offset + lfi < 0)) { if (adinicb || (offset + lfi < 0)) {
memcpy((uint8_t *)sfi->fileIdent + liu, fileident, lfi); memcpy(udf_get_fi_ident(sfi), fileident, lfi);
} else if (offset >= 0) { } else if (offset >= 0) {
memcpy(fibh->ebh->b_data + offset, fileident, lfi); memcpy(fibh->ebh->b_data + offset, fileident, lfi);
} else { } else {
memcpy((uint8_t *)sfi->fileIdent + liu, fileident, memcpy(udf_get_fi_ident(sfi), fileident, -offset);
-offset);
memcpy(fibh->ebh->b_data, fileident - offset, memcpy(fibh->ebh->b_data, fileident - offset,
lfi + offset); lfi + offset);
} }
...@@ -88,11 +87,11 @@ int udf_write_fi(struct inode *inode, struct fileIdentDesc *cfi, ...@@ -88,11 +87,11 @@ int udf_write_fi(struct inode *inode, struct fileIdentDesc *cfi,
offset += lfi; offset += lfi;
if (adinicb || (offset + padlen < 0)) { if (adinicb || (offset + padlen < 0)) {
memset((uint8_t *)sfi->padding + liu + lfi, 0x00, padlen); memset(udf_get_fi_ident(sfi) + lfi, 0x00, padlen);
} else if (offset >= 0) { } else if (offset >= 0) {
memset(fibh->ebh->b_data + offset, 0x00, padlen); memset(fibh->ebh->b_data + offset, 0x00, padlen);
} else { } else {
memset((uint8_t *)sfi->padding + liu + lfi, 0x00, -offset); memset(udf_get_fi_ident(sfi) + lfi, 0x00, -offset);
memset(fibh->ebh->b_data, 0x00, padlen + offset); memset(fibh->ebh->b_data, 0x00, padlen + offset);
} }
...@@ -226,7 +225,7 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir, ...@@ -226,7 +225,7 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir,
lfi = cfi->lengthFileIdent; lfi = cfi->lengthFileIdent;
if (fibh->sbh == fibh->ebh) { if (fibh->sbh == fibh->ebh) {
nameptr = fi->fileIdent + liu; nameptr = udf_get_fi_ident(fi);
} else { } else {
int poffset; /* Unpaded ending offset */ int poffset; /* Unpaded ending offset */
...@@ -246,7 +245,7 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir, ...@@ -246,7 +245,7 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir,
} }
} }
nameptr = copy_name; nameptr = copy_name;
memcpy(nameptr, fi->fileIdent + liu, memcpy(nameptr, udf_get_fi_ident(fi),
lfi - poffset); lfi - poffset);
memcpy(nameptr + lfi - poffset, memcpy(nameptr + lfi - poffset,
fibh->ebh->b_data, poffset); fibh->ebh->b_data, poffset);
......
...@@ -111,7 +111,7 @@ struct logicalVolIntegrityDescImpUse { ...@@ -111,7 +111,7 @@ struct logicalVolIntegrityDescImpUse {
__le16 minUDFReadRev; __le16 minUDFReadRev;
__le16 minUDFWriteRev; __le16 minUDFWriteRev;
__le16 maxUDFWriteRev; __le16 maxUDFWriteRev;
uint8_t impUse[0]; uint8_t impUse[];
} __packed; } __packed;
/* Implementation Use Volume Descriptor (UDF 2.60 2.2.7) */ /* Implementation Use Volume Descriptor (UDF 2.60 2.2.7) */
...@@ -178,15 +178,6 @@ struct metadataPartitionMap { ...@@ -178,15 +178,6 @@ struct metadataPartitionMap {
uint8_t reserved2[5]; uint8_t reserved2[5];
} __packed; } __packed;
/* Virtual Allocation Table (UDF 1.5 2.2.10) */
struct virtualAllocationTable15 {
__le32 vatEntry[0];
struct regid vatIdent;
__le32 previousVATICBLoc;
} __packed;
#define ICBTAG_FILE_TYPE_VAT15 0x00U
/* Virtual Allocation Table (UDF 2.60 2.2.11) */ /* Virtual Allocation Table (UDF 2.60 2.2.11) */
struct virtualAllocationTable20 { struct virtualAllocationTable20 {
__le16 lengthHeader; __le16 lengthHeader;
...@@ -199,8 +190,8 @@ struct virtualAllocationTable20 { ...@@ -199,8 +190,8 @@ struct virtualAllocationTable20 {
__le16 minUDFWriteRev; __le16 minUDFWriteRev;
__le16 maxUDFWriteRev; __le16 maxUDFWriteRev;
__le16 reserved; __le16 reserved;
uint8_t impUse[0]; uint8_t impUse[];
__le32 vatEntry[0]; /* __le32 vatEntry[]; */
} __packed; } __packed;
#define ICBTAG_FILE_TYPE_VAT20 0xF8U #define ICBTAG_FILE_TYPE_VAT20 0xF8U
...@@ -217,8 +208,7 @@ struct sparingTable { ...@@ -217,8 +208,7 @@ struct sparingTable {
__le16 reallocationTableLen; __le16 reallocationTableLen;
__le16 reserved; __le16 reserved;
__le32 sequenceNum; __le32 sequenceNum;
struct sparingEntry struct sparingEntry mapEntry[];
mapEntry[0];
} __packed; } __packed;
/* Metadata File (and Metadata Mirror File) (UDF 2.60 2.2.13.1) */ /* Metadata File (and Metadata Mirror File) (UDF 2.60 2.2.13.1) */
...@@ -241,7 +231,7 @@ struct allocDescImpUse { ...@@ -241,7 +231,7 @@ struct allocDescImpUse {
/* FreeEASpace (UDF 2.60 3.3.4.5.1.1) */ /* FreeEASpace (UDF 2.60 3.3.4.5.1.1) */
struct freeEaSpace { struct freeEaSpace {
__le16 headerChecksum; __le16 headerChecksum;
uint8_t freeEASpace[0]; uint8_t freeEASpace[];
} __packed; } __packed;
/* DVD Copyright Management Information (UDF 2.60 3.3.4.5.1.2) */ /* DVD Copyright Management Information (UDF 2.60 3.3.4.5.1.2) */
...@@ -265,7 +255,7 @@ struct LVExtensionEA { ...@@ -265,7 +255,7 @@ struct LVExtensionEA {
/* FreeAppEASpace (UDF 2.60 3.3.4.6.1) */ /* FreeAppEASpace (UDF 2.60 3.3.4.6.1) */
struct freeAppEASpace { struct freeAppEASpace {
__le16 headerChecksum; __le16 headerChecksum;
uint8_t freeEASpace[0]; uint8_t freeEASpace[];
} __packed; } __packed;
/* UDF Defined System Stream (UDF 2.60 3.3.7) */ /* UDF Defined System Stream (UDF 2.60 3.3.7) */
......
...@@ -108,16 +108,10 @@ struct logicalVolIntegrityDescImpUse *udf_sb_lvidiu(struct super_block *sb) ...@@ -108,16 +108,10 @@ struct logicalVolIntegrityDescImpUse *udf_sb_lvidiu(struct super_block *sb)
return NULL; return NULL;
lvid = (struct logicalVolIntegrityDesc *)UDF_SB(sb)->s_lvid_bh->b_data; lvid = (struct logicalVolIntegrityDesc *)UDF_SB(sb)->s_lvid_bh->b_data;
partnum = le32_to_cpu(lvid->numOfPartitions); partnum = le32_to_cpu(lvid->numOfPartitions);
if ((sb->s_blocksize - sizeof(struct logicalVolIntegrityDescImpUse) -
offsetof(struct logicalVolIntegrityDesc, impUse)) /
(2 * sizeof(uint32_t)) < partnum) {
udf_err(sb, "Logical volume integrity descriptor corrupted "
"(numOfPartitions = %u)!\n", partnum);
return NULL;
}
/* The offset is to skip freeSpaceTable and sizeTable arrays */ /* The offset is to skip freeSpaceTable and sizeTable arrays */
offset = partnum * 2 * sizeof(uint32_t); offset = partnum * 2 * sizeof(uint32_t);
return (struct logicalVolIntegrityDescImpUse *)&(lvid->impUse[offset]); return (struct logicalVolIntegrityDescImpUse *)
(((uint8_t *)(lvid + 1)) + offset);
} }
/* UDF filesystem type */ /* UDF filesystem type */
...@@ -349,10 +343,10 @@ static int udf_show_options(struct seq_file *seq, struct dentry *root) ...@@ -349,10 +343,10 @@ static int udf_show_options(struct seq_file *seq, struct dentry *root)
seq_printf(seq, ",lastblock=%u", sbi->s_last_block); seq_printf(seq, ",lastblock=%u", sbi->s_last_block);
if (sbi->s_anchor != 0) if (sbi->s_anchor != 0)
seq_printf(seq, ",anchor=%u", sbi->s_anchor); seq_printf(seq, ",anchor=%u", sbi->s_anchor);
if (UDF_QUERY_FLAG(sb, UDF_FLAG_UTF8)) if (sbi->s_nls_map)
seq_puts(seq, ",utf8");
if (UDF_QUERY_FLAG(sb, UDF_FLAG_NLS_MAP) && sbi->s_nls_map)
seq_printf(seq, ",iocharset=%s", sbi->s_nls_map->charset); seq_printf(seq, ",iocharset=%s", sbi->s_nls_map->charset);
else
seq_puts(seq, ",iocharset=utf8");
return 0; return 0;
} }
...@@ -558,19 +552,24 @@ static int udf_parse_options(char *options, struct udf_options *uopt, ...@@ -558,19 +552,24 @@ static int udf_parse_options(char *options, struct udf_options *uopt,
/* Ignored (never implemented properly) */ /* Ignored (never implemented properly) */
break; break;
case Opt_utf8: case Opt_utf8:
uopt->flags |= (1 << UDF_FLAG_UTF8); if (!remount) {
unload_nls(uopt->nls_map);
uopt->nls_map = NULL;
}
break; break;
case Opt_iocharset: case Opt_iocharset:
if (!remount) { if (!remount) {
if (uopt->nls_map)
unload_nls(uopt->nls_map); unload_nls(uopt->nls_map);
/* uopt->nls_map = NULL;
* load_nls() failure is handled later in }
* udf_fill_super() after all options are /* When nls_map is not loaded then UTF-8 is used */
* parsed. if (!remount && strcmp(args[0].from, "utf8") != 0) {
*/
uopt->nls_map = load_nls(args[0].from); uopt->nls_map = load_nls(args[0].from);
uopt->flags |= (1 << UDF_FLAG_NLS_MAP); if (!uopt->nls_map) {
pr_err("iocharset %s not found\n",
args[0].from);
return 0;
}
} }
break; break;
case Opt_uforget: case Opt_uforget:
...@@ -1542,6 +1541,7 @@ static void udf_load_logicalvolint(struct super_block *sb, struct kernel_extent_ ...@@ -1542,6 +1541,7 @@ static void udf_load_logicalvolint(struct super_block *sb, struct kernel_extent_
struct udf_sb_info *sbi = UDF_SB(sb); struct udf_sb_info *sbi = UDF_SB(sb);
struct logicalVolIntegrityDesc *lvid; struct logicalVolIntegrityDesc *lvid;
int indirections = 0; int indirections = 0;
u32 parts, impuselen;
while (++indirections <= UDF_MAX_LVID_NESTING) { while (++indirections <= UDF_MAX_LVID_NESTING) {
final_bh = NULL; final_bh = NULL;
...@@ -1568,15 +1568,27 @@ static void udf_load_logicalvolint(struct super_block *sb, struct kernel_extent_ ...@@ -1568,15 +1568,27 @@ static void udf_load_logicalvolint(struct super_block *sb, struct kernel_extent_
lvid = (struct logicalVolIntegrityDesc *)final_bh->b_data; lvid = (struct logicalVolIntegrityDesc *)final_bh->b_data;
if (lvid->nextIntegrityExt.extLength == 0) if (lvid->nextIntegrityExt.extLength == 0)
return; goto check;
loc = leea_to_cpu(lvid->nextIntegrityExt); loc = leea_to_cpu(lvid->nextIntegrityExt);
} }
udf_warn(sb, "Too many LVID indirections (max %u), ignoring.\n", udf_warn(sb, "Too many LVID indirections (max %u), ignoring.\n",
UDF_MAX_LVID_NESTING); UDF_MAX_LVID_NESTING);
out_err:
brelse(sbi->s_lvid_bh); brelse(sbi->s_lvid_bh);
sbi->s_lvid_bh = NULL; sbi->s_lvid_bh = NULL;
return;
check:
parts = le32_to_cpu(lvid->numOfPartitions);
impuselen = le32_to_cpu(lvid->lengthOfImpUse);
if (parts >= sb->s_blocksize || impuselen >= sb->s_blocksize ||
sizeof(struct logicalVolIntegrityDesc) + impuselen +
2 * parts * sizeof(u32) > sb->s_blocksize) {
udf_warn(sb, "Corrupted LVID (parts=%u, impuselen=%u), "
"ignoring.\n", parts, impuselen);
goto out_err;
}
} }
/* /*
...@@ -2139,21 +2151,6 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent) ...@@ -2139,21 +2151,6 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
if (!udf_parse_options((char *)options, &uopt, false)) if (!udf_parse_options((char *)options, &uopt, false))
goto parse_options_failure; goto parse_options_failure;
if (uopt.flags & (1 << UDF_FLAG_UTF8) &&
uopt.flags & (1 << UDF_FLAG_NLS_MAP)) {
udf_err(sb, "utf8 cannot be combined with iocharset\n");
goto parse_options_failure;
}
if ((uopt.flags & (1 << UDF_FLAG_NLS_MAP)) && !uopt.nls_map) {
uopt.nls_map = load_nls_default();
if (!uopt.nls_map)
uopt.flags &= ~(1 << UDF_FLAG_NLS_MAP);
else
udf_debug("Using default NLS map\n");
}
if (!(uopt.flags & (1 << UDF_FLAG_NLS_MAP)))
uopt.flags |= (1 << UDF_FLAG_UTF8);
fileset.logicalBlockNum = 0xFFFFFFFF; fileset.logicalBlockNum = 0xFFFFFFFF;
fileset.partitionReferenceNum = 0xFFFF; fileset.partitionReferenceNum = 0xFFFF;
...@@ -2308,7 +2305,6 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent) ...@@ -2308,7 +2305,6 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
error_out: error_out:
iput(sbi->s_vat_inode); iput(sbi->s_vat_inode);
parse_options_failure: parse_options_failure:
if (uopt.nls_map)
unload_nls(uopt.nls_map); unload_nls(uopt.nls_map);
if (lvid_open) if (lvid_open)
udf_close_lvid(sb); udf_close_lvid(sb);
...@@ -2359,7 +2355,6 @@ static void udf_put_super(struct super_block *sb) ...@@ -2359,7 +2355,6 @@ static void udf_put_super(struct super_block *sb)
sbi = UDF_SB(sb); sbi = UDF_SB(sb);
iput(sbi->s_vat_inode); iput(sbi->s_vat_inode);
if (UDF_QUERY_FLAG(sb, UDF_FLAG_NLS_MAP))
unload_nls(sbi->s_nls_map); unload_nls(sbi->s_nls_map);
if (!sb_rdonly(sb)) if (!sb_rdonly(sb))
udf_close_lvid(sb); udf_close_lvid(sb);
......
...@@ -20,8 +20,6 @@ ...@@ -20,8 +20,6 @@
#define UDF_FLAG_UNDELETE 6 #define UDF_FLAG_UNDELETE 6
#define UDF_FLAG_UNHIDE 7 #define UDF_FLAG_UNHIDE 7
#define UDF_FLAG_VARCONV 8 #define UDF_FLAG_VARCONV 8
#define UDF_FLAG_NLS_MAP 9
#define UDF_FLAG_UTF8 10
#define UDF_FLAG_UID_FORGET 11 /* save -1 for uid to disk */ #define UDF_FLAG_UID_FORGET 11 /* save -1 for uid to disk */
#define UDF_FLAG_GID_FORGET 12 #define UDF_FLAG_GID_FORGET 12
#define UDF_FLAG_UID_SET 13 #define UDF_FLAG_UID_SET 13
......
...@@ -130,6 +130,10 @@ static inline unsigned int udf_dir_entry_len(struct fileIdentDesc *cfi) ...@@ -130,6 +130,10 @@ static inline unsigned int udf_dir_entry_len(struct fileIdentDesc *cfi)
le16_to_cpu(cfi->lengthOfImpUse) + cfi->lengthFileIdent, le16_to_cpu(cfi->lengthOfImpUse) + cfi->lengthFileIdent,
UDF_NAME_PAD); UDF_NAME_PAD);
} }
static inline uint8_t *udf_get_fi_ident(struct fileIdentDesc *fi)
{
return ((uint8_t *)(fi + 1)) + le16_to_cpu(fi->lengthOfImpUse);
}
/* file.c */ /* file.c */
extern long udf_ioctl(struct file *, unsigned int, unsigned long); extern long udf_ioctl(struct file *, unsigned int, unsigned long);
......
...@@ -177,7 +177,7 @@ static int udf_name_from_CS0(struct super_block *sb, ...@@ -177,7 +177,7 @@ static int udf_name_from_CS0(struct super_block *sb,
return 0; return 0;
} }
if (UDF_QUERY_FLAG(sb, UDF_FLAG_NLS_MAP)) if (UDF_SB(sb)->s_nls_map)
conv_f = UDF_SB(sb)->s_nls_map->uni2char; conv_f = UDF_SB(sb)->s_nls_map->uni2char;
else else
conv_f = NULL; conv_f = NULL;
...@@ -285,7 +285,7 @@ static int udf_name_to_CS0(struct super_block *sb, ...@@ -285,7 +285,7 @@ static int udf_name_to_CS0(struct super_block *sb,
if (ocu_max_len <= 0) if (ocu_max_len <= 0)
return 0; return 0;
if (UDF_QUERY_FLAG(sb, UDF_FLAG_NLS_MAP)) if (UDF_SB(sb)->s_nls_map)
conv_f = UDF_SB(sb)->s_nls_map->char2uni; conv_f = UDF_SB(sb)->s_nls_map->char2uni;
else else
conv_f = NULL; conv_f = NULL;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment